@@ -13,7 +13,7 @@ use rustc_ast::NodeId;
13
13
use rustc_ast:: { self as ast, AttrStyle , Attribute , HasAttrs , HasTokens , MetaItem } ;
14
14
use rustc_attr as attr;
15
15
use rustc_data_structures:: flat_map_in_place:: FlatMapInPlace ;
16
- use rustc_data_structures:: fx:: FxHashMap ;
16
+ use rustc_data_structures:: fx:: FxHashSet ;
17
17
use rustc_feature:: { Feature , Features , State as FeatureState } ;
18
18
use rustc_feature:: { ACCEPTED_FEATURES , ACTIVE_FEATURES , REMOVED_FEATURES } ;
19
19
use rustc_parse:: validate_attr;
@@ -55,55 +55,37 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
55
55
}
56
56
57
57
let mut features = Features :: default ( ) ;
58
- let mut edition_enabled_features = FxHashMap :: default ( ) ;
59
- let crate_edition = sess. edition ( ) ;
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.
66
- for & edition in ALL_EDITIONS {
67
- if edition <= crate_edition {
68
- edition_enabled_features. insert ( edition. feature_name ( ) , edition) ;
69
- }
70
- }
71
58
72
- // Enable edition-dependent features based on the crate edition.
73
- // - E.g. `test_2018_feature` if the crate edition is 2018 or higher
74
- for feature in active_features_up_to ( crate_edition) {
75
- feature. set ( & mut features) ;
76
- edition_enabled_features. insert ( feature. name , crate_edition) ;
77
- }
59
+ // The edition from `--edition`.
60
+ let crate_edition = sess. edition ( ) ;
78
61
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
62
+ // The maximum of (a) the edition from `--edition` and (b) any edition
63
+ // umbrella feature-gates declared in the code.
64
+ // - E.g. if `crate_edition` is 2015 but `rust_2018_preview` is present,
65
+ // `feature_edition` is 2018
66
+ let mut features_edition = crate_edition;
83
67
for attr in krate_attrs {
84
68
for mi in feature_list ( attr) {
85
- if !mi. is_word ( ) {
86
- continue ;
87
- }
88
-
89
- let name = mi. name_or_empty ( ) ;
90
-
91
- let edition = ALL_EDITIONS . iter ( ) . find ( |e| name == e. feature_name ( ) ) . copied ( ) ;
92
- if let Some ( edition) = edition {
93
- if edition <= crate_edition {
94
- continue ;
95
- }
96
-
97
- for feature in active_features_up_to ( edition) {
98
- // FIXME(Manishearth) there is currently no way to set
99
- // lib features by edition
100
- feature. set ( & mut features) ;
101
- edition_enabled_features. insert ( feature. name , edition) ;
69
+ if mi. is_word ( ) {
70
+ let name = mi. name_or_empty ( ) ;
71
+ let edition = ALL_EDITIONS . iter ( ) . find ( |e| name == e. feature_name ( ) ) . copied ( ) ;
72
+ if let Some ( edition) = edition && edition > features_edition {
73
+ features_edition = edition;
102
74
}
103
75
}
104
76
}
105
77
}
106
78
79
+ // Enable edition-dependent features based on `features_edition`.
80
+ // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher
81
+ let mut edition_enabled_features = FxHashSet :: default ( ) ;
82
+ for feature in active_features_up_to ( features_edition) {
83
+ // FIXME(Manishearth) there is currently no way to set lib features by
84
+ // edition.
85
+ edition_enabled_features. insert ( feature. name ) ;
86
+ feature. set ( & mut features) ;
87
+ }
88
+
107
89
// Process all features declared in the code.
108
90
for attr in krate_attrs {
109
91
for mi in feature_list ( attr) {
@@ -128,30 +110,37 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
128
110
}
129
111
} ;
130
112
131
- // If the declared feature is edition-specific and already enabled
132
- // due to the crate edition or a declared edition umbrella
133
- // feature-gate, give a warning.
134
- // - E.g. warn if `test_2018_feature` is declared when the crate
135
- // edition is 2018 or higher
113
+ // If the declared feature is an edition umbrella feature-gate,
114
+ // warn if it was redundant w.r.t. `crate_edition`.
115
+ // - E.g. warn if `rust_2018_preview` is declared when
116
+ // `crate_edition` is 2018
117
+ // - E.g. don't warn if `rust_2018_preview` is declared when
118
+ // `crate_edition` is 2015.
119
+ if let Some ( & edition) = ALL_EDITIONS . iter ( ) . find ( |e| name == e. feature_name ( ) ) {
120
+ if edition <= crate_edition {
121
+ sess. emit_warning ( FeatureIncludedInEdition {
122
+ span : mi. span ( ) ,
123
+ feature : name,
124
+ edition,
125
+ } ) ;
126
+ }
127
+ continue ;
128
+ }
129
+
130
+ // If the declared feature is edition-dependent and was already
131
+ // enabled due to `feature_edition`, give a warning.
136
132
// - E.g. warn if `test_2018_feature` is declared when
137
- // `rust_2018_preview` or higher is declared .
138
- if let Some ( & edition ) = edition_enabled_features. get ( & name) {
133
+ // `feature_edition` is 2018 or higher .
134
+ if edition_enabled_features. contains ( & name) {
139
135
sess. emit_warning ( FeatureIncludedInEdition {
140
136
span : mi. span ( ) ,
141
137
feature : name,
142
- edition,
138
+ edition : features_edition ,
143
139
} ) ;
144
140
continue ;
145
141
}
146
142
147
- // If the declared feature is an edition umbrella feature-gate,
148
- // ignore it, because it was already handled above.
149
- // - E.g. `rust_20XX_preview`
150
- if ALL_EDITIONS . iter ( ) . any ( |e| name == e. feature_name ( ) ) {
151
- continue ;
152
- }
153
-
154
- // If the declared feature is removed, issue an error.
143
+ // If the declared feature has been removed, issue an error.
155
144
if let Some ( Feature { state, .. } ) = REMOVED_FEATURES . iter ( ) . find ( |f| name == f. name ) {
156
145
if let FeatureState :: Removed { reason } = state {
157
146
sess. emit_err ( FeatureRemoved {
0 commit comments