about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJana Dönszelmann <jana@donsz.nl>2025-03-08 18:58:05 +0100
committerJana Dönszelmann <jana@donsz.nl>2025-06-17 23:22:51 +0200
commit5ab5f8a24a99cdbb178c886487d4c1971b86a32b (patch)
treefbb303eab922913bf4e4c50dea1a2c2ca1a2aad9
parent672452d573e3f499a8edc4308400a6d116974938 (diff)
downloadrust-5ab5f8a24a99cdbb178c886487d4c1971b86a32b.tar.gz
rust-5ab5f8a24a99cdbb178c886487d4c1971b86a32b.zip
make error codes reflect reality better
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/confusables.rs6
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/deprecation.rs100
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/inline.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/repr.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/stability.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs31
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs49
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0534.md8
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0535.md9
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0539.md29
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0565.md7
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0805.md26
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs9
-rw-r--r--compiler/rustc_passes/src/check_attr.rs7
-rw-r--r--tests/ui/attributes/rustc_confusables.stderr20
-rw-r--r--tests/ui/deprecation/deprecation-sanity.rs4
-rw-r--r--tests/ui/deprecation/deprecation-sanity.stderr73
-rw-r--r--tests/ui/deprecation/invalid-literal.stderr19
-rw-r--r--tests/ui/error-codes/E0534.stderr22
-rw-r--r--tests/ui/error-codes/E0539.rs (renamed from tests/ui/error-codes/E0565-2.rs)2
-rw-r--r--tests/ui/error-codes/E0539.stderr13
-rw-r--r--tests/ui/error-codes/E0540.rs (renamed from tests/ui/error-codes/E0534.rs)0
-rw-r--r--tests/ui/error-codes/E0540.stderr19
-rw-r--r--tests/ui/error-codes/E0565-1.stderr20
-rw-r--r--tests/ui/error-codes/E0565-2.stderr11
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr20
-rw-r--r--tests/ui/force-inlining/invalid.stderr32
-rw-r--r--tests/ui/invalid/invalid-inline.stderr24
-rw-r--r--tests/ui/issues/issue-43988.stderr48
-rw-r--r--tests/ui/lint/unused/unused-attr-duplicate.stderr36
-rw-r--r--tests/ui/macros/genercs-in-path-with-prettry-hir.stdout2
-rw-r--r--tests/ui/repr/repr.stderr22
-rw-r--r--tests/ui/span/E0539.rs (renamed from tests/ui/span/E0535.rs)0
-rw-r--r--tests/ui/span/E0539.stderr (renamed from tests/ui/span/E0535.stderr)11
-rw-r--r--tests/ui/stability-attribute/stability-attribute-sanity-2.stderr11
-rw-r--r--tests/ui/stability-attribute/stability-attribute-sanity.stderr44
39 files changed, 411 insertions, 341 deletions
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index 70de83f2f74..b9b386635f6 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -121,10 +121,6 @@ attr_parsing_unsupported_literal_cfg_boolean =
     literal in `cfg` predicate value must be a boolean
 attr_parsing_unsupported_literal_cfg_string =
     literal in `cfg` predicate value must be a string
-attr_parsing_unsupported_literal_deprecated_kv_pair =
-    item in `deprecated` must be a key/value pair
-attr_parsing_unsupported_literal_deprecated_string =
-    literal in `deprecated` value must be a string
 attr_parsing_unsupported_literal_generic =
     unsupported literal
 attr_parsing_unsupported_literal_suggestion =
diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs
index f4505cbc0e1..c911908dfb3 100644
--- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs
@@ -30,12 +30,12 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
             for param in list.mixed() {
                 let span = param.span();
 
-                let Some(lit) = param.lit() else {
-                    cx.expected_string_literal(span);
+                let Some(lit) = param.lit().and_then(|i| i.value_str()) else {
+                    cx.expected_string_literal(span, param.lit());
                     continue;
                 };
 
-                this.confusables.push(lit.symbol);
+                this.confusables.push(lit);
             }
 
             this.first_span.get_or_insert(cx.attr_span);
diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
index 0983a153efa..702ad66f578 100644
--- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
@@ -7,7 +7,6 @@ use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics;
-use crate::session_diagnostics::UnsupportedLiteralReason;
 
 pub(crate) struct DeprecationParser;
 
@@ -26,13 +25,7 @@ fn get<S: Stage>(
         if let Some(value_str) = v.value_as_str() {
             Some(value_str)
         } else {
-            let lit = v.value_as_lit();
-            cx.emit_err(session_diagnostics::UnsupportedLiteral {
-                span: v.value_span,
-                reason: UnsupportedLiteralReason::DeprecatedString,
-                is_bytestr: lit.kind.is_bytestr(),
-                start_point_span: cx.sess().source_map().start_point(lit.span),
-            });
+            cx.expected_string_literal(v.value_span, Some(&v.value_as_lit()));
             None
         }
     } else {
@@ -60,57 +53,60 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
 
         let is_rustc = features.staged_api();
 
-        if let Some(value) = args.name_value()
-            && let Some(value_str) = value.value_as_str()
-        {
-            note = Some(value_str)
-        } else if let Some(list) = args.list() {
-            for param in list.mixed() {
-                let param_span = param.span();
-                let Some(param) = param.meta_item() else {
-                    cx.emit_err(session_diagnostics::UnsupportedLiteral {
-                        span: param_span,
-                        reason: UnsupportedLiteralReason::DeprecatedKvPair,
-                        is_bytestr: false,
-                        start_point_span: cx.sess().source_map().start_point(param_span),
-                    });
-                    return None;
-                };
+        match args {
+            ArgParser::NoArgs => {
+                // ok
+            }
+            ArgParser::List(list) => {
+                for param in list.mixed() {
+                    let Some(param) = param.meta_item() else {
+                        cx.unexpected_literal(param.span());
+                        return None;
+                    };
 
-                let ident_name = param.path().word_sym();
+                    let ident_name = param.path().word_sym();
 
-                match ident_name {
-                    Some(name @ sym::since) => {
-                        since = Some(get(cx, name, param_span, param.args(), &since)?);
-                    }
-                    Some(name @ sym::note) => {
-                        note = Some(get(cx, name, param_span, param.args(), &note)?);
-                    }
-                    Some(name @ sym::suggestion) => {
-                        if !features.deprecated_suggestion() {
-                            cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
-                                span: param_span,
-                                is_nightly: cx.sess().is_nightly_build(),
-                                details: (),
-                            });
+                    match ident_name {
+                        Some(name @ sym::since) => {
+                            since = Some(get(cx, name, param.span(), param.args(), &since)?);
+                        }
+                        Some(name @ sym::note) => {
+                            note = Some(get(cx, name, param.span(), param.args(), &note)?);
                         }
+                        Some(name @ sym::suggestion) => {
+                            if !features.deprecated_suggestion() {
+                                cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
+                                    span: param.span(),
+                                    is_nightly: cx.sess().is_nightly_build(),
+                                    details: (),
+                                });
+                            }
 
-                        suggestion = Some(get(cx, name, param_span, param.args(), &suggestion)?);
-                    }
-                    _ => {
-                        cx.unknown_key(
-                            param_span,
-                            param.path().to_string(),
-                            if features.deprecated_suggestion() {
-                                &["since", "note", "suggestion"]
-                            } else {
-                                &["since", "note"]
-                            },
-                        );
-                        return None;
+                            suggestion =
+                                Some(get(cx, name, param.span(), param.args(), &suggestion)?);
+                        }
+                        _ => {
+                            cx.unknown_key(
+                                param.span(),
+                                param.path().to_string(),
+                                if features.deprecated_suggestion() {
+                                    &["since", "note", "suggestion"]
+                                } else {
+                                    &["since", "note"]
+                                },
+                            );
+                            return None;
+                        }
                     }
                 }
             }
+            ArgParser::NameValue(v) => {
+                let Some(value) = v.value_as_str() else {
+                    cx.expected_string_literal(v.value_span, Some(v.value_as_lit()));
+                    return None;
+                };
+                note = Some(value);
+            }
         }
 
         let since = if let Some(since) = since {
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index 75ae1d6a6c1..25efc3ae49b 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -73,7 +73,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
                 };
 
                 let Some(reason) = l.lit().and_then(|i| i.kind.str()) else {
-                    cx.expected_string_literal(l.span());
+                    cx.expected_string_literal(l.span(), l.lit());
                     return None;
                 };
 
@@ -81,7 +81,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
             }
             ArgParser::NameValue(v) => {
                 let Some(reason) = v.value_as_str() else {
-                    cx.expected_string_literal(v.value_span);
+                    cx.expected_string_literal(v.value_span, Some(v.value_as_lit()));
                     return None;
                 };
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
index 32a20d4c5b5..d4c846de56e 100644
--- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
@@ -1,4 +1,5 @@
 use rustc_attr_data_structures::AttributeKind;
+use rustc_feature::{AttributeTemplate, template};
 use rustc_span::{Symbol, sym};
 
 use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
@@ -9,10 +10,9 @@ pub(crate) struct AsPtrParser;
 
 impl<S: Stage> SingleAttributeParser<S> for AsPtrParser {
     const PATH: &[Symbol] = &[sym::rustc_as_ptr];
-
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
-
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const TEMPLATE: AttributeTemplate = template!(Word);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
         // FIXME: check that there's no args (this is currently checked elsewhere)
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index 6fb618541e3..ae9e7871874 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -34,6 +34,7 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
         let mut reprs = Vec::new();
 
         let Some(list) = args.list() else {
+            cx.expected_list(cx.attr_span);
             return reprs;
         };
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index 65de13972a0..6871ff4ec9f 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -369,7 +369,9 @@ pub(crate) fn parse_unstability<S: Stage>(
             Some(sym::implied_by) => {
                 insert_value_into_option_or_error(cx, &param, &mut implied_by, word.unwrap())?
             }
-            Some(sym::old_name) => insert_value_into_option_or_error(cx, &param, &mut old_name)?,
+            Some(sym::old_name) => {
+                insert_value_into_option_or_error(cx, &param, &mut old_name, word.unwrap())?
+            }
             _ => {
                 cx.emit_err(session_diagnostics::UnknownMetaItem {
                     span: param.span(),
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index d6dfa2c7477..51c1760da30 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -5,8 +5,7 @@ use std::ops::{Deref, DerefMut};
 use std::sync::LazyLock;
 
 use private::Sealed;
-use rustc_ast as ast;
-use rustc_ast::NodeId;
+use rustc_ast::{self as ast, MetaItemLit, NodeId};
 use rustc_attr_data_structures::AttributeKind;
 use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind};
 use rustc_errors::{DiagCtxtHandle, Diagnostic};
@@ -200,13 +199,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
         self.emit_err(UnknownMetaItem { span, item: found, expected: options })
     }
 
-    pub(crate) fn expected_string_literal(&self, span: Span) -> ErrorGuaranteed {
+    /// error that a string literal was expected.
+    /// You can optionally give the literal you did find (which you found not to be a string literal)
+    /// which can make better errors. For example, if the literal was a byte string it will suggest
+    /// removing the `b` prefix.
+    pub(crate) fn expected_string_literal(
+        &self,
+        span: Span,
+        actual_literal: Option<&MetaItemLit>,
+    ) -> ErrorGuaranteed {
         self.emit_err(AttributeParseError {
             span,
             attr_span: self.attr_span,
             template: self.template.clone(),
             attribute: self.attr_path.clone(),
-            reason: AttributeParseErrorReason::ExpectedStringLiteral,
+            reason: AttributeParseErrorReason::ExpectedStringLiteral {
+                byte_string: actual_literal.and_then(|i| {
+                    i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
+                }),
+            },
         })
     }
 
@@ -243,6 +254,18 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
         })
     }
 
+    /// an error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
+    /// was expected *not* to be a literal, but instead a meta item.
+    pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
+        self.emit_err(AttributeParseError {
+            span,
+            attr_span: self.attr_span,
+            template: self.template.clone(),
+            attribute: self.attr_path.clone(),
+            reason: AttributeParseErrorReason::UnexpectedLiteral,
+        })
+    }
+
     pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
         self.emit_err(AttributeParseError {
             span,
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 3d865c1d14e..57ac92a0ca1 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -16,8 +16,6 @@ pub(crate) enum UnsupportedLiteralReason {
     Generic,
     CfgString,
     CfgBoolean,
-    DeprecatedString,
-    DeprecatedKvPair,
 }
 
 #[derive(Diagnostic)]
@@ -190,6 +188,7 @@ pub(crate) struct InvalidReprHintNoValue {
 }
 
 /// Error code: E0565
+// FIXME(jdonszelmann): slowly phased out
 pub(crate) struct UnsupportedLiteral {
     pub span: Span,
     pub reason: UnsupportedLiteralReason,
@@ -212,12 +211,6 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
                 UnsupportedLiteralReason::CfgBoolean => {
                     fluent::attr_parsing_unsupported_literal_cfg_boolean
                 }
-                UnsupportedLiteralReason::DeprecatedString => {
-                    fluent::attr_parsing_unsupported_literal_deprecated_string
-                }
-                UnsupportedLiteralReason::DeprecatedKvPair => {
-                    fluent::attr_parsing_unsupported_literal_deprecated_kv_pair
-                }
             },
         );
         diag.span(self.span);
@@ -473,9 +466,10 @@ pub(crate) struct UnrecognizedReprHint {
 }
 
 pub(crate) enum AttributeParseErrorReason {
-    ExpectedStringLiteral,
+    ExpectedStringLiteral { byte_string: Option<Span> },
     ExpectedSingleArgument,
     ExpectedList,
+    UnexpectedLiteral,
     ExpectedNameValue(Option<Symbol>),
     DuplicateKey(Symbol),
     ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
@@ -497,27 +491,44 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
         diag.span(self.attr_span);
         diag.code(E0539);
         match self.reason {
-            AttributeParseErrorReason::ExpectedStringLiteral => {
-                diag.span_note(self.span, "expected a string literal here");
+            AttributeParseErrorReason::ExpectedStringLiteral { byte_string } => {
+                if let Some(start_point_span) = byte_string {
+                    diag.span_suggestion(
+                        start_point_span,
+                        fluent::attr_parsing_unsupported_literal_suggestion,
+                        "",
+                        Applicability::MaybeIncorrect,
+                    );
+                    diag.note("expected a normal string literal, not a byte string literal");
+
+                    return diag;
+                } else {
+                    diag.span_label(self.span, "expected a string literal here");
+                }
             }
             AttributeParseErrorReason::ExpectedSingleArgument => {
-                diag.span_note(self.span, "expected a single argument here");
+                diag.span_label(self.span, "expected a single argument here");
+                diag.code(E0805);
             }
             AttributeParseErrorReason::ExpectedList => {
-                diag.span_note(self.span, "expected this to be a list");
+                diag.span_label(self.span, "expected this to be a list");
             }
             AttributeParseErrorReason::DuplicateKey(key) => {
-                diag.span_note(self.span, format!("found `{key}` used as a key more than once"));
+                diag.span_label(self.span, format!("found `{key}` used as a key more than once"));
                 diag.code(E0538);
             }
+            AttributeParseErrorReason::UnexpectedLiteral => {
+                diag.span_label(self.span, format!("didn't expect a literal here"));
+                diag.code(E0565);
+            }
             AttributeParseErrorReason::ExpectedNameValue(None) => {
-                diag.span_note(
+                diag.span_label(
                     self.span,
                     format!("expected this to be of the form `{name} = \"...\"`"),
                 );
             }
             AttributeParseErrorReason::ExpectedNameValue(Some(name)) => {
-                diag.span_note(
+                diag.span_label(
                     self.span,
                     format!("expected this to be of the form `{name} = \"...\"`"),
                 );
@@ -527,13 +538,13 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
                 match possibilities.as_slice() {
                     &[] => {}
                     &[x] => {
-                        diag.span_note(
+                        diag.span_label(
                             self.span,
                             format!("the only valid argument here is {quote}{x}{quote}"),
                         );
                     }
                     [first, second] => {
-                        diag.span_note(self.span, format!("valid arguments are {quote}{first}{quote} or {quote}{second}{quote}"));
+                        diag.span_label(self.span, format!("valid arguments are {quote}{first}{quote} or {quote}{second}{quote}"));
                     }
                     [first @ .., second_to_last, last] => {
                         let mut res = String::new();
@@ -544,7 +555,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
                             "{quote}{second_to_last}{quote} or {quote}{last}{quote}"
                         ));
 
-                        diag.span_note(self.span, format!("valid arguments are {res}"));
+                        diag.span_label(self.span, format!("valid arguments are {res}"));
                     }
                 }
             }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0534.md b/compiler/rustc_error_codes/src/error_codes/E0534.md
index 1ca9411b8d4..023c38c730c 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0534.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0534.md
@@ -1,8 +1,14 @@
+#### Note: this error code is no longer emitted by the compiler
+
+This is because it was too specific to the `inline` attribute.
+Similar diagnostics occur for other attributes too.
+The example here will now emit `E0805`
+
 The `inline` attribute was malformed.
 
 Erroneous code example:
 
-```compile_fail,E0534
+```compile_fail,E0805
 #[inline()] // error: expected one argument
 pub fn something() {}
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0535.md b/compiler/rustc_error_codes/src/error_codes/E0535.md
index 0cf3118b02c..93e2ba53826 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0535.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0535.md
@@ -1,8 +1,13 @@
-An unknown argument was given to the `inline` attribute.
+#### Note: this error code is no longer emitted by the compiler
+
+This is because it was too specific to the `inline` attribute.
+Similar diagnostics occur for other attributes too.
+The example here will now emit `E0539`
+
 
 Erroneous code example:
 
-```compile_fail,E0535
+```compile_fail,E0539
 #[inline(unknown)] // error: invalid argument
 pub fn something() {}
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0539.md b/compiler/rustc_error_codes/src/error_codes/E0539.md
index 6b2e23ba2d8..c76b60ac108 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0539.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0539.md
@@ -24,8 +24,7 @@ struct Stable;
 const fn stable_fn() {}
 ```
 
-Meta items are the key-value pairs inside of an attribute.
-To fix these issues you need to give required key-value pairs.
+To fix the above example, you can write the following:
 
 ```
 #![feature(staged_api)]
@@ -49,3 +48,29 @@ struct Stable;
 #[rustc_const_stable(feature = "stable_fn", since = "1.39.0")] // ok!
 const fn stable_fn() {}
 ```
+
+Several causes of this are,
+an attribute may have expected you to give a list but you gave a
+`name = value` pair:
+
+```compile_fail,E0539
+// wrong, should be `#[repr(C)]`
+#[repr = "C"]
+struct Foo {}
+```
+
+Or a `name = value` pair, but you gave a list:
+
+```compile_fail,E0539
+// wrong, should be `note = "reason"`
+#[deprecated(since = "1.0.0", note("reason"))]
+struct Foo {}
+```
+
+Or it expected some specific word but you gave an unexpected one:
+
+```compile_fail,E0539
+// should be `always` or `never`
+#[inline(maybe_if_you_feel_like_it)]
+fn foo() {}
+```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0565.md b/compiler/rustc_error_codes/src/error_codes/E0565.md
index d5bba941c1d..34152eb7cfe 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0565.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0565.md
@@ -9,10 +9,9 @@ struct Repr {}
 fn main() {}
 ```
 
-Literals in attributes are new and largely unsupported in built-in attributes.
-Work to support literals where appropriate is ongoing. Try using an unquoted
-name instead:
-
+Not all attributes support literals in their input,
+and in some cases they expect an identifier instead.
+That would be the solution in the case of `repr`:
 ```
 #[repr(C)] // ok!
 struct Repr {}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0805.md b/compiler/rustc_error_codes/src/error_codes/E0805.md
new file mode 100644
index 00000000000..b1ed3a11d48
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0805.md
@@ -0,0 +1,26 @@
+An attribute was given an invalid number of arguments
+
+Erroneous code example:
+
+```compile_fail,E0805
+#[inline()] // error! should either have a single argument, or no parentheses
+fn foo() {}
+
+#[inline(always, never)] // error! should have only one argument, not two
+fn bar() {}
+```
+
+To fix this, either give the right number of arguments the attribute needs.
+In the case of inline, this could be none at all:
+
+```
+#[inline]
+fn foo() {}
+```
+
+or only one:
+
+```
+#[inline(always)]
+fn foo() {}
+```
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 2488d870899..6f5e4829802 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -547,6 +547,7 @@ E0801: 0801,
 E0802: 0802,
 E0803: 0803,
 E0804: 0804,
+E0805: 0805,
         );
     )
 }
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 2296ec10432..b3096e46b09 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -283,7 +283,14 @@ fn emit_malformed_attribute(
     template: AttributeTemplate,
 ) {
     // attrs with new parsers are locally validated so excluded here
-    if matches!(name, sym::inline | sym::rustc_force_inline | sym::rustc_confusables) {
+    if matches!(
+        name,
+        sym::inline
+            | sym::rustc_force_inline
+            | sym::rustc_confusables
+            | sym::repr
+            | sym::deprecated
+    ) {
         return;
     }
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index d543abb5411..5ce803aa1f8 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -728,13 +728,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     }
                 }
             }
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[naked]` attribute with just a lint, because we previously
-            // erroneously allowed it and some crates used it accidentally, to be compatible
-            // with crates depending on them, we can't throw an error here.
-            Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "naked")
-            }
             _ => {
                 self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span(),
diff --git a/tests/ui/attributes/rustc_confusables.stderr b/tests/ui/attributes/rustc_confusables.stderr
index be16da2f873..3ed4efeb4db 100644
--- a/tests/ui/attributes/rustc_confusables.stderr
+++ b/tests/ui/attributes/rustc_confusables.stderr
@@ -8,25 +8,19 @@ error[E0539]: malformed `rustc_confusables` attribute input
   --> $DIR/rustc_confusables.rs:34:5
    |
 LL |     #[rustc_confusables]
-   |     ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]`
-   |
-note: expected this to be a list
-  --> $DIR/rustc_confusables.rs:34:5
-   |
-LL |     #[rustc_confusables]
    |     ^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected this to be a list
+   |     help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]`
 
 error[E0539]: malformed `rustc_confusables` attribute input
   --> $DIR/rustc_confusables.rs:39:5
    |
 LL |     #[rustc_confusables(invalid_meta_item)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]`
-   |
-note: expected a string literal here
-  --> $DIR/rustc_confusables.rs:39:25
-   |
-LL |     #[rustc_confusables(invalid_meta_item)]
-   |                         ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^-----------------^^
+   |     |                   |
+   |     |                   expected a string literal here
+   |     help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]`
 
 error: attribute should be applied to an inherent method
   --> $DIR/rustc_confusables.rs:45:1
diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs
index e40b017378a..80198ab8196 100644
--- a/tests/ui/deprecation/deprecation-sanity.rs
+++ b/tests/ui/deprecation/deprecation-sanity.rs
@@ -16,10 +16,10 @@ mod bogus_attribute_types_1 {
     #[deprecated(since(b), note = "a")] //~ ERROR malformed `deprecated` attribute input [E0539]
     fn f6() { }
 
-    #[deprecated(note = b"test")] //~ ERROR literal in `deprecated` value must be a string
+    #[deprecated(note = b"test")] //~ ERROR malformed `deprecated` attribute input [E0539]
     fn f7() { }
 
-    #[deprecated("test")] //~ ERROR item in `deprecated` must be a key/value pair
+    #[deprecated("test")] //~ ERROR malformed `deprecated` attribute input [E0565]
     fn f8() { }
 }
 
diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr
index 8854ebb70d2..f1b4697485c 100644
--- a/tests/ui/deprecation/deprecation-sanity.stderr
+++ b/tests/ui/deprecation/deprecation-sanity.stderr
@@ -8,13 +8,10 @@ error[E0539]: malformed `deprecated` attribute input
   --> $DIR/deprecation-sanity.rs:7:5
    |
 LL |     #[deprecated(since = "a", note)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^----^^
+   |                               |
+   |                               expected this to be of the form `note = "..."`
    |
-note: expected this to be of the form `note = "..."`
-  --> $DIR/deprecation-sanity.rs:7:31
-   |
-LL |     #[deprecated(since = "a", note)]
-   |                               ^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[deprecated(since = "a", note)]
@@ -31,13 +28,10 @@ error[E0539]: malformed `deprecated` attribute input
   --> $DIR/deprecation-sanity.rs:10:5
    |
 LL |     #[deprecated(since, note = "a")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: expected this to be of the form `since = "..."`
-  --> $DIR/deprecation-sanity.rs:10:18
+   |     ^^^^^^^^^^^^^-----^^^^^^^^^^^^^^
+   |                  |
+   |                  expected this to be of the form `since = "..."`
    |
-LL |     #[deprecated(since, note = "a")]
-   |                  ^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[deprecated(since, note = "a")]
@@ -54,13 +48,10 @@ error[E0539]: malformed `deprecated` attribute input
   --> $DIR/deprecation-sanity.rs:13:5
    |
 LL |     #[deprecated(since = "a", note(b))]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: expected this to be of the form `note = "..."`
-  --> $DIR/deprecation-sanity.rs:13:31
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
+   |                               |
+   |                               expected this to be of the form `note = "..."`
    |
-LL |     #[deprecated(since = "a", note(b))]
-   |                               ^^^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[deprecated(since = "a", note(b))]
@@ -77,13 +68,10 @@ error[E0539]: malformed `deprecated` attribute input
   --> $DIR/deprecation-sanity.rs:16:5
    |
 LL |     #[deprecated(since(b), note = "a")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^--------^^^^^^^^^^^^^^
+   |                  |
+   |                  expected this to be of the form `since = "..."`
    |
-note: expected this to be of the form `since = "..."`
-  --> $DIR/deprecation-sanity.rs:16:18
-   |
-LL |     #[deprecated(since(b), note = "a")]
-   |                  ^^^^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[deprecated(since(b), note = "a")]
@@ -96,19 +84,35 @@ LL -     #[deprecated(since(b), note = "a")]
 LL +     #[deprecated]
    |
 
-error[E0565]: literal in `deprecated` value must be a string
-  --> $DIR/deprecation-sanity.rs:19:25
+error[E0539]: malformed `deprecated` attribute input
+  --> $DIR/deprecation-sanity.rs:19:5
    |
 LL |     #[deprecated(note = b"test")]
-   |                         -^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^-^^^^^^^^
    |                         |
    |                         help: consider removing the prefix
+   |
+   = note: expected a normal string literal, not a byte string literal
 
-error[E0565]: item in `deprecated` must be a key/value pair
-  --> $DIR/deprecation-sanity.rs:22:18
+error[E0565]: malformed `deprecated` attribute input
+  --> $DIR/deprecation-sanity.rs:22:5
    |
 LL |     #[deprecated("test")]
-   |                  ^^^^^^
+   |     ^^^^^^^^^^^^^------^^
+   |                  |
+   |                  didn't expect a literal here
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL -     #[deprecated("test")]
+LL +     #[deprecated = "reason"]
+   |
+LL -     #[deprecated("test")]
+LL +     #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")]
+   |
+LL -     #[deprecated("test")]
+LL +     #[deprecated]
+   |
 
 error: multiple `deprecated` attributes
   --> $DIR/deprecation-sanity.rs:27:1
@@ -126,13 +130,10 @@ error[E0538]: malformed `deprecated` attribute input
   --> $DIR/deprecation-sanity.rs:30:1
    |
 LL | #[deprecated(since = "a", since = "b", note = "c")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^
+   |                           |
+   |                           found `since` used as a key more than once
    |
-note: found `since` used as a key more than once
-  --> $DIR/deprecation-sanity.rs:30:27
-   |
-LL | #[deprecated(since = "a", since = "b", note = "c")]
-   |                           ^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[deprecated(since = "a", since = "b", note = "c")]
diff --git a/tests/ui/deprecation/invalid-literal.stderr b/tests/ui/deprecation/invalid-literal.stderr
index cbe1fcca023..6f25aebc315 100644
--- a/tests/ui/deprecation/invalid-literal.stderr
+++ b/tests/ui/deprecation/invalid-literal.stderr
@@ -1,20 +1,13 @@
-error: malformed `deprecated` attribute input
+error[E0539]: malformed `deprecated` attribute input
   --> $DIR/invalid-literal.rs:1:1
    |
 LL | #[deprecated = b"test"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL - #[deprecated = b"test"]
-LL + #[deprecated = "reason"]
-   |
-LL - #[deprecated = b"test"]
-LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")]
-   |
-LL - #[deprecated = b"test"]
-LL + #[deprecated]
+   | ^^^^^^^^^^^^^^^-^^^^^^^
+   |                |
+   |                help: consider removing the prefix
    |
+   = note: expected a normal string literal, not a byte string literal
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/error-codes/E0534.stderr b/tests/ui/error-codes/E0534.stderr
deleted file mode 100644
index de97ef18b73..00000000000
--- a/tests/ui/error-codes/E0534.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0539]: malformed `inline` attribute input
-  --> $DIR/E0534.rs:1:1
-   |
-LL | #[inline()]
-   | ^^^^^^^^^^^
-   |
-note: expected a single argument here
-  --> $DIR/E0534.rs:1:9
-   |
-LL | #[inline()]
-   |         ^^
-help: try changing it to one of the following valid forms of the attribute
-   |
-LL | #[inline(always|never)]
-   |          ++++++++++++
-LL - #[inline()]
-LL + #[inline]
-   |
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/error-codes/E0565-2.rs b/tests/ui/error-codes/E0539.rs
index 0319ecb11f9..0e2c537f473 100644
--- a/tests/ui/error-codes/E0565-2.rs
+++ b/tests/ui/error-codes/E0539.rs
@@ -1,5 +1,5 @@
 // repr currently doesn't support literals
-#[deprecated(since = b"1.29", note = "hi")] //~ ERROR E0565
+#[deprecated(since = b"1.29", note = "hi")] //~ ERROR E0539
 struct A {  }
 
 fn main() {  }
diff --git a/tests/ui/error-codes/E0539.stderr b/tests/ui/error-codes/E0539.stderr
new file mode 100644
index 00000000000..18ed1c23b40
--- /dev/null
+++ b/tests/ui/error-codes/E0539.stderr
@@ -0,0 +1,13 @@
+error[E0539]: malformed `deprecated` attribute input
+  --> $DIR/E0539.rs:2:1
+   |
+LL | #[deprecated(since = b"1.29", note = "hi")]
+   | ^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^
+   |                      |
+   |                      help: consider removing the prefix
+   |
+   = note: expected a normal string literal, not a byte string literal
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/error-codes/E0534.rs b/tests/ui/error-codes/E0540.rs
index db29e6801f5..db29e6801f5 100644
--- a/tests/ui/error-codes/E0534.rs
+++ b/tests/ui/error-codes/E0540.rs
diff --git a/tests/ui/error-codes/E0540.stderr b/tests/ui/error-codes/E0540.stderr
new file mode 100644
index 00000000000..3e5f408feb5
--- /dev/null
+++ b/tests/ui/error-codes/E0540.stderr
@@ -0,0 +1,19 @@
+error[E0805]: malformed `inline` attribute input
+  --> $DIR/E0540.rs:1:1
+   |
+LL | #[inline()]
+   | ^^^^^^^^--^
+   |         |
+   |         expected a single argument here
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[inline(always|never)]
+   |          ++++++++++++
+LL - #[inline()]
+LL + #[inline]
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0805`.
diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr
index 806eed2a632..6277e6400d7 100644
--- a/tests/ui/error-codes/E0565-1.stderr
+++ b/tests/ui/error-codes/E0565-1.stderr
@@ -1,8 +1,22 @@
-error[E0565]: item in `deprecated` must be a key/value pair
-  --> $DIR/E0565-1.rs:2:14
+error[E0565]: malformed `deprecated` attribute input
+  --> $DIR/E0565-1.rs:2:1
    |
 LL | #[deprecated("since")]
-   |              ^^^^^^^
+   | ^^^^^^^^^^^^^-------^^
+   |              |
+   |              didn't expect a literal here
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[deprecated("since")]
+LL + #[deprecated = "reason"]
+   |
+LL - #[deprecated("since")]
+LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")]
+   |
+LL - #[deprecated("since")]
+LL + #[deprecated]
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0565-2.stderr b/tests/ui/error-codes/E0565-2.stderr
deleted file mode 100644
index 42199351c3d..00000000000
--- a/tests/ui/error-codes/E0565-2.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0565]: literal in `deprecated` value must be a string
-  --> $DIR/E0565-2.rs:2:22
-   |
-LL | #[deprecated(since = b"1.29", note = "hi")]
-   |                      -^^^^^^
-   |                      |
-   |                      help: consider removing the prefix
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0565`.
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 a9ef0bbc6e7..1620bf72922 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
@@ -8,16 +8,6 @@ LL | #![rustc_main]
    = note: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable
    = note: the `#[rustc_main]` attribute is used internally to specify test entry point function
 
-error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
-   |
-LL |     #[inline = "2100"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: `#[deny(ill_formed_attribute_input)]` on by default
-
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1
    |
@@ -314,6 +304,16 @@ error[E0517]: attribute should be applied to a struct, enum, or union
 LL |     #[repr(Rust)] impl S { }
    |            ^^^^   ---------- not a struct, enum, or union
 
+error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
+   |
+LL |     #[inline = "2100"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(ill_formed_attribute_input)]` on by default
+
 error: aborting due to 38 previous errors
 
 Some errors have detailed explanations: E0517, E0518, E0658.
diff --git a/tests/ui/force-inlining/invalid.stderr b/tests/ui/force-inlining/invalid.stderr
index a12f633b3f2..3b3da00ae88 100644
--- a/tests/ui/force-inlining/invalid.stderr
+++ b/tests/ui/force-inlining/invalid.stderr
@@ -4,17 +4,14 @@ error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed
 LL | fn barqux(#[rustc_force_inline] _x: u32) {}
    |           ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0539]: malformed `rustc_force_inline` attribute input
+error[E0805]: malformed `rustc_force_inline` attribute input
   --> $DIR/invalid.rs:15:1
    |
 LL | #[rustc_force_inline(bar, baz)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: expected a single argument here
-  --> $DIR/invalid.rs:15:21
+   | ^^^^^^^^^^^^^^^^^^^^----------^
+   |                     |
+   |                     expected a single argument here
    |
-LL | #[rustc_force_inline(bar, baz)]
-   |                     ^^^^^^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[rustc_force_inline(bar, baz)]
@@ -31,13 +28,10 @@ error[E0539]: malformed `rustc_force_inline` attribute input
   --> $DIR/invalid.rs:20:1
    |
 LL | #[rustc_force_inline(2)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: expected a string literal here
-  --> $DIR/invalid.rs:20:22
+   | ^^^^^^^^^^^^^^^^^^^^^-^^
+   |                      |
+   |                      expected a string literal here
    |
-LL | #[rustc_force_inline(2)]
-   |                      ^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[rustc_force_inline(2)]
@@ -54,13 +48,10 @@ error[E0539]: malformed `rustc_force_inline` attribute input
   --> $DIR/invalid.rs:25:1
    |
 LL | #[rustc_force_inline = 2]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: expected a string literal here
-  --> $DIR/invalid.rs:25:24
+   | ^^^^^^^^^^^^^^^^^^^^^^^-^
+   |                        |
+   |                        expected a string literal here
    |
-LL | #[rustc_force_inline = 2]
-   |                        ^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[rustc_force_inline = 2]
@@ -392,4 +383,5 @@ LL |     fn foo();
 
 error: aborting due to 37 previous errors
 
-For more information about this error, try `rustc --explain E0539`.
+Some errors have detailed explanations: E0539, E0805.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/invalid/invalid-inline.stderr b/tests/ui/invalid/invalid-inline.stderr
index 8a230351d32..54e6b2b5408 100644
--- a/tests/ui/invalid/invalid-inline.stderr
+++ b/tests/ui/invalid/invalid-inline.stderr
@@ -1,14 +1,11 @@
-error[E0539]: malformed `inline` attribute input
+error[E0805]: malformed `inline` attribute input
   --> $DIR/invalid-inline.rs:3:1
    |
 LL | #[inline(please,no)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^-----------^
+   |         |
+   |         expected a single argument here
    |
-note: expected a single argument here
-  --> $DIR/invalid-inline.rs:3:9
-   |
-LL | #[inline(please,no)]
-   |         ^^^^^^^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[inline(please,no)]
@@ -18,17 +15,14 @@ LL - #[inline(please,no)]
 LL + #[inline]
    |
 
-error[E0539]: malformed `inline` attribute input
+error[E0805]: malformed `inline` attribute input
   --> $DIR/invalid-inline.rs:7:1
    |
 LL | #[inline()]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^--^
+   |         |
+   |         expected a single argument here
    |
-note: expected a single argument here
-  --> $DIR/invalid-inline.rs:7:9
-   |
-LL | #[inline()]
-   |         ^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[inline(always|never)]
@@ -39,4 +33,4 @@ LL + #[inline]
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0539`.
+For more information about this error, try `rustc --explain E0805`.
diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr
index 8e731db6f2e..bd4eb8bbed3 100644
--- a/tests/ui/issues/issue-43988.stderr
+++ b/tests/ui/issues/issue-43988.stderr
@@ -1,26 +1,11 @@
-error: malformed `repr` attribute input
-  --> $DIR/issue-43988.rs:24:5
-   |
-LL |     #[repr]
-   |     ^^^^^^^ help: must be of the form: `#[repr(C)]`
-
-error: malformed `repr` attribute input
-  --> $DIR/issue-43988.rs:34:14
-   |
-LL |     let _z = #[repr] 1;
-   |              ^^^^^^^ help: must be of the form: `#[repr(C)]`
-
 error[E0539]: malformed `inline` attribute input
   --> $DIR/issue-43988.rs:10:5
    |
 LL |     #[inline(XYZ)]
-   |     ^^^^^^^^^^^^^^
+   |     ^^^^^^^^^---^^
+   |              |
+   |              valid arguments are `always` or `never`
    |
-note: valid arguments are `always` or `never`
-  --> $DIR/issue-43988.rs:10:14
-   |
-LL |     #[inline(XYZ)]
-   |              ^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[inline(XYZ)]
@@ -46,17 +31,23 @@ LL |     #[repr(something_not_real)]
    |
    = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
 
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/issue-43988.rs:24:5
+   |
+LL |     #[repr]
+   |     ^^^^^^^
+   |     |
+   |     expected this to be a list
+   |     help: must be of the form: `#[repr(C)]`
+
 error[E0539]: malformed `inline` attribute input
   --> $DIR/issue-43988.rs:30:5
    |
 LL |     #[inline(ABC)]
-   |     ^^^^^^^^^^^^^^
-   |
-note: valid arguments are `always` or `never`
-  --> $DIR/issue-43988.rs:30:14
+   |     ^^^^^^^^^---^^
+   |              |
+   |              valid arguments are `always` or `never`
    |
-LL |     #[inline(ABC)]
-   |              ^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[inline(ABC)]
@@ -66,6 +57,15 @@ LL -     #[inline(ABC)]
 LL +     #[inline]
    |
 
+error[E0539]: malformed `repr` attribute input
+  --> $DIR/issue-43988.rs:34:14
+   |
+LL |     let _z = #[repr] 1;
+   |              ^^^^^^^
+   |              |
+   |              expected this to be a list
+   |              help: must be of the form: `#[repr(C)]`
+
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43988.rs:5:5
    |
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 5ea623a713e..e1c45e832af 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -1,22 +1,4 @@
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:74:1
-   |
-LL | #[inline(never)]
-   | ^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:73:1
-   |
-LL | #[inline(always)]
-   | ^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-note: the lint level is defined here
-  --> $DIR/unused-attr-duplicate.rs:12:9
-   |
-LL | #![deny(unused_attributes)]
-   |         ^^^^^^^^^^^^^^^^^
-
-error: unused attribute
   --> $DIR/unused-attr-duplicate.rs:33:1
    |
 LL | #[no_link]
@@ -27,6 +9,11 @@ note: attribute also specified here
    |
 LL | #[no_link]
    | ^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/unused-attr-duplicate.rs:12:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
 
 error: unused attribute
   --> $DIR/unused-attr-duplicate.rs:37:1
@@ -289,5 +276,18 @@ note: attribute also specified here
 LL |     #[macro_export]
    |     ^^^^^^^^^^^^^^^
 
+error: unused attribute
+  --> $DIR/unused-attr-duplicate.rs:74:1
+   |
+LL | #[inline(never)]
+   | ^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/unused-attr-duplicate.rs:73:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
 error: aborting due to 23 previous errors
 
diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
index 834954d8dc0..7c41225f95e 100644
--- a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
+++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout
@@ -8,7 +8,7 @@ extern crate std;
 // issue#97006
 
 macro_rules! m { ($attr_path: path) => { #[$attr_path] fn f() {} } }
-#[attr="Inline(Hint)")]
+#[attr = Inline(Hint)]
 fn f() { }
 
 fn main() { }
diff --git a/tests/ui/repr/repr.stderr b/tests/ui/repr/repr.stderr
index e0bec666381..f3b11398eaa 100644
--- a/tests/ui/repr/repr.stderr
+++ b/tests/ui/repr/repr.stderr
@@ -1,20 +1,30 @@
-error: malformed `repr` attribute input
+error[E0539]: malformed `repr` attribute input
   --> $DIR/repr.rs:1:1
    |
 LL | #[repr]
-   | ^^^^^^^ help: must be of the form: `#[repr(C)]`
+   | ^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[repr(C)]`
 
-error: malformed `repr` attribute input
+error[E0539]: malformed `repr` attribute input
   --> $DIR/repr.rs:4:1
    |
 LL | #[repr = "B"]
-   | ^^^^^^^^^^^^^ help: must be of the form: `#[repr(C)]`
+   | ^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[repr(C)]`
 
-error: malformed `repr` attribute input
+error[E0539]: malformed `repr` attribute input
   --> $DIR/repr.rs:7:1
    |
 LL | #[repr = "C"]
-   | ^^^^^^^^^^^^^ help: must be of the form: `#[repr(C)]`
+   | ^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[repr(C)]`
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/span/E0535.rs b/tests/ui/span/E0539.rs
index e0c6dbfc591..e0c6dbfc591 100644
--- a/tests/ui/span/E0535.rs
+++ b/tests/ui/span/E0539.rs
diff --git a/tests/ui/span/E0535.stderr b/tests/ui/span/E0539.stderr
index fb0b72c0001..01f091a2676 100644
--- a/tests/ui/span/E0535.stderr
+++ b/tests/ui/span/E0539.stderr
@@ -1,14 +1,11 @@
 error[E0539]: malformed `inline` attribute input
-  --> $DIR/E0535.rs:1:1
+  --> $DIR/E0539.rs:1:1
    |
 LL | #[inline(unknown)]
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^-------^^
+   |          |
+   |          valid arguments are `always` or `never`
    |
-note: valid arguments are `always` or `never`
-  --> $DIR/E0535.rs:1:10
-   |
-LL | #[inline(unknown)]
-   |          ^^^^^^^
 help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[inline(unknown)]
diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr
index 412af87bad6..5b35a51cad7 100644
--- a/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr
+++ b/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr
@@ -2,13 +2,10 @@ error[E0538]: malformed `stable` attribute input
   --> $DIR/stability-attribute-sanity-2.rs:7:1
    |
 LL | #[stable(feature = "a", feature = "b", since = "1.0.0")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]`
-   |
-note: found `feature` used as a key more than once
-  --> $DIR/stability-attribute-sanity-2.rs:7:25
-   |
-LL | #[stable(feature = "a", feature = "b", since = "1.0.0")]
-   |                         ^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |                       |
+   | |                       found `feature` used as a key more than once
+   | help: must be of the form: `#[stable(feature = "name", since = "version")]`
 
 error[E0541]: unknown meta item 'sinse'
   --> $DIR/stability-attribute-sanity-2.rs:10:25
diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.stderr b/tests/ui/stability-attribute/stability-attribute-sanity.stderr
index 86284b0c1b8..ae948237d7e 100644
--- a/tests/ui/stability-attribute/stability-attribute-sanity.stderr
+++ b/tests/ui/stability-attribute/stability-attribute-sanity.stderr
@@ -8,49 +8,37 @@ error[E0539]: malformed `stable` attribute input
   --> $DIR/stability-attribute-sanity.rs:11:5
    |
 LL |     #[stable(feature = "a", since)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]`
-   |
-note: expected this to be of the form `since = "..."`
-  --> $DIR/stability-attribute-sanity.rs:11:29
-   |
-LL |     #[stable(feature = "a", since)]
-   |                             ^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^-----^^
+   |     |                       |
+   |     |                       expected this to be of the form `since = "..."`
+   |     help: must be of the form: `#[stable(feature = "name", since = "version")]`
 
 error[E0539]: malformed `stable` attribute input
   --> $DIR/stability-attribute-sanity.rs:14:5
    |
 LL |     #[stable(feature, since = "3.3.3")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]`
-   |
-note: expected this to be of the form `feature = "..."`
-  --> $DIR/stability-attribute-sanity.rs:14:14
-   |
-LL |     #[stable(feature, since = "3.3.3")]
-   |              ^^^^^^^
+   |     ^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^
+   |     |        |
+   |     |        expected this to be of the form `feature = "..."`
+   |     help: must be of the form: `#[stable(feature = "name", since = "version")]`
 
 error[E0539]: malformed `stable` attribute input
   --> $DIR/stability-attribute-sanity.rs:17:5
    |
 LL |     #[stable(feature = "a", since(b))]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]`
-   |
-note: expected this to be of the form `since = "..."`
-  --> $DIR/stability-attribute-sanity.rs:17:29
-   |
-LL |     #[stable(feature = "a", since(b))]
-   |                             ^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^--------^^
+   |     |                       |
+   |     |                       expected this to be of the form `since = "..."`
+   |     help: must be of the form: `#[stable(feature = "name", since = "version")]`
 
 error[E0539]: malformed `stable` attribute input
   --> $DIR/stability-attribute-sanity.rs:20:5
    |
 LL |     #[stable(feature(b), since = "3.3.3")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]`
-   |
-note: expected this to be of the form `feature = "..."`
-  --> $DIR/stability-attribute-sanity.rs:20:14
-   |
-LL |     #[stable(feature(b), since = "3.3.3")]
-   |              ^^^^^^^^^^
+   |     ^^^^^^^^^----------^^^^^^^^^^^^^^^^^^^
+   |     |        |
+   |     |        expected this to be of the form `feature = "..."`
+   |     help: must be of the form: `#[stable(feature = "name", since = "version")]`
 
 error[E0546]: missing 'feature'
   --> $DIR/stability-attribute-sanity.rs:25:5