1
- use rustc_ast:: { MetaItemInner , MetaItemKind , ast, attr} ;
1
+ use rustc_ast:: { MetaItem , MetaItemInner , MetaItemKind , ast, attr} ;
2
2
use rustc_attr:: { InlineAttr , InstructionSetAttr , OptimizeAttr , list_contains_name} ;
3
3
use rustc_data_structures:: fx:: FxHashMap ;
4
4
use rustc_errors:: codes:: * ;
@@ -17,7 +17,7 @@ use rustc_middle::ty::{self as ty, TyCtxt};
17
17
use rustc_session:: parse:: feature_err;
18
18
use rustc_session:: { Session , lint} ;
19
19
use rustc_span:: symbol:: Ident ;
20
- use rustc_span:: { Span , sym} ;
20
+ use rustc_span:: { Span , Symbol , sym} ;
21
21
use rustc_target:: spec:: { SanitizerSet , abi} ;
22
22
23
23
use crate :: errors:: { self , MissingFeatures , TargetFeatureDisableOrEnable } ;
@@ -525,10 +525,36 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
525
525
struct_span_code_err ! ( tcx. dcx( ) , attr. span, E0534 , "expected one argument" )
526
526
. emit ( ) ;
527
527
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
+ )
528
546
} else if list_contains_name ( items, sym:: always) {
529
547
InlineAttr :: Always
530
548
} else if list_contains_name ( items, sym:: never) {
531
549
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
532
558
} else {
533
559
struct_span_code_err ! ( tcx. dcx( ) , items[ 0 ] . span( ) , E0535 , "invalid argument" )
534
560
. with_help ( "valid inline arguments are `always` and `never`" )
@@ -586,7 +612,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
586
612
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
587
613
if tcx. features ( ) . target_feature_11
588
614
&& tcx. is_closure_like ( did. to_def_id ( ) )
589
- && codegen_fn_attrs. inline != InlineAttr :: Always
615
+ && ! codegen_fn_attrs. inline . always ( )
590
616
{
591
617
let owner_id = tcx. parent ( did. to_def_id ( ) ) ;
592
618
if tcx. def_kind ( owner_id) . has_codegen_attrs ( ) {
@@ -600,8 +626,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
600
626
// purpose functions as they wouldn't have the right target features
601
627
// enabled. For that reason we also forbid #[inline(always)] as it can't be
602
628
// 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 ( ) {
605
630
if let Some ( span) = inline_span {
606
631
tcx. dcx ( ) . span_err (
607
632
span,
@@ -611,7 +636,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
611
636
}
612
637
}
613
638
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 ( ) {
615
640
if let ( Some ( no_sanitize_span) , Some ( inline_span) ) = ( no_sanitize_span, inline_span) {
616
641
let hir_id = tcx. local_def_id_to_hir_id ( did) ;
617
642
tcx. node_span_lint (
@@ -706,6 +731,37 @@ pub fn check_tied_features(
706
731
None
707
732
}
708
733
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
+
709
765
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
710
766
/// applied to the method prototype.
711
767
fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
0 commit comments