From 2d187d54fda6333af7003999a887749fca4a5db1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 17 Nov 2023 23:40:04 +0000 Subject: [PATCH] Store feature stability un-split --- compiler/rustc_metadata/src/rmeta/decoder.rs | 20 ++++------ .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_middle/src/middle/mod.rs | 14 ++----- compiler/rustc_passes/src/lib_features.rs | 38 ++++++++----------- compiler/rustc_passes/src/stability.rs | 18 ++++----- 5 files changed, 37 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 20f26e10866..333dc8ec911 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1177,19 +1177,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over all the stability attributes in the given crate. - 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); - } - } + fn get_lib_features(self) -> LibFeatures { + LibFeatures { + stability: self + .root + .lib_features + .decode(self) + .map(|(sym, stab)| (sym, (stab, DUMMY_SP))) + .collect(), } - 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 ceab2d83915..909a977ccc9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -346,7 +346,7 @@ provide! { tcx, def_id, other, cdata, module_children => { tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess)) } - lib_features => { cdata.get_lib_features(tcx) } + lib_features => { cdata.get_lib_features() } stability_implications => { cdata.get_stability_implications(tcx).iter().copied().collect() } diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 06b3ab22090..8c1b1ff12e9 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -16,20 +16,14 @@ pub mod lib_features { #[derive(HashStable, Debug, Default)] pub struct LibFeatures { - /// A map from feature to stabilisation version. - pub stable: FxHashMap, - pub unstable: FxHashMap, + pub stability: FxHashMap, } impl LibFeatures { pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> { - let mut all_features: Vec<_> = self - .stable - .iter() - .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()); + let mut all_features: Vec<_> = + self.stability.iter().map(|(&sym, &(stab, _))| (sym, stab)).collect(); + all_features.sort_unstable_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str())); all_features } } diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 33743eaf0fc..6c0412beda2 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -86,26 +86,21 @@ impl<'tcx> LibFeatureCollector<'tcx> { } 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); + let existing_stability = self.lib_features.stability.get(&feature).cloned(); - 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)); + match (stability, existing_stability) { + (_, None) => { + self.lib_features.stability.insert(feature, (stability, span)); } - (FeatureStability::AcceptedSince(_), _, true) => { + ( + FeatureStability::AcceptedSince(since), + Some((FeatureStability::AcceptedSince(prev_since), _)), + ) => { + if prev_since != since { + self.tcx.sess.emit_err(FeatureStableTwice { span, feature, since, prev_since }); + } + } + (FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable, _))) => { self.tcx.sess.emit_err(FeaturePreviouslyDeclared { span, feature, @@ -113,10 +108,7 @@ impl<'tcx> LibFeatureCollector<'tcx> { prev_declared: "unstable", }); } - (FeatureStability::Unstable, false, _) => { - self.lib_features.unstable.insert(feature, span); - } - (FeatureStability::Unstable, true, _) => { + (FeatureStability::Unstable, Some((FeatureStability::AcceptedSince(_), _))) => { self.tcx.sess.emit_err(FeaturePreviouslyDeclared { span, feature, @@ -124,6 +116,8 @@ impl<'tcx> LibFeatureCollector<'tcx> { prev_declared: "stable", }); } + // duplicate `unstable` feature is ok. + (FeatureStability::Unstable, Some((FeatureStability::Unstable, _))) => {} } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 1622214089c..03070dc6f28 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -9,7 +9,7 @@ use rustc_attr::{ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; @@ -1008,12 +1008,11 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } // All local crate implications need to have the feature that implies it confirmed to exist. - let mut remaining_implications = - tcx.stability_implications(rustc_hir::def_id::LOCAL_CRATE).clone(); + let mut remaining_implications = tcx.stability_implications(LOCAL_CRATE).clone(); // 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(rustc_hir::def_id::LOCAL_CRATE); + let local_defined_features = tcx.lib_features(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 @@ -1050,13 +1049,12 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } for (implied_by, feature) in remaining_implications { - let local_defined_features = tcx.lib_features(rustc_hir::def_id::LOCAL_CRATE); - let span = *local_defined_features - .stable + let local_defined_features = tcx.lib_features(LOCAL_CRATE); + let span = local_defined_features + .stability .get(&feature) - .map(|(_, span)| span) - .or_else(|| local_defined_features.unstable.get(&feature)) - .expect("feature that implied another does not exist"); + .expect("feature that implied another does not exist") + .1; tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by }); }