Unnamed repository; edit this file 'description' to name the repository.
Record enabled unstable features into DefMap
iDawer 2022-09-02
parent 1fa9d5e · commit 8ae58b9
-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 45f631936d..fc8444394c 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 8a6bb929c3..ee27aa2554 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 2b859f7750..4ce21a5796 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 4bb4ff8f10..c4d709a975 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
}
}