Change:
This works (but it shouldn't): similar to , cc (tracking issue) label T-lang T-compiler C-bug I-unsound F-targetfeature11
cc , author of Note that this is about the nostd panic handler, not about the function. This fails as it should: gives
ugh we really need a way to make sure that every single "this is called by rust" function gets a check... I assume that these functions can't be unsafe, so I guess those checks are a food way to start looking and make sure to deduplicate the logic there?
Yeah sadly we do need to make sure, not just for the constructs that we have now but also it needs to be kept in mind for the future constructs we add or stabilize. A lot thankfully goes through either the trait system (operators or the GlobalAlloc trait used by ) or function pointers (alloc error hook, std panic hook). Functions that you can make callable solely by setting an attribute, those are rare. The best list of lang items I could find was in the , so that would be a great start for such an exhaustive search. Thankfully most of them are unstable, but still it needs to be addressed for each of them before stabilization (if that is a target).
WG-prioritization assigning priority (). label -I-prioritize +P-medium
label +requires-nightly
There is also another table of lang items in the source code, .

Discussion:
.label = invalid stability version .item = the stability attribute annotates this item <ins> passes_lang_item_fn_with_target_feature = `{$name}` language item function is not allowed to have `#[target_feature]` .label = `{$name}` language item function is not allowed to have `#[target_feature]` </ins> passes_lang_item_on_incorrect_target = `{$name}` language item must be applied to a {$expected_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target}

sym::coverage => self.check_coverage(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), sym::marker => self.check_marker(hir_id, attr, span, target), <del> sym::target_feature => self.check_target_feature(hir_id, attr, span, target), </del> <ins> sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs), </ins> sym::thread_local => self.check_thread_local(attr, span, target), sym::track_caller => { self.check_track_caller(hir_id, attr.span, attrs, span, target)

attr: &Attribute, span: Span, target: Target, <ins> attrs: &[Attribute], </ins> ) -> bool { match target { <del> Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, </del> <ins> Target::Fn => { // `#[target_feature]` is not allowed in language items. if let Some((lang_item, _)) = hir::lang_items::extract(attrs) // Calling functions with `#[target_feature]` is // not unsafe on WASM, see #84988 && !self.tcx.sess.target.is_like_wasm && !self.tcx.sess.opts.actually_rustdoc { let hir::Node::Item(item) = self.tcx.hir().get(hir_id) else { unreachable!(); }; let hir::ItemKind::Fn(sig, _, _) = item.kind else { // target is `Fn` unreachable!(); }; self.tcx.sess.emit_err(errors::LangItemWithTargetFeature { attr_span: attr.span, name: lang_item, sig_span: sig.span, }); false } else { true } } Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, </ins> // FIXME: #[target_feature] was previously erroneously allowed on statements and some // crates used this, so only emit a warning. Target::Statement => {

} #[derive(Diagnostic)] <ins> #[diag(passes_lang_item_fn_with_target_feature)] pub struct LangItemWithTargetFeature { #[primary_span] pub attr_span: Span, pub name: Symbol, #[label] pub sig_span: Span, } #[derive(Diagnostic)] </ins> #[diag(passes_lang_item_on_incorrect_target, code = "E0718")] pub struct LangItemOnIncorrectTarget { #[primary_span]

<ins> // only-x86_64 // check-fail #![feature(lang_items, no_core, target_feature_11)] #![no_core] #[lang = "copy"] pub trait Copy {} #[lang = "sized"] pub trait Sized {} #[lang = "start"] #[target_feature(enable = "avx2")] //~^ ERROR `start` language item function is not allowed to have `#[target_feature]` fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { 0 } fn main() {} </ins>

<ins> error: `start` language item function is not allowed to have `#[target_feature]` --> $DIR/start_lang_item_with_target_feature.rs:13:1 | LL | #[target_feature(enable = "avx2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { | ------------------------------------------------------------------------------------------- `start` language item function is not allowed to have `#[target_feature]` error: aborting due to previous error </ins>

<ins> // compile-flags:-C panic=abort // only-x86_64 #![feature(target_feature_11)] #![no_std] #![no_main] use core::panic::PanicInfo; #[panic_handler] #[target_feature(enable = "avx2")] //~^ ERROR `panic_impl` language item function is not allowed to have `#[target_feature]` fn panic(info: &PanicInfo) -> ! { unimplemented!(); } </ins>

<ins> error: `panic_impl` language item function is not allowed to have `#[target_feature]` --> $DIR/panic-handler-with-target-feature.rs:11:1 | LL | #[target_feature(enable = "avx2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn panic(info: &PanicInfo) -> ! { | ------------------------------- `panic_impl` language item function is not allowed to have `#[target_feature]` error: aborting due to previous error </ins>