Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22111 from ChayimFriedman2/unstable-features
internal: Create a struct of bools for unstable features, like we did for lang items
Shoyu Vanilla (Flint) 4 weeks ago
parent f381976 · parent b3202d3 · commit 8eb5cb9
-rw-r--r--crates/hir-def/src/lang_item.rs2
-rw-r--r--crates/hir-def/src/lib.rs1
-rw-r--r--crates/hir-def/src/nameres.rs12
-rw-r--r--crates/hir-def/src/nameres/collector.rs4
-rw-r--r--crates/hir-def/src/unstable_features.rs91
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs6
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs16
-rw-r--r--crates/hir-ty/src/infer.rs11
-rw-r--r--crates/hir-ty/src/infer/fallback.rs3
-rw-r--r--crates/hir-ty/src/method_resolution.rs26
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs5
-rw-r--r--crates/hir-ty/src/method_resolution/probe.rs12
-rw-r--r--crates/hir-ty/src/specialization.rs11
-rw-r--r--crates/hir/src/attrs.rs9
-rw-r--r--crates/hir/src/lib.rs18
-rw-r--r--crates/hir/src/source_analyzer.rs3
16 files changed, 147 insertions, 83 deletions
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 37d70b1e33..5b6ebe2a0b 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -40,7 +40,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
let crate_def_map = crate_def_map(db, krate);
- if !crate_def_map.is_unstable_feature_enabled(&sym::lang_items) {
+ if !crate_def_map.features().lang_items {
return None;
}
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 9a7fbc812f..2c7685b189 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -32,6 +32,7 @@ pub mod item_tree;
pub mod builtin_derive;
pub mod lang_item;
+pub mod unstable_features;
pub mod hir;
pub use self::hir::type_ref;
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 56b3f03f7b..88e3408a33 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -68,7 +68,7 @@ use hir_expand::{
};
use intern::Symbol;
use itertools::Itertools;
-use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_hash::FxHashMap;
use span::{Edition, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
use stdx::format_to;
use syntax::{AstNode, SmolStr, SyntaxNode, ToSmolStr, ast};
@@ -83,6 +83,7 @@ use crate::{
item_tree::TreeId,
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
per_ns::PerNs,
+ unstable_features::UnstableFeatures,
visibility::{Visibility, VisibilityExplicitness},
};
@@ -216,7 +217,7 @@ struct DefMapCrateData {
/// Custom tool modules registered with `#![register_tool]`.
registered_tools: Vec<Symbol>,
/// Unstable features of Rust enabled with `#![feature(A, B)]`.
- unstable_features: FxHashSet<Symbol>,
+ unstable_features: UnstableFeatures,
/// `#[rustc_coherence_is_core]`
rustc_coherence_is_core: bool,
no_core: bool,
@@ -233,7 +234,7 @@ impl DefMapCrateData {
fn_proc_macro_mapping: FxHashMap::default(),
fn_proc_macro_mapping_back: FxHashMap::default(),
registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
- unstable_features: FxHashSet::default(),
+ unstable_features: UnstableFeatures::default(),
rustc_coherence_is_core: false,
no_core: false,
no_std: false,
@@ -554,8 +555,9 @@ impl DefMap {
&self.data.registered_tools
}
- pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool {
- self.data.unstable_features.contains(feature)
+ #[inline]
+ pub fn features(&self) -> &UnstableFeatures {
+ &self.data.unstable_features
}
pub fn is_rustc_coherence_is_core(&self) -> bool {
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 703f070dba..5ef51dbb2c 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -316,7 +316,7 @@ impl<'db> DefCollector<'db> {
_ => None,
},
);
- crate_data.unstable_features.extend(features);
+ features.for_each(|feature| crate_data.unstable_features.enable(feature));
}
() if *attr_name == sym::register_tool => {
if let Some(ident) = attr.single_ident_value() {
@@ -2840,6 +2840,6 @@ foo!(KABOOM);
assert_eq!(def_map.recursion_limit(), 4);
assert!(def_map.is_no_core());
assert!(def_map.is_no_std());
- assert!(def_map.is_unstable_feature_enabled(&sym::register_tool));
+ assert!(def_map.features().is_enabled(&sym::register_tool));
}
}
diff --git a/crates/hir-def/src/unstable_features.rs b/crates/hir-def/src/unstable_features.rs
new file mode 100644
index 0000000000..3b7f83081f
--- /dev/null
+++ b/crates/hir-def/src/unstable_features.rs
@@ -0,0 +1,91 @@
+//! Handling of unstable features.
+//!
+//! We define two kinds of handling: we have a map of all unstable features for a crate
+//! as `Symbol`s. This is mostly for external consumers.
+//!
+//! For analysis, we store them as a struct of bools, for fast access.
+
+use std::fmt;
+
+use base_db::Crate;
+use intern::{Symbol, sym};
+use rustc_hash::FxHashSet;
+
+use crate::db::DefDatabase;
+
+impl fmt::Debug for UnstableFeatures {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_set().entries(&self.all).finish()
+ }
+}
+
+impl PartialEq for UnstableFeatures {
+ fn eq(&self, other: &Self) -> bool {
+ self.all == other.all
+ }
+}
+
+impl Eq for UnstableFeatures {}
+
+impl UnstableFeatures {
+ #[inline]
+ pub fn is_enabled(&self, feature: &Symbol) -> bool {
+ self.all.contains(feature)
+ }
+
+ #[inline]
+ pub fn iter(&self) -> impl Iterator<Item = Symbol> {
+ self.all.iter().cloned()
+ }
+
+ pub(crate) fn shrink_to_fit(&mut self) {
+ self.all.shrink_to_fit();
+ }
+}
+
+#[salsa::tracked]
+impl UnstableFeatures {
+ /// Query unstable features for a crate.
+ ///
+ /// This is also available as `DefMap::features()`. Use that if you have a DefMap available.
+ /// Otherwise, use this, to not draw a dependency to the def map.
+ #[salsa::tracked(returns(ref))]
+ pub fn query(db: &dyn DefDatabase, krate: Crate) -> UnstableFeatures {
+ crate::crate_def_map(db, krate).features().clone()
+ }
+}
+
+macro_rules! define_unstable_features {
+ ( $( $feature:ident, )* ) => {
+ #[derive(Clone, Default)]
+ pub struct UnstableFeatures {
+ all: FxHashSet<Symbol>,
+
+ $( pub $feature: bool, )*
+ }
+
+ impl UnstableFeatures {
+ pub(crate) fn enable(&mut self, feature: Symbol) {
+ match () {
+ $( () if feature == sym::$feature => self.$feature = true, )*
+ _ => {}
+ }
+
+ self.all.insert(feature);
+ }
+ }
+ };
+}
+
+define_unstable_features! {
+ lang_items,
+ exhaustive_patterns,
+ generic_associated_type_extended,
+ arbitrary_self_types,
+ arbitrary_self_types_pointers,
+ supertrait_item_shadowing,
+ new_range,
+ never_type_fallback,
+ specialization,
+ min_specialization,
+}
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index bc3d9bbec6..5ed7eb7a66 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -4,9 +4,8 @@ use std::{cell::LazyCell, fmt};
use hir_def::{
EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId, attrs::AttrFlags,
- signatures::VariantFields,
+ signatures::VariantFields, unstable_features::UnstableFeatures,
};
-use intern::sym;
use rustc_pattern_analysis::{
IndexVec, PatCx, PrivateUninhabitedField,
constructor::{Constructor, ConstructorSet, VariantVisibility},
@@ -82,8 +81,7 @@ pub(crate) struct MatchCheckCtx<'a, 'db> {
impl<'a, 'db> MatchCheckCtx<'a, 'db> {
pub(crate) fn new(module: ModuleId, infcx: &'a InferCtxt<'db>, env: ParamEnv<'db>) -> Self {
let db = infcx.interner.db;
- let def_map = module.crate_def_map(db);
- let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
+ let exhaustive_patterns = UnstableFeatures::query(db, module.krate(db)).exhaustive_patterns;
Self { module, db, exhaustive_patterns, env, infcx }
}
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index ba63343d49..ee7527446a 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -6,8 +6,8 @@ use hir_def::{
AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId,
hir::generics::{GenericParams, LocalTypeOrConstParamId},
- nameres::crate_def_map,
signatures::{FunctionSignature, TraitFlags, TraitSignature},
+ unstable_features::UnstableFeatures,
};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
@@ -111,8 +111,9 @@ where
// rustc checks for non-lifetime binders here, but we don't support HRTB yet
let trait_data = trait_.trait_items(db);
+ let mut features = None;
for (_, assoc_item) in &trait_data.items {
- dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
+ dyn_compatibility_violation_for_assoc_item(db, &mut features, trait_, *assoc_item, cb)?;
}
ControlFlow::Continue(())
@@ -274,8 +275,9 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable<DbI
t.visit_with(&mut visitor).is_break()
}
-fn dyn_compatibility_violation_for_assoc_item<F>(
- db: &dyn HirDatabase,
+fn dyn_compatibility_violation_for_assoc_item<'db, F>(
+ db: &'db dyn HirDatabase,
+ features: &mut Option<&'db UnstableFeatures>,
trait_: TraitId,
item: AssocItemId,
cb: &mut F,
@@ -297,8 +299,10 @@ where
})
}
AssocItemId::TypeAliasId(it) => {
- let def_map = crate_def_map(db, trait_.krate(db));
- if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) {
+ if features
+ .get_or_insert_with(|| UnstableFeatures::query(db, trait_.krate(db)))
+ .generic_associated_type_extended
+ {
ControlFlow::Continue(())
} else {
let generic_params = GenericParams::of(db, item.into());
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 339ce7933a..9acd5c0e0f 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -44,6 +44,7 @@ use hir_def::{
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},
type_ref::{ConstRef, LifetimeRefId, TypeRef, TypeRefId},
+ unstable_features::UnstableFeatures,
};
use hir_expand::{mod_path::ModPath, name::Name};
use indexmap::IndexSet;
@@ -78,7 +79,7 @@ use crate::{
lower::{
ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic,
},
- method_resolution::{CandidateId, MethodResolutionUnstableFeatures},
+ method_resolution::CandidateId,
next_solver::{
AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region,
StoredGenericArgs, StoredTy, StoredTys, Ty, TyKind, Tys,
@@ -1112,11 +1113,11 @@ pub(crate) struct InferenceContext<'body, 'db> {
/// and resolve the path via its methods. This will ensure proper error reporting.
pub(crate) resolver: Resolver<'db>,
target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,
- pub(crate) unstable_features: MethodResolutionUnstableFeatures,
pub(crate) edition: Edition,
pub(crate) generic_def: GenericDefId,
pub(crate) table: unify::InferenceTable<'db>,
pub(crate) lang_items: &'db LangItems,
+ pub(crate) features: &'db UnstableFeatures,
/// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>,
pub(crate) result: InferenceResult,
@@ -1218,10 +1219,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
return_ty: types.types.error, // set in collect_* calls
types,
target_features: OnceCell::new(),
- unstable_features: MethodResolutionUnstableFeatures::from_def_map(
- resolver.top_level_def_map(),
- ),
lang_items: table.interner().lang_items(),
+ features: resolver.top_level_def_map().features(),
edition: resolver.krate().data(db).edition,
table,
tuple_field_accesses_rev: Default::default(),
@@ -2317,7 +2316,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
fn has_new_range_feature(&self) -> bool {
- self.resolver.top_level_def_map().is_unstable_feature_enabled(&sym::new_range)
+ self.features.new_range
}
fn resolve_range(&self) -> Option<AdtId> {
diff --git a/crates/hir-ty/src/infer/fallback.rs b/crates/hir-ty/src/infer/fallback.rs
index c7669b346f..160749591d 100644
--- a/crates/hir-ty/src/infer/fallback.rs
+++ b/crates/hir-ty/src/infer/fallback.rs
@@ -1,6 +1,5 @@
//! Fallback of infer vars to `!` and `i32`/`f64`.
-use intern::sym;
use petgraph::{
Graph,
visit::{Dfs, Walker},
@@ -80,7 +79,7 @@ impl<'db> InferenceContext<'_, 'db> {
return DivergingFallbackBehavior::ToNever;
}
- if self.resolver.def_map().is_unstable_feature_enabled(&sym::never_type_fallback) {
+ if self.features.never_type_fallback {
return DivergingFallbackBehavior::ContextDependent;
}
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 68c4833d81..25c2df0d9f 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -23,8 +23,9 @@ use hir_def::{
nameres::{DefMap, block_def_map, crate_def_map},
resolver::Resolver,
signatures::{ConstSignature, FunctionSignature},
+ unstable_features::UnstableFeatures,
};
-use intern::{Symbol, sym};
+use intern::Symbol;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::{
TypeVisitableExt,
@@ -57,32 +58,13 @@ pub use self::probe::{
Candidate, CandidateKind, CandidateStep, CandidateWithPrivate, Mode, Pick, PickKind,
};
-#[derive(Debug, Clone)]
-pub struct MethodResolutionUnstableFeatures {
- arbitrary_self_types: bool,
- arbitrary_self_types_pointers: bool,
- supertrait_item_shadowing: bool,
-}
-
-impl MethodResolutionUnstableFeatures {
- pub fn from_def_map(def_map: &DefMap) -> Self {
- Self {
- arbitrary_self_types: def_map.is_unstable_feature_enabled(&sym::arbitrary_self_types),
- arbitrary_self_types_pointers: def_map
- .is_unstable_feature_enabled(&sym::arbitrary_self_types_pointers),
- supertrait_item_shadowing: def_map
- .is_unstable_feature_enabled(&sym::supertrait_item_shadowing),
- }
- }
-}
-
pub struct MethodResolutionContext<'a, 'db> {
pub infcx: &'a InferCtxt<'db>,
pub resolver: &'a Resolver<'db>,
pub param_env: ParamEnv<'db>,
pub traits_in_scope: &'a FxHashSet<TraitId>,
pub edition: Edition,
- pub unstable_features: &'a MethodResolutionUnstableFeatures,
+ pub features: &'a UnstableFeatures,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
@@ -201,7 +183,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
param_env: self.table.param_env,
traits_in_scope,
edition: self.edition,
- unstable_features: &self.unstable_features,
+ features: self.features,
};
f(&ctx)
}
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index 94c70c29f7..3bdef44dd3 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -320,8 +320,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
// We don't need to gate this behind arbitrary self types
// per se, but it does make things a bit more gated.
- if self.ctx.unstable_features.arbitrary_self_types
- || self.ctx.unstable_features.arbitrary_self_types_pointers
+ if self.ctx.features.arbitrary_self_types || self.ctx.features.arbitrary_self_types_pointers
{
autoderef = autoderef.use_receiver_trait();
}
@@ -483,7 +482,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
self.ctx.table.register_infer_ok(infer_ok);
}
Err(_) => {
- if self.ctx.unstable_features.arbitrary_self_types {
+ if self.ctx.features.arbitrary_self_types {
self.ctx.result.type_mismatches.get_or_insert_default().insert(
self.expr.into(),
TypeMismatch { expected: method_self_ty.store(), actual: self_ty.store() },
diff --git a/crates/hir-ty/src/method_resolution/probe.rs b/crates/hir-ty/src/method_resolution/probe.rs
index 3604076ccd..afdc62183e 100644
--- a/crates/hir-ty/src/method_resolution/probe.rs
+++ b/crates/hir-ty/src/method_resolution/probe.rs
@@ -315,7 +315,7 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
// ambiguous.
if let Some(bad_ty) = &steps.opt_bad_ty {
if bad_ty.reached_raw_pointer
- && !self.unstable_features.arbitrary_self_types_pointers
+ && !self.features.arbitrary_self_types_pointers
&& self.edition.at_least_2018()
{
// this case used to be allowed by the compiler,
@@ -404,8 +404,8 @@ impl<'a, 'db> MethodResolutionContext<'a, 'db> {
Autoderef::new(infcx, self.param_env, self_ty).include_raw_pointers();
let mut reached_raw_pointer = false;
- let arbitrary_self_types_enabled = self.unstable_features.arbitrary_self_types
- || self.unstable_features.arbitrary_self_types_pointers;
+ let arbitrary_self_types_enabled =
+ self.features.arbitrary_self_types || self.features.arbitrary_self_types_pointers;
let (mut steps, reached_recursion_limit) = if arbitrary_self_types_enabled {
let reachable_via_deref =
autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
@@ -613,7 +613,7 @@ impl<'db> ProbeChoice<'db> for ProbeForNameChoice<'db> {
// We collapse to a subtrait pick *after* filtering unstable candidates
// to make sure we don't prefer a unstable subtrait method over a stable
// supertrait method.
- if this.ctx.unstable_features.supertrait_item_shadowing
+ if this.ctx.features.supertrait_item_shadowing
&& let Some(pick) =
this.collapse_candidates_to_subtrait_pick(self_ty, &applicable_candidates)
{
@@ -1183,8 +1183,8 @@ impl<'a, 'db> ProbeContext<'a, 'db, ProbeForNameChoice<'db>> {
// The errors emitted by this function are part of
// the arbitrary self types work, and should not impact
// other users.
- if !self.ctx.unstable_features.arbitrary_self_types
- && !self.ctx.unstable_features.arbitrary_self_types_pointers
+ if !self.ctx.features.arbitrary_self_types
+ && !self.ctx.features.arbitrary_self_types_pointers
{
return Ok(());
}
diff --git a/crates/hir-ty/src/specialization.rs b/crates/hir-ty/src/specialization.rs
index 8bc6c51fae..a0bac48250 100644
--- a/crates/hir-ty/src/specialization.rs
+++ b/crates/hir-ty/src/specialization.rs
@@ -1,10 +1,9 @@
//! Impl specialization related things
use hir_def::{
- ExpressionStoreOwnerId, GenericDefId, HasModule, ImplId, nameres::crate_def_map,
- signatures::ImplSignature,
+ ExpressionStoreOwnerId, GenericDefId, HasModule, ImplId, signatures::ImplSignature,
+ unstable_features::UnstableFeatures,
};
-use intern::sym;
use tracing::debug;
use crate::{
@@ -153,10 +152,8 @@ pub(crate) fn specializes(
// `#[allow_internal_unstable(specialization)]`, but `#[allow_internal_unstable]`
// is an internal feature, std is not using it for specialization nor is likely to
// ever use it, and we don't have the span information necessary to replicate that.
- let def_map = crate_def_map(db, module.krate(db));
- if !def_map.is_unstable_feature_enabled(&sym::specialization)
- && !def_map.is_unstable_feature_enabled(&sym::min_specialization)
- {
+ let features = UnstableFeatures::query(db, module.krate(db));
+ if !features.specialization && !features.min_specialization {
return false;
}
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 223103b6e5..9943b718fd 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -18,9 +18,7 @@ use hir_expand::{
};
use hir_ty::{
db::HirDatabase,
- method_resolution::{
- self, CandidateId, MethodError, MethodResolutionContext, MethodResolutionUnstableFeatures,
- },
+ method_resolution::{self, CandidateId, MethodError, MethodResolutionContext},
next_solver::{DbInterner, TypingMode, infer::DbInternerInferExt},
};
use intern::Symbol;
@@ -498,15 +496,14 @@ fn resolve_impl_trait_item<'db>(
// FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
let interner = DbInterner::new_with(db, environment.krate);
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
- let unstable_features =
- MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map());
+ let features = resolver.top_level_def_map().features();
let ctx = MethodResolutionContext {
infcx: &infcx,
resolver: &resolver,
param_env: environment.param_env,
traits_in_scope: &traits_in_scope,
edition: krate.edition(db),
- unstable_features: &unstable_features,
+ features,
};
let resolution = ctx.probe_for_name(method_resolution::Mode::Path, name.clone(), ty.ty);
let resolution = match resolution {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ebcc1da43d..91b48bbfb6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -75,6 +75,7 @@ use hir_def::{
TypeAliasSignature, UnionSignature, VariantFields,
},
src::HasSource as _,
+ unstable_features::UnstableFeatures,
visibility::visibility_from_ast,
};
use hir_expand::{
@@ -89,9 +90,7 @@ use hir_ty::{
diagnostics::BodyValidationDiagnostic,
direct_super_traits, known_const_to_ast,
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
- method_resolution::{
- self, InherentImpls, MethodResolutionContext, MethodResolutionUnstableFeatures,
- },
+ method_resolution::{self, InherentImpls, MethodResolutionContext},
mir::interpret_mir,
next_solver::{
AliasTy, AnyImplId, ClauseKind, ConstKind, DbInterner, EarlyBinder, EarlyParamRegion,
@@ -343,7 +342,7 @@ impl Crate {
}
pub fn is_unstable_feature_enabled(self, db: &dyn HirDatabase, feature: &Symbol) -> bool {
- crate_def_map(db, self.id).is_unstable_feature_enabled(feature)
+ UnstableFeatures::query(db, self.id).is_enabled(feature)
}
}
@@ -983,10 +982,8 @@ impl Module {
// relationship here would be significantly more expensive.
if !missing.is_empty() {
let krate = self.krate(db).id;
- let def_map = crate_def_map(db, krate);
- if def_map.is_unstable_feature_enabled(&sym::specialization)
- || def_map.is_unstable_feature_enabled(&sym::min_specialization)
- {
+ let features = UnstableFeatures::query(db, krate);
+ if features.specialization || features.min_specialization {
missing.retain(|(assoc_name, assoc_item)| {
let AssocItem::Function(_) = assoc_item else {
return true;
@@ -6177,8 +6174,7 @@ impl<'db> Type<'db> {
TypingMode::non_body_analysis()
};
let infcx = interner.infer_ctxt().build(typing_mode);
- let unstable_features =
- MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map());
+ let features = resolver.top_level_def_map().features();
let environment = param_env_from_resolver(db, resolver);
let ctx = MethodResolutionContext {
infcx: &infcx,
@@ -6186,7 +6182,7 @@ impl<'db> Type<'db> {
param_env: environment.param_env,
traits_in_scope,
edition: resolver.krate().data(db).edition,
- unstable_features: &unstable_features,
+ features,
};
f(&ctx)
}
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 6c43f80ce8..bbe1e670de 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -626,8 +626,7 @@ impl<'db> SourceAnalyzer<'db> {
has_start: bool,
has_end: bool,
) -> Option<StructId> {
- let has_new_range =
- self.resolver.top_level_def_map().is_unstable_feature_enabled(&sym::new_range);
+ let has_new_range = self.resolver.top_level_def_map().features().new_range;
let lang_items = self.lang_items(db);
match (op_kind, has_start, has_end) {
(RangeOp::Exclusive, false, false) => lang_items.RangeFull,