From 2c8257493da0e452c03f34cc6f409d98234746db Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 9 Jun 2025 21:55:17 +0200 Subject: [PATCH] use correct edition when warning for unsafe attributes If an attribute is re-emitted by a macro, the incorrect edition was used to emit warnings for unsafe attributes --- compiler/rustc_parse/src/validate_attr.rs | 7 ++++- .../unsafe-attr-edition-span.e2024.stderr | 24 +++++++++++++++++ tests/ui/editions/unsafe-attr-edition-span.rs | 27 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/ui/editions/unsafe-attr-edition-span.e2024.stderr create mode 100644 tests/ui/editions/unsafe-attr-edition-span.rs diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 378cbb846379d..555ab3cdb2b6e 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -180,9 +180,14 @@ pub fn check_attribute_safety( let diag_span = attr_item.span(); // Attributes can be safe in earlier editions, and become unsafe in later ones. + // + // Use the span of the attribute's name to determine the edition: the span of the + // attribute as a whole may be inaccurate if it was emitted by a macro. + // + // See https://github.com/rust-lang/rust/issues/142182. let emit_error = match unsafe_since { None => true, - Some(unsafe_since) => attr.span.edition() >= unsafe_since, + Some(unsafe_since) => path_span.edition() >= unsafe_since, }; if emit_error { diff --git a/tests/ui/editions/unsafe-attr-edition-span.e2024.stderr b/tests/ui/editions/unsafe-attr-edition-span.e2024.stderr new file mode 100644 index 0000000000000..28871a1cce4fe --- /dev/null +++ b/tests/ui/editions/unsafe-attr-edition-span.e2024.stderr @@ -0,0 +1,24 @@ +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attr-edition-span.rs:21:3 + | +LL | #[no_mangle] + | ^^^^^^^^^ usage of unsafe attribute + | +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(no_mangle)] + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attr-edition-span.rs:25:7 + | +LL | #[no_mangle] + | ^^^^^^^^^ usage of unsafe attribute + | +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(no_mangle)] + | +++++++ + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/editions/unsafe-attr-edition-span.rs b/tests/ui/editions/unsafe-attr-edition-span.rs new file mode 100644 index 0000000000000..bc44b34063ccf --- /dev/null +++ b/tests/ui/editions/unsafe-attr-edition-span.rs @@ -0,0 +1,27 @@ +// Tests that the correct span is used to determine the edition of an attribute that was safe to use +// in earlier editions, but has become `unsafe` in later editions. +// +// Determining the correct edition is non-trivial because of macro expansion. For instance, +// the `thread_local!` macro (defined in std and hence using the most recent edition) parses the +// attribute, and then re-emits it. Therefore, the span of the `#` token starting the +// `#[no_mangle]` attribute has std's edition, while the attribute name has the edition of this +// file, which may be different. + +//@ revisions: e2015 e2018 e2021 e2024 + +//@[e2018] edition:2018 +//@[e2021] edition:2021 +//@[e2024] edition:2024 +// +//@[e2015] check-pass +//@[e2018] check-pass +//@[e2021] check-pass +#![crate_type = "lib"] + +#[no_mangle] //[e2024]~ ERROR unsafe attribute used without unsafe +static TEST_OUTSIDE: usize = 0; + +thread_local! { + #[no_mangle]//[e2024]~ ERROR unsafe attribute used without unsafe + static TEST: usize = 0; +}