@@ -58,21 +58,28 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
58
58
let mut edition_enabled_features = FxHashMap :: default ( ) ;
59
59
let crate_edition = sess. edition ( ) ;
60
60
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.
61
66
for & edition in ALL_EDITIONS {
62
67
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).
65
68
edition_enabled_features. insert ( edition. feature_name ( ) , edition) ;
66
69
}
67
70
}
68
71
72
+ // Enable edition-dependent features based on the crate edition.
73
+ // - E.g. `test_2018_feature` if the crate edition is 2018 or higher
69
74
for feature in active_features_up_to ( crate_edition) {
70
75
feature. set ( & mut features) ;
71
76
edition_enabled_features. insert ( feature. name , crate_edition) ;
72
77
}
73
78
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
76
83
for attr in krate_attrs {
77
84
if !attr. has_name ( sym:: feature) {
78
85
continue ;
@@ -105,6 +112,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
105
112
}
106
113
}
107
114
115
+ // Process all features declared in the code.
108
116
for attr in krate_attrs {
109
117
if !attr. has_name ( sym:: feature) {
110
118
continue ;
@@ -136,6 +144,13 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
136
144
}
137
145
} ;
138
146
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.
139
154
if let Some ( & edition) = edition_enabled_features. get ( & name) {
140
155
sess. emit_warning ( FeatureIncludedInEdition {
141
156
span : mi. span ( ) ,
@@ -145,11 +160,14 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
145
160
continue ;
146
161
}
147
162
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`
148
166
if ALL_EDITIONS . iter ( ) . any ( |e| name == e. feature_name ( ) ) {
149
- // Handled in the separate loop above.
150
167
continue ;
151
168
}
152
169
170
+ // If the declared feature is removed, issue an error.
153
171
let removed = REMOVED_FEATURES . iter ( ) . find ( |f| name == f. name ) ;
154
172
let stable_removed = STABLE_REMOVED_FEATURES . iter ( ) . find ( |f| name == f. name ) ;
155
173
if let Some ( Feature { state, .. } ) = removed. or ( stable_removed) {
@@ -161,27 +179,34 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
161
179
}
162
180
}
163
181
182
+ // If the declared feature is stable, record it.
164
183
if let Some ( Feature { since, .. } ) = ACCEPTED_FEATURES . iter ( ) . find ( |f| name == f. name ) {
165
184
let since = Some ( Symbol :: intern ( since) ) ;
166
185
features. declared_lang_features . push ( ( name, mi. span ( ) , since) ) ;
167
186
features. active_features . insert ( name) ;
168
187
continue ;
169
188
}
170
189
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.
171
193
if let Some ( allowed) = sess. opts . unstable_opts . allow_features . as_ref ( ) {
172
194
if allowed. iter ( ) . all ( |f| name. as_str ( ) != f) {
173
195
sess. emit_err ( FeatureNotAllowed { span : mi. span ( ) , name } ) ;
174
196
continue ;
175
197
}
176
198
}
177
199
200
+ // If the declared feature is unstable, record it.
178
201
if let Some ( f) = ACTIVE_FEATURES . iter ( ) . find ( |f| name == f. name ) {
179
202
f. set ( & mut features) ;
180
203
features. declared_lang_features . push ( ( name, mi. span ( ) , None ) ) ;
181
204
features. active_features . insert ( name) ;
182
205
continue ;
183
206
}
184
207
208
+ // Otherwise, the feature is unknown. Record it at a lib feature.
209
+ // It will be checked later.
185
210
features. declared_lib_features . push ( ( name, mi. span ( ) ) ) ;
186
211
features. active_features . insert ( name) ;
187
212
}
0 commit comments