about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-22 05:07:45 +0000
committerbors <bors@rust-lang.org>2023-09-22 05:07:45 +0000
commitaace2dfa37f4589b0071530d2ed7b352f6196704 (patch)
tree085e424b22822d32e05954baa744c3b27e9fa42f
parentb7573187180a6ad13ba557f85b7e19a51f8fdaf1 (diff)
parent9102816bc4deca950b66cce402ea45573acc8fa0 (diff)
downloadrust-aace2dfa37f4589b0071530d2ed7b352f6196704.tar.gz
rust-aace2dfa37f4589b0071530d2ed7b352f6196704.zip
Auto merge of #115910 - eduardosm:lang-fns-target-features, r=cjgillot
Prevent using `#[target_feature]` on lang item functions

Fixes https://github.com/rust-lang/rust/issues/109411 and also prevents from using `#[target_feature]` on other `fn` lang items to mitigate the concerns from https://github.com/rust-lang/rust/issues/109411#issuecomment-1477030273.
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs32
-rw-r--r--compiler/rustc_passes/src/errors.rs10
-rw-r--r--tests/ui/lang-items/start_lang_item_with_target_feature.rs19
-rw-r--r--tests/ui/lang-items/start_lang_item_with_target_feature.stderr11
-rw-r--r--tests/ui/panic-handler/panic-handler-with-target-feature.rs15
-rw-r--r--tests/ui/panic-handler/panic-handler-with-target-feature.stderr11
7 files changed, 99 insertions, 3 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 4f8ce99417a..dc0776c5dad 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -407,6 +407,10 @@ passes_invalid_stability =
     .label = invalid stability version
     .item = the stability attribute annotates this item
 
+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]`
+
 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}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2d94354e3e1..12118a0268b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -118,7 +118,7 @@ impl CheckAttrVisitor<'_> {
                 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),
-                sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
+                sym::target_feature => self.check_target_feature(hir_id, attr, span, target, attrs),
                 sym::thread_local => self.check_thread_local(attr, span, target),
                 sym::track_caller => {
                     self.check_track_caller(hir_id, attr.span, attrs, span, target)
@@ -591,10 +591,36 @@ impl CheckAttrVisitor<'_> {
         attr: &Attribute,
         span: Span,
         target: Target,
+        attrs: &[Attribute],
     ) -> bool {
         match target {
-            Target::Fn
-            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+            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,
             // FIXME: #[target_feature] was previously erroneously allowed on statements and some
             // crates used this, so only emit a warning.
             Target::Statement => {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 8b65e301b74..2ec6a0b9241 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -809,6 +809,16 @@ pub struct MissingLangItem {
 }
 
 #[derive(Diagnostic)]
+#[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)]
 #[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
 pub struct LangItemOnIncorrectTarget {
     #[primary_span]
diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.rs b/tests/ui/lang-items/start_lang_item_with_target_feature.rs
new file mode 100644
index 00000000000..3052b7bb563
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_with_target_feature.rs
@@ -0,0 +1,19 @@
+// 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() {}
diff --git a/tests/ui/lang-items/start_lang_item_with_target_feature.stderr b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr
new file mode 100644
index 00000000000..ff55a1365e4
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_with_target_feature.stderr
@@ -0,0 +1,11 @@
+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
+
diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.rs b/tests/ui/panic-handler/panic-handler-with-target-feature.rs
new file mode 100644
index 00000000000..8ea0275d7e9
--- /dev/null
+++ b/tests/ui/panic-handler/panic-handler-with-target-feature.rs
@@ -0,0 +1,15 @@
+// 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!();
+}
diff --git a/tests/ui/panic-handler/panic-handler-with-target-feature.stderr b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr
new file mode 100644
index 00000000000..4210a4200ae
--- /dev/null
+++ b/tests/ui/panic-handler/panic-handler-with-target-feature.stderr
@@ -0,0 +1,11 @@
+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
+