Skip to content

Commit 8eb5cb9

Browse files
authored
Merge pull request #22111 from ChayimFriedman2/unstable-features
internal: Create a struct of bools for unstable features, like we did for lang items
2 parents f381976 + b3202d3 commit 8eb5cb9

16 files changed

Lines changed: 147 additions & 83 deletions

File tree

crates/hir-def/src/lang_item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
4040

4141
let crate_def_map = crate_def_map(db, krate);
4242

43-
if !crate_def_map.is_unstable_feature_enabled(&sym::lang_items) {
43+
if !crate_def_map.features().lang_items {
4444
return None;
4545
}
4646

crates/hir-def/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod item_tree;
3232

3333
pub mod builtin_derive;
3434
pub mod lang_item;
35+
pub mod unstable_features;
3536

3637
pub mod hir;
3738
pub use self::hir::type_ref;

crates/hir-def/src/nameres.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use hir_expand::{
6868
};
6969
use intern::Symbol;
7070
use itertools::Itertools;
71-
use rustc_hash::{FxHashMap, FxHashSet};
71+
use rustc_hash::FxHashMap;
7272
use span::{Edition, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
7373
use stdx::format_to;
7474
use syntax::{AstNode, SmolStr, SyntaxNode, ToSmolStr, ast};
@@ -83,6 +83,7 @@ use crate::{
8383
item_tree::TreeId,
8484
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
8585
per_ns::PerNs,
86+
unstable_features::UnstableFeatures,
8687
visibility::{Visibility, VisibilityExplicitness},
8788
};
8889

@@ -216,7 +217,7 @@ struct DefMapCrateData {
216217
/// Custom tool modules registered with `#![register_tool]`.
217218
registered_tools: Vec<Symbol>,
218219
/// Unstable features of Rust enabled with `#![feature(A, B)]`.
219-
unstable_features: FxHashSet<Symbol>,
220+
unstable_features: UnstableFeatures,
220221
/// `#[rustc_coherence_is_core]`
221222
rustc_coherence_is_core: bool,
222223
no_core: bool,
@@ -233,7 +234,7 @@ impl DefMapCrateData {
233234
fn_proc_macro_mapping: FxHashMap::default(),
234235
fn_proc_macro_mapping_back: FxHashMap::default(),
235236
registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
236-
unstable_features: FxHashSet::default(),
237+
unstable_features: UnstableFeatures::default(),
237238
rustc_coherence_is_core: false,
238239
no_core: false,
239240
no_std: false,
@@ -554,8 +555,9 @@ impl DefMap {
554555
&self.data.registered_tools
555556
}
556557

557-
pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool {
558-
self.data.unstable_features.contains(feature)
558+
#[inline]
559+
pub fn features(&self) -> &UnstableFeatures {
560+
&self.data.unstable_features
559561
}
560562

561563
pub fn is_rustc_coherence_is_core(&self) -> bool {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl<'db> DefCollector<'db> {
316316
_ => None,
317317
},
318318
);
319-
crate_data.unstable_features.extend(features);
319+
features.for_each(|feature| crate_data.unstable_features.enable(feature));
320320
}
321321
() if *attr_name == sym::register_tool => {
322322
if let Some(ident) = attr.single_ident_value() {
@@ -2840,6 +2840,6 @@ foo!(KABOOM);
28402840
assert_eq!(def_map.recursion_limit(), 4);
28412841
assert!(def_map.is_no_core());
28422842
assert!(def_map.is_no_std());
2843-
assert!(def_map.is_unstable_feature_enabled(&sym::register_tool));
2843+
assert!(def_map.features().is_enabled(&sym::register_tool));
28442844
}
28452845
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//! Handling of unstable features.
2+
//!
3+
//! We define two kinds of handling: we have a map of all unstable features for a crate
4+
//! as `Symbol`s. This is mostly for external consumers.
5+
//!
6+
//! For analysis, we store them as a struct of bools, for fast access.
7+
8+
use std::fmt;
9+
10+
use base_db::Crate;
11+
use intern::{Symbol, sym};
12+
use rustc_hash::FxHashSet;
13+
14+
use crate::db::DefDatabase;
15+
16+
impl fmt::Debug for UnstableFeatures {
17+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18+
f.debug_set().entries(&self.all).finish()
19+
}
20+
}
21+
22+
impl PartialEq for UnstableFeatures {
23+
fn eq(&self, other: &Self) -> bool {
24+
self.all == other.all
25+
}
26+
}
27+
28+
impl Eq for UnstableFeatures {}
29+
30+
impl UnstableFeatures {
31+
#[inline]
32+
pub fn is_enabled(&self, feature: &Symbol) -> bool {
33+
self.all.contains(feature)
34+
}
35+
36+
#[inline]
37+
pub fn iter(&self) -> impl Iterator<Item = Symbol> {
38+
self.all.iter().cloned()
39+
}
40+
41+
pub(crate) fn shrink_to_fit(&mut self) {
42+
self.all.shrink_to_fit();
43+
}
44+
}
45+
46+
#[salsa::tracked]
47+
impl UnstableFeatures {
48+
/// Query unstable features for a crate.
49+
///
50+
/// This is also available as `DefMap::features()`. Use that if you have a DefMap available.
51+
/// Otherwise, use this, to not draw a dependency to the def map.
52+
#[salsa::tracked(returns(ref))]
53+
pub fn query(db: &dyn DefDatabase, krate: Crate) -> UnstableFeatures {
54+
crate::crate_def_map(db, krate).features().clone()
55+
}
56+
}
57+
58+
macro_rules! define_unstable_features {
59+
( $( $feature:ident, )* ) => {
60+
#[derive(Clone, Default)]
61+
pub struct UnstableFeatures {
62+
all: FxHashSet<Symbol>,
63+
64+
$( pub $feature: bool, )*
65+
}
66+
67+
impl UnstableFeatures {
68+
pub(crate) fn enable(&mut self, feature: Symbol) {
69+
match () {
70+
$( () if feature == sym::$feature => self.$feature = true, )*
71+
_ => {}
72+
}
73+
74+
self.all.insert(feature);
75+
}
76+
}
77+
};
78+
}
79+
80+
define_unstable_features! {
81+
lang_items,
82+
exhaustive_patterns,
83+
generic_associated_type_extended,
84+
arbitrary_self_types,
85+
arbitrary_self_types_pointers,
86+
supertrait_item_shadowing,
87+
new_range,
88+
never_type_fallback,
89+
specialization,
90+
min_specialization,
91+
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ use std::{cell::LazyCell, fmt};
44

55
use hir_def::{
66
EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId, attrs::AttrFlags,
7-
signatures::VariantFields,
7+
signatures::VariantFields, unstable_features::UnstableFeatures,
88
};
9-
use intern::sym;
109
use rustc_pattern_analysis::{
1110
IndexVec, PatCx, PrivateUninhabitedField,
1211
constructor::{Constructor, ConstructorSet, VariantVisibility},
@@ -82,8 +81,7 @@ pub(crate) struct MatchCheckCtx<'a, 'db> {
8281
impl<'a, 'db> MatchCheckCtx<'a, 'db> {
8382
pub(crate) fn new(module: ModuleId, infcx: &'a InferCtxt<'db>, env: ParamEnv<'db>) -> Self {
8483
let db = infcx.interner.db;
85-
let def_map = module.crate_def_map(db);
86-
let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
84+
let exhaustive_patterns = UnstableFeatures::query(db, module.krate(db)).exhaustive_patterns;
8785
Self { module, db, exhaustive_patterns, env, infcx }
8886
}
8987

crates/hir-ty/src/dyn_compatibility.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use hir_def::{
66
AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId,
77
TypeOrConstParamId, TypeParamId,
88
hir::generics::{GenericParams, LocalTypeOrConstParamId},
9-
nameres::crate_def_map,
109
signatures::{FunctionSignature, TraitFlags, TraitSignature},
10+
unstable_features::UnstableFeatures,
1111
};
1212
use rustc_hash::FxHashSet;
1313
use rustc_type_ir::{
@@ -111,8 +111,9 @@ where
111111
// rustc checks for non-lifetime binders here, but we don't support HRTB yet
112112

113113
let trait_data = trait_.trait_items(db);
114+
let mut features = None;
114115
for (_, assoc_item) in &trait_data.items {
115-
dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
116+
dyn_compatibility_violation_for_assoc_item(db, &mut features, trait_, *assoc_item, cb)?;
116117
}
117118

118119
ControlFlow::Continue(())
@@ -274,8 +275,9 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI
274275
t.visit_with(&mut visitor).is_break()
275276
}
276277

277-
fn dyn_compatibility_violation_for_assoc_item<F>(
278-
db: &dyn HirDatabase,
278+
fn dyn_compatibility_violation_for_assoc_item<'db, F>(
279+
db: &'db dyn HirDatabase,
280+
features: &mut Option<&'db UnstableFeatures>,
279281
trait_: TraitId,
280282
item: AssocItemId,
281283
cb: &mut F,
@@ -297,8 +299,10 @@ where
297299
})
298300
}
299301
AssocItemId::TypeAliasId(it) => {
300-
let def_map = crate_def_map(db, trait_.krate(db));
301-
if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) {
302+
if features
303+
.get_or_insert_with(|| UnstableFeatures::query(db, trait_.krate(db)))
304+
.generic_associated_type_extended
305+
{
302306
ControlFlow::Continue(())
303307
} else {
304308
let generic_params = GenericParams::of(db, item.into());

crates/hir-ty/src/infer.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use hir_def::{
4444
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
4545
signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},
4646
type_ref::{ConstRef, LifetimeRefId, TypeRef, TypeRefId},
47+
unstable_features::UnstableFeatures,
4748
};
4849
use hir_expand::{mod_path::ModPath, name::Name};
4950
use indexmap::IndexSet;
@@ -78,7 +79,7 @@ use crate::{
7879
lower::{
7980
ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic,
8081
},
81-
method_resolution::{CandidateId, MethodResolutionUnstableFeatures},
82+
method_resolution::CandidateId,
8283
next_solver::{
8384
AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region,
8485
StoredGenericArgs, StoredTy, StoredTys, Ty, TyKind, Tys,
@@ -1112,11 +1113,11 @@ pub(crate) struct InferenceContext<'body, 'db> {
11121113
/// and resolve the path via its methods. This will ensure proper error reporting.
11131114
pub(crate) resolver: Resolver<'db>,
11141115
target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,
1115-
pub(crate) unstable_features: MethodResolutionUnstableFeatures,
11161116
pub(crate) edition: Edition,
11171117
pub(crate) generic_def: GenericDefId,
11181118
pub(crate) table: unify::InferenceTable<'db>,
11191119
pub(crate) lang_items: &'db LangItems,
1120+
pub(crate) features: &'db UnstableFeatures,
11201121
/// The traits in scope, disregarding block modules. This is used for caching purposes.
11211122
traits_in_scope: FxHashSet<TraitId>,
11221123
pub(crate) result: InferenceResult,
@@ -1218,10 +1219,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
12181219
return_ty: types.types.error, // set in collect_* calls
12191220
types,
12201221
target_features: OnceCell::new(),
1221-
unstable_features: MethodResolutionUnstableFeatures::from_def_map(
1222-
resolver.top_level_def_map(),
1223-
),
12241222
lang_items: table.interner().lang_items(),
1223+
features: resolver.top_level_def_map().features(),
12251224
edition: resolver.krate().data(db).edition,
12261225
table,
12271226
tuple_field_accesses_rev: Default::default(),
@@ -2317,7 +2316,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
23172316
}
23182317

23192318
fn has_new_range_feature(&self) -> bool {
2320-
self.resolver.top_level_def_map().is_unstable_feature_enabled(&sym::new_range)
2319+
self.features.new_range
23212320
}
23222321

23232322
fn resolve_range(&self) -> Option<AdtId> {

crates/hir-ty/src/infer/fallback.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Fallback of infer vars to `!` and `i32`/`f64`.
22
3-
use intern::sym;
43
use petgraph::{
54
Graph,
65
visit::{Dfs, Walker},
@@ -80,7 +79,7 @@ impl<'db> InferenceContext<'_, 'db> {
8079
return DivergingFallbackBehavior::ToNever;
8180
}
8281

83-
if self.resolver.def_map().is_unstable_feature_enabled(&sym::never_type_fallback) {
82+
if self.features.never_type_fallback {
8483
return DivergingFallbackBehavior::ContextDependent;
8584
}
8685

crates/hir-ty/src/method_resolution.rs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ use hir_def::{
2323
nameres::{DefMap, block_def_map, crate_def_map},
2424
resolver::Resolver,
2525
signatures::{ConstSignature, FunctionSignature},
26+
unstable_features::UnstableFeatures,
2627
};
27-
use intern::{Symbol, sym};
28+
use intern::Symbol;
2829
use rustc_hash::{FxHashMap, FxHashSet};
2930
use rustc_type_ir::{
3031
TypeVisitableExt,
@@ -57,32 +58,13 @@ pub use self::probe::{
5758
Candidate, CandidateKind, CandidateStep, CandidateWithPrivate, Mode, Pick, PickKind,
5859
};
5960

60-
#[derive(Debug, Clone)]
61-
pub struct MethodResolutionUnstableFeatures {
62-
arbitrary_self_types: bool,
63-
arbitrary_self_types_pointers: bool,
64-
supertrait_item_shadowing: bool,
65-
}
66-
67-
impl MethodResolutionUnstableFeatures {
68-
pub fn from_def_map(def_map: &DefMap) -> Self {
69-
Self {
70-
arbitrary_self_types: def_map.is_unstable_feature_enabled(&sym::arbitrary_self_types),
71-
arbitrary_self_types_pointers: def_map
72-
.is_unstable_feature_enabled(&sym::arbitrary_self_types_pointers),
73-
supertrait_item_shadowing: def_map
74-
.is_unstable_feature_enabled(&sym::supertrait_item_shadowing),
75-
}
76-
}
77-
}
78-
7961
pub struct MethodResolutionContext<'a, 'db> {
8062
pub infcx: &'a InferCtxt<'db>,
8163
pub resolver: &'a Resolver<'db>,
8264
pub param_env: ParamEnv<'db>,
8365
pub traits_in_scope: &'a FxHashSet<TraitId>,
8466
pub edition: Edition,
85-
pub unstable_features: &'a MethodResolutionUnstableFeatures,
67+
pub features: &'a UnstableFeatures,
8668
}
8769

8870
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
@@ -201,7 +183,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
201183
param_env: self.table.param_env,
202184
traits_in_scope,
203185
edition: self.edition,
204-
unstable_features: &self.unstable_features,
186+
features: self.features,
205187
};
206188
f(&ctx)
207189
}

0 commit comments

Comments
 (0)