Skip to content

Commit

Permalink
Tweak suggestion spans for invalid crate-level inner attribute
Browse files Browse the repository at this point in the history
CC #89566.
  • Loading branch information
estebank committed Oct 26, 2023
1 parent 6f65201 commit 27919ce
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 60 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}
}
Expand Down
20 changes: 15 additions & 5 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,15 @@ pub struct UnknownLangItem {

pub struct InvalidAttrAtCrateLevel {
pub span: Span,
pub snippet: Option<String>,
pub sugg_span: Option<Span>,
pub name: Symbol,
pub item: Option<ItemFollowingInnerAttr>,
}

#[derive(Clone, Copy)]
pub struct ItemFollowingInnerAttr {
pub span: Span,
pub kind: &'static str,
}

impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
Expand All @@ -871,15 +878,18 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
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
}
}
Expand Down
8 changes: 6 additions & 2 deletions tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

40 changes: 30 additions & 10 deletions tests/ui/derives/issue-36617.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

6 changes: 5 additions & 1 deletion tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 27919ce

Please sign in to comment.