@@ -35,7 +35,7 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
35
35
Some ( sym:: speed) => OptimizeAttr :: Speed ,
36
36
Some ( sym:: none) => OptimizeAttr :: DoNotOptimize ,
37
37
_ => {
38
- cx. expected_specific_argument ( single. span ( ) , vec ! [ " size" , " speed" , " none" ] ) ;
38
+ cx. expected_specific_argument ( single. span ( ) , & [ sym :: size, sym :: speed, sym :: none] ) ;
39
39
OptimizeAttr :: Default
40
40
}
41
41
} ;
@@ -82,7 +82,7 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
82
82
83
83
fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
84
84
let Some ( args) = args. list ( ) else {
85
- cx. expected_specific_argument_and_list ( cx. attr_span , vec ! [ "on" , " off" ] ) ;
85
+ cx. expected_specific_argument_and_list ( cx. attr_span , & [ sym :: on , sym :: off] ) ;
86
86
return None ;
87
87
} ;
88
88
@@ -91,7 +91,8 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
91
91
return None ;
92
92
} ;
93
93
94
- let fail_incorrect_argument = |span| cx. expected_specific_argument ( span, vec ! [ "on" , "off" ] ) ;
94
+ let fail_incorrect_argument =
95
+ |span| cx. expected_specific_argument ( span, & [ sym:: on, sym:: off] ) ;
95
96
96
97
let Some ( arg) = arg. meta_item ( ) else {
97
98
fail_incorrect_argument ( args. span ) ;
@@ -343,7 +344,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
343
344
UsedBy :: Linker
344
345
}
345
346
_ => {
346
- cx. expected_specific_argument ( l. span ( ) , vec ! [ " compiler" , " linker" ] ) ;
347
+ cx. expected_specific_argument ( l. span ( ) , & [ sym :: compiler, sym :: linker] ) ;
347
348
return ;
348
349
}
349
350
}
@@ -376,57 +377,68 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
376
377
}
377
378
}
378
379
380
+ fn parse_tf_attribute < ' c , S : Stage > (
381
+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
382
+ args : & ' c ArgParser < ' _ > ,
383
+ ) -> impl IntoIterator < Item = ( Symbol , Span ) > + ' c {
384
+ let mut features = Vec :: new ( ) ;
385
+ let ArgParser :: List ( list) = args else {
386
+ cx. expected_list ( cx. attr_span ) ;
387
+ return features;
388
+ } ;
389
+ if list. is_empty ( ) {
390
+ cx. warn_empty_attribute ( cx. attr_span ) ;
391
+ return features;
392
+ }
393
+ for item in list. mixed ( ) {
394
+ let Some ( name_value) = item. meta_item ( ) else {
395
+ cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
396
+ return features;
397
+ } ;
398
+
399
+ // Validate name
400
+ let Some ( name) = name_value. path ( ) . word_sym ( ) else {
401
+ cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
402
+ return features;
403
+ } ;
404
+ if name != sym:: enable {
405
+ cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
406
+ return features;
407
+ }
408
+
409
+ // Use value
410
+ let Some ( name_value) = name_value. args ( ) . name_value ( ) else {
411
+ cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
412
+ return features;
413
+ } ;
414
+ let Some ( value_str) = name_value. value_as_str ( ) else {
415
+ cx. expected_string_literal ( name_value. value_span , Some ( name_value. value_as_lit ( ) ) ) ;
416
+ return features;
417
+ } ;
418
+ for feature in value_str. as_str ( ) . split ( "," ) {
419
+ features. push ( ( Symbol :: intern ( feature) , item. span ( ) ) ) ;
420
+ }
421
+ }
422
+ features
423
+ }
424
+
379
425
pub ( crate ) struct TargetFeatureParser ;
380
426
381
427
impl < S : Stage > CombineAttributeParser < S > for TargetFeatureParser {
382
428
type Item = ( Symbol , Span ) ;
383
429
const PATH : & [ Symbol ] = & [ sym:: target_feature] ;
384
- const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature ( items, span) ;
430
+ const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature {
431
+ features : items,
432
+ attr_span : span,
433
+ was_forced : false ,
434
+ } ;
385
435
const TEMPLATE : AttributeTemplate = template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ;
386
436
387
437
fn extend < ' c > (
388
438
cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
389
439
args : & ' c ArgParser < ' _ > ,
390
440
) -> impl IntoIterator < Item = Self :: Item > + ' c {
391
- let mut features = Vec :: new ( ) ;
392
- let ArgParser :: List ( list) = args else {
393
- cx. expected_list ( cx. attr_span ) ;
394
- return features;
395
- } ;
396
- if list. is_empty ( ) {
397
- cx. warn_empty_attribute ( cx. attr_span ) ;
398
- return features;
399
- }
400
- for item in list. mixed ( ) {
401
- let Some ( name_value) = item. meta_item ( ) else {
402
- cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
403
- return features;
404
- } ;
405
-
406
- // Validate name
407
- let Some ( name) = name_value. path ( ) . word_sym ( ) else {
408
- cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
409
- return features;
410
- } ;
411
- if name != sym:: enable {
412
- cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
413
- return features;
414
- }
415
-
416
- // Use value
417
- let Some ( name_value) = name_value. args ( ) . name_value ( ) else {
418
- cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
419
- return features;
420
- } ;
421
- let Some ( value_str) = name_value. value_as_str ( ) else {
422
- cx. expected_string_literal ( name_value. value_span , Some ( name_value. value_as_lit ( ) ) ) ;
423
- return features;
424
- } ;
425
- for feature in value_str. as_str ( ) . split ( "," ) {
426
- features. push ( ( Symbol :: intern ( feature) , item. span ( ) ) ) ;
427
- }
428
- }
429
- features
441
+ parse_tf_attribute ( cx, args)
430
442
}
431
443
432
444
const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( & [
@@ -440,3 +452,30 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
440
452
Warn ( Target :: MacroDef ) ,
441
453
] ) ;
442
454
}
455
+
456
+ pub ( crate ) struct ForceTargetFeatureParser ;
457
+
458
+ impl < S : Stage > CombineAttributeParser < S > for ForceTargetFeatureParser {
459
+ type Item = ( Symbol , Span ) ;
460
+ const PATH : & [ Symbol ] = & [ sym:: force_target_feature] ;
461
+ const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature {
462
+ features : items,
463
+ attr_span : span,
464
+ was_forced : true ,
465
+ } ;
466
+ const TEMPLATE : AttributeTemplate = template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ;
467
+
468
+ fn extend < ' c > (
469
+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
470
+ args : & ' c ArgParser < ' _ > ,
471
+ ) -> impl IntoIterator < Item = Self :: Item > + ' c {
472
+ parse_tf_attribute ( cx, args)
473
+ }
474
+
475
+ const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( & [
476
+ Allow ( Target :: Fn ) ,
477
+ Allow ( Target :: Method ( MethodKind :: Inherent ) ) ,
478
+ Allow ( Target :: Method ( MethodKind :: Trait { body : true } ) ) ,
479
+ Allow ( Target :: Method ( MethodKind :: TraitImpl ) ) ,
480
+ ] ) ;
481
+ }
0 commit comments