From d221878bf4b0683998b1037b6d22b813690536ec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Sep 2023 05:38:49 +0000 Subject: [PATCH] Unify defined_lib_features and lib_features queries --- compiler/rustc_metadata/src/rmeta/decoder.rs | 16 ++++- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_metadata/src/rmeta/mod.rs | 3 +- compiler/rustc_middle/src/middle/mod.rs | 15 +++-- compiler/rustc_middle/src/query/mod.rs | 7 +- compiler/rustc_middle/src/ty/parameterized.rs | 1 + compiler/rustc_passes/src/lib_features.rs | 67 ++++++++++--------- compiler/rustc_passes/src/stability.rs | 26 +++---- 9 files changed, 84 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 7fd3c0f494a11..9dde1a168b0e9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -21,6 +21,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; +use rustc_middle::middle::lib_features::LibFeatures; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -1007,8 +1008,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over all the stability attributes in the given crate. - fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { - tcx.arena.alloc_from_iter(self.root.lib_features.decode(self)) + fn get_lib_features(self, _tcx: TyCtxt<'tcx>) -> LibFeatures { + let mut features = LibFeatures::default(); + for (symbol, stability) in self.root.lib_features.decode(self) { + match stability { + FeatureStability::AcceptedSince(since) => { + features.stable.insert(symbol, (since, DUMMY_SP)); + } + FeatureStability::Unstable => { + features.unstable.insert(symbol, DUMMY_SP); + } + } + } + features } /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index aeda8af6d2cab..f4b9e4ee34191 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -343,7 +343,7 @@ provide! { tcx, def_id, other, cdata, module_children => { tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess)) } - defined_lib_features => { cdata.get_lib_features(tcx) } + lib_features => { cdata.get_lib_features(tcx) } stability_implications => { cdata.get_stability_implications(tcx).iter().copied().collect() } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4f4351633a2ce..7c6e9654db00a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -24,6 +24,7 @@ use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, }; +use rustc_middle::middle::lib_features::FeatureStability; use rustc_middle::mir::interpret; use rustc_middle::query::LocalCrate; use rustc_middle::query::Providers; @@ -1871,10 +1872,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_array(deps.iter().map(|(_, dep)| dep)) } - fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option)> { + fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> { empty_proc_macro!(self); let tcx = self.tcx; - let lib_features = tcx.lib_features(()); + let lib_features = tcx.lib_features(LOCAL_CRATE); self.lazy_array(lib_features.to_vec()) } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 71269779d4239..b36dd584bdbf5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -3,6 +3,7 @@ use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; use rustc_data_structures::fx::FxHashMap; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; +use rustc_middle::middle::lib_features::FeatureStability; use table::TableBuilder; use rustc_ast as ast; @@ -264,7 +265,7 @@ pub(crate) struct CrateRoot { crate_deps: LazyArray, dylib_dependency_formats: LazyArray>, - lib_features: LazyArray<(Symbol, Option)>, + lib_features: LazyArray<(Symbol, FeatureStability)>, stability_implications: LazyArray<(Symbol, Symbol)>, lang_items: LazyArray<(DefIndex, LangItem)>, lang_items_missing: LazyArray, diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 85c5af9ca13cb..06b3ab2209098 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -7,7 +7,14 @@ pub mod lib_features { use rustc_data_structures::fx::FxHashMap; use rustc_span::{symbol::Symbol, Span}; - #[derive(HashStable, Debug)] + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + #[derive(HashStable, TyEncodable, TyDecodable)] + pub enum FeatureStability { + AcceptedSince(Symbol), + Unstable, + } + + #[derive(HashStable, Debug, Default)] pub struct LibFeatures { /// A map from feature to stabilisation version. pub stable: FxHashMap, @@ -15,12 +22,12 @@ pub mod lib_features { } impl LibFeatures { - pub fn to_vec(&self) -> Vec<(Symbol, Option)> { + pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> { let mut all_features: Vec<_> = self .stable .iter() - .map(|(f, (s, _))| (*f, Some(*s))) - .chain(self.unstable.keys().map(|f| (*f, None))) + .map(|(f, (s, _))| (*f, FeatureStability::AcceptedSince(*s))) + .chain(self.unstable.iter().map(|(f, _)| (*f, FeatureStability::Unstable))) .collect(); all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap()); all_features diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bf340846f108c..c6434ef8d2d35 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1744,13 +1744,10 @@ rustc_queries! { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) } } - query lib_features(_: ()) -> &'tcx LibFeatures { - arena_cache - desc { "calculating the lib features map" } - } - query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option)] { + query lib_features(_: CrateNum) -> &'tcx LibFeatures { desc { "calculating the lib features defined in a crate" } separate_provide_extern + arena_cache } query stability_implications(_: CrateNum) -> &'tcx FxHashMap { arena_cache diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index f1c38984296c7..91e1cad21e1a8 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! { crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, + crate::middle::lib_features::FeatureStability, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::AssocItemContainer, diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 44174b1b89d11..c4b88243c12aa 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -8,18 +8,14 @@ use rustc_ast::Attribute; use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER}; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; -use rustc_middle::middle::lib_features::LibFeatures; -use rustc_middle::query::Providers; +use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; +use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use rustc_span::{sym, Span}; use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice}; -fn new_lib_features() -> LibFeatures { - LibFeatures { stable: Default::default(), unstable: Default::default() } -} - pub struct LibFeatureCollector<'tcx> { tcx: TyCtxt<'tcx>, lib_features: LibFeatures, @@ -27,10 +23,10 @@ pub struct LibFeatureCollector<'tcx> { impl<'tcx> LibFeatureCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> { - LibFeatureCollector { tcx, lib_features: new_lib_features() } + LibFeatureCollector { tcx, lib_features: LibFeatures::default() } } - fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { + fn extract(&self, attr: &Attribute) -> Option<(Symbol, FeatureStability, Span)> { let stab_attrs = [ sym::stable, sym::unstable, @@ -70,8 +66,11 @@ impl<'tcx> LibFeatureCollector<'tcx> { | sym::rustc_const_unstable | sym::rustc_default_body_unstable ); - if since.is_some() || is_unstable { - return Some((feature, since, attr.span)); + if is_unstable { + return Some((feature, FeatureStability::Unstable, attr.span)); + } + if let Some(since) = since { + return Some((feature, FeatureStability::AcceptedSince(since), attr.span)); } } // We need to iterate over the other attributes, because @@ -84,37 +83,43 @@ impl<'tcx> LibFeatureCollector<'tcx> { None } - fn collect_feature(&mut self, feature: Symbol, since: Option, span: Span) { + fn collect_feature(&mut self, feature: Symbol, stability: FeatureStability, span: Span) { let already_in_stable = self.lib_features.stable.contains_key(&feature); let already_in_unstable = self.lib_features.unstable.contains_key(&feature); - match (since, already_in_stable, already_in_unstable) { - (Some(since), _, false) => { - if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) { - if *prev_since != since { - self.tcx.sess.emit_err(FeatureStableTwice { - span, - feature, - since, - prev_since: *prev_since, - }); - return; - } + match (stability, already_in_stable, already_in_unstable) { + (FeatureStability::AcceptedSince(since), _, false) => { + if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) + && *prev_since != since + { + self.tcx.sess.emit_err(FeatureStableTwice { + span, + feature, + since, + prev_since: *prev_since, + }); + return; } self.lib_features.stable.insert(feature, (since, span)); } - (None, false, _) => { + (FeatureStability::AcceptedSince(_), _, true) => { + self.tcx.sess.emit_err(FeaturePreviouslyDeclared { + span, + feature, + declared: "stable", + prev_declared: "unstable", + }); + } + (FeatureStability::Unstable, false, _) => { self.lib_features.unstable.insert(feature, span); } - (Some(_), _, true) | (None, true, _) => { - let declared = if since.is_some() { "stable" } else { "unstable" }; - let prev_declared = if since.is_none() { "stable" } else { "unstable" }; + (FeatureStability::Unstable, true, _) => { self.tcx.sess.emit_err(FeaturePreviouslyDeclared { span, feature, - declared, - prev_declared, + declared: "unstable", + prev_declared: "stable", }); } } @@ -135,11 +140,11 @@ impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> { } } -fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { +fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures { // If `staged_api` is not enabled then we aren't allowed to define lib // features; there is no point collecting them. if !tcx.features().staged_api { - return new_lib_features(); + return LibFeatures::default(); } let mut collector = LibFeatureCollector::new(tcx); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9c265e8ec11e5..887205cd8e289 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -14,6 +14,7 @@ use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; +use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index}; use rustc_middle::query::Providers; @@ -994,26 +995,27 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { tcx: TyCtxt<'tcx>, remaining_lib_features: &mut FxIndexMap<&Symbol, Span>, remaining_implications: &mut FxHashMap, - defined_features: &[(Symbol, Option)], + defined_features: &LibFeatures, all_implications: &FxHashMap, ) { - for (feature, since) in defined_features { - if let Some(since) = since && let Some(span) = remaining_lib_features.get(&feature) { + for (feature, stability) in defined_features.to_vec() { + if let FeatureStability::AcceptedSince(since) = stability + && let Some(span) = remaining_lib_features.get(&feature) + { // Warn if the user has enabled an already-stable lib feature. if let Some(implies) = all_implications.get(&feature) { - unnecessary_partially_stable_feature_lint(tcx, *span, *feature, *implies, *since); + unnecessary_partially_stable_feature_lint(tcx, *span, feature, *implies, since); } else { - unnecessary_stable_feature_lint(tcx, *span, *feature, *since); + unnecessary_stable_feature_lint(tcx, *span, feature, since); } - } - remaining_lib_features.remove(feature); + remaining_lib_features.remove(&feature); // `feature` is the feature doing the implying, but `implied_by` is the feature with // the attribute that establishes this relationship. `implied_by` is guaranteed to be a // feature defined in the local crate because `remaining_implications` is only the // implications from this crate. - remaining_implications.remove(feature); + remaining_implications.remove(&feature); if remaining_lib_features.is_empty() && remaining_implications.is_empty() { break; @@ -1027,7 +1029,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // We always collect the lib features declared in the current crate, even if there are // no unknown features, because the collection also does feature attribute validation. - let local_defined_features = tcx.lib_features(()).to_vec(); + let local_defined_features = tcx.lib_features(rustc_hir::def_id::LOCAL_CRATE); if !remaining_lib_features.is_empty() || !remaining_implications.is_empty() { // Loading the implications of all crates is unavoidable to be able to emit the partial // stabilization diagnostic, but it can be avoided when there are no @@ -1041,7 +1043,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { tcx, &mut remaining_lib_features, &mut remaining_implications, - local_defined_features.as_slice(), + local_defined_features, &all_implications, ); @@ -1053,7 +1055,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { tcx, &mut remaining_lib_features, &mut remaining_implications, - tcx.defined_lib_features(cnum).to_vec().as_slice(), + tcx.lib_features(cnum), &all_implications, ); } @@ -1064,7 +1066,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } for (implied_by, feature) in remaining_implications { - let local_defined_features = tcx.lib_features(()); + let local_defined_features = tcx.lib_features(rustc_hir::def_id::LOCAL_CRATE); let span = *local_defined_features .stable .get(&feature)