Skip to content

Commit e24f394

Browse files
committed
Add comments to config::features.
I found this function very confusing, and it took me quite some time to work out what it was doing. These comments capture that hard-earned knowledge.
1 parent 1ddb287 commit e24f394

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

compiler/rustc_expand/src/config.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,28 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
5858
let mut edition_enabled_features = FxHashMap::default();
5959
let crate_edition = sess.edition();
6060

61+
// Enable edition umbrella feature-gates based on the crate edition.
62+
// - enable `rust_2015_preview` always
63+
// - enable `rust_2018_preview` if the crate edition is 2018 or higher
64+
// - enable `rust_2021_preview` if the crate edition is 2021 or higher
65+
// - etc.
6166
for &edition in ALL_EDITIONS {
6267
if edition <= crate_edition {
63-
// The `crate_edition` implies its respective umbrella feature-gate
64-
// (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
6568
edition_enabled_features.insert(edition.feature_name(), edition);
6669
}
6770
}
6871

72+
// Enable edition-dependent features based on the crate edition.
73+
// - E.g. `test_2018_feature` if the crate edition is 2018 or higher
6974
for feature in active_features_up_to(crate_edition) {
7075
feature.set(&mut features);
7176
edition_enabled_features.insert(feature.name, crate_edition);
7277
}
7378

74-
// Process the edition umbrella feature-gates first, to ensure
75-
// `edition_enabled_features` is completed before it's queried.
79+
// Enable edition umbrella feature-gates that are declared in the code. If
80+
// present, enable edition-specific features based on that.
81+
// - E.g. enable `test_2018_feature` if the crate edition is 2015 but
82+
// `rust_2018_preview` is present
7683
for attr in krate_attrs {
7784
if !attr.has_name(sym::feature) {
7885
continue;
@@ -105,6 +112,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
105112
}
106113
}
107114

115+
// Process all features declared in the code.
108116
for attr in krate_attrs {
109117
if !attr.has_name(sym::feature) {
110118
continue;
@@ -136,6 +144,13 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
136144
}
137145
};
138146

147+
// If the declared feature is edition-specific and already enabled
148+
// due to the crate edition or a declared edition umbrella
149+
// feature-gate, give a warning.
150+
// - E.g. warn if `test_2018_feature` is declared when the crate
151+
// edition is 2018 or higher
152+
// - E.g. warn if `test_2018_feature` is declared when
153+
// `rust_2018_preview` or higher is declared.
139154
if let Some(&edition) = edition_enabled_features.get(&name) {
140155
sess.emit_warning(FeatureIncludedInEdition {
141156
span: mi.span(),
@@ -145,11 +160,14 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
145160
continue;
146161
}
147162

163+
// If the declared feature is an edition umbrella feature-gate,
164+
// ignore it, because it was already handled above.
165+
// - E.g. `rust_20XX_preview`
148166
if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
149-
// Handled in the separate loop above.
150167
continue;
151168
}
152169

170+
// If the declared feature is removed, issue an error.
153171
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
154172
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
155173
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
@@ -161,27 +179,34 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
161179
}
162180
}
163181

182+
// If the declared feature is stable, record it.
164183
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
165184
let since = Some(Symbol::intern(since));
166185
features.declared_lang_features.push((name, mi.span(), since));
167186
features.active_features.insert(name);
168187
continue;
169188
}
170189

190+
// If `-Z allow-features` is used and the declared feature is
191+
// unstable and not also listed as one of the allowed features,
192+
// issue an error.
171193
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
172194
if allowed.iter().all(|f| name.as_str() != f) {
173195
sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
174196
continue;
175197
}
176198
}
177199

200+
// If the declared feature is unstable, record it.
178201
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
179202
f.set(&mut features);
180203
features.declared_lang_features.push((name, mi.span(), None));
181204
features.active_features.insert(name);
182205
continue;
183206
}
184207

208+
// Otherwise, the feature is unknown. Record it at a lib feature.
209+
// It will be checked later.
185210
features.declared_lib_features.push((name, mi.span()));
186211
features.active_features.insert(name);
187212
}

0 commit comments

Comments
 (0)