@@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
29
29
use rustc_hir:: def_id:: { DefId , LocalDefId , LOCAL_CRATE } ;
30
30
use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
31
31
use rustc_hir:: weak_lang_items;
32
- use rustc_hir:: { GenericParamKind , Node , Unsafety } ;
32
+ use rustc_hir:: { GenericParamKind , Node } ;
33
33
use rustc_middle:: hir:: map:: blocks:: FnLikeNode ;
34
34
use rustc_middle:: hir:: map:: Map ;
35
35
use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
@@ -2404,13 +2404,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2404
2404
codegen_fn_attrs. export_name = Some ( s) ;
2405
2405
}
2406
2406
} else if attr. check_name ( sym:: target_feature) {
2407
- if tcx. is_closure ( id) || tcx. fn_sig ( id) . unsafety ( ) == Unsafety :: Normal {
2408
- let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions" ;
2409
- tcx. sess
2410
- . struct_span_err ( attr. span , msg)
2411
- . span_label ( attr. span , "can only be applied to `unsafe` functions" )
2412
- . span_label ( tcx. def_span ( id) , "not an `unsafe` function" )
2413
- . emit ( ) ;
2407
+ if !tcx. features ( ) . target_feature_11 {
2408
+ check_target_feature_safe_fn ( tcx, id, attr. span ) ;
2409
+ } else if let Some ( local_id) = id. as_local ( ) {
2410
+ if tcx. fn_sig ( id) . unsafety ( ) == hir:: Unsafety :: Normal {
2411
+ check_target_feature_trait_unsafe ( tcx, local_id, attr. span ) ;
2412
+ }
2414
2413
}
2415
2414
from_target_feature ( tcx, id, attr, & whitelist, & mut codegen_fn_attrs. target_features ) ;
2416
2415
} else if attr. check_name ( sym:: linkage) {
@@ -2657,3 +2656,39 @@ fn check_link_name_xor_ordinal(
2657
2656
tcx. sess . err ( msg) ;
2658
2657
}
2659
2658
}
2659
+
2660
+ /// Checks the function annotated with `#[target_feature]` is unsafe,
2661
+ /// reporting an error if it isn't.
2662
+ fn check_target_feature_safe_fn ( tcx : TyCtxt < ' _ > , id : DefId , attr_span : Span ) {
2663
+ if tcx. is_closure ( id) || tcx. fn_sig ( id) . unsafety ( ) == hir:: Unsafety :: Normal {
2664
+ let mut err = feature_err (
2665
+ & tcx. sess . parse_sess ,
2666
+ sym:: target_feature_11,
2667
+ attr_span,
2668
+ "`#[target_feature(..)]` can only be applied to `unsafe` functions" ,
2669
+ ) ;
2670
+ err. span_label ( tcx. def_span ( id) , "not an `unsafe` function" ) ;
2671
+ err. emit ( ) ;
2672
+ }
2673
+ }
2674
+
2675
+ /// Checks the function annotated with `#[target_feature]` is not a safe
2676
+ /// trait method implementation, reporting an error if it is.
2677
+ fn check_target_feature_trait_unsafe ( tcx : TyCtxt < ' _ > , id : LocalDefId , attr_span : Span ) {
2678
+ let hir_id = tcx. hir ( ) . as_local_hir_id ( id) ;
2679
+ let node = tcx. hir ( ) . get ( hir_id) ;
2680
+ if let Node :: ImplItem ( hir:: ImplItem { kind : hir:: ImplItemKind :: Fn ( ..) , .. } ) = node {
2681
+ let parent_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
2682
+ let parent_item = tcx. hir ( ) . expect_item ( parent_id) ;
2683
+ if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = parent_item. kind {
2684
+ tcx. sess
2685
+ . struct_span_err (
2686
+ attr_span,
2687
+ "`#[target_feature(..)]` cannot be applied to safe trait method" ,
2688
+ )
2689
+ . span_label ( attr_span, "cannot be applied to safe trait method" )
2690
+ . span_label ( tcx. def_span ( id) , "not an `unsafe` function" )
2691
+ . emit ( ) ;
2692
+ }
2693
+ }
2694
+ }
0 commit comments