about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_expand/src/config.rs48
-rw-r--r--compiler/rustc_feature/src/accepted.rs17
-rw-r--r--compiler/rustc_feature/src/active.rs36
-rw-r--r--compiler/rustc_feature/src/lib.rs38
-rw-r--r--compiler/rustc_feature/src/removed.rs19
5 files changed, 61 insertions, 97 deletions
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 4b213ff1922..9909a9ade8b 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -14,12 +14,12 @@ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem
 use rustc_attr as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_feature::{Feature, Features, State as FeatureState};
+use rustc_feature::Features;
 use rustc_feature::{ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES};
 use rustc_parse::validate_attr;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
-use rustc_span::edition::{Edition, ALL_EDITIONS};
+use rustc_span::edition::ALL_EDITIONS;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use thin_vec::ThinVec;
@@ -36,16 +36,6 @@ pub struct StripUnconfigured<'a> {
 }
 
 pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
-    fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
-        ACTIVE_FEATURES.iter().filter(move |feature| {
-            if let Some(feature_edition) = feature.edition {
-                feature_edition <= edition
-            } else {
-                false
-            }
-        })
-    }
-
     fn feature_list(attr: &Attribute) -> ThinVec<ast::NestedMetaItem> {
         if attr.has_name(sym::feature)
             && let Some(list) = attr.meta_item_list()
@@ -83,11 +73,13 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
     // Enable edition-dependent features based on `features_edition`.
     // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher
     let mut edition_enabled_features = FxHashSet::default();
-    for feature in active_features_up_to(features_edition) {
-        // FIXME(Manishearth) there is currently no way to set lib features by
-        // edition.
-        edition_enabled_features.insert(feature.name);
-        feature.set(&mut features);
+    for f in ACTIVE_FEATURES {
+        if let Some(edition) = f.feature.edition && edition <= features_edition {
+            // FIXME(Manishearth) there is currently no way to set lib features by
+            // edition.
+            edition_enabled_features.insert(f.feature.name);
+            (f.set_enabled)(&mut features);
+        }
     }
 
     // Process all features declared in the code.
@@ -147,19 +139,17 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
             }
 
             // If the declared feature has been removed, issue an error.
-            if let Some(Feature { state, .. }) = REMOVED_FEATURES.iter().find(|f| name == f.name) {
-                if let FeatureState::Removed { reason } = state {
-                    sess.emit_err(FeatureRemoved {
-                        span: mi.span(),
-                        reason: reason.map(|reason| FeatureRemovedReason { reason }),
-                    });
-                    continue;
-                }
+            if let Some(f) = REMOVED_FEATURES.iter().find(|f| name == f.feature.name) {
+                sess.emit_err(FeatureRemoved {
+                    span: mi.span(),
+                    reason: f.reason.map(|reason| FeatureRemovedReason { reason }),
+                });
+                continue;
             }
 
             // If the declared feature is stable, record it.
-            if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
-                let since = Some(Symbol::intern(since));
+            if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
+                let since = Some(Symbol::intern(f.since));
                 features.set_declared_lang_feature(name, mi.span(), since);
                 continue;
             }
@@ -175,8 +165,8 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
             }
 
             // If the declared feature is unstable, record it.
-            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
-                f.set(&mut features);
+            if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.feature.name) {
+                (f.set_enabled)(&mut features);
                 features.set_declared_lang_feature(name, mi.span(), None);
                 continue;
             }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index b198876b05c..46ff43fa9aa 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -1,6 +1,6 @@
 //! List of the accepted feature gates.
 
-use super::{to_nonzero, Feature, State};
+use super::{to_nonzero, Feature};
 use rustc_span::symbol::sym;
 
 macro_rules! declare_features {
@@ -9,15 +9,12 @@ macro_rules! declare_features {
     )+) => {
         /// Those language feature has since been Accepted (it was once Active)
         pub const ACCEPTED_FEATURES: &[Feature] = &[
-            $(
-                Feature {
-                    state: State::Accepted,
-                    name: sym::$feature,
-                    since: $ver,
-                    issue: to_nonzero($issue),
-                    edition: None,
-                }
-            ),+
+            $(Feature {
+                name: sym::$feature,
+                since: $ver,
+                issue: to_nonzero($issue),
+                edition: None,
+            }),+
         ];
     }
 }
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index ef672487b98..95ddd19fcb2 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -1,12 +1,17 @@
 //! List of the active feature gates.
 
