@@ -385,57 +385,68 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
385
385
}
386
386
}
387
387
388
+ fn parse_tf_attribute < ' c , S : Stage > (
389
+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
390
+ args : & ' c ArgParser < ' _ > ,
391
+ ) -> impl IntoIterator < Item = ( Symbol , Span ) > + ' c {
392
+ let mut features = Vec :: new ( ) ;
393
+ let ArgParser :: List ( list) = args else {
394
+ cx. expected_list ( cx. attr_span ) ;
395
+ return features;
396
+ } ;
397
+ if list. is_empty ( ) {
398
+ cx. warn_empty_attribute ( cx. attr_span ) ;
399
+ return features;
400
+ }
401
+ for item in list. mixed ( ) {
402
+ let Some ( name_value) = item. meta_item ( ) else {
403
+ cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
404
+ return features;
405
+ } ;
406
+
407
+ // Validate name
408
+ let Some ( name) = name_value. path ( ) . word_sym ( ) else {
409
+ cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
410
+ return features;
411
+ } ;
412
+ if name != sym:: enable {
413
+ cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
414
+ return features;
415
+ }
416
+
417
+ // Use value
418
+ let Some ( name_value) = name_value. args ( ) . name_value ( ) else {
419
+ cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
420
+ return features;
421
+ } ;
422
+ let Some ( value_str) = name_value. value_as_str ( ) else {
423
+ cx. expected_string_literal ( name_value. value_span , Some ( name_value. value_as_lit ( ) ) ) ;
424
+ return features;
425
+ } ;
426
+ for feature in value_str. as_str ( ) . split ( "," ) {
427
+ features. push ( ( Symbol :: intern ( feature) , item. span ( ) ) ) ;
428
+ }
429
+ }
430
+ features
431
+ }
432
+
388
433
pub ( crate ) struct TargetFeatureParser ;
389
434
390
435
impl < S : Stage > CombineAttributeParser < S > for TargetFeatureParser {
391
436
type Item = ( Symbol , Span ) ;
392
437
const PATH : & [ Symbol ] = & [ sym:: target_feature] ;
393
- const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature ( items, span) ;
438
+ const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature {
439
+ features : items,
440
+ attr_span : span,
441
+ was_forced : false ,
442
+ } ;
394
443
const TEMPLATE : AttributeTemplate = template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ;
395
444
396
445
fn extend < ' c > (
397
446
cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
398
447
args : & ' c ArgParser < ' _ > ,
399
448
) -> impl IntoIterator < Item = Self :: Item > + ' c {
400
- let mut features = Vec :: new ( ) ;
401
- let ArgParser :: List ( list) = args else {
402
- cx. expected_list ( cx. attr_span ) ;
403
- return features;
404
- } ;
405
- if list. is_empty ( ) {
406
- cx. warn_empty_attribute ( cx. attr_span ) ;
407
- return features;
408
- }
409
- for item in list. mixed ( ) {
410
- let Some ( name_value) = item. meta_item ( ) else {
411
- cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
412
- return features;
413
- } ;
414
-
415
- // Validate name
416
- let Some ( name) = name_value. path ( ) . word_sym ( ) else {
417
- cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
418
- return features;
419
- } ;
420
- if name != sym:: enable {
421
- cx. expected_name_value ( name_value. path ( ) . span ( ) , Some ( sym:: enable) ) ;
422
- return features;
423
- }
424
-
425
- // Use value
426
- let Some ( name_value) = name_value. args ( ) . name_value ( ) else {
427
- cx. expected_name_value ( item. span ( ) , Some ( sym:: enable) ) ;
428
- return features;
429
- } ;
430
- let Some ( value_str) = name_value. value_as_str ( ) else {
431
- cx. expected_string_literal ( name_value. value_span , Some ( name_value. value_as_lit ( ) ) ) ;
432
- return features;
433
- } ;
434
- for feature in value_str. as_str ( ) . split ( "," ) {
435
- features. push ( ( Symbol :: intern ( feature) , item. span ( ) ) ) ;
436
- }
437
- }
438
- features
449
+ parse_tf_attribute ( cx, args)
439
450
}
440
451
441
452
const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( & [
@@ -449,3 +460,30 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
449
460
Warn ( Target :: MacroDef ) ,
450
461
] ) ;
451
462
}
463
+
464
+ pub ( crate ) struct ForceTargetFeatureParser ;
465
+
466
+ impl < S : Stage > CombineAttributeParser < S > for ForceTargetFeatureParser {
467
+ type Item = ( Symbol , Span ) ;
468
+ const PATH : & [ Symbol ] = & [ sym:: force_target_feature] ;
469
+ const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature {
470
+ features : items,
471
+ attr_span : span,
472
+ was_forced : true ,
473
+ } ;
474
+ const TEMPLATE : AttributeTemplate = template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ;
475
+
476
+ fn extend < ' c > (
477
+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
478
+ args : & ' c ArgParser < ' _ > ,
479
+ ) -> impl IntoIterator < Item = Self :: Item > + ' c {
480
+ parse_tf_attribute ( cx, args)
481
+ }
482
+
483
+ const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( & [
484
+ Allow ( Target :: Fn ) ,
485
+ Allow ( Target :: Method ( MethodKind :: Inherent ) ) ,
486
+ Allow ( Target :: Method ( MethodKind :: Trait { body : true } ) ) ,
487
+ Allow ( Target :: Method ( MethodKind :: TraitImpl ) ) ,
488
+ ] ) ;
489
+ }
0 commit comments