@@ -3,7 +3,7 @@ use std::num::IntErrorKind;
3
3
use rustc_hir:: limit:: Limit ;
4
4
5
5
use super :: prelude:: * ;
6
- use crate :: session_diagnostics:: LimitInvalid ;
6
+ use crate :: session_diagnostics:: { FeatureExpectedSingleWord , LimitInvalid } ;
7
7
8
8
impl < S : Stage > AcceptContext < ' _ , ' _ , S > {
9
9
fn parse_limit_int ( & self , nv : & NameValueParser ) -> Option < Limit > {
@@ -183,3 +183,55 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
183
183
const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: CrateLevel ;
184
184
const CREATE : fn ( Span ) -> AttributeKind = AttributeKind :: RustcCoherenceIsCore ;
185
185
}
186
+
187
+ pub ( crate ) struct FeatureParser ;
188
+
189
+ impl < S : Stage > CombineAttributeParser < S > for FeatureParser {
190
+ const PATH : & [ Symbol ] = & [ sym:: feature] ;
191
+ type Item = Ident ;
192
+ const CONVERT : ConvertFn < Self :: Item > = AttributeKind :: Feature ;
193
+ const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: CrateLevel ;
194
+ const TEMPLATE : AttributeTemplate = template ! ( List : & [ "feature1, feature2, ..." ] ) ;
195
+
196
+ fn extend < ' c > (
197
+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
198
+ args : & ' c ArgParser < ' _ > ,
199
+ ) -> impl IntoIterator < Item = Self :: Item > + ' c {
200
+ let ArgParser :: List ( list) = args else {
201
+ cx. expected_list ( cx. attr_span ) ;
202
+ return Vec :: new ( ) ;
203
+ } ;
204
+
205
+ if list. is_empty ( ) {
206
+ cx. warn_empty_attribute ( cx. attr_span ) ;
207
+ }
208
+
209
+ let mut res = Vec :: new ( ) ;
210
+
211
+ for elem in list. mixed ( ) {
212
+ let Some ( elem) = elem. meta_item ( ) else {
213
+ cx. expected_identifier ( elem. span ( ) ) ;
214
+ continue ;
215
+ } ;
216
+ if let Err ( arg_span) = elem. args ( ) . no_args ( ) {
217
+ cx. expected_no_args ( arg_span) ;
218
+ continue ;
219
+ }
220
+
221
+ let path = elem. path ( ) ;
222
+ let Some ( ident) = path. word ( ) else {
223
+ let first_segment = elem. path ( ) . segments ( ) . next ( ) . expect ( "at least one segment" ) ;
224
+ cx. emit_err ( FeatureExpectedSingleWord {
225
+ span : path. span ( ) ,
226
+ first_segment_span : first_segment. span ,
227
+ first_segment : first_segment. name ,
228
+ } ) ;
229
+ continue ;
230
+ } ;
231
+
232
+ res. push ( ident) ;
233
+ }
234
+
235
+ res
236
+ }
237
+ }
0 commit comments