Skip to content

Commit 8ae58b9

Browse files
committed
Record enabled unstable features into DefMap
1 parent 1fa9d5e commit 8ae58b9

File tree

4 files changed

+27
-18
lines changed

4 files changed

+27
-18
lines changed

crates/hir-def/src/nameres.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId};
6464
use itertools::Itertools;
6565
use la_arena::Arena;
6666
use profile::Count;
67-
use rustc_hash::FxHashMap;
67+
use rustc_hash::{FxHashMap, FxHashSet};
6868
use stdx::format_to;
6969
use syntax::{ast, SmolStr};
7070

@@ -114,6 +114,8 @@ pub struct DefMap {
114114
registered_attrs: Vec<SmolStr>,
115115
/// Custom tool modules registered with `#![register_tool]`.
116116
registered_tools: Vec<SmolStr>,
117+
/// Unstable features of Rust enabled with `#![feature(A, B)]`.
118+
unstable_features: FxHashSet<SmolStr>,
117119

118120
edition: Edition,
119121
recursion_limit: Option<u32>,
@@ -284,6 +286,7 @@ impl DefMap {
284286
modules,
285287
registered_attrs: Vec::new(),
286288
registered_tools: Vec::new(),
289+
unstable_features: FxHashSet::default(),
287290
diagnostics: Vec::new(),
288291
}
289292
}
@@ -314,6 +317,10 @@ impl DefMap {
314317
&self.registered_attrs
315318
}
316319

320+
pub fn is_unstable_feature_enabled(&self, feature: &str) -> bool {
321+
self.unstable_features.contains(feature)
322+
}
323+
317324
pub fn root(&self) -> LocalModuleId {
318325
self.root
319326
}
@@ -483,6 +490,7 @@ impl DefMap {
483490
registered_tools,
484491
fn_proc_macro_mapping,
485492
derive_helpers_in_scope,
493+
unstable_features,
486494
proc_macro_loading_error: _,
487495
block: _,
488496
edition: _,
@@ -500,6 +508,7 @@ impl DefMap {
500508
registered_tools.shrink_to_fit();
501509
fn_proc_macro_mapping.shrink_to_fit();
502510
derive_helpers_in_scope.shrink_to_fit();
511+
unstable_features.shrink_to_fit();
503512
for (_, module) in modules.iter_mut() {
504513
module.children.shrink_to_fit();
505514
module.scope.shrink_to_fit();

crates/hir-def/src/nameres/collector.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,17 @@ impl DefCollector<'_> {
294294
continue;
295295
}
296296

297+
if *attr_name == hir_expand::name![feature] {
298+
let features =
299+
attr.parse_path_comma_token_tree().into_iter().flatten().filter_map(
300+
|feat| match feat.segments() {
301+
[name] => Some(name.to_smol_str()),
302+
_ => None,
303+
},
304+
);
305+
self.def_map.unstable_features.extend(features);
306+
}
307+
297308
let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
298309
|| *attr_name == hir_expand::name![register_tool];
299310
if !attr_is_register_like {

crates/hir-expand/src/name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ pub mod known {
336336
test,
337337
test_case,
338338
recursion_limit,
339+
feature,
339340
// Safe intrinsics
340341
abort,
341342
add_with_overflow,

crates/hir-ty/src/diagnostics/match_check/usefulness.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@
274274
use std::iter::once;
275275

276276
use hir_def::{AdtId, DefWithBodyId, HasModule, ModuleId};
277-
use once_cell::unsync::OnceCell;
278277
use smallvec::{smallvec, SmallVec};
279278
use typed_arena::Arena;
280279

@@ -290,7 +289,7 @@ pub(crate) struct MatchCheckCtx<'a, 'p> {
290289
pub(crate) db: &'a dyn HirDatabase,
291290
/// Lowered patterns from arms plus generated by the check.
292291
pub(crate) pattern_arena: &'p Arena<DeconstructedPat<'p>>,
293-
feature_exhaustive_patterns: OnceCell<bool>,
292+
exhaustive_patterns: bool,
294293
}
295294

296295
impl<'a, 'p> MatchCheckCtx<'a, 'p> {
@@ -300,7 +299,9 @@ impl<'a, 'p> MatchCheckCtx<'a, 'p> {
300299
db: &'a dyn HirDatabase,
301300
pattern_arena: &'p Arena<DeconstructedPat<'p>>,
302301
) -> Self {
303-
Self { module, body, db, pattern_arena, feature_exhaustive_patterns: Default::default() }
302+
let def_map = db.crate_def_map(module.krate());
303+
let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns");
304+
Self { module, body, db, pattern_arena, exhaustive_patterns }
304305
}
305306

306307
pub(super) fn is_uninhabited(&self, ty: &Ty) -> bool {
@@ -326,20 +327,7 @@ impl<'a, 'p> MatchCheckCtx<'a, 'p> {
326327

327328
// Rust's unstable feature described as "Allows exhaustive pattern matching on types that contain uninhabited types."
328329
pub(super) fn feature_exhaustive_patterns(&self) -> bool {
329-
*self.feature_exhaustive_patterns.get_or_init(|| {
330-
let def_map = self.db.crate_def_map(self.module.krate());
331-
let root_mod = def_map.module_id(def_map.root());
332-
let rood_attrs = self.db.attrs(root_mod.into());
333-
let mut nightly_features = rood_attrs
334-
.by_key("feature")
335-
.attrs()
336-
.map(|attr| attr.parse_path_comma_token_tree())
337-
.flatten()
338-
.flatten();
339-
nightly_features.any(
340-
|feat| matches!(feat.segments(), [name] if name.to_smol_str() == "exhaustive_patterns"),
341-
)
342-
})
330+
self.exhaustive_patterns
343331
}
344332
}
345333

0 commit comments

Comments
 (0)