@@ -19,6 +19,7 @@ use rustc_session::{Session, lint};
1919use  rustc_span:: symbol:: Ident ; 
2020use  rustc_span:: { Span ,  sym} ; 
2121use  rustc_target:: spec:: { SanitizerSet ,  abi} ; 
22+ use  tracing:: debug; 
2223
2324use  crate :: errors; 
2425use  crate :: target_features:: { check_target_feature_trait_unsafe,  from_target_feature_attr} ; 
@@ -514,31 +515,50 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
514515    } 
515516
516517    codegen_fn_attrs. inline  = attrs. iter ( ) . fold ( InlineAttr :: None ,  |ia,  attr| { 
517-         if  !attr. has_name ( sym:: inline)  { 
518-             return  ia; 
519-         } 
520-         match  attr. meta_kind ( )  { 
521-             Some ( MetaItemKind :: Word )  => InlineAttr :: Hint , 
522-             Some ( MetaItemKind :: List ( ref  items) )  => { 
523-                 inline_span = Some ( attr. span ) ; 
524-                 if  items. len ( )  != 1  { 
525-                     struct_span_code_err ! ( tcx. dcx( ) ,  attr. span,  E0534 ,  "expected one argument" ) 
526-                         . emit ( ) ; 
527-                     InlineAttr :: None 
528-                 }  else  if  list_contains_name ( items,  sym:: always)  { 
529-                     InlineAttr :: Always 
530-                 }  else  if  list_contains_name ( items,  sym:: never)  { 
531-                     InlineAttr :: Never 
532-                 }  else  { 
533-                     struct_span_code_err ! ( tcx. dcx( ) ,  items[ 0 ] . span( ) ,  E0535 ,  "invalid argument" ) 
518+         if  attr. has_name ( sym:: inline)  { 
519+             match  attr. meta_kind ( )  { 
520+                 Some ( MetaItemKind :: Word )  => InlineAttr :: Hint , 
521+                 Some ( MetaItemKind :: List ( ref  items) )  => { 
522+                     inline_span = Some ( attr. span ) ; 
523+                     if  items. len ( )  != 1  { 
524+                         struct_span_code_err ! ( tcx. dcx( ) ,  attr. span,  E0534 ,  "expected one argument" ) 
525+                             . emit ( ) ; 
526+                         InlineAttr :: None 
527+                     }  else  if  list_contains_name ( items,  sym:: always)  { 
528+                         InlineAttr :: Always 
529+                     }  else  if  list_contains_name ( items,  sym:: never)  { 
530+                         InlineAttr :: Never 
531+                     }  else  { 
532+                         struct_span_code_err ! ( 
533+                             tcx. dcx( ) , 
534+                             items[ 0 ] . span( ) , 
535+                             E0535 , 
536+                             "invalid argument" 
537+                         ) 
534538                        . with_help ( "valid inline arguments are `always` and `never`" ) 
535539                        . emit ( ) ; 
536540
537-                     InlineAttr :: None 
541+                         InlineAttr :: None 
542+                     } 
538543                } 
544+                 Some ( MetaItemKind :: NameValue ( _) )  => ia, 
545+                 None  => ia, 
539546            } 
540-             Some ( MetaItemKind :: NameValue ( _) )  => ia, 
541-             None  => ia, 
547+         }  else  if  attr. has_name ( sym:: rustc_force_inline)  && tcx. features ( ) . rustc_attrs ( )  { 
548+             match  attr. meta_kind ( )  { 
549+                 Some ( MetaItemKind :: NameValue ( lit) )  => { 
550+                     InlineAttr :: Force  {  attr_span :  attr. span ,  reason :  Some ( lit. symbol )  } 
551+                 } 
552+                 Some ( MetaItemKind :: Word )  => { 
553+                     InlineAttr :: Force  {  attr_span :  attr. span ,  reason :  None  } 
554+                 } 
555+                 _ => { 
556+                     debug ! ( "`rustc_force_inline` not checked by attribute validation" ) ; 
557+                     ia
558+                 } 
559+             } 
560+         }  else  { 
561+             ia
542562        } 
543563    } ) ; 
544564
@@ -586,7 +606,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
586606    // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute. 
587607    if  tcx. features ( ) . target_feature_11 ( ) 
588608        && tcx. is_closure_like ( did. to_def_id ( ) ) 
589-         && codegen_fn_attrs. inline  !=  InlineAttr :: Always 
609+         && ! codegen_fn_attrs. inline . always ( ) 
590610    { 
591611        let  owner_id = tcx. parent ( did. to_def_id ( ) ) ; 
592612        if  tcx. def_kind ( owner_id) . has_codegen_attrs ( )  { 
@@ -596,11 +616,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
596616        } 
597617    } 
598618
599-     // If a function uses #[target_feature] it can't be inlined into general 
619+     // If a function uses ` #[target_feature]`  it can't be inlined into general 
600620    // purpose functions as they wouldn't have the right target features 
601-     // enabled. For that reason we also forbid #[inline(always)] as it can't be 
621+     // enabled. For that reason we also forbid ` #[inline(always)]`  as it can't be 
602622    // respected. 
603-     if  !codegen_fn_attrs. target_features . is_empty ( )  && codegen_fn_attrs. inline  == InlineAttr :: Always 
623+     // 
624+     // `#[rustc_force_inline]` doesn't need to be prohibited here, that 
625+     // is implemented entirely in rustc can attempt to inline and error if it cannot. 
626+     if  !codegen_fn_attrs. target_features . is_empty ( ) 
627+         && matches ! ( codegen_fn_attrs. inline,  InlineAttr :: Always ) 
604628    { 
605629        if  let  Some ( span)  = inline_span { 
606630            tcx. dcx ( ) . span_err ( 
@@ -611,7 +635,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
611635        } 
612636    } 
613637
614-     if  !codegen_fn_attrs. no_sanitize . is_empty ( )  && codegen_fn_attrs. inline  ==  InlineAttr :: Always  { 
638+     if  !codegen_fn_attrs. no_sanitize . is_empty ( )  && codegen_fn_attrs. inline . always ( )  { 
615639        if  let  ( Some ( no_sanitize_span) ,  Some ( inline_span) )  = ( no_sanitize_span,  inline_span)  { 
616640            let  hir_id = tcx. local_def_id_to_hir_id ( did) ; 
617641            tcx. node_span_lint ( 
0 commit comments