about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorJana Dönszelmann <jana@donsz.nl>2025-08-11 11:46:30 +0200
committerJana Dönszelmann <jana@donsz.nl>2025-08-16 10:51:09 +0200
commit70e26c1b7bd4e9f8ba610de6dca2d74ab233cb64 (patch)
treea8fb911385eafee0361851fbffa06296429e3229 /compiler
parent1ae7c4907275f10b3db9e886bc8809ec063e45ee (diff)
downloadrust-70e26c1b7bd4e9f8ba610de6dca2d74ab233cb64.tar.gz
rust-70e26c1b7bd4e9f8ba610de6dca2d74ab233cb64.zip
take attr style into account in attr diagnostics
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/inline.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/must_use.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/test_attrs.rs6
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs18
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs6
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs8
7 files changed, 35 insertions, 13 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index 6a659a95b85..33c21bad240 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -62,8 +62,8 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
                 }
             }
             ArgParser::NameValue(_) => {
-                let suggestions =
-                    <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "inline");
+                let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
+                    .suggestions(cx.attr_style, "inline");
                 let span = cx.attr_span;
                 cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
                 return None;
diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
index c9b5dd35fa1..8928129c201 100644
--- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
@@ -107,7 +107,7 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
                     }
                 }
                 ArgParser::NameValue(_) => {
-                    let suggestions = MACRO_USE_TEMPLATE.suggestions(false, sym::macro_use);
+                    let suggestions = MACRO_USE_TEMPLATE.suggestions(cx.attr_style, sym::macro_use);
                     cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
                         num_suggestions: suggestions.len(),
                         suggestions: DiagArgValue::StrListSepByAnd(
diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs
index b6cfc780590..b0ee3d1ba6e 100644
--- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs
@@ -35,8 +35,8 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
                     Some(value_str)
                 }
                 ArgParser::List(_) => {
-                    let suggestions =
-                        <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use");
+                    let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
+                        .suggestions(cx.attr_style, "must_use");
                     cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
                         num_suggestions: suggestions.len(),
                         suggestions: DiagArgValue::StrListSepByAnd(
diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
index 8b666c3868b..164c680b8a8 100644
--- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
@@ -29,7 +29,7 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
                 ArgParser::NameValue(name_value) => {
                     let Some(str_value) = name_value.value_as_str() else {
                         let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
-                            .suggestions(false, "ignore");
+                            .suggestions(cx.attr_style, "ignore");
                         let span = cx.attr_span;
                         cx.emit_lint(
                             AttributeLintKind::IllFormedAttributeInput { suggestions },
@@ -40,8 +40,8 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
                     Some(str_value)
                 }
                 ArgParser::List(_) => {
-                    let suggestions =
-                        <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "ignore");
+                    let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
+                        .suggestions(cx.attr_style, "ignore");
                     let span = cx.attr_span;
                     cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
                     return None;
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index bebe3350c4e..13b7621001d 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -5,7 +5,7 @@ use std::sync::LazyLock;
 
 use itertools::Itertools;
 use private::Sealed;
-use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId};
+use rustc_ast::{self as ast, AttrStyle, LitKind, MetaItemLit, NodeId};
 use rustc_errors::{DiagCtxtHandle, Diagnostic};
 use rustc_feature::{AttributeTemplate, Features};
 use rustc_hir::attrs::AttributeKind;
@@ -313,6 +313,7 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
     /// The span of the attribute currently being parsed
     pub(crate) attr_span: Span,
 
+    pub(crate) attr_style: AttrStyle,
     /// The expected structure of the attribute.
     ///
     /// Used in reporting errors to give a hint to users what the attribute *should* look like.
@@ -394,6 +395,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
                     i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
                 }),
             },
+            attr_style: self.attr_style,
         })
     }
 
@@ -404,6 +406,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
+            attr_style: self.attr_style,
         })
     }
 
@@ -414,6 +417,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedList,
+            attr_style: self.attr_style,
         })
     }
 
@@ -424,6 +428,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedNoArgs,
+            attr_style: self.attr_style,
         })
     }
 
@@ -435,6 +440,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedIdentifier,
+            attr_style: self.attr_style,
         })
     }
 
@@ -447,6 +453,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedNameValue(name),
+            attr_style: self.attr_style,
         })
     }
 
@@ -458,6 +465,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::DuplicateKey(key),
+            attr_style: self.attr_style,
         })
     }
 
@@ -470,6 +478,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::UnexpectedLiteral,
+            attr_style: self.attr_style,
         })
     }
 
@@ -480,6 +489,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedSingleArgument,
+            attr_style: self.attr_style,
         })
     }
 
@@ -490,6 +500,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
             reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
+            attr_style: self.attr_style,
         })
     }
 
@@ -508,6 +519,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
                 strings: false,
                 list: false,
             },
+            attr_style: self.attr_style,
         })
     }
 
@@ -526,6 +538,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
                 strings: false,
                 list: true,
             },
+            attr_style: self.attr_style,
         })
     }
 
@@ -544,6 +557,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
                 strings: true,
                 list: false,
             },
+            attr_style: self.attr_style,
         })
     }
 
@@ -802,6 +816,7 @@ impl<'sess> AttributeParser<'sess, Early> {
                 },
             },
             attr_span: attr.span,
+            attr_style: attr.style,
             template,
             attr_path: path.get_attribute_path(),
         };
@@ -912,6 +927,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
                                     emit_lint: &mut emit_lint,
                                 },
                                 attr_span: lower_span(attr.span),
+                                attr_style: attr.style,
                                 template: &accept.template,
                                 attr_path: path.get_attribute_path(),
                             };
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 95e85667cd6..c65937b35b3 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -1,6 +1,6 @@
 use std::num::IntErrorKind;
 
-use rustc_ast as ast;
+use rustc_ast::{self as ast, AttrStyle};
 use rustc_errors::codes::*;
 use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
@@ -579,6 +579,7 @@ pub(crate) enum AttributeParseErrorReason {
 pub(crate) struct AttributeParseError {
     pub(crate) span: Span,
     pub(crate) attr_span: Span,
+    pub(crate) attr_style: AttrStyle,
     pub(crate) template: AttributeTemplate,
     pub(crate) attribute: AttrPath,
     pub(crate) reason: AttributeParseErrorReason,
@@ -717,7 +718,8 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
         if let Some(link) = self.template.docs {
             diag.note(format!("for more information, visit <{link}>"));
         }
-        let suggestions = self.template.suggestions(false, &name);
+        let suggestions = self.template.suggestions(self.attr_style, &name);
+
         diag.span_suggestions(
             self.attr_span,
             if suggestions.len() == 1 {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index ab6b8f92802..1f648edaa7d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -6,6 +6,7 @@ use AttributeDuplicates::*;
 use AttributeGate::*;
 use AttributeType::*;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::AttrStyle;
 use rustc_hir::attrs::EncodeCrossCrate;
 use rustc_span::edition::Edition;
 use rustc_span::{Symbol, sym};
@@ -132,9 +133,12 @@ pub struct AttributeTemplate {
 }
 
 impl AttributeTemplate {
-    pub fn suggestions(&self, inner: bool, name: impl std::fmt::Display) -> Vec<String> {
+    pub fn suggestions(&self, style: AttrStyle, name: impl std::fmt::Display) -> Vec<String> {
         let mut suggestions = vec![];
-        let inner = if inner { "!" } else { "" };
+        let inner = match style {
+            AttrStyle::Outer => "",
+            AttrStyle::Inner => "!",
+        };
         if self.word {
             suggestions.push(format!("#{inner}[{name}]"));
         }