diff options
Diffstat (limited to 'compiler/rustc_feature/src')
| -rw-r--r-- | compiler/rustc_feature/src/accepted.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/builtin_attrs.rs | 48 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/lib.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/removed.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/unstable.rs | 154 |
5 files changed, 88 insertions, 132 deletions
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 53445804694..4f71bdaca1b 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -9,7 +9,7 @@ macro_rules! declare_features { $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr), )+) => { /// Formerly unstable features that have now been accepted (stabilized). - pub const ACCEPTED_FEATURES: &[Feature] = &[ + pub const ACCEPTED_LANG_FEATURES: &[Feature] = &[ $(Feature { name: sym::$feature, since: $ver, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 477760a4597..753195bf691 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -12,33 +12,31 @@ use crate::{Features, Stability}; type GateFn = fn(&Features) -> bool; -macro_rules! cfg_fn { - ($field: ident) => { - (|features| features.$field) as GateFn - }; -} - pub type GatedCfg = (Symbol, Symbol, GateFn); /// `cfg(...)`'s that are feature gated. const GATED_CFGS: &[GatedCfg] = &[ // (name in cfg, feature, function to check if the feature is enabled) - (sym::overflow_checks, sym::cfg_overflow_checks, cfg_fn!(cfg_overflow_checks)), - (sym::ub_checks, sym::cfg_ub_checks, cfg_fn!(cfg_ub_checks)), - (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), + (sym::overflow_checks, sym::cfg_overflow_checks, Features::cfg_overflow_checks), + (sym::ub_checks, sym::cfg_ub_checks, Features::cfg_ub_checks), + (sym::target_thread_local, sym::cfg_target_thread_local, Features::cfg_target_thread_local), ( sym::target_has_atomic_equal_alignment, sym::cfg_target_has_atomic_equal_alignment, - cfg_fn!(cfg_target_has_atomic_equal_alignment), - ), - (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), - (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), - (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), - (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)), - (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)), - (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, cfg_fn!(cfg_sanitizer_cfi)), + Features::cfg_target_has_atomic_equal_alignment, + ), + ( + sym::target_has_atomic_load_store, + sym::cfg_target_has_atomic, + Features::cfg_target_has_atomic, + ), + (sym::sanitize, sym::cfg_sanitize, Features::cfg_sanitize), + (sym::version, sym::cfg_version, Features::cfg_version), + (sym::relocation_model, sym::cfg_relocation_model, Features::cfg_relocation_model), + (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi), + (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi), // this is consistent with naming of the compiler flag it's for - (sym::fmt_debug, sym::fmt_debug, cfg_fn!(fmt_debug)), + (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. @@ -220,7 +218,7 @@ macro_rules! gated { safety: AttributeSafety::Unsafe, template: $tpl, duplicates: $duplicates, - gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), + gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate), } }; (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => { @@ -231,7 +229,7 @@ macro_rules! gated { safety: AttributeSafety::Unsafe, template: $tpl, duplicates: $duplicates, - gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), + gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr), } }; ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => { @@ -242,7 +240,7 @@ macro_rules! gated { safety: AttributeSafety::Normal, template: $tpl, duplicates: $duplicates, - gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), + gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate), } }; ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => { @@ -253,7 +251,7 @@ macro_rules! gated { safety: AttributeSafety::Normal, template: $tpl, duplicates: $duplicates, - gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), + gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr), } }; } @@ -282,7 +280,7 @@ macro_rules! rustc_attr { safety: AttributeSafety::Normal, template: $tpl, duplicates: $duplicates, - gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), + gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, Features::rustc_attrs), } }; } @@ -935,7 +933,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ Stability::Unstable, sym::rustc_attrs, "diagnostic items compiler internal support for linting", - cfg_fn!(rustc_attrs), + Features::rustc_attrs, ), }, gated!( @@ -1193,7 +1191,7 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool { match sym { sym::on_unimplemented => true, - sym::do_not_recommend => features.do_not_recommend, + sym::do_not_recommend => features.do_not_recommend(), _ => false, } } diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 8f4c0b0ac95..216793485e5 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -94,13 +94,13 @@ impl UnstableFeatures { fn find_lang_feature_issue(feature: Symbol) -> Option<NonZero<u32>> { // Search in all the feature lists. - if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| f.feature.name == feature) { - return f.feature.issue; + if let Some(f) = UNSTABLE_LANG_FEATURES.iter().find(|f| f.name == feature) { + return f.issue; } - if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| f.name == feature) { + if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature) { return f.issue; } - if let Some(f) = REMOVED_FEATURES.iter().find(|f| f.feature.name == feature) { + if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| f.feature.name == feature) { return f.feature.issue; } panic!("feature `{feature}` is not declared anywhere"); @@ -127,12 +127,12 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u } } -pub use accepted::ACCEPTED_FEATURES; +pub use accepted::ACCEPTED_LANG_FEATURES; pub use builtin_attrs::{ AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType, BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute, is_valid_for_get_attr, }; -pub use removed::REMOVED_FEATURES; -pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES}; +pub use removed::REMOVED_LANG_FEATURES; +pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES}; diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index d797fee000d..fe3a67fd667 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -14,7 +14,7 @@ macro_rules! declare_features { $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr), )+) => { /// Formerly unstable features that have now been removed. - pub const REMOVED_FEATURES: &[RemovedFeature] = &[ + pub const REMOVED_LANG_FEATURES: &[RemovedFeature] = &[ $(RemovedFeature { feature: Feature { name: sym::$feature, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 0606f2914c3..8f4c208f1fb 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -6,11 +6,6 @@ use rustc_span::symbol::{Symbol, sym}; use super::{Feature, to_nonzero}; -pub struct UnstableFeature { - pub feature: Feature, - set_enabled: fn(&mut Features), -} - #[derive(PartialEq)] enum FeatureStatus { Default, @@ -30,110 +25,73 @@ macro_rules! status_to_enum { }; } +/// A set of features to be used by later passes. +/// +/// There are two ways to check if a language feature `foo` is enabled: +/// - Directly with the `foo` method, e.g. `if tcx.features().foo() { ... }`. +/// - With the `enabled` method, e.g. `if tcx.features.enabled(sym::foo) { ... }`. +/// +/// The former is preferred. `enabled` should only be used when the feature symbol is not a +/// constant, e.g. a parameter, or when the feature is a library feature. +#[derive(Clone, Default, Debug)] +pub struct Features { + /// `#![feature]` attrs for language features, for error reporting. + enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>, + /// `#![feature]` attrs for non-language (library) features. + enabled_lib_features: Vec<(Symbol, Span)>, + /// `enabled_lang_features` + `enabled_lib_features`. + enabled_features: FxHashSet<Symbol>, +} + +impl Features { + 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_lib_feature(&mut self, name: Symbol, span: Span) { + self.enabled_lib_features.push((name, span)); + self.enabled_features.insert(name); + } + + 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) + } +} + macro_rules! declare_features { ($( $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr), )+) => { /// Unstable language features that are being implemented or being /// considered for acceptance (stabilization) or removal. - pub const UNSTABLE_FEATURES: &[UnstableFeature] = &[ - $(UnstableFeature { - feature: Feature { - name: sym::$feature, - since: $ver, - issue: to_nonzero($issue), - }, - // Sets this feature's corresponding bool within `features`. - set_enabled: |features| features.$feature = true, + pub const UNSTABLE_LANG_FEATURES: &[Feature] = &[ + $(Feature { + name: sym::$feature, + since: $ver, + issue: to_nonzero($issue), }),+ ]; - const NUM_FEATURES: usize = UNSTABLE_FEATURES.len(); - - /// A set of features to be used by later passes. - #[derive(Clone, Default, Debug)] - pub struct Features { - /// `#![feature]` attrs for language features, for error reporting. - enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>, - /// `#![feature]` attrs for non-language (library) features. - enabled_lib_features: Vec<(Symbol, Span)>, - /// `enabled_lang_features` + `enabled_lib_features`. - 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`. - $( - $(#[doc = $doc])* - pub $feature: bool - ),+ - } - impl Features { - pub fn set_enabled_lang_feature( - &mut self, - name: Symbol, - span: Span, - since: Option<Symbol>, - feature: Option<&UnstableFeature>, - ) { - 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, 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. - /// - /// The expectation is that this produces much smaller code than other alternatives. - /// - /// Note that the total feature count is pretty small, so this is not a huge array. - #[inline] - pub fn all_lang_features(&self) -> [u8; NUM_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 { - 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}" - ); - } + $( + pub fn $feature(&self) -> bool { + self.enabled_features.contains(&sym::$feature) } - e - } + )* /// Some features are known to be incomplete and using them is likely to have /// unanticipated results, such as compiler crashes. We warn the user about these |
