about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/no_mangle_with_rust_abi.rs28
-rw-r--r--tests/ui/no_mangle_with_rust_abi.fixed48
-rw-r--r--tests/ui/no_mangle_with_rust_abi.rs2
-rw-r--r--tests/ui/no_mangle_with_rust_abi.stderr74
4 files changed, 71 insertions, 81 deletions
diff --git a/clippy_lints/src/no_mangle_with_rust_abi.rs b/clippy_lints/src/no_mangle_with_rust_abi.rs
index bc64ccb295c..8fd9ae351a0 100644
--- a/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -1,9 +1,10 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{BytePos, Pos};
 use rustc_target::spec::abi::Abi;
 
 declare_clippy_lint! {
@@ -38,25 +39,28 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let ItemKind::Fn(fn_sig, _, _) = &item.kind {
             let attrs = cx.tcx.hir().attrs(item.hir_id());
-            let mut applicability = Applicability::MachineApplicable;
-            let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut applicability);
+            let mut app = Applicability::MaybeIncorrect;
+            let 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
-                    && !snippet.contains("extern") {
+                    && let Some((fn_attrs, _)) = 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 suggestion = snippet.split_once("fn")
-                        .map_or(String::new(), |(first, second)| format!(r#"{first}extern "C" fn{second}"#));
-
-                    span_lint_and_sugg(
+                    span_lint_and_then(
                         cx,
                         NO_MANGLE_WITH_RUST_ABI,
                         fn_sig.span,
-                        "attribute #[no_mangle] set on a Rust ABI function",
-                        "try",
-                        suggestion,
-                        applicability
+                        "`#[no_mangle]` 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.fixed b/tests/ui/no_mangle_with_rust_abi.fixed
deleted file mode 100644
index d18dec22a8b..00000000000
--- a/tests/ui/no_mangle_with_rust_abi.fixed
+++ /dev/null
@@ -1,48 +0,0 @@
-// run-rustfix
-
-#![allow(unused)]
-#![warn(clippy::no_mangle_with_rust_abi)]
-
-#[no_mangle]
-extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
-
-#[no_mangle]
-pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
-
-/// # Safety
-/// This function shouldn't be called unless the horsemen are ready
-#[no_mangle]
-pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
-
-/// # Safety
-/// This function shouldn't be called unless the horsemen are ready
-#[no_mangle]
-unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
-
-#[no_mangle]
-extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
-    arg_one: u32,
-    arg_two: usize,
-) -> u32 {
-    0
-}
-
-// Must not run on functions that explicitly opt in to 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.rs b/tests/ui/no_mangle_with_rust_abi.rs
index 481e1b6d961..b32e721110e 100644
--- a/tests/ui/no_mangle_with_rust_abi.rs
+++ b/tests/ui/no_mangle_with_rust_abi.rs
@@ -1,5 +1,3 @@
-// run-rustfix
-
 #![allow(unused)]
 #![warn(clippy::no_mangle_with_rust_abi)]
 
diff --git a/tests/ui/no_mangle_with_rust_abi.stderr b/tests/ui/no_mangle_with_rust_abi.stderr
index 71517d31809..da5d31d8f2d 100644
--- a/tests/ui/no_mangle_with_rust_abi.stderr
+++ b/tests/ui/no_mangle_with_rust_abi.stderr
@@ -1,31 +1,66 @@
-error: attribute #[no_mangle] set on a Rust ABI function
-  --> $DIR/no_mangle_with_rust_abi.rs:7:1
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> $DIR/no_mangle_with_rust_abi.rs:5:1
    |
 LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize)`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
+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: attribute #[no_mangle] set on a Rust ABI function
-  --> $DIR/no_mangle_with_rust_abi.rs:10:1
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> $DIR/no_mangle_with_rust_abi.rs:8:1
    |
 LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `pub extern "C" 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: attribute #[no_mangle] set on a Rust ABI function
-  --> $DIR/no_mangle_with_rust_abi.rs:15:1
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> $DIR/no_mangle_with_rust_abi.rs:13:1
    |
 LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `pub unsafe extern "C" 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: attribute #[no_mangle] set on a Rust ABI function
-  --> $DIR/no_mangle_with_rust_abi.rs:20:1
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> $DIR/no_mangle_with_rust_abi.rs:18:1
    |
 LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe extern "C" 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: attribute #[no_mangle] set on a Rust ABI function
-  --> $DIR/no_mangle_with_rust_abi.rs:23:1
+error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
+  --> $DIR/no_mangle_with_rust_abi.rs:21:1
    |
 LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
 LL | |     arg_one: u32,
@@ -33,13 +68,14 @@ LL | |     arg_two: usize,
 LL | | ) -> u32 {
    | |________^
    |
-help: try
+help: set an ABI
    |
-LL + extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
-LL +     arg_one: u32,
-LL +     arg_two: usize,
-LL ~ ) -> u32 {
+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