diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 84d3b84e13f..026186cbe6c 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -393,6 +393,9 @@ passes_invalid_attr_at_crate_level = `{$name}` attribute cannot be used at crate level .suggestion = perhaps you meant to use an outer attribute +passes_invalid_attr_at_crate_level_item = + the inner attribute doesn't annotate this {$kind} + passes_invalid_deprecation_version = invalid deprecation version found .label = invalid deprecation version diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dfe75ea5e8e..a8a27e761cb 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2534,10 +2534,30 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { if attr.style == AttrStyle::Inner { for attr_to_check in ATTRS_TO_CHECK { if attr.has_name(*attr_to_check) { + let item = tcx + .hir() + .items() + .map(|id| tcx.hir().item(id)) + .find(|item| !item.span.is_dummy()) // Skip prelude `use`s + .map(|item| errors::ItemFollowingInnerAttr { + span: item.ident.span, + kind: item.kind.descr(), + }); tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel { span: attr.span, - snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(), + sugg_span: tcx + .sess + .source_map() + .span_to_snippet(attr.span) + .ok() + .filter(|src| src.starts_with("#![")) + .map(|_| { + attr.span + .with_lo(attr.span.lo() + BytePos(1)) + .with_hi(attr.span.lo() + BytePos(2)) + }), name: *attr_to_check, + item, }); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 6e840f24c69..eca0fb7748b 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -856,8 +856,15 @@ pub struct UnknownLangItem { pub struct InvalidAttrAtCrateLevel { pub span: Span, - pub snippet: Option, + pub sugg_span: Option, pub name: Symbol, + pub item: Option, +} + +#[derive(Clone, Copy)] +pub struct ItemFollowingInnerAttr { + pub span: Span, + pub kind: &'static str, } impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { @@ -871,15 +878,18 @@ fn into_diagnostic( diag.set_arg("name", self.name); // Only emit an error with a suggestion if we can create a string out // of the attribute span - if let Some(src) = self.snippet { - let replacement = src.replace("#!", "#"); + if let Some(span) = self.sugg_span { diag.span_suggestion_verbose( - self.span, + span, fluent::passes_suggestion, - replacement, + String::new(), rustc_errors::Applicability::MachineApplicable, ); } + if let Some(item) = self.item { + diag.set_arg("kind", item.kind); + diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item); + } diag } } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr index a1fb4d6787c..225b8e8f32f 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr @@ -3,11 +3,15 @@ error: `unix_sigpipe` attribute cannot be used at crate level | LL | #![unix_sigpipe = "inherit"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[unix_sigpipe = "inherit"] - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL - #![unix_sigpipe = "inherit"] +LL + #[unix_sigpipe = "inherit"] + | error: aborting due to previous error diff --git a/tests/ui/derives/issue-36617.stderr b/tests/ui/derives/issue-36617.stderr index 9cc0a29b065..98be7963e5e 100644 --- a/tests/ui/derives/issue-36617.stderr +++ b/tests/ui/derives/issue-36617.stderr @@ -43,55 +43,75 @@ error: `derive` attribute cannot be used at crate level | LL | #![derive(Copy)] | ^^^^^^^^^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[derive(Copy)] - | ~~~~~~~~~~~~~~~ +LL - #![derive(Copy)] +LL + #[derive(Copy)] + | error: `test` attribute cannot be used at crate level --> $DIR/issue-36617.rs:4:1 | LL | #![test] | ^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[test] - | ~~~~~~~ +LL - #![test] +LL + #[test] + | error: `test_case` attribute cannot be used at crate level --> $DIR/issue-36617.rs:7:1 | LL | #![test_case] | ^^^^^^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[test_case] - | ~~~~~~~~~~~~ +LL - #![test_case] +LL + #[test_case] + | error: `bench` attribute cannot be used at crate level --> $DIR/issue-36617.rs:10:1 | LL | #![bench] | ^^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[bench] - | ~~~~~~~~ +LL - #![bench] +LL + #[bench] + | error: `global_allocator` attribute cannot be used at crate level --> $DIR/issue-36617.rs:13:1 | LL | #![global_allocator] | ^^^^^^^^^^^^^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[global_allocator] - | ~~~~~~~~~~~~~~~~~~~ +LL - #![global_allocator] +LL + #[global_allocator] + | error: aborting due to 10 previous errors diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr index 6b332211942..8270d46d492 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr @@ -11,10 +11,14 @@ error: `bench` attribute cannot be used at crate level | LL | #![bench = "4100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[bench = "4100"] +LL - #![bench = "4100"] +LL + #[bench = "4100"] | error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index 1fe133ac2bc..0f833f793bd 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -32,6 +32,12 @@ //~^ ERROR attribute should be applied to function or closure mod inline { //~^ NOTE not a function or closure + //~| NOTE the inner attribute doesn't annotate this module + //~| NOTE the inner attribute doesn't annotate this module + //~| NOTE the inner attribute doesn't annotate this module + //~| NOTE the inner attribute doesn't annotate this module + //~| NOTE the inner attribute doesn't annotate this module + //~| NOTE the inner attribute doesn't annotate this module mod inner { #![inline] } //~^ ERROR attribute should be applied to function or closure diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 78767040421..f01153dcb96 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -7,7 +7,7 @@ LL | #![rustc_main] = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ @@ -17,31 +17,31 @@ LL | #[inline = "2100"] fn f() { } = note: `#[deny(ill_formed_attribute_input)]` on by default error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:125:1 | LL | #[start] | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:122:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:128:17 | LL | mod inner { #![start] } | ^^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:5 | LL | #[start] struct S; | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:130:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:136:5 | LL | #[start] type T = S; | ^^^^^^^^ error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:5 | LL | #[start] impl S { } | ^^^^^^^^ @@ -55,14 +55,14 @@ LL | LL | / mod inline { LL | | LL | | -LL | | mod inner { #![inline] } +LL | | ... | LL | | LL | | } | |_- not a function or closure error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:59:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65:1 | LL | #[no_link] | ^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | | } | |_- not an `extern crate` item error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:1 | LL | #[export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | | } | |_- not a free function, impl method or static error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:143:8 | LL | #[repr(C)] | ^ @@ -129,10 +129,14 @@ error: `macro_export` attribute cannot be used at crate level | LL | #![macro_export] | ^^^^^^^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module | help: perhaps you meant to use an outer attribute | -LL | #[macro_export] +LL - #![macro_export] +LL + #[macro_export] | error: `rustc_main` attribute cannot be used at crate level @@ -140,21 +144,29 @@ error: `rustc_main` attribute cannot be used at crate level | LL | #![rustc_main] | ^^^^^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module | help: perhaps you meant to use an outer attribute | -LL | #[rustc_main] - | ~~~~~~~~~~~~~ +LL - #![rustc_main] +LL + #[rustc_main] + | error: `start` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1 | LL | #![start] | ^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module | help: perhaps you meant to use an outer attribute | -LL | #[start] +LL - #![start] +LL + #[start] | error: `repr` attribute cannot be used at crate level @@ -162,10 +174,14 @@ error: `repr` attribute cannot be used at crate level | LL | #![repr()] | ^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module | help: perhaps you meant to use an outer attribute | -LL | #[repr()] +LL - #![repr()] +LL + #[repr()] | error: `path` attribute cannot be used at crate level @@ -173,10 +189,14 @@ error: `path` attribute cannot be used at crate level | LL | #![path = "3800"] | ^^^^^^^^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module | help: perhaps you meant to use an outer attribute | -LL | #[path = "3800"] +LL - #![path = "3800"] +LL + #[path = "3800"] | error: `automatically_derived` attribute cannot be used at crate level @@ -184,122 +204,126 @@ error: `automatically_derived` attribute cannot be used at crate level | LL | #![automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | mod inline { + | ------ the inner attribute doesn't annotate this module | help: perhaps you meant to use an outer attribute | -LL | #[automatically_derived] +LL - #![automatically_derived] +LL + #[automatically_derived] | error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:42:17 | LL | mod inner { #![inline] } | ------------^^^^^^^^^^-- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:52:5 | LL | #[inline] struct S; | ^^^^^^^^^ --------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:56:5 | LL | #[inline] type T = S; | ^^^^^^^^^ ----------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:60:5 | LL | #[inline] impl S { } | ^^^^^^^^^ ---------- not a function or closure error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:64:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:70:17 | LL | mod inner { #![no_link] } | ------------^^^^^^^^^^^-- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:68:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:74:5 | LL | #[no_link] fn f() { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:72:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:78:5 | LL | #[no_link] struct S; | ^^^^^^^^^^ --------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:76:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:82:5 | LL | #[no_link]type T = S; | ^^^^^^^^^^----------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:86:5 | LL | #[no_link] impl S { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:17 | LL | mod inner { #![export_name="2200"] } | ------------^^^^^^^^^^^^^^^^^^^^^^-- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:102:5 | LL | #[export_name = "2200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:5 | LL | #[export_name = "2200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:104:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:110:5 | LL | #[export_name = "2200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:9 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:115:9 | LL | #[export_name = "2200"] fn foo(); | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:9 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:9 | LL | #[export_name = "2200"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:147:25 | LL | mod inner { #![repr(C)] } | --------------------^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12 | LL | #[repr(C)] fn f() { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:157:12 | LL | #[repr(C)] type T = S; | ^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:161:12 | LL | #[repr(C)] impl S { } | ^ ---------- not a struct, enum, or union diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr index 300a9966dd8..922c9861aa3 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr @@ -11,10 +11,14 @@ error: `test` attribute cannot be used at crate level | LL | #![test = "4200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn main() {} + | ---- the inner attribute doesn't annotate this function | help: perhaps you meant to use an outer attribute | -LL | #[test = "4200"] +LL - #![test = "4200"] +LL + #[test = "4200"] | error: aborting due to 2 previous errors diff --git a/tests/ui/imports/issue-28134.stderr b/tests/ui/imports/issue-28134.stderr index 33cb53f202a..5315c2e9fee 100644 --- a/tests/ui/imports/issue-28134.stderr +++ b/tests/ui/imports/issue-28134.stderr @@ -14,8 +14,9 @@ LL | #![test] | help: perhaps you meant to use an outer attribute | -LL | #[test] - | ~~~~~~~ +LL - #![test] +LL + #[test] + | error: aborting due to 2 previous errors diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr index e3ae37e3689..a22a4d2b40a 100644 --- a/tests/ui/span/issue-43927-non-ADT-derive.stderr +++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr @@ -11,11 +11,15 @@ error: `derive` attribute cannot be used at crate level | LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct DerivedOn; + | --------- the inner attribute doesn't annotate this struct | help: perhaps you meant to use an outer attribute | -LL | #[derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL - #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! +LL + #[derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | error: aborting due to 2 previous errors