about summary refs log tree commit diff
diff options
context:
space:
mode:
authoriDawer <ilnur.iskhakov.oss@outlook.com>2022-09-02 12:52:58 +0500
committeriDawer <ilnur.iskhakov.oss@outlook.com>2022-09-02 16:31:15 +0500
commit8ae58b9fe45aac9534475e2042729327c4485d5f (patch)
treecb3ca7dc71a0571bd81d3afab923d6da68f49353
parent1fa9d5e07b1b2035be2eca70d0e2bb81f10edd8a (diff)
downloadrust-8ae58b9fe45aac9534475e2042729327c4485d5f.tar.gz
rust-8ae58b9fe45aac9534475e2042729327c4485d5f.zip
Record enabled unstable features into DefMap
-rw-r--r--crates/hir-def/src/nameres.rs11
-rw-r--r--crates/hir-def/src/nameres/collector.rs11
-rw-r--r--crates/hir-expand/src/name.rs1
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/usefulness.rs22
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<SmolStr>,
     /// Custom tool modules registered with `#![register_tool]`.
     registered_tools: Vec<SmolStr>,
+    /// Unstable features of Rust enabled with `#![feature(A, B)]`.
+    unstable_features: FxHashSet<SmolStr>,
 
     edition: Edition,
     recursion_limit: Option<u32>,
@@ -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<DeconstructedPat<'p>>,
-    feature_exhaustive_patterns: OnceCell<bool>,
+    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<DeconstructedPat<'p>>,
     ) -> 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
     }
 }