@@ -18,6 +18,7 @@ use rustc_session::parse::feature_err;
18
18
use rustc_session:: { Session , lint} ;
19
19
use rustc_span:: { Ident , Span , sym} ;
20
20
use rustc_target:: spec:: { SanitizerSet , abi} ;
21
+ use tracing:: debug;
21
22
22
23
use crate :: errors;
23
24
use crate :: target_features:: { check_target_feature_trait_unsafe, from_target_feature_attr} ;
@@ -522,26 +523,36 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
522
523
mixed_export_name_no_mangle_lint_state. lint_if_mixed ( tcx) ;
523
524
524
525
codegen_fn_attrs. inline = attrs. iter ( ) . fold ( InlineAttr :: None , |ia, attr| {
525
- if !attr. has_name ( sym:: inline) {
526
- return ia;
527
- }
528
- if attr. is_word ( ) {
529
- InlineAttr :: Hint
530
- } else if let Some ( ref items) = attr. meta_item_list ( ) {
531
- inline_span = Some ( attr. span ) ;
532
- if items. len ( ) != 1 {
533
- struct_span_code_err ! ( tcx. dcx( ) , attr. span, E0534 , "expected one argument" ) . emit ( ) ;
534
- InlineAttr :: None
535
- } else if list_contains_name ( items, sym:: always) {
536
- InlineAttr :: Always
537
- } else if list_contains_name ( items, sym:: never) {
538
- InlineAttr :: Never
539
- } else {
540
- struct_span_code_err ! ( tcx. dcx( ) , items[ 0 ] . span( ) , E0535 , "invalid argument" )
541
- . with_help ( "valid inline arguments are `always` and `never`" )
542
- . emit ( ) ;
526
+ if attr. has_name ( sym:: inline) {
527
+ if attr. is_word ( ) {
528
+ InlineAttr :: Hint
529
+ } else if let Some ( ref items) = attr. meta_item_list ( ) {
530
+ inline_span = Some ( attr. span ) ;
531
+ if items. len ( ) != 1 {
532
+ struct_span_code_err ! ( tcx. dcx( ) , attr. span, E0534 , "expected one argument" ) . emit ( ) ;
533
+ InlineAttr :: None
534
+ } else if list_contains_name ( items, sym:: always) {
535
+ InlineAttr :: Always
536
+ } else if list_contains_name ( items, sym:: never) {
537
+ InlineAttr :: Never
538
+ } else {
539
+ struct_span_code_err ! ( tcx. dcx( ) , items[ 0 ] . span( ) , E0535 , "invalid argument" )
540
+ . with_help ( "valid inline arguments are `always` and `never`" )
541
+ . emit ( ) ;
543
542
544
- InlineAttr :: None
543
+ InlineAttr :: None
544
+ }
545
+ } else {
546
+ ia
547
+ }
548
+ } else if attr. has_name ( sym:: rustc_force_inline) && tcx. features ( ) . rustc_attrs ( ) {
549
+ if attr. is_word ( ) {
550
+ InlineAttr :: Force { attr_span : attr. span , reason : None }
551
+ } else if let Some ( val) = attr. value_str ( ) {
552
+ InlineAttr :: Force { attr_span : attr. span , reason : Some ( val) }
553
+ } else {
554
+ debug ! ( "`rustc_force_inline` not checked by attribute validation" ) ;
555
+ ia
545
556
}
546
557
} else {
547
558
ia
@@ -596,7 +607,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
596
607
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
597
608
if tcx. features ( ) . target_feature_11 ( )
598
609
&& tcx. is_closure_like ( did. to_def_id ( ) )
599
- && codegen_fn_attrs. inline != InlineAttr :: Always
610
+ && ! codegen_fn_attrs. inline . always ( )
600
611
{
601
612
let owner_id = tcx. parent ( did. to_def_id ( ) ) ;
602
613
if tcx. def_kind ( owner_id) . has_codegen_attrs ( ) {
@@ -606,11 +617,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
606
617
}
607
618
}
608
619
609
- // If a function uses #[target_feature] it can't be inlined into general
620
+ // If a function uses ` #[target_feature]` it can't be inlined into general
610
621
// purpose functions as they wouldn't have the right target features
611
- // enabled. For that reason we also forbid #[inline(always)] as it can't be
622
+ // enabled. For that reason we also forbid ` #[inline(always)]` as it can't be
612
623
// respected.
613
- if !codegen_fn_attrs. target_features . is_empty ( ) && codegen_fn_attrs. inline == InlineAttr :: Always
624
+ //
625
+ // `#[rustc_force_inline]` doesn't need to be prohibited here, that
626
+ // is implemented entirely in rustc can attempt to inline and error if it cannot.
627
+ if !codegen_fn_attrs. target_features . is_empty ( )
628
+ && matches ! ( codegen_fn_attrs. inline, InlineAttr :: Always )
614
629
{
615
630
if let Some ( span) = inline_span {
616
631
tcx. dcx ( ) . span_err (
@@ -621,7 +636,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
621
636
}
622
637
}
623
638
624
- 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 ( ) {
625
640
if let ( Some ( no_sanitize_span) , Some ( inline_span) ) = ( no_sanitize_span, inline_span) {
626
641
let hir_id = tcx. local_def_id_to_hir_id ( did) ;
627
642
tcx. node_span_lint (
0 commit comments