@@ -35,7 +35,7 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
3535 Some ( sym:: speed) => OptimizeAttr :: Speed ,
3636 Some ( sym:: none) => OptimizeAttr :: DoNotOptimize ,
3737 _ => {
38- cx. expected_specific_argument ( single. span ( ) , vec ! [ " size" , " speed" , " none" ] ) ;
38+ cx. expected_specific_argument ( single. span ( ) , & [ sym :: size, sym :: speed, sym :: none] ) ;
3939 OptimizeAttr :: Default
4040 }
4141 } ;
@@ -82,7 +82,7 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
8282
8383 fn convert ( cx : & mut AcceptContext < ' _ , ' _ , S > , args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
8484 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] ) ;
8686 return None ;
8787 } ;
8888
@@ -91,7 +91,8 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
9191 return None ;
9292 } ;
9393
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] ) ;
9596
9697 let Some ( arg) = arg. meta_item ( ) else {
9798 fail_incorrect_argument ( args. span ) ;
@@ -343,7 +344,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
343344 UsedBy :: Linker
344345 }
345346 _ => {
346- cx. expected_specific_argument ( l. span ( ) , vec ! [ " compiler" , " linker" ] ) ;
347+ cx. expected_specific_argument ( l. span ( ) , & [ sym :: compiler, sym :: linker] ) ;
347348 return ;
348349 }
349350 }
@@ -376,57 +377,68 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
376377 }
377378}
378379
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+
379425pub ( crate ) struct TargetFeatureParser ;
380426
381427impl < S : Stage > CombineAttributeParser < S > for TargetFeatureParser {
382428 type Item = ( Symbol , Span ) ;
383429 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+ } ;
385435 const TEMPLATE : AttributeTemplate = template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ;
386436
387437 fn extend < ' c > (
388438 cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
389439 args : & ' c ArgParser < ' _ > ,
390440 ) -> 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)
430442 }
431443
432444 const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( & [
@@ -440,3 +452,30 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
440452 Warn ( Target :: MacroDef ) ,
441453 ] ) ;
442454}
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