-use super::{to_nonzero, Feature, State};
+use super::{to_nonzero, Feature};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
+pub struct ActiveFeature {
+    pub feature: Feature,
+    pub set_enabled: fn(&mut Features),
+}
+
 #[derive(PartialEq)]
 enum FeatureStatus {
     Default,
@@ -32,21 +37,18 @@ macro_rules! declare_features {
     )+) => {
         /// Represents active features that are currently being implemented or
         /// currently being considered for addition/removal.
-        pub const ACTIVE_FEATURES:
-            &[Feature] =
-            &[$(
-                // (sym::$feature, $ver, $issue, $edition, set!($feature))
-                Feature {
-                    state: State::Active {
-                        // Sets this feature's corresponding bool within `features`.
-                        set: |features| features.$feature = true,
-                    },
+        pub const ACTIVE_FEATURES: &[ActiveFeature] = &[
+            $(ActiveFeature {
+                feature: Feature {
                     name: sym::$feature,
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: $edition,
-                }
-            ),+];
+                },
+                // Sets this feature's corresponding bool within `features`.
+                set_enabled: |features| features.$feature = true,
+            }),+
+        ];
 
         /// A set of features to be used by later passes.
         #[derive(Clone, Default, Debug)]
@@ -134,16 +136,6 @@ macro_rules! declare_features {
     };
 }
 
-impl Feature {
-    /// Sets this feature in `Features`. Panics if called on a non-active feature.
-    pub fn set(&self, features: &mut Features) {
-        match self.state {
-            State::Active { set } => set(features),
-            _ => panic!("called `set` on feature `{}` which is not `active`", self.name),
-        }
-    }
-}
-
 // See https://rustc-dev-guide.rust-lang.org/feature-gates.html#feature-gates for more
 // documentation about handling feature gates.
 //
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 4721bff0ec7..42bf15262d7 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -24,29 +24,10 @@ mod removed;
 mod tests;
 
 use rustc_span::{edition::Edition, symbol::Symbol};
-use std::fmt;
 use std::num::NonZeroU32;
 
-#[derive(Clone, Copy)]
-pub enum State {
-    Accepted,
-    Active { set: fn(&mut Features) },
-    Removed { reason: Option<&'static str> },
-}
-
-impl fmt::Debug for State {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            State::Accepted { .. } => write!(f, "accepted"),
-            State::Active { .. } => write!(f, "active"),
-            State::Removed { .. } => write!(f, "removed"),
-        }
-    }
-}
-
 #[derive(Debug, Clone)]
 pub struct Feature {
-    pub state: State,
     pub name: Symbol,
     pub since: &'static str,
     issue: Option<NonZeroU32>,
@@ -106,17 +87,16 @@ impl UnstableFeatures {
 
 fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
     // Search in all the feature lists.
-    let found = []
-        .iter()
-        .chain(ACTIVE_FEATURES)
-        .chain(ACCEPTED_FEATURES)
-        .chain(REMOVED_FEATURES)
-        .find(|t| t.name == feature);
-
-    match found {
-        Some(found) => found.issue,
-        None => panic!("feature `{feature}` is not declared anywhere"),
+    if let Some(f) = ACTIVE_FEATURES.iter().find(|f| f.feature.name == feature) {
+        return f.feature.issue;
+    }
+    if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| f.name == feature) {
+        return f.issue;
+    }
+    if let Some(f) = REMOVED_FEATURES.iter().find(|f| f.feature.name == feature) {
+        return f.feature.issue;
     }
+    panic!("feature `{feature}` is not declared anywhere");
 }
 
 const fn to_nonzero(n: Option<u32>) -> Option<NonZeroU32> {
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 1697e929eda..91c556dc465 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -1,23 +1,28 @@
 //! List of the removed feature gates.
 
-use super::{to_nonzero, Feature, State};
+use super::{to_nonzero, Feature};
 use rustc_span::symbol::sym;
 
+pub struct RemovedFeature {
+    pub feature: Feature,
+    pub reason: Option<&'static str>,
+}
+
 macro_rules! declare_features {
     ($(
         $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr),
     )+) => {
         /// Represents unstable features which have since been removed (it was once Active)
-        pub const REMOVED_FEATURES: &[Feature] = &[
-            $(
-                Feature {
-                    state: State::Removed { reason: $reason },
+        pub const REMOVED_FEATURES: &[RemovedFeature] = &[
+            $(RemovedFeature {
+                feature: Feature {
                     name: sym::$feature,
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                }
-            ),+
+                },
+                reason: $reason
+            }),+
         ];
     };
 }