@@ -13,7 +13,7 @@ use rustc_ast::NodeId;
1313use rustc_ast:: { self as ast, AttrStyle , Attribute , HasAttrs , HasTokens , MetaItem } ;
1414use rustc_attr as attr;
1515use rustc_data_structures:: flat_map_in_place:: FlatMapInPlace ;
16- use rustc_data_structures:: fx:: FxHashMap ;
16+ use rustc_data_structures:: fx:: FxHashSet ;
1717use rustc_feature:: { Feature , Features , State as FeatureState } ;
1818use rustc_feature:: { ACCEPTED_FEATURES , ACTIVE_FEATURES , REMOVED_FEATURES } ;
1919use rustc_parse:: validate_attr;
@@ -55,55 +55,37 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
5555 }
5656
5757 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- }
7158
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 ( ) ;
7861
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;
8367 for attr in krate_attrs {
8468 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;
10274 }
10375 }
10476 }
10577 }
10678
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+
10789 // Process all features declared in the code.
10890 for attr in krate_attrs {
10991 for mi in feature_list ( attr) {
@@ -128,30 +110,37 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
128110 }
129111 } ;
130112
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.
136132 // - 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) {
139135 sess. emit_warning ( FeatureIncludedInEdition {
140136 span : mi. span ( ) ,
141137 feature : name,
142- edition,
138+ edition : features_edition ,
143139 } ) ;
144140 continue ;
145141 }
146142
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.
155144 if let Some ( Feature { state, .. } ) = REMOVED_FEATURES . iter ( ) . find ( |f| name == f. name ) {
156145 if let FeatureState :: Removed { reason } = state {
157146 sess. emit_err ( FeatureRemoved {
0 commit comments