about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs23
-rw-r--r--compiler/rustc_expand/src/config.rs21
-rw-r--r--compiler/rustc_feature/src/lib.rs4
-rw-r--r--compiler/rustc_feature/src/unstable.rs47
-rw-r--r--compiler/rustc_lint/src/builtin.rs16
-rw-r--r--compiler/rustc_passes/src/stability.rs24
-rw-r--r--compiler/rustc_query_system/src/ich/impls_syntax.rs17
7 files changed, 101 insertions, 51 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 348a602fd59..d646150a620 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -623,8 +623,9 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
             let stable_since = features
                 .enabled_lang_features()
                 .iter()
-                .flat_map(|&(feature, _, since)| if feature == name { since } else { None })
-                .next();
+                .find(|feat| feat.gate_name == name)
+                .map(|feat| feat.stable_since)
+                .flatten();
             if let Some(since) = stable_since {
                 err.stable_features.push(errors::StableFeature { name, since });
             } else {
@@ -642,16 +643,15 @@ 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()
-        .iter()
-        .copied()
-        .map(|(name, span, _)| (name, span))
-        .chain(features.enabled_lib_features().iter().copied());
+    let enabled_lang_features =
+        features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
+    let enabled_lib_features =
+        features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
+    let enabled_features = enabled_lang_features.chain(enabled_lib_features);
 
     for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
         .iter()
-        .filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2))
+        .filter(|(f1, f2)| features.enabled(*f1) && features.enabled(*f2))
     {
         if let Some((f1_name, f1_span)) = enabled_features.clone().find(|(name, _)| name == f1) {
             if let Some((f2_name, f2_span)) = enabled_features.clone().find(|(name, _)| name == f2)
@@ -673,10 +673,11 @@ 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
+    if let Some(gce_span) = features
         .enabled_lang_features()
         .iter()
-        .find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
+        .find(|feat| feat.gate_name == sym::generic_const_exprs)
+        .map(|feat| feat.attr_sp)
     {
         sess.dcx().emit_err(errors::IncompatibleFeatures {
             spans: vec![gce_span],
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 5bd9e2fbcb9..dc6aa110f45 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -11,8 +11,8 @@ use rustc_ast::{
 use rustc_attr as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_feature::{
-    ACCEPTED_LANG_FEATURES, AttributeSafety, Features, REMOVED_LANG_FEATURES,
-    UNSTABLE_LANG_FEATURES,
+    ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features,
+    REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
 };
 use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::validate_attr;
@@ -88,8 +88,11 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
 
             // If the enabled feature is stable, record it.
             if let Some(f) = ACCEPTED_LANG_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(EnabledLangFeature {
+                    gate_name: name,
+                    attr_sp: mi.span(),
+                    stable_since: Some(Symbol::intern(f.since)),
+                });
                 continue;
             }
 
@@ -115,13 +118,19 @@ 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(EnabledLangFeature {
+                    gate_name: name,
+                    attr_sp: mi.span(),
+                    stable_since: None,
+                });
                 continue;
             }
 
             // Otherwise, the feature is unknown. Enable it as a lib feature.
             // It will be checked later whether the feature really exists.
-            features.set_enabled_lib_feature(name, mi.span());
+            features
+                .set_enabled_lib_feature(EnabledLibFeature { gate_name: name, attr_sp: mi.span() });
 
             // Similar to above, detect internal lib features to suppress
             // the ICE message that asks for a report.
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 216793485e5..9f42d3ec45c 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -135,4 +135,6 @@ pub use builtin_attrs::{
     is_valid_for_get_attr,
 };
 pub use removed::REMOVED_LANG_FEATURES;
-pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES};
+pub use unstable::{
+    EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES,
+};
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 39db0b31f9a..a81058e6ea1 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -36,35 +36,54 @@ macro_rules! status_to_enum {
 #[derive(Clone, Default, Debug)]
 pub struct Features {
     /// `#![feature]` attrs for language features, for error reporting.
-    enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
+    enabled_lang_features: Vec<EnabledLangFeature>,
     /// `#![feature]` attrs for non-language (library) features.
-    enabled_lib_features: Vec<(Symbol, Span)>,
+    enabled_lib_features: Vec<EnabledLibFeature>,
     /// `enabled_lang_features` + `enabled_lib_features`.
     enabled_features: FxHashSet<Symbol>,
 }
 
+/// Information about an enabled language feature.
+#[derive(Debug, Copy, Clone)]
+pub struct EnabledLangFeature {
+    /// Name of the feature gate guarding the language feature.
+    pub gate_name: Symbol,
+    /// Span of the `#[feature(...)]` attribute.
+    pub attr_sp: Span,
+    /// If the lang feature is stable, the version number when it was stabilized.
+    pub stable_since: Option<Symbol>,
+}
+
+/// Information abhout an enabled library feature.
+#[derive(Debug, Copy, Clone)]
+pub struct EnabledLibFeature {
+    pub gate_name: Symbol,
+    pub attr_sp: Span,
+}
+
 impl Features {
     /// `since` should be set for stable features that are nevertheless enabled with a `#[feature]`
     /// attribute, indicating since when they are stable.
-    pub fn set_enabled_lang_feature(&mut self, name: Symbol, span: Span, since: Option<Symbol>) {
-        self.enabled_lang_features.push((name, span, since));
-        self.enabled_features.insert(name);
+    pub fn set_enabled_lang_feature(&mut self, lang_feat: EnabledLangFeature) {
+        self.enabled_lang_features.push(lang_feat);
+        self.enabled_features.insert(lang_feat.gate_name);
     }
 
-    pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
-        self.enabled_lib_features.push((name, span));
-        self.enabled_features.insert(name);
+    pub fn set_enabled_lib_feature(&mut self, lib_feat: EnabledLibFeature) {
+        self.enabled_lib_features.push(lib_feat);
+        self.enabled_features.insert(lib_feat.gate_name);
     }
 
-    /// Returns a list of triples with:
-    /// - feature gate name
-    /// - the span of the `#[feature]` attribute
-    /// - (for already stable features) the version since which it is stable
-    pub fn enabled_lang_features(&self) -> &Vec<(Symbol, Span, Option<Symbol>)> {
+    /// Returns a list of [`EnabledLangFeature`] with info about:
+    ///
+    /// - Feature gate name.
+    /// - The span of the `#[feature]` attribute.
+    /// - For stable language features, version info for when it was stabilized.
+    pub fn enabled_lang_features(&self) -> &Vec<EnabledLangFeature> {
         &self.enabled_lang_features
     }
 
-    pub fn enabled_lib_features(&self) -> &Vec<(Symbol, Span)> {
+    pub fn enabled_lib_features(&self) -> &Vec<EnabledLibFeature> {
         &self.enabled_lib_features
     }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 12f8e4ed239..70d51c92750 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2289,13 +2289,15 @@ declare_lint_pass!(
 impl EarlyLintPass for IncompleteInternalFeatures {
     fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
         let features = cx.builder.features();
-        features
-            .enabled_lang_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)| {
+        let lang_features =
+            features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
+        let lib_features =
+            features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
+
+        lang_features
+            .chain(lib_features)
+            .filter(|(name, _)| features.incomplete(*name) || features.internal(*name))
+            .for_each(|(name, span)| {
                 if features.incomplete(name) {
                     let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
                         .map(|n| BuiltinFeatureIssueNote { n });
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 67e7496771d..466ea32735b 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -10,7 +10,7 @@ use rustc_attr::{
 };
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
-use rustc_feature::ACCEPTED_LANG_FEATURES;
+use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
@@ -994,25 +994,25 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
 
     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 {
+    for EnabledLangFeature { gate_name, attr_sp, stable_since } in enabled_lang_features {
+        if let Some(version) = stable_since {
             // Warn if the user has enabled an already-stable lang feature.
-            unnecessary_stable_feature_lint(tcx, span, feature, since);
+            unnecessary_stable_feature_lint(tcx, *attr_sp, *gate_name, *version);
         }
-        if !lang_features.insert(feature) {
+        if !lang_features.insert(gate_name) {
             // Warn if the user enables a lang feature multiple times.
-            tcx.dcx().emit_err(errors::DuplicateFeatureErr { span, feature });
+            tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *attr_sp, feature: *gate_name });
         }
     }
 
     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) {
+    for EnabledLibFeature { gate_name, attr_sp } in enabled_lib_features {
+        if remaining_lib_features.contains_key(gate_name) {
             // Warn if the user enables a lib feature multiple times.
-            tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
+            tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *attr_sp, feature: *gate_name });
         }
-        remaining_lib_features.insert(feature, *span);
+        remaining_lib_features.insert(*gate_name, *attr_sp);
     }
     // `stdbuild` has special handling for `libc`, so we need to
     // recognise the feature when building std.
@@ -1044,7 +1044,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     /// time, less loading from metadata is performed and thus compiler performance is improved.
     fn check_features<'tcx>(
         tcx: TyCtxt<'tcx>,
-        remaining_lib_features: &mut FxIndexMap<&Symbol, Span>,
+        remaining_lib_features: &mut FxIndexMap<Symbol, Span>,
         remaining_implications: &mut UnordMap<Symbol, Symbol>,
         defined_features: &LibFeatures,
         all_implications: &UnordMap<Symbol, Symbol>,
@@ -1114,7 +1114,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     }
 
     for (feature, span) in remaining_lib_features {
-        tcx.dcx().emit_err(errors::UnknownFeature { span, feature: *feature });
+        tcx.dcx().emit_err(errors::UnknownFeature { span, feature });
     }
 
     for (&implied_by, &feature) in remaining_implications.to_sorted_stable_ord() {
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 0665401df8e..5a72e80a0a5 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -116,3 +116,20 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
         self.enabled_lib_features().hash_stable(hcx, hasher);
     }
 }
+
+impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLangFeature {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
+        let rustc_feature::EnabledLangFeature { gate_name, attr_sp, stable_since } = self;
+        gate_name.hash_stable(hcx, hasher);
+        attr_sp.hash_stable(hcx, hasher);
+        stable_since.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLibFeature {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
+        let rustc_feature::EnabledLibFeature { gate_name, attr_sp } = self;
+        gate_name.hash_stable(hcx, hasher);
+        attr_sp.hash_stable(hcx, hasher);
+    }
+}