@@ -10,7 +10,7 @@ use crate::attributes::AttributeSafety;
1010use crate :: session_diagnostics:: {
1111 EmptyExportName , NakedFunctionIncompatibleAttribute , NullOnExport , NullOnObjcClass ,
1212 NullOnObjcSelector , ObjcClassExpectedStringLiteral , ObjcSelectorExpectedStringLiteral ,
13- SanitizeInvalidStatic ,
13+ SanitizeInvalidStatic , TargetFeatureOnLangItem ,
1414} ;
1515use crate :: target_checking:: Policy :: AllowSilent ;
1616
@@ -513,26 +513,22 @@ fn parse_tf_attribute(
513513 features
514514}
515515
516- pub ( crate ) struct TargetFeatureParser ;
517-
518- impl CombineAttributeParser for TargetFeatureParser {
519- type Item = ( Symbol , Span ) ;
520- const PATH : & [ Symbol ] = & [ sym:: target_feature] ;
521- const CONVERT : ConvertFn < Self :: Item > = |items, span| AttributeKind :: TargetFeature {
522- features : items,
523- attr_span : span,
524- was_forced : false ,
525- } ;
526- const TEMPLATE : AttributeTemplate = template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ;
527- const STABILITY : AttributeStability = AttributeStability :: Stable ;
528-
529- fn extend (
530- cx : & mut AcceptContext < ' _ , ' _ > ,
531- args : & ArgParser ,
532- ) -> impl IntoIterator < Item = Self :: Item > {
533- parse_tf_attribute ( cx, args)
534- }
516+ #[ derive( Default ) ]
517+ pub ( crate ) struct TargetFeatureParser {
518+ features : ThinVec < ( Symbol , Span ) > ,
519+ first_span : Option < Span > ,
520+ }
535521
522+ impl AttributeParser for TargetFeatureParser {
523+ const ATTRIBUTES : AcceptMapping < Self > = & [ (
524+ & [ sym:: target_feature] ,
525+ template ! ( List : & [ "enable = \" feat1, feat2\" " ] ) ,
526+ AttributeStability :: Stable ,
527+ |this, cx, args| {
528+ this. first_span . get_or_insert ( cx. attr_span ) ;
529+ this. features . extend ( parse_tf_attribute ( cx, args) ) ;
530+ } ,
531+ ) ] ;
536532 const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( & [
537533 Allow ( Target :: Fn ) ,
538534 Allow ( Target :: Method ( MethodKind :: Inherent ) ) ,
@@ -544,6 +540,38 @@ impl CombineAttributeParser for TargetFeatureParser {
544540 Warn ( Target :: MacroDef ) ,
545541 Warn ( Target :: MacroCall ) ,
546542 ] ) ;
543+
544+ fn finalize ( self , cx : & FinalizeContext < ' _ , ' _ > ) -> Option < AttributeKind > {
545+ let first_span = self . first_span ?;
546+
547+ // `#[target_feature]` is incompatible with lang item functions,
548+ // except on WASM where calling target-feature functions is safe (see #84988).
549+ if matches ! (
550+ cx. target,
551+ Target :: Fn | Target :: Method ( MethodKind :: Trait { body: true } | MethodKind :: Inherent )
552+ ) && !cx. sess ( ) . target . is_like_wasm
553+ && !cx. sess ( ) . opts . actually_rustdoc
554+ {
555+ // `#[panic_handler]` is checked first so it takes priority in the diagnostic.
556+ let lang_kind = cx
557+ . all_attrs
558+ . iter ( )
559+ . find_map ( |a| [ sym:: panic_handler, sym:: lang] . into_iter ( ) . find ( |& s| a. word_is ( s) ) ) ;
560+ if let Some ( kind) = lang_kind {
561+ cx. emit_err ( TargetFeatureOnLangItem {
562+ attr_span : first_span,
563+ kind,
564+ item_span : cx. target_span ,
565+ } ) ;
566+ }
567+ }
568+
569+ Some ( AttributeKind :: TargetFeature {
570+ features : self . features ,
571+ attr_span : first_span,
572+ was_forced : false ,
573+ } )
574+ }
547575}
548576
549577pub ( crate ) struct ForceTargetFeatureParser ;
0 commit comments