1- use rustc_ast:: { MetaItemInner , MetaItemKind , ast, attr} ;
1+ use rustc_ast:: { MetaItem , MetaItemInner , MetaItemKind , ast, attr} ;
22use rustc_attr:: { InlineAttr , InstructionSetAttr , OptimizeAttr , list_contains_name} ;
33use rustc_data_structures:: fx:: FxHashMap ;
44use rustc_errors:: codes:: * ;
@@ -17,7 +17,7 @@ use rustc_middle::ty::{self as ty, TyCtxt};
1717use rustc_session:: parse:: feature_err;
1818use rustc_session:: { Session , lint} ;
1919use rustc_span:: symbol:: Ident ;
20- use rustc_span:: { Span , sym} ;
20+ use rustc_span:: { Span , Symbol , sym} ;
2121use rustc_target:: spec:: { SanitizerSet , abi} ;
2222
2323use crate :: errors:: { self , MissingFeatures , TargetFeatureDisableOrEnable } ;
@@ -525,10 +525,36 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
525525 struct_span_code_err ! ( tcx. dcx( ) , attr. span, E0534 , "expected one argument" )
526526 . emit ( ) ;
527527 InlineAttr :: None
528+ } else if list_contains_name ( items, sym:: must) && tcx. features ( ) . required_inlining {
529+ parse_inline_must_required (
530+ tcx,
531+ items,
532+ attr. span ,
533+ sym:: must,
534+ |attr_span, reason| InlineAttr :: Must { attr_span, reason } ,
535+ )
536+ } else if list_contains_name ( items, sym:: required)
537+ && tcx. features ( ) . required_inlining
538+ {
539+ parse_inline_must_required (
540+ tcx,
541+ items,
542+ attr. span ,
543+ sym:: required,
544+ |attr_span, reason| InlineAttr :: Required { attr_span, reason } ,
545+ )
528546 } else if list_contains_name ( items, sym:: always) {
529547 InlineAttr :: Always
530548 } else if list_contains_name ( items, sym:: never) {
531549 InlineAttr :: Never
550+ } else if tcx. features ( ) . required_inlining {
551+ struct_span_code_err ! ( tcx. dcx( ) , items[ 0 ] . span( ) , E0535 , "invalid argument" )
552+ . with_help (
553+ "valid inline arguments are `required`, `must`, `always` and `never`" ,
554+ )
555+ . emit ( ) ;
556+
557+ InlineAttr :: None
532558 } else {
533559 struct_span_code_err ! ( tcx. dcx( ) , items[ 0 ] . span( ) , E0535 , "invalid argument" )
534560 . with_help ( "valid inline arguments are `always` and `never`" )
@@ -586,7 +612,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
586612 // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
587613 if tcx. features ( ) . target_feature_11
588614 && tcx. is_closure_like ( did. to_def_id ( ) )
589- && codegen_fn_attrs. inline != InlineAttr :: Always
615+ && ! codegen_fn_attrs. inline . always ( )
590616 {
591617 let owner_id = tcx. parent ( did. to_def_id ( ) ) ;
592618 if tcx. def_kind ( owner_id) . has_codegen_attrs ( ) {
@@ -600,8 +626,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
600626 // purpose functions as they wouldn't have the right target features
601627 // enabled. For that reason we also forbid #[inline(always)] as it can't be
602628 // respected.
603- if !codegen_fn_attrs. target_features . is_empty ( ) && codegen_fn_attrs. inline == InlineAttr :: Always
604- {
629+ if !codegen_fn_attrs. target_features . is_empty ( ) && codegen_fn_attrs. inline . always ( ) {
605630 if let Some ( span) = inline_span {
606631 tcx. dcx ( ) . span_err (
607632 span,
@@ -611,7 +636,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
611636 }
612637 }
613638
614- if !codegen_fn_attrs. no_sanitize . is_empty ( ) && codegen_fn_attrs. inline == InlineAttr :: Always {
639+ if !codegen_fn_attrs. no_sanitize . is_empty ( ) && codegen_fn_attrs. inline . always ( ) {
615640 if let ( Some ( no_sanitize_span) , Some ( inline_span) ) = ( no_sanitize_span, inline_span) {
616641 let hir_id = tcx. local_def_id_to_hir_id ( did) ;
617642 tcx. node_span_lint (
@@ -706,6 +731,37 @@ pub fn check_tied_features(
706731 None
707732}
708733
734+ fn parse_inline_must_required < ' tcx > (
735+ tcx : TyCtxt < ' tcx > ,
736+ items : & [ MetaItemInner ] ,
737+ attr_span : Span ,
738+ expected_symbol : Symbol ,
739+ create : impl Fn ( Span , Option < Symbol > ) -> InlineAttr ,
740+ ) -> InlineAttr {
741+ match items. iter ( ) . find ( |i| i. has_name ( expected_symbol) ) . expect ( "called on items w/out sym" ) {
742+ MetaItemInner :: MetaItem ( mi @ MetaItem { kind : MetaItemKind :: Word , .. } ) => {
743+ debug_assert ! ( mi. has_name( expected_symbol) ) ;
744+ create ( attr_span, None )
745+ }
746+ nested => {
747+ if let Some ( ( found_symbol, reason) ) = nested. singleton_lit_list ( )
748+ && reason. kind . is_str ( )
749+ {
750+ debug_assert_eq ! ( found_symbol, expected_symbol) ;
751+ create ( attr_span, reason. kind . str ( ) )
752+ } else {
753+ struct_span_code_err ! ( tcx. dcx( ) , attr_span, E0535 , "invalid argument" )
754+ . with_help ( format ! (
755+ "expected one string argument to `#[inline({})]`" ,
756+ expected_symbol. as_str( )
757+ ) )
758+ . emit ( ) ;
759+ create ( attr_span, None )
760+ }
761+ }
762+ }
763+ }
764+
709765/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
710766/// applied to the method prototype.
711767fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
0 commit comments