From 8ae58b9fe45aac9534475e2042729327c4485d5f Mon Sep 17 00:00:00 2001 From: iDawer Date: Fri, 2 Sep 2022 12:52:58 +0500 Subject: [PATCH] Record enabled unstable features into DefMap --- crates/hir-def/src/nameres.rs | 11 +++++++++- crates/hir-def/src/nameres/collector.rs | 11 ++++++++++ crates/hir-expand/src/name.rs | 1 + .../src/diagnostics/match_check/usefulness.rs | 22 +++++-------------- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 45f631936d2..fc8444394cf 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -64,7 +64,7 @@ use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId}; use itertools::Itertools; use la_arena::Arena; use profile::Count; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use stdx::format_to; use syntax::{ast, SmolStr}; @@ -114,6 +114,8 @@ pub struct DefMap { registered_attrs: Vec, /// Custom tool modules registered with `#![register_tool]`. registered_tools: Vec, + /// Unstable features of Rust enabled with `#![feature(A, B)]`. + unstable_features: FxHashSet, edition: Edition, recursion_limit: Option, @@ -284,6 +286,7 @@ impl DefMap { modules, registered_attrs: Vec::new(), registered_tools: Vec::new(), + unstable_features: FxHashSet::default(), diagnostics: Vec::new(), } } @@ -314,6 +317,10 @@ impl DefMap { &self.registered_attrs } + pub fn is_unstable_feature_enabled(&self, feature: &str) -> bool { + self.unstable_features.contains(feature) + } + pub fn root(&self) -> LocalModuleId { self.root } @@ -483,6 +490,7 @@ impl DefMap { registered_tools, fn_proc_macro_mapping, derive_helpers_in_scope, + unstable_features, proc_macro_loading_error: _, block: _, edition: _, @@ -500,6 +508,7 @@ impl DefMap { registered_tools.shrink_to_fit(); fn_proc_macro_mapping.shrink_to_fit(); derive_helpers_in_scope.shrink_to_fit(); + unstable_features.shrink_to_fit(); for (_, module) in modules.iter_mut() { module.children.shrink_to_fit(); module.scope.shrink_to_fit(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 8a6bb929c3d..ee27aa2554a 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -294,6 +294,17 @@ impl DefCollector<'_> { continue; } + if *attr_name == hir_expand::name![feature] { + let features = + attr.parse_path_comma_token_tree().into_iter().flatten().filter_map( + |feat| match feat.segments() { + [name] => Some(name.to_smol_str()), + _ => None, + }, + ); + self.def_map.unstable_features.extend(features); + } + let attr_is_register_like = *attr_name == hir_expand::name![register_attr] || *attr_name == hir_expand::name![register_tool]; if !attr_is_register_like { diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 2b859f77509..4ce21a57967 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -336,6 +336,7 @@ pub mod known { test, test_case, recursion_limit, + feature, // Safe intrinsics abort, add_with_overflow, diff --git a/crates/hir-ty/src/diagnostics/match_check/usefulness.rs b/crates/hir-ty/src/diagnostics/match_check/usefulness.rs index 4bb4ff8f10a..c4d709a975b 100644 --- a/crates/hir-ty/src/diagnostics/match_check/usefulness.rs +++ b/crates/hir-ty/src/diagnostics/match_check/usefulness.rs @@ -274,7 +274,6 @@ use std::iter::once; use hir_def::{AdtId, DefWithBodyId, HasModule, ModuleId}; -use once_cell::unsync::OnceCell; use smallvec::{smallvec, SmallVec}; use typed_arena::Arena; @@ -290,7 +289,7 @@ pub(crate) struct MatchCheckCtx<'a, 'p> { pub(crate) db: &'a dyn HirDatabase, /// Lowered patterns from arms plus generated by the check. pub(crate) pattern_arena: &'p Arena>, - feature_exhaustive_patterns: OnceCell, + exhaustive_patterns: bool, } impl<'a, 'p> MatchCheckCtx<'a, 'p> { @@ -300,7 +299,9 @@ impl<'a, 'p> MatchCheckCtx<'a, 'p> { db: &'a dyn HirDatabase, pattern_arena: &'p Arena>, ) -> Self { - Self { module, body, db, pattern_arena, feature_exhaustive_patterns: Default::default() } + let def_map = db.crate_def_map(module.krate()); + let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns"); + Self { module, body, db, pattern_arena, exhaustive_patterns } } pub(super) fn is_uninhabited(&self, ty: &Ty) -> bool { @@ -326,20 +327,7 @@ impl<'a, 'p> MatchCheckCtx<'a, 'p> { // Rust's unstable feature described as "Allows exhaustive pattern matching on types that contain uninhabited types." pub(super) fn feature_exhaustive_patterns(&self) -> bool { - *self.feature_exhaustive_patterns.get_or_init(|| { - let def_map = self.db.crate_def_map(self.module.krate()); - let root_mod = def_map.module_id(def_map.root()); - let rood_attrs = self.db.attrs(root_mod.into()); - let mut nightly_features = rood_attrs - .by_key("feature") - .attrs() - .map(|attr| attr.parse_path_comma_token_tree()) - .flatten() - .flatten(); - nightly_features.any( - |feat| matches!(feat.segments(), [name] if name.to_smol_str() == "exhaustive_patterns"), - ) - }) + self.exhaustive_patterns } }