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