Skip to content

Commit 3528149

Browse files
committed
Introduce Enabled{Lang,Lib}Feature
Instead of passing around random n-tuples of e.g. `(gate_name, attr_sp, since)`.
1 parent 5ae4d75 commit 3528149

File tree

7 files changed

+101
-51
lines changed

7 files changed

+101
-51
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,9 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
623623
let stable_since = features
624624
.enabled_lang_features()
625625
.iter()
626-
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
627-
.next();
626+
.find(|feat| feat.gate_name == name)
627+
.map(|feat| feat.stable_since)
628+
.flatten();
628629
if let Some(since) = stable_since {
629630
err.stable_features.push(errors::StableFeature { name, since });
630631
} else {
@@ -642,16 +643,15 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate)
642643
}
643644

644645
fn check_incompatible_features(sess: &Session, features: &Features) {
645-
let enabled_features = features
646-
.enabled_lang_features()
647-
.iter()
648-
.copied()
649-
.map(|(name, span, _)| (name, span))
650-
.chain(features.enabled_lib_features().iter().copied());
646+
let enabled_lang_features =
647+
features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
648+
let enabled_lib_features =
649+
features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
650+
let enabled_features = enabled_lang_features.chain(enabled_lib_features);
651651

652652
for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
653653
.iter()
654-
.filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2))
654+
.filter(|(f1, f2)| features.enabled(*f1) && features.enabled(*f2))
655655
{
656656
if let Some((f1_name, f1_span)) = enabled_features.clone().find(|(name, _)| name == f1) {
657657
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) {
673673
}
674674

675675
// Ban GCE with the new solver, because it does not implement GCE correctly.
676-
if let Some(&(_, gce_span, _)) = features
676+
if let Some(gce_span) = features
677677
.enabled_lang_features()
678678
.iter()
679-
.find(|&&(feat, _, _)| feat == sym::generic_const_exprs)
679+
.find(|feat| feat.gate_name == sym::generic_const_exprs)
680+
.map(|feat| feat.attr_sp)
680681
{
681682
sess.dcx().emit_err(errors::IncompatibleFeatures {
682683
spans: vec![gce_span],

compiler/rustc_expand/src/config.rs

+15-6
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, EnabledLibFeature, Features,
15+
REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
1616
};
1717
use rustc_lint_defs::BuiltinLintDiag;
1818
use rustc_parse::validate_attr;
@@ -88,8 +88,11 @@ 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+
stable_since: Some(Symbol::intern(f.since)),
95+
});
9396
continue;
9497
}
9598

@@ -115,13 +118,19 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
115118
{
116119
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
117120
}
118-
features.set_enabled_lang_feature(name, mi.span(), None);
121+
122+
features.set_enabled_lang_feature(EnabledLangFeature {
123+
gate_name: name,
124+
attr_sp: mi.span(),
125+
stable_since: None,
126+
});
119127
continue;
120128
}
121129

122130
// Otherwise, the feature is unknown. Enable it as a lib feature.
123131
// It will be checked later whether the feature really exists.
124-
features.set_enabled_lib_feature(name, mi.span());
132+
features
133+
.set_enabled_lib_feature(EnabledLibFeature { gate_name: name, attr_sp: mi.span() });
125134

126135
// Similar to above, detect internal lib features to suppress
127136
// the ICE message that asks for a report.

compiler/rustc_feature/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,6 @@ 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, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES,
140+
};

compiler/rustc_feature/src/unstable.rs

