@@ -18,6 +18,7 @@ use rustc_session::{Session, lint};
18
18
use rustc_span:: symbol:: Ident ;
19
19
use rustc_span:: { 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,31 +523,50 @@ 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
- match attr. meta_kind ( ) {
529
- Some ( MetaItemKind :: Word ) => InlineAttr :: Hint ,
530
- Some ( MetaItemKind :: List ( ref items) ) => {
531
- inline_span = Some ( attr. span ) ;
532
- if items. len ( ) != 1 {
533
- struct_span_code_err ! ( tcx. dcx( ) , attr. span, E0534 , "expected one argument" )
534
- . emit ( ) ;
535
- InlineAttr :: None
536
- } else if list_contains_name ( items, sym:: always) {
537
- InlineAttr :: Always
538
- } else if list_contains_name ( items, sym:: never) {
539
- InlineAttr :: Never
540
- } else {
541
- struct_span_code_err ! ( tcx. dcx( ) , items[ 0 ] . span( ) , E0535 , "invalid argument" )
526
+ if attr. has_name ( sym:: inline) {
527
+ match attr. meta_kind ( ) {
528
+ Some ( MetaItemKind :: Word ) => InlineAttr :: Hint ,
529
+ Some ( MetaItemKind :: List ( ref items) ) => {
530
+ inline_span = Some ( attr. span ) ;
531
+ if items. len ( ) != 1 {
532
+ struct_span_code_err ! ( tcx. dcx( ) , attr. span, E0534 , "expected one argument" )
533
+ . 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 ! (
541
+ tcx. dcx( ) ,
542
+ items[ 0 ] . span( ) ,
543
+ E0535 ,
544
+ "invalid argument"
545
+ )
542
546
. with_help ( "valid inline arguments are `always` and `never`" )
543
547
. emit ( ) ;
544
548
545
- InlineAttr :: None
549
+ InlineAttr :: None
550
+ }
546
551
}
552
+ Some ( MetaItemKind :: NameValue ( _) ) => ia,
553
+ None => ia,
547
554
}
548
- Some ( MetaItemKind :: NameValue ( _) ) => ia,
549
- None => ia,
555
+ } else if attr. has_name ( sym:: rustc_force_inline) && tcx. features ( ) . rustc_attrs ( ) {
556
+ match attr. meta_kind ( ) {
557
+ Some ( MetaItemKind :: NameValue ( lit) ) => {
558
+ InlineAttr :: Force { attr_span : attr. span , reason : Some ( lit. symbol ) }
559
+ }
560
+ Some ( MetaItemKind :: Word ) => {
561
+ InlineAttr :: Force { attr_span : attr. span , reason : None }
562
+ }
563
+ _ => {
564
+ debug ! ( "`rustc_force_inline` not checked by attribute validation" ) ;
565
+ ia
566
+ }
567
+ }
568
+ } else {
569
+ ia
550
570
}
551
571
} ) ;
552
572
@@ -601,7 +621,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
601
621
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
602
622
if tcx. features ( ) . target_feature_11 ( )
603
623
&& tcx. is_closure_like ( did. to_def_id ( ) )
604
- && codegen_fn_attrs. inline != InlineAttr :: Always
624
+ && ! codegen_fn_attrs. inline . always ( )
605
625
{
606
626
let owner_id = tcx. parent ( did. to_def_id ( ) ) ;
607
627
if tcx. def_kind ( owner_id) . has_codegen_attrs ( ) {
@@ -611,11 +631,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
611
631
}
612
632
}
613
633
614
- // If a function uses #[target_feature] it can't be inlined into general
634
+ // If a function uses ` #[target_feature]` it can't be inlined into general
615
635
// purpose functions as they wouldn't have the right target features
616
- // enabled. For that reason we also forbid #[inline(always)] as it can't be
636
+ // enabled. For that reason we also forbid ` #[inline(always)]` as it can't be
617
637
// respected.
618
- if !codegen_fn_attrs. target_features . is_empty ( ) && codegen_fn_attrs. inline == InlineAttr :: Always
638
+ //
639
+ // `#[rustc_force_inline]` doesn't need to be prohibited here, that
640
+ // is implemented entirely in rustc can attempt to inline and error if it cannot.
641
+ if !codegen_fn_attrs. target_features . is_empty ( )
642
+ && matches ! ( codegen_fn_attrs. inline, InlineAttr :: Always )
619
643
{
620
644
if let Some ( span) = inline_span {
621
645
tcx. dcx ( ) . span_err (
@@ -626,7 +650,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
626
650
}
627
651
}
628
652
629
- if !codegen_fn_attrs. no_sanitize . is_empty ( ) && codegen_fn_attrs. inline == InlineAttr :: Always {
653
+ if !codegen_fn_attrs. no_sanitize . is_empty ( ) && codegen_fn_attrs. inline . always ( ) {
630
654
if let ( Some ( no_sanitize_span) , Some ( inline_span) ) = ( no_sanitize_span, inline_span) {
631
655
let hir_id = tcx. local_def_id_to_hir_id ( did) ;
632
656
tcx. node_span_lint (
0 commit comments