about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-11-03 19:43:19 +0000
committerbors <bors@rust-lang.org>2024-11-03 19:43:19 +0000
commita1a9aaef87cf15a97ca1766bbcd2e12314784417 (patch)
tree0b0d20518d45402821a380839335336ced432846
parent040129b7745fdf661a395d7de13b4ef7944cd1e0 (diff)
parent805245161a7044cd04bed12062e18045864b9c47 (diff)
downloadrust-a1a9aaef87cf15a97ca1766bbcd2e12314784417.tar.gz
rust-a1a9aaef87cf15a97ca1766bbcd2e12314784417.zip
Auto merge of #13631 - samueltardieu:push-uoowutzkvsrk, r=Centri3
no_mangle attribute requires unsafe in Rust 2024

Tests without unsafe must not run in edition 2024. Also, error messages have been modified to include the full attribute, so that a use of `#[unsafe(no_mangle)]` does not produce an error message containing `#[no_mangle]`.

changelog: [`no_mangle_attribute`]: handle `#[unsafe(no_mangle)]` as well
-rw-r--r--clippy_lints/src/no_mangle_with_rust_abi.rs13
-rw-r--r--tests/ui/no_mangle_with_rust_abi.rs24
-rw-r--r--tests/ui/no_mangle_with_rust_abi.stderr10
-rw-r--r--tests/ui/no_mangle_with_rust_abi_2021.rs57
-rw-r--r--tests/ui/no_mangle_with_rust_abi_2021.stderr83
5 files changed, 164 insertions, 23 deletions
diff --git a/clippy_lints/src/no_mangle_with_rust_abi.rs b/clippy_lints/src/no_mangle_with_rust_abi.rs
index 8d5a523fd8f..e21c1ae6f82 100644
--- a/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::{snippet, snippet_with_applicability};
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -18,13 +18,13 @@ declare_clippy_lint! {
     /// Rust ABI can break this at any point.
     ///
     /// ### Example
-    /// ```no_run
+    /// ```rust,ignore
     ///  #[no_mangle]
     ///  fn example(arg_one: u32, arg_two: usize) {}
     /// ```
     ///
     /// Use instead:
-    /// ```no_run
+    /// ```rust,ignore
     ///  #[no_mangle]
     ///  extern "C" fn example(arg_one: u32, arg_two: usize) {}
     /// ```
@@ -40,24 +40,25 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
         if let ItemKind::Fn(fn_sig, _, _) = &item.kind {
             let attrs = cx.tcx.hir().attrs(item.hir_id());
             let mut app = Applicability::MaybeIncorrect;
-            let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut app);
+            let fn_snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut app);
             for attr in attrs {
                 if let Some(ident) = attr.ident()
                     && ident.name == rustc_span::sym::no_mangle
                     && fn_sig.header.abi == Abi::Rust
-                    && let Some((fn_attrs, _)) = snippet.split_once("fn")
+                    && let Some((fn_attrs, _)) = fn_snippet.split_once("fn")
                     && !fn_attrs.contains("extern")
                 {
                     let sugg_span = fn_sig
                         .span
                         .with_lo(fn_sig.span.lo() + BytePos::from_usize(fn_attrs.len()))
                         .shrink_to_lo();
+                    let attr_snippet = snippet(cx, attr.span, "..");
 
                     span_lint_and_then(
                         cx,
                         NO_MANGLE_WITH_RUST_ABI,
                         fn_sig.span,
-                        "`#[no_mangle]` set on a function with the default (`Rust`) ABI",
+                        format!("`{attr_snippet}` set on a function with the default (`Rust`) ABI"),
                         |diag| {
                             diag.span_suggestion(sugg_span, "set an ABI", "extern \"C\" ", app)
                                 .span_suggestion(sugg_span, "or explicitly set the default", "extern \"Rust\" ", app);
diff --git a/tests/ui/no_mangle_with_rust_abi.rs b/tests/ui/no_mangle_with_rust_abi.rs
index 8c1ea81d2ac..8a732e56acc 100644
--- a/tests/ui/no_mangle_with_rust_abi.rs
+++ b/tests/ui/no_mangle_with_rust_abi.rs
@@ -2,30 +2,30 @@
 #![allow(unused)]
 #![warn(clippy::no_mangle_with_rust_abi)]
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
-//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
 //~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
-//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
 
 /// # Safety
 /// This function shouldn't be called unless the horsemen are ready
-#[no_mangle]
+#[unsafe(no_mangle)]
 pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
-//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
 
 /// # Safety
 /// This function shouldn't be called unless the horsemen are ready
-#[no_mangle]
+#[unsafe(no_mangle)]
 unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
-//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
-    //~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+    //~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
     arg_one: u32,
     arg_two: usize,
 ) -> u32 {
@@ -33,13 +33,13 @@ fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lin
 }
 
 // Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"`
-#[no_mangle]
+#[unsafe(no_mangle)]
 #[rustfmt::skip]
 extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
 
 fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
 
-#[no_mangle]
+#[unsafe(no_mangle)]
 extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
 
 extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
diff --git a/tests/ui/no_mangle_with_rust_abi.stderr b/tests/ui/no_mangle_with_rust_abi.stderr
index 27b8b39a21a..f2ceaeaa8db 100644
--- a/tests/ui/no_mangle_with_rust_abi.stderr
+++ b/tests/ui/no_mangle_with_rust_abi.stderr
@@ -1,4 +1,4 @@
-error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
   --> tests/ui/no_mangle_with_rust_abi.rs:6:1
    |
 LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
@@ -15,7 +15,7 @@ help: or explicitly set the default
 LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
    | +++++++++++++
 
-error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
   --> tests/ui/no_mangle_with_rust_abi.rs:11:1
    |
 LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
@@ -30,7 +30,7 @@ help: or explicitly set the default
 LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
    |     +++++++++++++
 
-error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
   --> tests/ui/no_mangle_with_rust_abi.rs:17:1
    |
 LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
@@ -45,7 +45,7 @@ help: or explicitly set the default
 LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
    |            +++++++++++++
 
-error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
   --> tests/ui/no_mangle_with_rust_abi.rs:23:1
    |
 LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
@@ -60,7 +60,7 @@ help: or explicitly set the default
 LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
    |        +++++++++++++
 
-error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
   --> tests/ui/no_mangle_with_rust_abi.rs:27:1
    |
 LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
diff --git a/tests/ui/no_mangle_with_rust_abi_2021.rs b/tests/ui/no_mangle_with_rust_abi_2021.rs
new file mode 100644
index 00000000000..c7c97335348
--- /dev/null
+++ b/tests/ui/no_mangle_with_rust_abi_2021.rs
@@ -0,0 +1,57 @@
+//@edition:2021
+//
+// Edition 2024 requires the use of #[unsafe(no_mangle)]
+
+//@no-rustfix: overlapping suggestions
+#![allow(unused)]
+#![warn(clippy::no_mangle_with_rust_abi)]
+
+#[no_mangle]
+fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+//~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
+
+#[no_mangle]
+pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+
+#[no_mangle]
+fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+    //~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+    arg_one: u32,
+    arg_two: usize,
+) -> u32 {
+    0
+}
+
+// Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"`
+#[no_mangle]
+#[rustfmt::skip]
+extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
+
+fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
+
+extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+extern "C" {
+    fn c_abi_in_block(arg_one: u32, arg_two: usize);
+}
+
+fn main() {
+    // test code goes here
+}
diff --git a/tests/ui/no_mangle_with_rust_abi_2021.stderr b/tests/ui/no_mangle_with_rust_abi_2021.stderr
new file mode 100644
index 00000000000..15075be72d0
--- /dev/null
+++ b/tests/ui/no_mangle_with_rust_abi_2021.stderr
@@ -0,0 +1,83 @@
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> tests/ui/no_mangle_with_rust_abi_2021.rs:10:1
+   |
+LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::no_mangle_with_rust_abi)]`
+help: set an ABI
+   |
+LL | extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+   | ++++++++++
+help: or explicitly set the default
+   |
+LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+   | +++++++++++++
+
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> tests/ui/no_mangle_with_rust_abi_2021.rs:15:1
+   |
+LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: set an ABI
+   |
+LL | pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+   |     ++++++++++
+help: or explicitly set the default
+   |
+LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+   |     +++++++++++++
+
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> tests/ui/no_mangle_with_rust_abi_2021.rs:21:1
+   |
+LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: set an ABI
+   |
+LL | pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+   |            ++++++++++
+help: or explicitly set the default
+   |
+LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+   |            +++++++++++++
+
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> tests/ui/no_mangle_with_rust_abi_2021.rs:27:1
+   |
+LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: set an ABI
+   |
+LL | unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+   |        ++++++++++
+help: or explicitly set the default
+   |
+LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+   |        +++++++++++++
+
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> tests/ui/no_mangle_with_rust_abi_2021.rs:31:1
+   |
+LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+LL | |
+LL | |     arg_one: u32,
+LL | |     arg_two: usize,
+LL | | ) -> u32 {
+   | |________^
+   |
+help: set an ABI
+   |
+LL | extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+   | ++++++++++
+help: or explicitly set the default
+   |
+LL | extern "Rust" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+   | +++++++++++++
+
+error: aborting due to 5 previous errors
+