@@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
2929use rustc_hir:: def_id:: { DefId , LocalDefId , LOCAL_CRATE } ;
3030use rustc_hir:: intravisit:: { self , NestedVisitorMap , Visitor } ;
3131use rustc_hir:: weak_lang_items;
32- use rustc_hir:: { GenericParamKind , Node , Unsafety } ;
32+ use rustc_hir:: { GenericParamKind , Node } ;
3333use rustc_middle:: hir:: map:: blocks:: FnLikeNode ;
3434use rustc_middle:: hir:: map:: Map ;
3535use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
@@ -2404,13 +2404,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
24042404 codegen_fn_attrs. export_name = Some ( s) ;
24052405 }
24062406 } 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+ }
24142413 }
24152414 from_target_feature ( tcx, id, attr, & whitelist, & mut codegen_fn_attrs. target_features ) ;
24162415 } else if attr. check_name ( sym:: linkage) {
@@ -2657,3 +2656,39 @@ fn check_link_name_xor_ordinal(
26572656 tcx. sess . err ( msg) ;
26582657 }
26592658}
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