+33-14
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,54 @@ 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.
41-
enabled_lib_features: Vec<(Symbol, Span)>,
41+
enabled_lib_features: Vec<EnabledLibFeature>,
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+
/// If the lang feature is stable, the version number when it was stabilized.
54+
pub stable_since: Option<Symbol>,
55+
}
56+
57+
/// Information abhout an enabled library feature.
58+
#[derive(Debug, Copy, Clone)]
59+
pub struct EnabledLibFeature {
60+
pub gate_name: Symbol,
61+
pub attr_sp: Span,
62+
}
63+
4664
impl Features {
4765
/// `since` should be set for stable features that are nevertheless enabled with a `#[feature]`
4866
/// 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);
67+
pub fn set_enabled_lang_feature(&mut self, lang_feat: EnabledLangFeature) {
68+
self.enabled_lang_features.push(lang_feat);
69+
self.enabled_features.insert(lang_feat.gate_name);
5270
}
5371

54-
pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
55-
self.enabled_lib_features.push((name, span));
56-
self.enabled_features.insert(name);
72+
pub fn set_enabled_lib_feature(&mut self, lib_feat: EnabledLibFeature) {
73+
self.enabled_lib_features.push(lib_feat);
74+
self.enabled_features.insert(lib_feat.gate_name);
5775
}
5876

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>)> {
77+
/// Returns a list of [`EnabledLangFeature`] with info about:
78+
///
79+
/// - Feature gate name.
80+
/// - The span of the `#[feature]` attribute.
81+
/// - For stable language features, version info for when it was stabilized.
82+
pub fn enabled_lang_features(&self) -> &Vec<EnabledLangFeature> {
6483
&self.enabled_lang_features
6584
}
6685

67-
pub fn enabled_lib_features(&self) -> &Vec<(Symbol, Span)> {
86+
pub fn enabled_lib_features(&self) -> &Vec<EnabledLibFeature> {
6887
&self.enabled_lib_features
6988
}
7089

compiler/rustc_lint/src/builtin.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -2287,13 +2287,15 @@ declare_lint_pass!(
22872287
impl EarlyLintPass for IncompleteInternalFeatures {
22882288
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
22892289
let features = cx.builder.features();
2290-
features
2291-
.enabled_lang_features()
2292-
.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)| {
2290+
let lang_features =
2291+
features.enabled_lang_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
2292+
let lib_features =
2293+
features.enabled_lib_features().iter().map(|feat| (feat.gate_name, feat.attr_sp));
2294+
2295+
lang_features
2296+
.chain(lib_features)
2297+
.filter(|(name, _)| features.incomplete(*name) || features.internal(*name))
2298+
.for_each(|(name, span)| {
22972299
if features.incomplete(name) {
22982300
let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
22992301
.map(|n| BuiltinFeatureIssueNote { n });

compiler/rustc_passes/src/stability.rs

+12-12
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, EnabledLibFeature};
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,25 +937,25 @@ 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, stable_since } in enabled_lang_features {
941+
if let Some(version) = stable_since {
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

951951
let enabled_lib_features = tcx.features().enabled_lib_features();
952952
let mut remaining_lib_features = FxIndexMap::default();
953-
for (feature, span) in enabled_lib_features {
954-
if remaining_lib_features.contains_key(&feature) {
953+
for EnabledLibFeature { gate_name, attr_sp } in enabled_lib_features {
954+
if remaining_lib_features.contains_key(gate_name) {
955955
// Warn if the user enables a lib feature multiple times.
956-
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
956+
tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *attr_sp, feature: *gate_name });
957957
}
958-
remaining_lib_features.insert(feature, *span);
958+
remaining_lib_features.insert(*gate_name, *attr_sp);
959959
}
960960
// `stdbuild` has special handling for `libc`, so we need to
961961
// recognise the feature when building std.
@@ -987,7 +987,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
987987
/// time, less loading from metadata is performed and thus compiler performance is improved.
988988
fn check_features<'tcx>(
989989
tcx: TyCtxt<'tcx>,
990-
remaining_lib_features: &mut FxIndexMap<&Symbol, Span>,
990+
remaining_lib_features: &mut FxIndexMap<Symbol, Span>,
991991
remaining_implications: &mut UnordMap<Symbol, Symbol>,
992992
defined_features: &LibFeatures,
993993
all_implications: &UnordMap<Symbol, Symbol>,
@@ -1057,7 +1057,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
10571057
}
10581058

10591059
for (feature, span) in remaining_lib_features {
1060-
tcx.dcx().emit_err(errors::UnknownFeature { span, feature: *feature });
1060+
tcx.dcx().emit_err(errors::UnknownFeature { span, feature });
10611061
}
10621062

10631063
for (&implied_by, &feature) in remaining_implications.to_sorted_stable_ord() {

compiler/rustc_query_system/src/ich/impls_syntax.rs

+17
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,20 @@ 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, stable_since } = self;
123+
gate_name.hash_stable(hcx, hasher);
124+
attr_sp.hash_stable(hcx, hasher);
125+
stable_since.hash_stable(hcx, hasher);
126+
}
127+
}
128+
129+
impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::EnabledLibFeature {
130+
fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
131+
let rustc_feature::EnabledLibFeature { gate_name, attr_sp } = self;
132+
gate_name.hash_stable(hcx, hasher);
133+
attr_sp.hash_stable(hcx, hasher);
134+
}
135+
}

0 commit comments

Comments
 (0)