@@ -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 } ;
@@ -2413,13 +2413,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
24132413 codegen_fn_attrs. export_name = Some ( s) ;
24142414 }
24152415 } 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+ }
24232422 }
24242423 from_target_feature ( tcx, id, attr, & whitelist, & mut codegen_fn_attrs. target_features ) ;
24252424 } else if attr. check_name ( sym:: linkage) {
@@ -2666,3 +2665,39 @@ fn check_link_name_xor_ordinal(
26662665 tcx. sess . err ( msg) ;
26672666 }
26682667}
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