about summary refs log tree commit diff
path: root/compiler/rustc_passes
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-10-27 11:48:05 +0200
committerGitHub <noreply@github.com>2023-10-27 11:48:05 +0200
commita69fb480a4cb8e6bedff17602fdf880b3fcee9b7 (patch)
tree5fb3dd694e0a9228ee9dbce2b3900d33d72903fa /compiler/rustc_passes
parent8d67c3212407523bede9c37387ce03363068a81e (diff)
parent27919ceba717cd5be7f7ebcb2f5e5f5afa955035 (diff)
downloadrust-a69fb480a4cb8e6bedff17602fdf880b3fcee9b7.tar.gz
rust-a69fb480a4cb8e6bedff17602fdf880b3fcee9b7.zip
Rollup merge of #116868 - estebank:suggestion, r=petrochenkov
Tweak suggestion span for outer attr and point at item following invalid inner attr

After:

```
error: `unix_sigpipe` attribute cannot be used at crate level
  --> $DIR/unix_sigpipe-crate.rs:2:1
   |
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"]
   |
```

Before:

```
error: `unix_sigpipe` attribute cannot be used at crate level
  --> $DIR/unix_sigpipe-crate.rs:2:1
   |
LL | #![unix_sigpipe = "inherit"]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
help: perhaps you meant to use an outer attribute
   |
LL | #[unix_sigpipe = "inherit"]
   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

CC #89566.
Diffstat (limited to 'compiler/rustc_passes')
-rw-r--r--compiler/rustc_passes/messages.ftl3
-rw-r--r--compiler/rustc_passes/src/check_attr.rs22
-rw-r--r--compiler/rustc_passes/src/errors.rs20
3 files changed, 39 insertions, 6 deletions
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<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 {
@@ -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
     }
 }