Skip to content

Commit cc95e5e

Browse files
committed
Introduce EnabledLangFeature and LangFeatureStability
Instead of passing around random 3-tuples of `(gate_name, attr_sp, since)`.
1 parent 5ae4d75 commit cc95e5e

File tree

7 files changed

+99
-36
lines changed

7 files changed

+99
-36
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use rustc_ast as ast;
22
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
33
use rustc_ast::{NodeId, PatKind, attr, token};
4-
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
4+
use rustc_feature::{
5+
AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue,
6+
LangFeatureStability,
7+
};
58
use rustc_session::Session;
69
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
710
use rustc_span::source_map::Spanned;
@@ -620,11 +623,15 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
620623
let mut all_stable = true;
621624
for ident in attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident()) {
622625
let name = ident.name;
623-
let stable_since = features
624-
.enabled_lang_features()
625-
.iter()
626-
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
627-
.next();
626+
let stable_since = features.enabled_lang_features().iter().find_map(|feat| {
627+
if feat.gate_name == name
628+
&& let LangFeatureStability::StableSince { version } = feat.stability
629+
{
630+
Some(version)
631+
} else {
632+
None
633+
}
634+
});
628635
if let Some(since) = stable_since {
629636
err.stable_features.push(errors::StableFeature { name, since });
630637
} else {
@@ -645,13 +652,12 @@ fn check_incompatible_features(sess: &Session, features: &Features) {
645652
let enabled_features = features
646653
.enabled_lang_features()
647654
.iter()
648-
.copied()
649-
.map(|(name, span, _)| (name, span))
655+
.map(|feat| (feat.gate_name, feat.attr_sp))
650656
.chain(features.enabled_lib_features().iter().copied());
651657

652658
for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
653659
.iter()
654-
.filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2))
660+
.filter(|(f1, f2)| features.enabled(*f1) && features.enabled(*f2))
655661
{
656662
if let Some((f1_name, f1_span)) = enabled_features.clone().find(|(name, _)| name == f1) {
657663
if let Some((f2_name, f2_span)) = enabled_features.clone().find(|(name, _)| name == f2)
@@ -673,10 +679,11 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
673679
}
674680

675681
// Ban GCE with the new solver, because it does not implement GCE correctly.
676-
if let Some(&(_, gce_span, _)) = features
682+
if let Some(gce_span) = features
677683
.enabled_lang_features()
678684
.iter()
679-
.find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
685+
.find(|feat| feat.gate_name == sym::generic_const_exprs)
686+
.map(|feat| feat.attr_sp)
680687
{
681688
sess.dcx().emit_err(errors::IncompatibleFeatures {
682689
spans: vec![gce_span],

compiler/rustc_expand/src/config.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use rustc_ast::{
1111
use rustc_attr as attr;
1212
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
1313
use rustc_feature::{
14-
ACCEPTED_LANG_FEATURES, AttributeSafety, Features, REMOVED_LANG_FEATURES,
15-
UNSTABLE_LANG_FEATURES,
14+
ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, Features, LangFeatureStability,
15+
REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
1616
};
1717
use rustc_lint_defs::BuiltinLintDiag;
1818
use rustc_parse::validate_attr;
@@ -88,8 +88,13 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
8888

8989
// If the enabled feature is stable, record it.
9090
if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| name == f.name) {
91-
let since = Some(Symbol::intern(f.since));
92-
features.set_enabled_lang_feature(name, mi.span(), since);
91+
features.set_enabled_lang_feature(EnabledLangFeature {
92+
gate_name: name,
93+
attr_sp: mi.span(),
94+
stability: LangFeatureStability::StableSince {
95+
version: Symbol::intern(f.since),
96+
},
97+
});
9398
continue;
9499
}
95100

@@ -115,7 +120,12 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
115120
{
116121
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
117122
}
118-
features.set_enabled_lang_feature(name, mi.span(), None);
123+
124+
features.set_enabled_lang_feature(EnabledLangFeature {
125+
gate_name: name,
126+
attr_sp: mi.span(),
127+
stability: LangFeatureStability::Unstable,
128+
});
119129
continue;
120130
}
121131

compiler/rustc_feature/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,7 @@ pub use builtin_attrs::{
135135
is_valid_for_get_attr,
136136
};
137137
pub use removed::REMOVED_LANG_FEATURES;
138-
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES};
138+
pub use unstable::{
139+
EnabledLangFeature, Features, INCOMPATIBLE_FEATURES, LangFeatureStability,
140+
UNSTABLE_LANG_FEATURES,
141+
};

compiler/rustc_feature/src/unstable.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,53 @@ macro_rules! status_to_enum {
3636
#[derive(Clone, Default, Debug)]
3737
pub struct Features {
3838
/// `#![feature]` attrs for language features, for error reporting.
39-
enabled_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
39+
enabled_lang_features: Vec<EnabledLangFeature>,
4040
/// `#![feature]` attrs for non-language (library) features.
4141
enabled_lib_features: Vec<(Symbol, Span)>,
4242
/// `enabled_lang_features` + `enabled_lib_features`.
4343
enabled_features: FxHashSet<Symbol>,
4444
}
4545

46+
/// Information about an enabled language feature.
47+
#[derive(Debug, Copy, Clone)]
48+
pub struct EnabledLangFeature {
49+
/// Name of the feature gate guarding the language feature.
50+
pub gate_name: Symbol,
51+
/// Span of the `#[feature(...)]` attribute.
52+
pub attr_sp: Span,
53+
/// Stability info of the language feature.
54+
pub stability: LangFeatureStability,
55+
}
56+
57+
/// Stability info for a given [`EnabledLangFeature`].
58+
#[derive(Debug, Copy, PartialEq, Clone)]
59+
pub enum LangFeatureStability {
60+
/// The [`EnabledLangFeature`] is not yet stable.
61+
Unstable,
62+
/// Version when the [`EnabledLangFeature`] became stable.
63+
StableSince { version: Symbol },
64+
}
65+
4666
impl Features {
4767
/// `since` should be set for stable features that are nevertheless enabled with a `#[feature]`
4868
/// attribute, indicating since when they are stable.
49-
pub fn set_enabled_lang_feature(&mut self, name: Symbol, span: Span, since: Option<Symbol>) {
50-
self.enabled_lang_features.push((name, span, since));
51-
self.enabled_features.insert(name);
69+
pub fn set_enabled_lang_feature(&mut self, feat: EnabledLangFeature) {
70+
self.enabled_lang_features.push(feat);
71+
self.enabled_features.insert(feat.gate_name);
5272
}
5373

5474
pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
5575
self.enabled_lib_features.push((name, span));
5676
self.enabled_features.insert(name);
5777
}
5878

59-
/// Returns a list of triples with:
60-
/// - feature gate name
61-
/// - the span of the `#[feature]` attribute
62-
/// - (for already stable features) the version since which it is stable
63-
pub fn enabled_lang_features(&self) -> &Vec<(Symbol, Span, Option<Symbol>)> {
79+
/// Returns a list of [`EnabledLangFeature`] with info about:
80+
///
81+
/// - Feature gate name.
82+
/// - The span of the `#[feature]` attribute.
83+
/// - Language feature stability. For stable language features, this will contain the version
84+
/// since which it is stable.
85+
pub fn enabled_lang_features(&self) -> &Vec<EnabledLangFeature> {
6486
&self.enabled_lang_features
6587
}
6688

compiler/rustc_lint/src/builtin.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,10 +2290,10 @@ impl EarlyLintPass for IncompleteInternalFeatures {
22902290
features
22912291
.enabled_lang_features()
22922292
.iter()
2293-
.map(|(name, span, _)| (name, span))
2294-
.chain(features.enabled_lib_features().iter().map(|(name, span)| (name, span)))
2295-
.filter(|(&name, _)| features.incomplete(name) || features.internal(name))
2296-
.for_each(|(&name, &span)| {
2293+
.map(|feat| (feat.gate_name, feat.attr_sp))
2294+
.chain(features.enabled_lib_features().into_iter().copied())
2295+
.filter(|(name, _)| features.incomplete(*name) || features.internal(*name))
2296+
.for_each(|(name, span)| {
22972297
if features.incomplete(name) {
22982298
let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
22992299
.map(|n| BuiltinFeatureIssueNote { n });

compiler/rustc_passes/src/stability.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_attr::{
1010
};
1111
use rustc_data_structures::fx::FxIndexMap;
1212
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
13-
use rustc_feature::ACCEPTED_LANG_FEATURES;
13+
use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, LangFeatureStability};
1414
use rustc_hir as hir;
1515
use rustc_hir::def::{DefKind, Res};
1616
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
@@ -937,14 +937,14 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
937937

938938
let enabled_lang_features = tcx.features().enabled_lang_features();
939939
let mut lang_features = UnordSet::default();
940-
for &(feature, span, since) in enabled_lang_features {
941-
if let Some(since) = since {
940+
for EnabledLangFeature { gate_name, attr_sp, stability } in enabled_lang_features {
941+
if let LangFeatureStability::StableSince { version } = stability {
942942
// Warn if the user has enabled an already-stable lang feature.
943-
unnecessary_stable_feature_lint(tcx, span, feature, since);
943+
unnecessary_stable_feature_lint(tcx, *attr_sp, *gate_name, *version);
944944
}
945-
if !lang_features.insert(feature) {
945+
if !lang_features.insert(gate_name) {
946946
// Warn if the user enables a lang feature multiple times.
947-
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span, feature });
947+
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *attr_sp, feature: *gate_name });
948948
}
949949
}
950950

compiler/rustc_query_system/src/ich/impls_syntax.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,24 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
116116
self.enabled_lib_features().hash_stable(hcx, hasher);
117117
}
118118
}
119+
120+
impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLangFeature {
121+
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
122+
let rustc_feature::EnabledLangFeature { gate_name, attr_sp, stability } = self;
123+
gate_name.hash_stable(hcx, hasher);
124+
attr_sp.hash_stable(hcx, hasher);
125+
stability.hash_stable(hcx, hasher);
126+
}
127+
}
128+
129+
impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::LangFeatureStability {
130+
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
131+
std::mem::discriminant(self).hash_stable(hcx, hasher);
132+
match self {
133+
rustc_feature::LangFeatureStability::Unstable => {}
134+
rustc_feature::LangFeatureStability::StableSince { version } => {
135+
version.hash_stable(hcx, hasher)
136+
}
137+
}
138+
}
139+
}

0 commit comments

Comments
 (0)