Skip to content

Commit 2474f0e

Browse files
Allow #[target_feature] on safe functions
1 parent eece58a commit 2474f0e

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

src/librustc_feature/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@ declare_features! (
559559
/// Allow negative trait implementations.
560560
(active, negative_impls, "1.44.0", Some(68318), None),
561561

562+
/// Allows the use of `#[target_feature]` on safe functions.
563+
(active, target_feature_11, "1.45.0", Some(69098), None),
564+
562565
// -------------------------------------------------------------------------
563566
// feature-group-end: actual feature gates
564567
// -------------------------------------------------------------------------

src/librustc_span/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ symbols! {
722722
suggestion,
723723
sync_trait,
724724
target_feature,
725+
target_feature_11,
725726
target_has_atomic,
726727
target_has_atomic_load_store,
727728
target_thread_local,

src/librustc_typeck/collect.rs

+43-8
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
2929
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
3030
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
3131
use rustc_hir::weak_lang_items;
32-
use rustc_hir::{GenericParamKind, Node, Unsafety};
32+
use rustc_hir::{GenericParamKind, Node};
3333
use rustc_middle::hir::map::blocks::FnLikeNode;
3434
use rustc_middle::hir::map::Map;
3535
use 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

Comments
 (0)