about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-10-09 08:30:43 +0200
committerRalf Jung <post@ralfj.de>2024-10-22 07:37:55 +0100
commit1381773e01210cc7f377a9ab1aa886e621ceafe4 (patch)
tree1ca3498ed29b4da5d19b96265fa99ff5cc2e7283
parent46ce5cbf339e1ea84d2b28ac04369084b9f2d948 (diff)
downloadrust-1381773e01210cc7f377a9ab1aa886e621ceafe4.tar.gz
rust-1381773e01210cc7f377a9ab1aa886e621ceafe4.zip
make some rustc_feature internals private, and ensure invariants with debug assertions
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs10
-rw-r--r--compiler/rustc_expand/src/config.rs5
-rw-r--r--compiler/rustc_feature/src/unstable.rs61
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_passes/src/stability.rs4
-rw-r--r--compiler/rustc_query_system/src/ich/impls_syntax.rs4
6 files changed, 62 insertions, 26 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 376ef85307b..94fcfabc32c 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -604,7 +604,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
     if sess.opts.unstable_features.is_nightly_build() {
         return;
     }
-    if features.enabled_features.is_empty() {
+    if features.enabled_features().is_empty() {
         return;
     }
     let mut errored = false;
@@ -621,7 +621,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
         for ident in attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) {
             let name = ident.name;
             let stable_since = features
-                .enabled_lang_features
+                .enabled_lang_features()
                 .iter()
                 .flat_map(|&(feature, _, since)| if feature == name { since } else { None })
                 .next();
@@ -643,11 +643,11 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
 
 fn check_incompatible_features(sess: &Session, features: &Features) {
     let enabled_features = features
-        .enabled_lang_features
+        .enabled_lang_features()
         .iter()
         .copied()
         .map(|(name, span, _)| (name, span))
-        .chain(features.enabled_lib_features.iter().copied());
+        .chain(features.enabled_lib_features().iter().copied());
 
     for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
         .iter()
@@ -674,7 +674,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
 
     // Ban GCE with the new solver, because it does not implement GCE correctly.
     if let Some(&(_, gce_span, _)) = features
-        .enabled_lang_features
+        .enabled_lang_features()
         .iter()
         .find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
     {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index d08ebc5a942..a6b7291ee8f 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -88,7 +88,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
             // If the enabled feature is stable, record it.
             if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
                 let since = Some(Symbol::intern(f.since));
-                features.set_enabled_lang_feature(name, mi.span(), since);
+                features.set_enabled_lang_feature(name, mi.span(), since, None);
                 continue;
             }
 
@@ -104,7 +104,6 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
 
             // If the enabled feature is unstable, record it.
             if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) {
-                (f.set_enabled)(&mut features);
                 // When the ICE comes from core, alloc or std (approximation of the standard
                 // library), there's a chance that the person hitting the ICE may be using
                 // -Zbuild-std or similar with an untested target. The bug is probably in the
@@ -115,7 +114,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
                 {
                     sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
                 }
-                features.set_enabled_lang_feature(name, mi.span(), None);
+                features.set_enabled_lang_feature(name, mi.span(), None, Some(f));
                 continue;
             }
 
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 166f2af2210..0f9cf34fc18 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -8,7 +8,7 @@ use super::{Feature, to_nonzero};
 
 pub struct UnstableFeature {
     pub feature: Feature,
-    pub set_enabled: fn(&mut Features),
+    set_enabled: fn(&mut Features),
 }
 
 #[derive(PartialEq)]
@@ -54,11 +54,11 @@ macro_rules! declare_features {
         #[derive(Clone, Default, Debug)]
         pub struct Features {
             /// `#![feature]` attrs for language features, for error reporting.
-            pub enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
+            enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
             /// `#![feature]` attrs for non-language (library) features.
-            pub enabled_lib_features: Vec<(Symbol, Span)>,
+            enabled_lib_features: Vec<(Symbol, Span)>,
             /// `enabled_lang_features` + `enabled_lib_features`.
-            pub enabled_features: FxHashSet<Symbol>,
+            enabled_features: FxHashSet<Symbol>,
             /// State of individual features (unstable lang features only).
             /// This is `true` if and only if the corresponding feature is listed in `enabled_lang_features`.
             $(
@@ -70,17 +70,27 @@ macro_rules! declare_features {
         impl Features {
             pub fn set_enabled_lang_feature(
                 &mut self,
-                symbol: Symbol,
+                name: Symbol,
                 span: Span,
-                since: Option<Symbol>
+                since: Option<Symbol>,
+                feature: Option<&UnstableFeature>,
             ) {
-                self.enabled_lang_features.push((symbol, span, since));
-                self.enabled_features.insert(symbol);
+                self.enabled_lang_features.push((name, span, since));
+                self.enabled_features.insert(name);
+                if let Some(feature) = feature {
+                    assert_eq!(feature.feature.name, name);
+                    (feature.set_enabled)(self);
+                } else {
+                    // Ensure we don't skip a `set_enabled` call.
+                    debug_assert!(UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_none());
+                }
             }
 
-            pub fn set_enabled_lib_feature(&mut self, symbol: Symbol, span: Span) {
-                self.enabled_lib_features.push((symbol, span));
-                self.enabled_features.insert(symbol);
+            pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
+                self.enabled_lib_features.push((name, span));
+                self.enabled_features.insert(name);
+                // Ensure we don't skip a `set_enabled` call.
+                debug_assert!(UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_none());
             }
 
             /// This is intended for hashing the set of enabled language features.
@@ -93,9 +103,36 @@ macro_rules! declare_features {
                 [$(self.$feature as u8),+]
             }
 
+            pub fn enabled_lang_features(&self) -> &Vec<(Symbol, Span, Option<Symbol>)> {
+                &self.enabled_lang_features
+            }
+
+            pub fn enabled_lib_features(&self) -> &Vec<(Symbol, Span)> {
+                &self.enabled_lib_features
+            }
+
+            pub fn enabled_features(&self) -> &FxHashSet<Symbol> {
+                &self.enabled_features
+            }
+
             /// Is the given feature enabled (via `#[feature(...)]`)?
             pub fn enabled(&self, feature: Symbol) -> bool {
-                self.enabled_features.contains(&feature)
+                let e = self.enabled_features.contains(&feature);
+                if cfg!(debug_assertions) {
+                    // Ensure this matches `self.$feature`, if that exists.
+                    let e2 = match feature {
+                        $( sym::$feature => Some(self.$feature), )*
+                        _ => None,
+                    };
+                    if let Some(e2) = e2 {
+                        assert_eq!(
+                            e, e2,
+                            "mismatch in feature state for `{feature}`: \
+                            `enabled_features` says {e} but `self.{feature}` says {e2}"
+                        );
+                    }
+                }
+                e
             }
 
             /// Some features are known to be incomplete and using them is likely to have
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8fac1a82e8a..125fe9b3f16 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2288,10 +2288,10 @@ impl EarlyLintPass for IncompleteInternalFeatures {
     fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
         let features = cx.builder.features();
         features
-            .enabled_lang_features
+            .enabled_lang_features()
             .iter()
             .map(|(name, span, _)| (name, span))
-            .chain(features.enabled_lib_features.iter().map(|(name, span)| (name, span)))
+            .chain(features.enabled_lib_features().iter().map(|(name, span)| (name, span)))
             .filter(|(&name, _)| features.incomplete(name) || features.internal(name))
             .for_each(|(&name, &span)| {
                 if features.incomplete(name) {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 2f94edc83a5..80ac2741c38 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -935,7 +935,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
         tcx.hir().visit_all_item_likes_in_crate(&mut missing);
     }
 
-    let enabled_lang_features = &tcx.features().enabled_lang_features;
+    let enabled_lang_features = tcx.features().enabled_lang_features();
     let mut lang_features = UnordSet::default();
     for &(feature, span, since) in enabled_lang_features {
         if let Some(since) = since {
@@ -948,7 +948,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
         }
     }
 
-    let enabled_lib_features = &tcx.features().enabled_lib_features;
+    let enabled_lib_features = tcx.features().enabled_lib_features();
     let mut remaining_lib_features = FxIndexMap::default();
     for (feature, span) in enabled_lib_features {
         if remaining_lib_features.contains_key(&feature) {
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 797db3a17bd..78c37688d34 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -112,8 +112,8 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
         // Unfortunately we cannot exhaustively list fields here, since the
         // struct is macro generated.
-        self.enabled_lang_features.hash_stable(hcx, hasher);
-        self.enabled_lib_features.hash_stable(hcx, hasher);
+        self.enabled_lang_features().hash_stable(hcx, hasher);
+        self.enabled_lib_features().hash_stable(hcx, hasher);
 
         self.all_lang_features()[..].hash_stable(hcx, hasher);
         for feature in rustc_feature::UNSTABLE_FEATURES.iter() {