@@ -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 } ;
@@ -2413,13 +2413,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
2413
2413
codegen_fn_attrs. export_name = Some ( s) ;
2414
2414
}
2415
2415
} else if attr. check_name ( sym:: target_feature) {
2416
- if tcx. is_closure ( id) || tcx. fn_sig ( id) . unsafety ( ) == Unsafety :: Normal {
2417
- let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions" ;
2418
- tcx. sess
2419
- . struct_span_err ( attr. span , msg)
2420
- . span_label ( attr. span , "can only be applied to `unsafe` functions" )
2421
- . span_label ( tcx. def_span ( id) , "not an `unsafe` function" )
2422
- . emit ( ) ;
2416
+ if !tcx. features ( ) . target_feature_11 {
2417
+ check_target_feature_safe_fn ( tcx, id, attr. span ) ;
2418
+ } else if let Some ( local_id) = id. as_local ( ) {
2419
+ if tcx. fn_sig ( id) . unsafety ( ) == hir:: Unsafety :: Normal {
2420
+ check_target_feature_trait_unsafe ( tcx, local_id, attr. span ) ;
2421
+ }
2423
2422
}
2424
2423
from_target_feature ( tcx, id, attr, & whitelist, & mut codegen_fn_attrs. target_features ) ;
2425
2424
} else if attr. check_name ( sym:: linkage) {
@@ -2666,3 +2665,39 @@ fn check_link_name_xor_ordinal(
2666
2665
tcx. sess . err ( msg) ;
2667
2666
}
2668
2667
}
2668
+
2669
+ /// Checks the function annotated with `#[target_feature]` is unsafe,
2670
+ /// reporting an error if it isn't.
2671
+ fn check_target_feature_safe_fn ( tcx : TyCtxt < ' _ > , id : DefId , attr_span : Span ) {
2672
+ if tcx. is_closure ( id) || tcx. fn_sig ( id) . unsafety ( ) == hir:: Unsafety :: Normal {
2673
+ let mut err = feature_err (
2674
+ & tcx. sess . parse_sess ,
2675
+ sym:: target_feature_11,
2676
+ attr_span,
2677
+ "`#[target_feature(..)]` can only be applied to `unsafe` functions" ,
2678
+ ) ;
2679
+ err. span_label ( tcx. def_span ( id) , "not an `unsafe` function" ) ;
2680
+ err. emit ( ) ;
2681
+ }
2682
+ }
2683
+
2684
+ /// Checks the function annotated with `#[target_feature]` is not a safe
2685
+ /// trait method implementation, reporting an error if it is.
2686
+ fn check_target_feature_trait_unsafe ( tcx : TyCtxt < ' _ > , id : LocalDefId , attr_span : Span ) {
2687
+ let hir_id = tcx. hir ( ) . as_local_hir_id ( id) ;
2688
+ let node = tcx. hir ( ) . get ( hir_id) ;
2689
+ if let Node :: ImplItem ( hir:: ImplItem { kind : hir:: ImplItemKind :: Fn ( ..) , .. } ) = node {
2690
+ let parent_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
2691
+ let parent_item = tcx. hir ( ) . expect_item ( parent_id) ;
2692
+ if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = parent_item. kind {
2693
+ tcx. sess
2694
+ . struct_span_err (
2695
+ attr_span,
2696
+ "`#[target_feature(..)]` cannot be applied to safe trait method" ,
2697
+ )
2698
+ . span_label ( attr_span, "cannot be applied to safe trait method" )
2699
+ . span_label ( tcx. def_span ( id) , "not an `unsafe` function" )
2700
+ . emit ( ) ;
2701
+ }
2702
+ }
2703
+ }
0 commit comments