Skip to content

Commit 8052451

Browse files
committed
no_mangle attribute requires unsafe in Rust 2024
1 parent 625d391 commit 8052451

5 files changed

+164
-23
lines changed

clippy_lints/src/no_mangle_with_rust_abi.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use clippy_utils::source::snippet_with_applicability;
2+
use clippy_utils::source::{snippet, snippet_with_applicability};
33
use rustc_errors::Applicability;
44
use rustc_hir::{Item, ItemKind};
55
use rustc_lint::{LateContext, LateLintPass};
@@ -18,13 +18,13 @@ declare_clippy_lint! {
1818
/// Rust ABI can break this at any point.
1919
///
2020
/// ### Example
21-
/// ```no_run
21+
/// ```rust,ignore
2222
/// #[no_mangle]
2323
/// fn example(arg_one: u32, arg_two: usize) {}
2424
/// ```
2525
///
2626
/// Use instead:
27-
/// ```no_run
27+
/// ```rust,ignore
2828
/// #[no_mangle]
2929
/// extern "C" fn example(arg_one: u32, arg_two: usize) {}
3030
/// ```
@@ -40,24 +40,25 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
4040
if let ItemKind::Fn(fn_sig, _, _) = &item.kind {
4141
let attrs = cx.tcx.hir().attrs(item.hir_id());
4242
let mut app = Applicability::MaybeIncorrect;
43-
let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut app);
43+
let fn_snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut app);
4444
for attr in attrs {
4545
if let Some(ident) = attr.ident()
4646
&& ident.name == rustc_span::sym::no_mangle
4747
&& fn_sig.header.abi == Abi::Rust
48-
&& let Some((fn_attrs, _)) = snippet.split_once("fn")
48+
&& let Some((fn_attrs, _)) = fn_snippet.split_once("fn")
4949
&& !fn_attrs.contains("extern")
5050
{
5151
let sugg_span = fn_sig
5252
.span
5353
.with_lo(fn_sig.span.lo() + BytePos::from_usize(fn_attrs.len()))
5454
.shrink_to_lo();
55+
let attr_snippet = snippet(cx, attr.span, "..");
5556

5657
span_lint_and_then(
5758
cx,
5859
NO_MANGLE_WITH_RUST_ABI,
5960
fn_sig.span,
60-
"`#[no_mangle]` set on a function with the default (`Rust`) ABI",
61+
format!("`{attr_snippet}` set on a function with the default (`Rust`) ABI"),
6162
|diag| {
6263
diag.span_suggestion(sugg_span, "set an ABI", "extern \"C\" ", app)
6364
.span_suggestion(sugg_span, "or explicitly set the default", "extern \"Rust\" ", app);

tests/ui/no_mangle_with_rust_abi.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,44 @@
22
#![allow(unused)]
33
#![warn(clippy::no_mangle_with_rust_abi)]
44

5-
#[no_mangle]
5+
#[unsafe(no_mangle)]
66
fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
7-
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
7+
//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
88
//~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
99

10-
#[no_mangle]
10+
#[unsafe(no_mangle)]
1111
pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
12-
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
12+
//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
1313

1414
/// # Safety
1515
/// This function shouldn't be called unless the horsemen are ready
16-
#[no_mangle]
16+
#[unsafe(no_mangle)]
1717
pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
18-
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
18+
//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
1919

2020
/// # Safety
2121
/// This function shouldn't be called unless the horsemen are ready
22-
#[no_mangle]
22+
#[unsafe(no_mangle)]
2323
unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
24-
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
24+
//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
2525

26-
#[no_mangle]
26+
#[unsafe(no_mangle)]
2727
fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
28-
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
28+
//~^ ERROR: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
2929
arg_one: u32,
3030
arg_two: usize,
3131
) -> u32 {
3232
0
3333
}
3434

3535
// Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"`
36-
#[no_mangle]
36+
#[unsafe(no_mangle)]
3737
#[rustfmt::skip]
3838
extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
3939

4040
fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
4141

42-
#[no_mangle]
42+
#[unsafe(no_mangle)]
4343
extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
4444

4545
extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}

tests/ui/no_mangle_with_rust_abi.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
1+
error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
22
--> tests/ui/no_mangle_with_rust_abi.rs:6:1
33
|
44
LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
@@ -15,7 +15,7 @@ help: or explicitly set the default
1515
LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
1616
| +++++++++++++
1717

18-
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
18+
error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
1919
--> tests/ui/no_mangle_with_rust_abi.rs:11:1
2020
|
2121
LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
@@ -30,7 +30,7 @@ help: or explicitly set the default
3030
LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
3131
| +++++++++++++
3232

33-
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
33+
error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
3434
--> tests/ui/no_mangle_with_rust_abi.rs:17:1
3535
|
3636
LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
@@ -45,7 +45,7 @@ help: or explicitly set the default
4545
LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
4646
| +++++++++++++
4747

48-
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
48+
error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
4949
--> tests/ui/no_mangle_with_rust_abi.rs:23:1
5050
|
5151
LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
@@ -60,7 +60,7 @@ help: or explicitly set the default
6060
LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
6161
| +++++++++++++
6262

63-
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
63+
error: `#[unsafe(no_mangle)]` set on a function with the default (`Rust`) ABI
6464
--> tests/ui/no_mangle_with_rust_abi.rs:27:1
6565
|
6666
LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//@edition:2021
2+
//
3+
// Edition 2024 requires the use of #[unsafe(no_mangle)]
4+
5+
//@no-rustfix: overlapping suggestions
6+
#![allow(unused)]
7+
#![warn(clippy::no_mangle_with_rust_abi)]
8+
9+
#[no_mangle]
10+
fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
11+
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
12+
//~| NOTE: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
13+
14+
#[no_mangle]
15+
pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
16+
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
17+
18+
/// # Safety
19+
/// This function shouldn't be called unless the horsemen are ready
20+
#[no_mangle]
21+
pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
22+
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
23+
24+
/// # Safety
25+
/// This function shouldn't be called unless the horsemen are ready
26+
#[no_mangle]
27+
unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
28+
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
29+
30+
#[no_mangle]
31+
fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
32+
//~^ ERROR: `#[no_mangle]` set on a function with the default (`Rust`) ABI
33+
arg_one: u32,
34+
arg_two: usize,
35+
) -> u32 {
36+
0
37+
}
38+
39+
// Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"`
40+
#[no_mangle]
41+
#[rustfmt::skip]
42+
extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
43+
44+
fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
45+
46+
#[no_mangle]
47+
extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
48+
49+
extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
50+
51+
extern "C" {
52+
fn c_abi_in_block(arg_one: u32, arg_two: usize);
53+
}
54+
55+
fn main() {
56+
// test code goes here
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
2+
--> tests/ui/no_mangle_with_rust_abi_2021.rs:10:1
3+
|
4+
LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::no_mangle_with_rust_abi)]`
9+
help: set an ABI
10+
|
11+
LL | extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
12+
| ++++++++++
13+
help: or explicitly set the default
14+
|
15+
LL | extern "Rust" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
16+
| +++++++++++++
17+
18+
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
19+
--> tests/ui/no_mangle_with_rust_abi_2021.rs:15:1
20+
|
21+
LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
help: set an ABI
25+
|
26+
LL | pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
27+
| ++++++++++
28+
help: or explicitly set the default
29+
|
30+
LL | pub extern "Rust" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
31+
| +++++++++++++
32+
33+
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
34+
--> tests/ui/no_mangle_with_rust_abi_2021.rs:21:1
35+
|
36+
LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
|
39+
help: set an ABI
40+
|
41+
LL | pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
42+
| ++++++++++
43+
help: or explicitly set the default
44+
|
45+
LL | pub unsafe extern "Rust" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
46+
| +++++++++++++
47+
48+
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
49+
--> tests/ui/no_mangle_with_rust_abi_2021.rs:27:1
50+
|
51+
LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
52+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53+
|
54+
help: set an ABI
55+
|
56+
LL | unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
57+
| ++++++++++
58+
help: or explicitly set the default
59+
|
60+
LL | unsafe extern "Rust" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
61+
| +++++++++++++
62+
63+
error: `#[no_mangle]` set on a function with the default (`Rust`) ABI
64+
--> tests/ui/no_mangle_with_rust_abi_2021.rs:31:1
65+
|
66+
LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
67+
LL | |
68+
LL | | arg_one: u32,
69+
LL | | arg_two: usize,
70+
LL | | ) -> u32 {
71+
| |________^
72+
|
73+
help: set an ABI
74+
|
75+
LL | extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
76+
| ++++++++++
77+
help: or explicitly set the default
78+
|
79+
LL | extern "Rust" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
80+
| +++++++++++++
81+
82+
error: aborting due to 5 previous errors
83+

0 commit comments

Comments
 (0)