about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-14 19:38:35 +0000
committerbors <bors@rust-lang.org>2025-08-14 19:38:35 +0000
commit898aff704d6f0d00343f21d31b8b9bfac8e43007 (patch)
tree966f8de19d1da441a9b1fa865fd3245a6e2a711a
parentbe00ea1968d8d5afb5d93d2dedeb97a8bba300cb (diff)
parent4bb7bf64e07fee97439ee6e647aa2b58cbaac54d (diff)
downloadrust-898aff704d6f0d00343f21d31b8b9bfac8e43007.tar.gz
rust-898aff704d6f0d00343f21d31b8b9bfac8e43007.zip
Auto merge of #145085 - JonathanBrouwer:target_checking, r=jdonszelmann
Rework target checking for built-in attributes

This is a refactoring of target checking for built-in attributes.
This PR has the following goals:
- Only refactor the 80% of the attributes that are simple to target check. More complicated ones like `#[repr]` will be in a future PR. Tho I have written the code in such a way that this will be possible to add in the future.
- No breaking changes.
  - This part of the codebase is not very well tested though, we can do a crater run if we want to be sure.
  - I've spotted quite a few weird situations (like I don't think an impl block should be deprecated?). We can propose fixing these to  in a future PR

Fixes https://github.com/rust-lang/rust/issues/143780
Fixes https://github.com/rust-lang/rust/issues/138510

I've split it in commits and left a description on some of the commits to help review.
r? `@jdonszelmann`
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast_lowering/src/block.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs31
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs4
-rw-r--r--compiler/rustc_attr_parsing/Cargo.toml1
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl6
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs22
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/body.rs5
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs77
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/confusables.rs7
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/deprecation.rs29
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/dummy.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/inline.rs20
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/link_attrs.rs32
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs27
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/loop_match.rs7
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs19
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs21
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/must_use.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs7
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs13
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/path.rs7
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs12
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/repr.rs17
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/semantics.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/stability.rs43
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/test_attrs.rs9
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs26
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/transparency.rs6
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs243
-rw-r--r--compiler/rustc_attr_parsing/src/lints.rs23
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs23
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl2
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs7
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0518.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0701.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0739.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0755.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0756.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0788.md4
-rw-r--r--compiler/rustc_hir/src/hir.rs14
-rw-r--r--compiler/rustc_hir/src/lints.rs5
-rw-r--r--compiler/rustc_hir/src/target.rs152
-rw-r--r--compiler/rustc_passes/messages.ftl152
-rw-r--r--compiler/rustc_passes/src/check_attr.rs943
-rw-r--r--compiler/rustc_passes/src/errors.rs298
-rw-r--r--compiler/rustc_passes/src/lang_items.rs2
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs2
-rw-r--r--tests/crashes/138510.rs7
-rw-r--r--tests/rustdoc-ui/check-doc-alias-attr-location.stderr4
-rw-r--r--tests/ui/asm/naked-invalid-attr.rs12
-rw-r--r--tests/ui/asm/naked-invalid-attr.stderr73
-rw-r--r--tests/ui/attributes/attrs-on-params.rs2
-rw-r--r--tests/ui/attributes/attrs-on-params.stderr9
-rw-r--r--tests/ui/attributes/cold-attribute-application-54044.rs12
-rw-r--r--tests/ui/attributes/cold-attribute-application-54044.stderr12
-rw-r--r--tests/ui/attributes/empty-repr.rs14
-rw-r--r--tests/ui/attributes/empty-repr.stderr14
-rw-r--r--tests/ui/attributes/inline-attribute-enum-variant-error.rs2
-rw-r--r--tests/ui/attributes/inline-attribute-enum-variant-error.stderr8
-rw-r--r--tests/ui/attributes/inline/attr-usage-inline.rs2
-rw-r--r--tests/ui/attributes/inline/attr-usage-inline.stderr6
-rw-r--r--tests/ui/attributes/issue-105594-invalid-attr-validation.rs2
-rw-r--r--tests/ui/attributes/issue-105594-invalid-attr-validation.stderr7
-rw-r--r--tests/ui/attributes/linkage.rs12
-rw-r--r--tests/ui/attributes/linkage.stderr49
-rw-r--r--tests/ui/attributes/lint_on_root.rs1
-rw-r--r--tests/ui/attributes/lint_on_root.stderr10
-rw-r--r--tests/ui/attributes/malformed-attrs.rs5
-rw-r--r--tests/ui/attributes/malformed-attrs.stderr186
-rw-r--r--tests/ui/attributes/malformed-fn-align.rs10
-rw-r--r--tests/ui/attributes/malformed-fn-align.stderr50
-rw-r--r--tests/ui/attributes/multiple-invalid.rs4
-rw-r--r--tests/ui/attributes/multiple-invalid.stderr23
-rw-r--r--tests/ui/attributes/optimize.rs8
-rw-r--r--tests/ui/attributes/optimize.stderr30
-rw-r--r--tests/ui/attributes/positions/used.rs10
-rw-r--r--tests/ui/attributes/positions/used.stderr30
-rw-r--r--tests/ui/attributes/rustc_confusables.rs3
-rw-r--r--tests/ui/attributes/rustc_confusables.stderr4
-rw-r--r--tests/ui/attributes/rustc_skip_during_method_dispatch.rs2
-rw-r--r--tests/ui/attributes/rustc_skip_during_method_dispatch.stderr7
-rw-r--r--tests/ui/coroutine/invalid_attr_usage.rs4
-rw-r--r--tests/ui/coroutine/invalid_attr_usage.stderr8
-rw-r--r--tests/ui/coverage-attr/allowed-positions.rs34
-rw-r--r--tests/ui/coverage-attr/allowed-positions.stderr163
-rw-r--r--tests/ui/coverage-attr/name-value.rs7
-rw-r--r--tests/ui/coverage-attr/name-value.stderr76
-rw-r--r--tests/ui/coverage-attr/word-only.rs7
-rw-r--r--tests/ui/coverage-attr/word-only.stderr76
-rw-r--r--tests/ui/deprecation/deprecation-sanity.rs5
-rw-r--r--tests/ui/deprecation/deprecation-sanity.stderr28
-rw-r--r--tests/ui/error-codes/E0518.rs9
-rw-r--r--tests/ui/error-codes/E0518.stderr20
-rw-r--r--tests/ui/error-codes/E0718.stderr2
-rw-r--r--tests/ui/extern/extern-no-mangle.rs12
-rw-r--r--tests/ui/extern/extern-no-mangle.stderr30
-rw-r--r--tests/ui/extern/issue-47725.rs17
-rw-r--r--tests/ui/extern/issue-47725.stderr34
-rw-r--r--tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr7
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs50
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr293
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs311
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr1272
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs19
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr48
-rw-r--r--tests/ui/ffi-attrs/ffi_const.rs6
-rw-r--r--tests/ui/ffi-attrs/ffi_const.stderr13
-rw-r--r--tests/ui/ffi-attrs/ffi_pure.rs6
-rw-r--r--tests/ui/ffi-attrs/ffi_pure.stderr13
-rw-r--r--tests/ui/force-inlining/invalid.rs60
-rw-r--r--tests/ui/force-inlining/invalid.stderr372
-rw-r--r--tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr19
-rw-r--r--tests/ui/issues/issue-31769.rs2
-rw-r--r--tests/ui/issues/issue-31769.stderr9
-rw-r--r--tests/ui/issues/issue-43988.rs4
-rw-r--r--tests/ui/issues/issue-43988.stderr48
-rw-r--r--tests/ui/issues/issue-78957.rs18
-rw-r--r--tests/ui/issues/issue-78957.stderr84
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs6
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr12
-rw-r--r--tests/ui/lint/inline-trait-and-foreign-items.rs18
-rw-r--r--tests/ui/lint/inline-trait-and-foreign-items.stderr75
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.rs6
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.stderr14
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.stderr42
-rw-r--r--tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs6
-rw-r--r--tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr11
-rw-r--r--tests/ui/loop-match/invalid-attribute.rs24
-rw-r--r--tests/ui/loop-match/invalid-attribute.stderr160
-rw-r--r--tests/ui/macros/issue-68060.rs3
-rw-r--r--tests/ui/macros/issue-68060.stderr7
-rw-r--r--tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs12
-rw-r--r--tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr42
-rw-r--r--tests/ui/panic-handler/panic-handler-wrong-location.stderr2
-rw-r--r--tests/ui/proc-macro/illegal-proc-macro-derive-use.rs2
-rw-r--r--tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs4
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr24
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs2
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr7
-rw-r--r--tests/ui/rustdoc/check-doc-alias-attr-location.stderr4
-rw-r--r--tests/ui/target-feature/invalid-attribute.rs51
-rw-r--r--tests/ui/target-feature/invalid-attribute.stderr189
-rw-r--r--tests/ui/traits/alias/not-a-marker.rs2
-rw-r--r--tests/ui/traits/alias/not-a-marker.stderr7
-rw-r--r--tests/ui/traits/const-traits/attr-misuse.rs4
-rw-r--r--tests/ui/traits/const-traits/attr-misuse.stderr20
-rw-r--r--tests/ui/unstable-feature-bound/unstable_inherent_method.rs4
-rw-r--r--tests/ui/unstable-feature-bound/unstable_inherent_method.stderr14
-rw-r--r--tests/ui/where-clauses/unsupported_attribute.rs20
-rw-r--r--tests/ui/where-clauses/unsupported_attribute.stderr100
157 files changed, 3443 insertions, 3670 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8a878faecbc..8c980616e83 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3480,6 +3480,7 @@ dependencies = [
 name = "rustc_attr_parsing"
 version = "0.0.0"
 dependencies = [
+ "itertools",
  "rustc_abi",
  "rustc_ast",
  "rustc_ast_pretty",
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index 2cc07694afb..f1e810a8b9e 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -1,5 +1,6 @@
 use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
 use rustc_hir as hir;
+use rustc_hir::Target;
 use rustc_span::sym;
 use smallvec::SmallVec;
 
@@ -109,7 +110,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         let span = self.lower_span(l.span);
         let source = hir::LocalSource::Normal;
-        self.lower_attrs(hir_id, &l.attrs, l.span);
+        self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement);
         self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source })
     }
 
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2ddbf083a09..cbd17d66b75 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{HirId, find_attr};
+use rustc_hir::{HirId, Target, find_attr};
 use rustc_middle::span_bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::errors::report_lit_error;
@@ -74,7 +74,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     if !e.attrs.is_empty() {
                         let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);
                         let new_attrs = self
-                            .lower_attrs_vec(&e.attrs, e.span, ex.hir_id)
+                            .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e))
                             .into_iter()
                             .chain(old_attrs.iter().cloned());
                         let new_attrs = &*self.arena.alloc_from_iter(new_attrs);
@@ -97,7 +97,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
 
             let expr_hir_id = self.lower_node_id(e.id);
-            let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span);
+            let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::from_expr(e));
 
             let kind = match &e.kind {
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@@ -639,7 +639,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
         let hir_id = self.next_id();
         let span = self.lower_span(arm.span);
-        self.lower_attrs(hir_id, &arm.attrs, arm.span);
+        self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm);
         let is_never_pattern = pat.is_never_pattern();
         // We need to lower the body even if it's unneeded for never pattern in match,
         // ensure that we can get HirId for DefId if need (issue #137708).
@@ -820,6 +820,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     span: unstable_span,
                 }],
                 span,
+                Target::Fn,
             );
         }
     }
@@ -1654,7 +1655,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
         let hir_id = self.lower_node_id(f.id);
-        self.lower_attrs(hir_id, &f.attrs, f.span);
+        self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField);
         hir::ExprField {
             hir_id,
             ident: self.lower_ident(f.ident),
@@ -1910,7 +1911,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         //
         // Also, add the attributes to the outer returned expr node.
         let expr = self.expr_drop_temps_mut(for_span, match_expr);
-        self.lower_attrs(expr.hir_id, &e.attrs, e.span);
+        self.lower_attrs(expr.hir_id, &e.attrs, e.span, Target::from_expr(e));
         expr
     }
 
@@ -1967,7 +1968,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
             let val_expr = self.expr_ident(span, val_ident, val_pat_nid);
-            self.lower_attrs(val_expr.hir_id, &attrs, span);
+            self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression);
             let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
             self.arm(continue_pat, val_expr)
         };
@@ -1998,7 +1999,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let ret_expr = self.checked_return(Some(from_residual_expr));
                 self.arena.alloc(self.expr(try_span, ret_expr))
             };
-            self.lower_attrs(ret_expr.hir_id, &attrs, span);
+            self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression);
 
             let break_pat = self.pat_cf_break(try_span, residual_local);
             self.arm(break_pat, ret_expr)
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 2cd2c41928e..72817a0a9a0 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -5,7 +5,7 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{DefKind, PerNS, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
-use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, find_attr};
+use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr};
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@@ -80,7 +80,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
                     self.with_lctx(CRATE_NODE_ID, |lctx| {
                         let module = lctx.lower_mod(&c.items, &c.spans);
                         // FIXME(jdonszelman): is dummy span ever a problem here?
-                        lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP);
+                        lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP, Target::Crate);
                         hir::OwnerNode::Crate(module)
                     })
                 }
@@ -136,7 +136,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
         let vis_span = self.lower_span(i.vis.span);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
-        let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
+        let attrs = self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_ast_item(i));
         let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind);
         let item = hir::Item {
             owner_id: hir_id.expect_owner(),
@@ -621,7 +621,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
         let owner_id = hir_id.expect_owner();
-        let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
+        let attrs =
+            self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_foreign_item_kind(&i.kind));
         let (ident, kind) = match &i.kind {
             ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => {
                 let fdec = &sig.decl;
@@ -690,7 +691,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> {
         let hir_id = self.lower_node_id(v.id);
-        self.lower_attrs(hir_id, &v.attrs, v.span);
+        self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant);
         hir::Variant {
             hir_id,
             def_id: self.local_def_id(v.id),
@@ -773,7 +774,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::FieldDef<'hir> {
         let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy));
         let hir_id = self.lower_node_id(f.id);
-        self.lower_attrs(hir_id, &f.attrs, f.span);
+        self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field);
         hir::FieldDef {
             span: self.lower_span(f.span),
             hir_id,
@@ -792,7 +793,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
-        let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
+        let attrs = self.lower_attrs(
+            hir_id,
+            &i.attrs,
+            i.span,
+            Target::from_assoc_item_kind(&i.kind, AssocCtxt::Trait),
+        );
         let trait_item_def_id = hir_id.expect_owner();
 
         let (ident, generics, kind, has_default) = match &i.kind {
@@ -1001,7 +1007,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let has_value = true;
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
-        let attrs = self.lower_attrs(hir_id, &i.attrs, i.span);
+        let attrs = self.lower_attrs(
+            hir_id,
+            &i.attrs,
+            i.span,
+            Target::from_assoc_item_kind(&i.kind, AssocCtxt::Impl { of_trait: is_in_trait_impl }),
+        );
 
         let (ident, (generics, kind)) = match &i.kind {
             AssocItemKind::Const(box ConstItem {
@@ -1171,7 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
         let hir_id = self.lower_node_id(param.id);
-        self.lower_attrs(hir_id, &param.attrs, param.span);
+        self.lower_attrs(hir_id, &param.attrs, param.span, Target::Param);
         hir::Param {
             hir_id,
             pat: self.lower_pat(&param.pat),
@@ -1851,7 +1862,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     ) -> hir::WherePredicate<'hir> {
         let hir_id = self.lower_node_id(pred.id);
         let span = self.lower_span(pred.span);
-        self.lower_attrs(hir_id, &pred.attrs, span);
+        self.lower_attrs(hir_id, &pred.attrs, span, Target::WherePredicate);
         let kind = self.arena.alloc(match &pred.kind {
             WherePredicateKind::BoundPredicate(WhereBoundPredicate {
                 bound_generic_params,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 465d9dc82bc..70595391b85 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -54,7 +54,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
 use rustc_hir::lints::DelayedLint;
 use rustc_hir::{
     self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
-    LifetimeSyntax, ParamName, TraitCandidate,
+    LifetimeSyntax, ParamName, Target, TraitCandidate,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -943,11 +943,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         id: HirId,
         attrs: &[Attribute],
         target_span: Span,
+        target: Target,
     ) -> &'hir [hir::Attribute] {
         if attrs.is_empty() {
             &[]
         } else {
-            let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id);
+            let lowered_attrs =
+                self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target);
 
             assert_eq!(id.owner, self.current_hir_id_owner);
             let ret = self.arena.alloc_from_iter(lowered_attrs);
@@ -972,12 +974,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         attrs: &[Attribute],
         target_span: Span,
         target_hir_id: HirId,
+        target: Target,
     ) -> Vec<hir::Attribute> {
         let l = self.span_lowerer();
         self.attribute_parser.parse_attribute_list(
             attrs,
             target_span,
             target_hir_id,
+            target,
             OmitDoc::Lower,
             |s| l.lower(s),
             |l| {
@@ -1942,7 +1946,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let (name, kind) = self.lower_generic_param_kind(param, source);
 
         let hir_id = self.lower_node_id(param.id);
-        self.lower_attrs(hir_id, &param.attrs, param.span());
+        self.lower_attrs(hir_id, &param.attrs, param.span(), Target::Param);
         hir::GenericParam {
             hir_id,
             def_id: self.local_def_id(param.id),
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index b6533060a76..b8f86247875 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{self as hir, LangItem};
+use rustc_hir::{self as hir, LangItem, Target};
 use rustc_middle::span_bug;
 use rustc_span::source_map::{Spanned, respan};
 use rustc_span::{DesugaringKind, Ident, Span};
@@ -93,7 +93,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                         let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
                             let hir_id = self.lower_node_id(f.id);
-                            self.lower_attrs(hir_id, &f.attrs, f.span);
+                            self.lower_attrs(hir_id, &f.attrs, f.span, Target::PatField);
 
                             hir::PatField {
                                 hir_id,
diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml
index cec9d62e656..bac89373b67 100644
--- a/compiler/rustc_attr_parsing/Cargo.toml
+++ b/compiler/rustc_attr_parsing/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index de22ea322c7..4fb66a81652 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -10,6 +10,12 @@ attr_parsing_empty_attribute =
     unused attribute
     .suggestion = remove this attribute
 
+attr_parsing_invalid_target = `#[{$name}]` attribute cannot be used on {$target}
+    .help = `#[{$name}]` can {$only}be applied to {$applied}
+attr_parsing_invalid_target_lint = `#[{$name}]` attribute cannot be used on {$target}
+    .warn = {-attr_parsing_previously_accepted}
+    .help = `#[{$name}]` can {$only}be applied to {$applied}
+
 attr_parsing_empty_confusables =
     expected at least one confusable name
 attr_parsing_expected_one_cfg_pattern =
diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
index b3393e93de8..4d995027814 100644
--- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
@@ -2,10 +2,12 @@ use std::iter;
 
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Span, Symbol, sym};
 
 use super::{CombineAttributeParser, ConvertFn};
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::{Allow, Warn};
+use crate::context::{AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics;
 
@@ -15,6 +17,12 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
     type Item = (Symbol, Span);
     const CONVERT: ConvertFn<Self::Item> =
         |items, span| AttributeKind::AllowInternalUnstable(items, span);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::MacroDef),
+        Allow(Target::Fn),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
 
     fn extend<'c>(
@@ -32,6 +40,11 @@ impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
     const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
     type Item = (Symbol, Span);
     const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Impl { of_trait: true }),
+        Allow(Target::Trait),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
 
     fn extend<'c>(
@@ -53,6 +66,13 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
     type Item = Symbol;
     const CONVERT: ConvertFn<Self::Item> =
         |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
 
     fn extend<'c>(
diff --git a/compiler/rustc_attr_parsing/src/attributes/body.rs b/compiler/rustc_attr_parsing/src/attributes/body.rs
index ab9330216f6..88540384621 100644
--- a/compiler/rustc_attr_parsing/src/attributes/body.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/body.rs
@@ -1,15 +1,18 @@
 //! Attributes that can be found in function body.
 
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Symbol, sym};
 
 use super::{NoArgsAttributeParser, OnDuplicate};
-use crate::context::Stage;
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AllowedTargets, Stage};
 
 pub(crate) struct CoroutineParser;
 
 impl<S: Stage> NoArgsAttributeParser<S> for CoroutineParser {
     const PATH: &[Symbol] = &[sym::coroutine];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]);
     const CREATE: fn(rustc_span::Span) -> AttributeKind = |span| AttributeKind::Coroutine(span);
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index a9f77195d1b..6ea073896c2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -1,5 +1,6 @@
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::{AttributeKind, CoverageAttrKind, OptimizeAttr, UsedBy};
+use rustc_hir::{MethodKind, Target};
 use rustc_session::parse::feature_err;
 use rustc_span::{Span, Symbol, sym};
 
@@ -7,7 +8,8 @@ use super::{
     AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
     NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
 };
-use crate::context::{AcceptContext, FinalizeContext, Stage};
+use crate::context::MaybeWarn::{Allow, Warn};
+use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport};
 
@@ -17,6 +19,13 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
     const PATH: &[Symbol] = &[sym::optimize];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Closure),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Method(MethodKind::Inherent)),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(List: &["size", "speed", "none"]);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -49,6 +58,15 @@ pub(crate) struct ColdParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
     const PATH: &[Symbol] = &[sym::cold];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::ForeignFn),
+        Allow(Target::Closure),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold;
 }
 
@@ -58,6 +76,17 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
     const PATH: &[Symbol] = &[sym::coverage];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Closure),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Impl { of_trait: true }),
+        Allow(Target::Impl { of_trait: false }),
+        Allow(Target::Mod),
+        Allow(Target::Crate),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -97,6 +126,16 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
     const PATH: &[rustc_span::Symbol] = &[sym::export_name];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Static),
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+        Warn(Target::MacroDef),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -138,6 +177,12 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
                 this.span = Some(cx.attr_span);
             }
         })];
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+    ]);
 
     fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         // FIXME(jdonszelmann): upgrade this list to *parsed* attributes
@@ -230,6 +275,18 @@ pub(crate) struct TrackCallerParser;
 impl<S: Stage> NoArgsAttributeParser<S> for TrackCallerParser {
     const PATH: &[Symbol] = &[sym::track_caller];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::ForeignFn),
+        Allow(Target::Closure),
+        Warn(Target::MacroDef),
+        Warn(Target::Arm),
+        Warn(Target::Field),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller;
 }
 
@@ -237,6 +294,12 @@ pub(crate) struct NoMangleParser;
 impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser {
     const PATH: &[Symbol] = &[sym::no_mangle];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+        Allow(Target::Fn),
+        Allow(Target::Static),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoMangle;
 }
 
@@ -310,6 +373,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
             }
         },
     )];
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]);
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         // Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
@@ -373,4 +437,15 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
         }
         features
     }
+
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Warn(Target::Statement),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+        Warn(Target::MacroDef),
+    ]);
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs
index edd22172ca2..00f949c82c5 100644
--- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs
@@ -1,12 +1,13 @@
 use rustc_feature::template;
 use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Span, Symbol, sym};
 use thin_vec::ThinVec;
 
 use super::{AcceptMapping, AttributeParser};
-use crate::context::{FinalizeContext, Stage};
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AllowedTargets, FinalizeContext, Stage};
 use crate::session_diagnostics;
-
 #[derive(Default)]
 pub(crate) struct ConfusablesParser {
     confusables: ThinVec<Symbol>,
@@ -41,6 +42,8 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
             this.first_span.get_or_insert(cx.attr_span);
         },
     )];
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         if self.confusables.is_empty() {
diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
index e57ea8bbb5c..8101c91460f 100644
--- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
@@ -1,13 +1,14 @@
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Span, Symbol, sym};
 
 use super::util::parse_version;
 use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::{Allow, Error};
+use crate::context::{AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics;
-
 pub(crate) struct DeprecationParser;
 
 fn get<S: Stage>(
@@ -38,6 +39,30 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
     const PATH: &[Symbol] = &[sym::deprecated];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+        Allow(Target::Fn),
+        Allow(Target::Mod),
+        Allow(Target::Struct),
+        Allow(Target::Enum),
+        Allow(Target::Union),
+        Allow(Target::Const),
+        Allow(Target::Static),
+        Allow(Target::MacroDef),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::TyAlias),
+        Allow(Target::Use),
+        Allow(Target::ForeignFn),
+        Allow(Target::Field),
+        Allow(Target::Trait),
+        Allow(Target::AssocTy),
+        Allow(Target::AssocConst),
+        Allow(Target::Variant),
+        Allow(Target::Impl { of_trait: false }), //FIXME This does not make sense
+        Allow(Target::Crate),
+        Error(Target::WherePredicate),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(
         Word,
         List: &[r#"since = "version""#, r#"note = "reason""#, r#"since = "version", note = "reason""#],
diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs
index bbcd9ab530c..85842b1b5c5 100644
--- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs
@@ -3,14 +3,14 @@ use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Symbol, sym};
 
 use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage};
+use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct DummyParser;
 impl<S: Stage> SingleAttributeParser<S> for DummyParser {
     const PATH: &[Symbol] = &[sym::rustc_dummy];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
     const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
 
     fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser<'_>) -> Option<AttributeKind> {
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index e9a45f20bff..6a659a95b85 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -5,19 +5,34 @@
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::{AttributeKind, InlineAttr};
 use rustc_hir::lints::AttributeLintKind;
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Symbol, sym};
 
 use super::{AcceptContext, AttributeOrder, OnDuplicate};
 use crate::attributes::SingleAttributeParser;
-use crate::context::Stage;
+use crate::context::MaybeWarn::{Allow, Warn};
+use crate::context::{AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct InlineParser;
 
 impl<S: Stage> SingleAttributeParser<S> for InlineParser {
     const PATH: &'static [Symbol] = &[sym::inline];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Closure),
+        Allow(Target::Delegation { mac: false }),
+        Warn(Target::Method(MethodKind::Trait { body: false })),
+        Warn(Target::ForeignFn),
+        Warn(Target::Field),
+        Warn(Target::MacroDef),
+        Warn(Target::Arm),
+        Warn(Target::AssocConst),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(
         Word,
         List: &["always", "never"],
@@ -63,6 +78,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
     const PATH: &'static [Symbol] = &[sym::rustc_force_inline];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
     const TEMPLATE: AttributeTemplate = template!(Word, List: &["reason"], NameValueStr: "reason");
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index e4ced2e37c5..552b9dfabc2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -1,21 +1,26 @@
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
 use rustc_hir::attrs::{AttributeKind, Linkage};
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{
     AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
 };
-use crate::context::{AcceptContext, Stage, parse_single_integer};
+use crate::context::MaybeWarn::Allow;
+use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage, parse_single_integer};
 use crate::parser::ArgParser;
 use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
-
 pub(crate) struct LinkNameParser;
 
 impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
     const PATH: &[Symbol] = &[sym::link_name];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+        Allow(Target::ForeignFn),
+        Allow(Target::ForeignStatic),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(
         NameValueStr: "name",
         "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute"
@@ -41,6 +46,8 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
     const PATH: &[Symbol] = &[sym::link_section];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowListWarnRest(&[Allow(Target::Static), Allow(Target::Fn)]);
     const TEMPLATE: AttributeTemplate = template!(
         NameValueStr: "name",
         "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"
@@ -70,6 +77,7 @@ pub(crate) struct ExportStableParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser {
     const PATH: &[Symbol] = &[sym::export_stable];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable;
 }
 
@@ -77,6 +85,7 @@ pub(crate) struct FfiConstParser;
 impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
     const PATH: &[Symbol] = &[sym::ffi_const];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst;
 }
 
@@ -84,6 +93,7 @@ pub(crate) struct FfiPureParser;
 impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
     const PATH: &[Symbol] = &[sym::ffi_pure];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
 }
 
@@ -91,6 +101,12 @@ pub(crate) struct StdInternalSymbolParser;
 impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
     const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::ForeignFn),
+        Allow(Target::Static),
+        Allow(Target::ForeignStatic),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol;
 }
 
@@ -100,6 +116,8 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
     const PATH: &[Symbol] = &[sym::link_ordinal];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]);
     const TEMPLATE: AttributeTemplate = template!(
         List: &["ordinal"],
         "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"
@@ -138,6 +156,16 @@ impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
 
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Static),
+        Allow(Target::ForeignStatic),
+        Allow(Target::ForeignFn),
+    ]);
 
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
         "available_externally",
diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
index 9530fec07d6..2b586d4003c 100644
--- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
@@ -1,13 +1,21 @@
 use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
-use crate::context::Stage;
-
+use crate::context::MaybeWarn::{Allow, Error};
+use crate::context::{AllowedTargets, Stage};
 pub(crate) struct AsPtrParser;
 impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser {
     const PATH: &[Symbol] = &[sym::rustc_as_ptr];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::AsPtr;
 }
 
@@ -15,6 +23,11 @@ pub(crate) struct PubTransparentParser;
 impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser {
     const PATH: &[Symbol] = &[sym::rustc_pub_transparent];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Struct),
+        Allow(Target::Enum),
+        Allow(Target::Union),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent;
 }
 
@@ -22,6 +35,11 @@ pub(crate) struct PassByValueParser;
 impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
     const PATH: &[Symbol] = &[sym::rustc_pass_by_value];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Struct),
+        Allow(Target::Enum),
+        Allow(Target::TyAlias),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue;
 }
 
@@ -29,5 +47,10 @@ pub(crate) struct AutomaticallyDerivedParser;
 impl<S: Stage> NoArgsAttributeParser<S> for AutomaticallyDerivedParser {
     const PATH: &[Symbol] = &[sym::automatically_derived];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+        Allow(Target::Impl { of_trait: true }),
+        Error(Target::Crate),
+        Error(Target::WherePredicate),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::AutomaticallyDerived;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs
index 868c113a6d1..242e2f2c1bc 100644
--- a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs
@@ -1,13 +1,15 @@
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
-use crate::context::Stage;
-
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AllowedTargets, Stage};
 pub(crate) struct LoopMatchParser;
 impl<S: Stage> NoArgsAttributeParser<S> for LoopMatchParser {
     const PATH: &[Symbol] = &[sym::loop_match];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::LoopMatch;
 }
 
@@ -15,5 +17,6 @@ pub(crate) struct ConstContinueParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ConstContinueParser {
     const PATH: &[Symbol] = &[sym::const_continue];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
index a1166bf9ac5..c9b5dd35fa1 100644
--- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
@@ -1,18 +1,20 @@
 use rustc_errors::DiagArgValue;
 use rustc_feature::{AttributeTemplate, template};
+use rustc_hir::Target;
 use rustc_hir::attrs::{AttributeKind, MacroUseArgs};
 use rustc_span::{Span, Symbol, sym};
 use thin_vec::ThinVec;
 
 use crate::attributes::{AcceptMapping, AttributeParser, NoArgsAttributeParser, OnDuplicate};
-use crate::context::{AcceptContext, FinalizeContext, Stage};
+use crate::context::MaybeWarn::{Allow, Error, Warn};
+use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics;
-
 pub(crate) struct MacroEscapeParser;
 impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
     const PATH: &[Symbol] = &[sym::macro_escape];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS;
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::MacroEscape;
 }
 
@@ -35,6 +37,12 @@ const MACRO_USE_TEMPLATE: AttributeTemplate = template!(
     Word, List: &["name1, name2, ..."],
     "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute"
 );
+const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+    Allow(Target::Mod),
+    Allow(Target::ExternCrate),
+    Allow(Target::Crate),
+    Error(Target::WherePredicate),
+]);
 
 impl<S: Stage> AttributeParser<S> for MacroUseParser {
     const ATTRIBUTES: AcceptMapping<Self, S> = &[(
@@ -111,6 +119,7 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
             }
         },
     )];
+    const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS;
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
@@ -122,5 +131,11 @@ pub(crate) struct AllowInternalUnsafeParser;
 impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
     const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::MacroDef),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index f7946ade6d2..ed5d1d92b8c 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -21,7 +21,7 @@ use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol};
 use thin_vec::ThinVec;
 
-use crate::context::{AcceptContext, FinalizeContext, Stage};
+use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics::UnusedMultiple;
 
@@ -80,6 +80,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
     /// If an attribute has this symbol, the `accept` function will be called on it.
     const ATTRIBUTES: AcceptMapping<Self, S>;
 
+    const ALLOWED_TARGETS: AllowedTargets;
+
     /// The parser has gotten a chance to accept the attributes on an item,
     /// here it can produce an attribute.
     ///
@@ -116,6 +118,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
     /// and this specified whether to, for example, warn or error on the other one.
     const ON_DUPLICATE: OnDuplicate<S>;
 
+    const ALLOWED_TARGETS: AllowedTargets;
+
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
@@ -163,6 +167,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
             }
         },
     )];
+    const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         Some(self.1?.0)
@@ -247,6 +252,7 @@ pub(crate) enum AttributeOrder {
 pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
     const PATH: &[Symbol];
     const ON_DUPLICATE: OnDuplicate<S>;
+    const ALLOWED_TARGETS: AllowedTargets;
 
     /// Create the [`AttributeKind`] given attribute's [`Span`].
     const CREATE: fn(Span) -> AttributeKind;
@@ -264,6 +270,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
     const PATH: &[Symbol] = T::PATH;
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
+    const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(Word);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -293,6 +300,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
     ///  where `x` is a vec of these individual reprs.
     const CONVERT: ConvertFn<Self::Item>;
 
+    const ALLOWED_TARGETS: AllowedTargets;
+
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
@@ -324,15 +333,13 @@ impl<T: CombineAttributeParser<S>, S: Stage> Default for Combine<T, S> {
 }
 
 impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S> {
-    const ATTRIBUTES: AcceptMapping<Self, S> = &[(
-        T::PATH,
-        <T as CombineAttributeParser<S>>::TEMPLATE,
-        |group: &mut Combine<T, S>, cx, args| {
+    const ATTRIBUTES: AcceptMapping<Self, S> =
+        &[(T::PATH, T::TEMPLATE, |group: &mut Combine<T, S>, cx, args| {
             // Keep track of the span of the first attribute, for diagnostics
             group.first_span.get_or_insert(cx.attr_span);
             group.items.extend(T::extend(cx, args))
-        },
-    )];
+        })];
+    const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         if let Some(first_span) = self.first_span {
diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs
index c88bb5a69e5..b6cfc780590 100644
--- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs
@@ -4,16 +4,16 @@ use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Symbol, sym};
 
 use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage};
+use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
 use crate::session_diagnostics;
-
 pub(crate) struct MustUseParser;
 
 impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
     const PATH: &[Symbol] = &[sym::must_use];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
     const TEMPLATE: AttributeTemplate = template!(
         Word, NameValueStr: "reason",
         "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"
diff --git a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs
index 40f8d00685e..589faf38f73 100644
--- a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs
@@ -1,13 +1,16 @@
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, sym};
 
 use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
-use crate::context::Stage;
-
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AllowedTargets, Stage};
 pub(crate) struct NoImplicitPreludeParser;
 
 impl<S: Stage> NoArgsAttributeParser<S> for NoImplicitPreludeParser {
     const PATH: &[rustc_span::Symbol] = &[sym::no_implicit_prelude];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Allow(Target::Crate)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoImplicitPrelude;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
index 361ac8e959d..41e9ca4de41 100644
--- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
@@ -1,13 +1,22 @@
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
-use crate::context::Stage;
-
+use crate::context::MaybeWarn::{Allow, Warn};
+use crate::context::{AllowedTargets, Stage};
 pub(crate) struct NonExhaustiveParser;
 
 impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {
     const PATH: &[Symbol] = &[sym::non_exhaustive];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Enum),
+        Allow(Target::Struct),
+        Allow(Target::Variant),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+        Warn(Target::MacroDef),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs
index c1c3de8cbfc..f9191d1abed 100644
--- a/compiler/rustc_attr_parsing/src/attributes/path.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/path.rs
@@ -1,17 +1,20 @@
 use rustc_feature::{AttributeTemplate, template};
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Symbol, sym};
 
 use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::{Allow, Error};
+use crate::context::{AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct PathParser;
 
 impl<S: Stage> SingleAttributeParser<S> for PathParser {
     const PATH: &[Symbol] = &[sym::path];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Error(Target::Crate)]);
     const TEMPLATE: AttributeTemplate = template!(
         NameValueStr: "file",
         "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute"
diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
index b267980914c..4624fa36287 100644
--- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
@@ -1,4 +1,5 @@
 use rustc_feature::{AttributeTemplate, template};
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol, sym};
 use thin_vec::ThinVec;
@@ -6,13 +7,15 @@ use thin_vec::ThinVec;
 use crate::attributes::{
     AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
 };
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::{Allow, Warn};
+use crate::context::{AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct ProcMacroParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
     const PATH: &[Symbol] = &[sym::proc_macro];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro;
 }
 
@@ -20,6 +23,8 @@ pub(crate) struct ProcMacroAttributeParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
     const PATH: &[Symbol] = &[sym::proc_macro_attribute];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute;
 }
 
@@ -28,6 +33,8 @@ impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
     const PATH: &[Symbol] = &[sym::proc_macro_derive];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
     const TEMPLATE: AttributeTemplate = template!(
         List: &["TraitName", "TraitName, attributes(name1, name2, ...)"],
         "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros"
@@ -48,6 +55,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
     const PATH: &[Symbol] = &[sym::rustc_builtin_macro];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
     const TEMPLATE: AttributeTemplate =
         template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]);
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index 996d2af5f37..7ab58ed9347 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -2,14 +2,15 @@ use rustc_abi::Align;
 use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::{AttributeKind, IntType, ReprAttr};
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 
 use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext};
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::Allow;
+use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
 use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser};
 use crate::session_diagnostics;
 use crate::session_diagnostics::IncorrectReprFormatGenericCause;
-
 /// Parse #[repr(...)] forms.
 ///
 /// Valid repr contents: any of the primitive integral type names (see
@@ -60,6 +61,10 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
 
         reprs
     }
+
+    //FIXME Still checked fully in `check_attr.rs`
+    //This one is slightly more complicated because the allowed targets depend on the arguments
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
 }
 
 macro_rules! int_pat {
@@ -318,6 +323,14 @@ impl AlignParser {
 
 impl<S: Stage> AttributeParser<S> for AlignParser {
     const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
+        Allow(Target::ForeignFn),
+    ]);
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         let (align, span) = self.0?;
diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
index 1a668b4416f..efd7b650e44 100644
--- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
@@ -1,17 +1,19 @@
 use rustc_feature::{AttributeTemplate, template};
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Symbol, sym};
 
 use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage, parse_single_integer};
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AcceptContext, AllowedTargets, Stage, parse_single_integer};
 use crate::parser::ArgParser;
-
 pub(crate) struct RustcLayoutScalarValidRangeStart;
 
 impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
     const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["start"]);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -26,6 +28,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd {
     const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["end"]);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
@@ -40,6 +43,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
     const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(Word);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs
index 70a8a002099..d4ad861a3a2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs
@@ -2,11 +2,11 @@ use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
-use crate::context::Stage;
-
+use crate::context::{ALL_TARGETS, AllowedTargets, Stage};
 pub(crate) struct MayDangleParser;
 impl<S: Stage> NoArgsAttributeParser<S> for MayDangleParser {
     const PATH: &[Symbol] = &[sym::may_dangle];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
     const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index c6707f5048b..5a26178f84b 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -4,15 +4,16 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_feature::template;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::{
-    DefaultBodyStability, PartialConstStability, Stability, StabilityLevel, StableSince,
-    UnstableReason, VERSION_PLACEHOLDER,
+    DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel,
+    StableSince, Target, UnstableReason, VERSION_PLACEHOLDER,
 };
 use rustc_span::{Ident, Span, Symbol, sym};
 
 use super::util::parse_version;
 use super::{AcceptMapping, AttributeParser, OnDuplicate};
 use crate::attributes::NoArgsAttributeParser;
-use crate::context::{AcceptContext, FinalizeContext, Stage};
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
 use crate::parser::{ArgParser, MetaItemParser};
 use crate::session_diagnostics::{self, UnsupportedLiteralReason};
 
@@ -26,6 +27,35 @@ macro_rules! reject_outside_std {
     };
 }
 
+const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+    Allow(Target::Fn),
+    Allow(Target::Struct),
+    Allow(Target::Enum),
+    Allow(Target::Union),
+    Allow(Target::Method(MethodKind::Inherent)),
+    Allow(Target::Method(MethodKind::Trait { body: false })),
+    Allow(Target::Method(MethodKind::Trait { body: true })),
+    Allow(Target::Method(MethodKind::TraitImpl)),
+    Allow(Target::Impl { of_trait: false }),
+    Allow(Target::Impl { of_trait: true }),
+    Allow(Target::MacroDef),
+    Allow(Target::Crate),
+    Allow(Target::Mod),
+    Allow(Target::Use), // FIXME I don't think this does anything?
+    Allow(Target::Const),
+    Allow(Target::AssocConst),
+    Allow(Target::AssocTy),
+    Allow(Target::Trait),
+    Allow(Target::TraitAlias),
+    Allow(Target::TyAlias),
+    Allow(Target::Variant),
+    Allow(Target::Field),
+    Allow(Target::Param),
+    Allow(Target::Static),
+    Allow(Target::ForeignFn),
+    Allow(Target::ForeignStatic),
+]);
+
 #[derive(Default)]
 pub(crate) struct StabilityParser {
     allowed_through_unstable_modules: Option<Symbol>,
@@ -87,6 +117,7 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
             },
         ),
     ];
+    const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS;
 
     fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         if let Some(atum) = self.allowed_through_unstable_modules {
@@ -142,6 +173,7 @@ impl<S: Stage> AttributeParser<S> for BodyStabilityParser {
             }
         },
     )];
+    const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS;
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         let (stability, span) = self.stability?;
@@ -154,6 +186,10 @@ pub(crate) struct ConstStabilityIndirectParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ConstStabilityIndirectParser {
     const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ConstStabilityIndirect;
 }
 
@@ -213,6 +249,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
             this.promotable = true;
         }),
     ];
+    const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS;
 
     fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         if self.promotable {
diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
index 3267855fb0d..8b666c3868b 100644
--- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
@@ -1,18 +1,21 @@
 use rustc_feature::{AttributeTemplate, template};
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::AttributeLintKind;
 use rustc_span::{Symbol, sym};
 
 use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::{Allow, Error};
+use crate::context::{AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct IgnoreParser;
 
 impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
     const PATH: &[Symbol] = &[sym::ignore];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]);
     const TEMPLATE: AttributeTemplate = template!(
         Word, NameValueStr: "reason",
         "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute"
@@ -54,6 +57,8 @@ impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
     const PATH: &[Symbol] = &[sym::should_panic];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]);
     const TEMPLATE: AttributeTemplate = template!(
         Word, List: &[r#"expected = "reason""#], NameValueStr: "reason",
         "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute"
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index 8514d799aa4..ee9d7ba99cd 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -2,19 +2,21 @@ use core::mem;
 
 use rustc_feature::{AttributeTemplate, template};
 use rustc_hir::attrs::AttributeKind;
+use rustc_hir::{MethodKind, Target};
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{
     AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
 };
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::{Allow, Warn};
+use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct SkipDuringMethodDispatchParser;
 impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
     const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
 
     const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]);
 
@@ -58,6 +60,7 @@ pub(crate) struct ParenSugarParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
     const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar;
 }
 
@@ -65,6 +68,7 @@ pub(crate) struct TypeConstParser;
 impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
     const PATH: &[Symbol] = &[sym::type_const];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
 }
 
@@ -74,6 +78,12 @@ pub(crate) struct MarkerParser;
 impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
     const PATH: &[Symbol] = &[sym::marker];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Trait),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+        Warn(Target::MacroDef),
+    ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
 }
 
@@ -81,6 +91,7 @@ pub(crate) struct DenyExplicitImplParser;
 impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
     const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
 }
 
@@ -88,6 +99,7 @@ pub(crate) struct DoNotImplementViaObjectParser;
 impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
     const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
 }
 
@@ -98,6 +110,7 @@ pub(crate) struct ConstTraitParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
     const PATH: &[Symbol] = &[sym::const_trait];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
 }
 
@@ -107,6 +120,7 @@ pub(crate) struct SpecializationTraitParser;
 impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
     const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait;
 }
 
@@ -114,6 +128,7 @@ pub(crate) struct UnsafeSpecializationMarkerParser;
 impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
     const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker;
 }
 
@@ -123,6 +138,7 @@ pub(crate) struct CoinductiveParser;
 impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
     const PATH: &[Symbol] = &[sym::rustc_coinductive];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive;
 }
 
@@ -130,6 +146,8 @@ pub(crate) struct AllowIncoherentImplParser;
 impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
     const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl;
 }
 
@@ -137,6 +155,7 @@ pub(crate) struct CoherenceIsCoreParser;
 impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
     const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
 }
 
@@ -144,6 +163,8 @@ pub(crate) struct FundamentalParser;
 impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
     const PATH: &[Symbol] = &[sym::fundamental];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]);
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
 }
 
@@ -151,5 +172,6 @@ pub(crate) struct PointeeParser;
 impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
     const PATH: &[Symbol] = &[sym::pointee];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
index d4d68eb8b27..0ffcf434b52 100644
--- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
@@ -1,12 +1,13 @@
 use rustc_feature::{AttributeTemplate, template};
+use rustc_hir::Target;
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{Symbol, sym};
 
 use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
-use crate::context::{AcceptContext, Stage};
+use crate::context::MaybeWarn::Allow;
+use crate::context::{AcceptContext, AllowedTargets, Stage};
 use crate::parser::ArgParser;
-
 pub(crate) struct TransparencyParser;
 
 // FIXME(jdonszelmann): make these proper diagnostics
@@ -18,6 +19,7 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
         cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
     });
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
     const TEMPLATE: AttributeTemplate =
         template!(NameValueStr: ["transparent", "semitransparent", "opaque"]);
 
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 6045a8b28a2..bebe3350c4e 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -3,13 +3,16 @@ use std::collections::BTreeMap;
 use std::ops::{Deref, DerefMut};
 use std::sync::LazyLock;
 
+use itertools::Itertools;
 use private::Sealed;
 use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId};
 use rustc_errors::{DiagCtxtHandle, Diagnostic};
 use rustc_feature::{AttributeTemplate, Features};
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId};
+use rustc_hir::{
+    AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId, MethodKind, Target,
+};
 use rustc_session::Session;
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
 
@@ -61,8 +64,11 @@ use crate::attributes::traits::{
 };
 use crate::attributes::transparency::TransparencyParser;
 use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
+use crate::context::MaybeWarn::{Allow, Error, Warn};
 use crate::parser::{ArgParser, MetaItemParser, PathParser};
-use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
+use crate::session_diagnostics::{
+    AttributeParseError, AttributeParseErrorReason, InvalidTarget, UnknownMetaItem,
+};
 
 type GroupType<S> = LazyLock<GroupTypeInner<S>>;
 
@@ -74,6 +80,7 @@ struct GroupTypeInner<S: Stage> {
 struct GroupTypeInnerAccept<S: Stage> {
     template: AttributeTemplate,
     accept_fn: AcceptFn<S>,
+    allowed_targets: AllowedTargets,
 }
 
 type AcceptFn<S> =
@@ -121,7 +128,8 @@ macro_rules! attribute_parsers {
                                 STATE_OBJECT.with_borrow_mut(|s| {
                                     accept_fn(s, cx, args)
                                 })
-                            })
+                            }),
+                            allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
                         });
                     }
 
@@ -643,6 +651,64 @@ impl ShouldEmit {
     }
 }
 
+#[derive(Debug)]
+pub(crate) enum AllowedTargets {
+    AllowList(&'static [MaybeWarn]),
+    AllowListWarnRest(&'static [MaybeWarn]),
+}
+
+pub(crate) enum AllowedResult {
+    Allowed,
+    Warn,
+    Error,
+}
+
+impl AllowedTargets {
+    pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult {
+        match self {
+            AllowedTargets::AllowList(list) => {
+                if list.contains(&Allow(target)) {
+                    AllowedResult::Allowed
+                } else if list.contains(&Warn(target)) {
+                    AllowedResult::Warn
+                } else {
+                    AllowedResult::Error
+                }
+            }
+            AllowedTargets::AllowListWarnRest(list) => {
+                if list.contains(&Allow(target)) {
+                    AllowedResult::Allowed
+                } else if list.contains(&Error(target)) {
+                    AllowedResult::Error
+                } else {
+                    AllowedResult::Warn
+                }
+            }
+        }
+    }
+
+    pub(crate) fn allowed_targets(&self) -> Vec<Target> {
+        match self {
+            AllowedTargets::AllowList(list) => list,
+            AllowedTargets::AllowListWarnRest(list) => list,
+        }
+        .iter()
+        .filter_map(|target| match target {
+            Allow(target) => Some(*target),
+            Warn(_) => None,
+            Error(_) => None,
+        })
+        .collect()
+    }
+}
+
+#[derive(Debug, Eq, PartialEq)]
+pub(crate) enum MaybeWarn {
+    Allow(Target),
+    Warn(Target),
+    Error(Target),
+}
+
 /// Context created once, for example as part of the ast lowering
 /// context, through which all attributes can be lowered.
 pub struct AttributeParser<'sess, S: Stage = Late> {
@@ -691,6 +757,7 @@ impl<'sess> AttributeParser<'sess, Early> {
             attrs,
             target_span,
             target_node_id,
+            Target::Crate, // Does not matter, we're not going to emit errors anyways
             OmitDoc::Skip,
             std::convert::identity,
             |_lint| {
@@ -777,6 +844,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
         attrs: &[ast::Attribute],
         target_span: Span,
         target_id: S::Id,
+        target: Target,
         omit_doc: OmitDoc,
 
         lower_span: impl Copy + Fn(Span) -> Span,
@@ -848,7 +916,48 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
                                 attr_path: path.get_attribute_path(),
                             };
 
-                            (accept.accept_fn)(&mut cx, args)
+                            (accept.accept_fn)(&mut cx, args);
+
+                            if self.stage.should_emit().should_emit() {
+                                match accept.allowed_targets.is_allowed(target) {
+                                    AllowedResult::Allowed => {}
+                                    AllowedResult::Warn => {
+                                        let allowed_targets =
+                                            accept.allowed_targets.allowed_targets();
+                                        let (applied, only) = allowed_targets_applied(
+                                            allowed_targets,
+                                            target,
+                                            self.features,
+                                        );
+                                        emit_lint(AttributeLint {
+                                            id: target_id,
+                                            span: attr.span,
+                                            kind: AttributeLintKind::InvalidTarget {
+                                                name: parts[0],
+                                                target,
+                                                only: if only { "only " } else { "" },
+                                                applied,
+                                            },
+                                        });
+                                    }
+                                    AllowedResult::Error => {
+                                        let allowed_targets =
+                                            accept.allowed_targets.allowed_targets();
+                                        let (applied, only) = allowed_targets_applied(
+                                            allowed_targets,
+                                            target,
+                                            self.features,
+                                        );
+                                        self.dcx().emit_err(InvalidTarget {
+                                            span: attr.span,
+                                            name: parts[0],
+                                            target: target.plural_name(),
+                                            only: if only { "only " } else { "" },
+                                            applied,
+                                        });
+                                    }
+                                }
+                            }
                         }
                     } else {
                         // If we're here, we must be compiling a tool attribute... Or someone
@@ -936,6 +1045,132 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
     }
 }
 
+/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
+/// Does some heuristic-based filtering to remove uninteresting targets, and formats the targets into a string
+pub(crate) fn allowed_targets_applied(
+    mut allowed_targets: Vec<Target>,
+    target: Target,
+    features: Option<&Features>,
+) -> (String, bool) {
+    // Remove unstable targets from `allowed_targets` if their features are not enabled
+    if let Some(features) = features {
+        if !features.fn_delegation() {
+            allowed_targets.retain(|t| !matches!(t, Target::Delegation { .. }));
+        }
+        if !features.stmt_expr_attributes() {
+            allowed_targets.retain(|t| !matches!(t, Target::Expression | Target::Statement));
+        }
+    }
+
+    // We define groups of "similar" targets.
+    // If at least two of the targets are allowed, and the `target` is not in the group,
+    // we collapse the entire group to a single entry to simplify the target list
+    const FUNCTION_LIKE: &[Target] = &[
+        Target::Fn,
+        Target::Closure,
+        Target::ForeignFn,
+        Target::Method(MethodKind::Inherent),
+        Target::Method(MethodKind::Trait { body: false }),
+        Target::Method(MethodKind::Trait { body: true }),
+        Target::Method(MethodKind::TraitImpl),
+    ];
+    const METHOD_LIKE: &[Target] = &[
+        Target::Method(MethodKind::Inherent),
+        Target::Method(MethodKind::Trait { body: false }),
+        Target::Method(MethodKind::Trait { body: true }),
+        Target::Method(MethodKind::TraitImpl),
+    ];
+    const IMPL_LIKE: &[Target] =
+        &[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }];
+    const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum];
+
+    let mut added_fake_targets = Vec::new();
+    filter_targets(
+        &mut allowed_targets,
+        FUNCTION_LIKE,
+        "functions",
+        target,
+        &mut added_fake_targets,
+    );
+    filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets);
+    filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets);
+    filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets);
+
+    // If there is now only 1 target left, show that as the only possible target
+    (
+        added_fake_targets
+            .iter()
+            .copied()
+            .chain(allowed_targets.iter().map(|t| t.plural_name()))
+            .join(", "),
+        allowed_targets.len() + added_fake_targets.len() == 1,
+    )
+}
+
+fn filter_targets(
+    allowed_targets: &mut Vec<Target>,
+    target_group: &'static [Target],
+    target_group_name: &'static str,
+    target: Target,
+    added_fake_targets: &mut Vec<&'static str>,
+) {
+    if target_group.contains(&target) {
+        return;
+    }
+    if allowed_targets.iter().filter(|at| target_group.contains(at)).count() < 2 {
+        return;
+    }
+    allowed_targets.retain(|t| !target_group.contains(t));
+    added_fake_targets.push(target_group_name);
+}
+
+/// This is the list of all targets to which a attribute can be applied
+/// This is used for:
+/// - `rustc_dummy`, which can be applied to all targets
+/// - Attributes that are not parted to the new target system yet can use this list as a placeholder
+pub(crate) const ALL_TARGETS: &'static [MaybeWarn] = &[
+    Allow(Target::ExternCrate),
+    Allow(Target::Use),
+    Allow(Target::Static),
+    Allow(Target::Const),
+    Allow(Target::Fn),
+    Allow(Target::Closure),
+    Allow(Target::Mod),
+    Allow(Target::ForeignMod),
+    Allow(Target::GlobalAsm),
+    Allow(Target::TyAlias),
+    Allow(Target::Enum),
+    Allow(Target::Variant),
+    Allow(Target::Struct),
+    Allow(Target::Field),
+    Allow(Target::Union),
+    Allow(Target::Trait),
+    Allow(Target::TraitAlias),
+    Allow(Target::Impl { of_trait: false }),
+    Allow(Target::Impl { of_trait: true }),
+    Allow(Target::Expression),
+    Allow(Target::Statement),
+    Allow(Target::Arm),
+    Allow(Target::AssocConst),
+    Allow(Target::Method(MethodKind::Inherent)),
+    Allow(Target::Method(MethodKind::Trait { body: false })),
+    Allow(Target::Method(MethodKind::Trait { body: true })),
+    Allow(Target::Method(MethodKind::TraitImpl)),
+    Allow(Target::AssocTy),
+    Allow(Target::ForeignFn),
+    Allow(Target::ForeignStatic),
+    Allow(Target::ForeignTy),
+    Allow(Target::MacroDef),
+    Allow(Target::Param),
+    Allow(Target::PatField),
+    Allow(Target::ExprField),
+    Allow(Target::WherePredicate),
+    Allow(Target::MacroCall),
+    Allow(Target::Crate),
+    Allow(Target::Delegation { mac: false }),
+    Allow(Target::Delegation { mac: true }),
+];
+
 /// Parse a single integer.
 ///
 /// Used by attributes that take a single integer as argument, such as
diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs
index 22f5531bc80..733225bab59 100644
--- a/compiler/rustc_attr_parsing/src/lints.rs
+++ b/compiler/rustc_attr_parsing/src/lints.rs
@@ -1,6 +1,7 @@
 use rustc_errors::{DiagArgValue, LintEmitter};
-use rustc_hir::HirId;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
+use rustc_hir::{HirId, Target};
+use rustc_span::sym;
 
 use crate::session_diagnostics;
 
@@ -34,5 +35,25 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
             *first_span,
             session_diagnostics::EmptyAttributeList { attr_span: *first_span },
         ),
+        &AttributeLintKind::InvalidTarget { name, target, ref applied, only } => lint_emitter
+            .emit_node_span_lint(
+                // This check is here because `deprecated` had its own lint group and removing this would be a breaking change
+                if name == sym::deprecated
+                    && ![Target::Closure, Target::Expression, Target::Statement, Target::Arm]
+                        .contains(&target)
+                {
+                    rustc_session::lint::builtin::USELESS_DEPRECATED
+                } else {
+                    rustc_session::lint::builtin::UNUSED_ATTRIBUTES
+                },
+                *id,
+                *span,
+                session_diagnostics::InvalidTargetLint {
+                    name,
+                    target: target.plural_name(),
+                    applied: applied.clone(),
+                    only,
+                },
+            ),
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 41179844152..95e85667cd6 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -480,6 +480,29 @@ pub(crate) struct EmptyAttributeList {
     pub attr_span: Span,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(attr_parsing_invalid_target_lint)]
+#[warning]
+#[help]
+pub(crate) struct InvalidTargetLint {
+    pub name: Symbol,
+    pub target: &'static str,
+    pub applied: String,
+    pub only: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[help]
+#[diag(attr_parsing_invalid_target)]
+pub(crate) struct InvalidTarget {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+    pub target: &'static str,
+    pub applied: String,
+    pub only: &'static str,
+}
+
 #[derive(Diagnostic)]
 #[diag(attr_parsing_invalid_alignment_value, code = E0589)]
 pub(crate) struct InvalidAlignmentValue {
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index ae186d744c4..eb3c40cc593 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -259,8 +259,6 @@ builtin_macros_only_one_argument = {$name} takes 1 argument
 
 builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
 
-builtin_macros_proc_macro_attribute_only_be_used_on_bare_functions = the `#[{$path}]` attribute may only be used on bare functions
-
 builtin_macros_proc_macro_attribute_only_usable_with_crate_type = the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type
 
 builtin_macros_requires_cfg_pattern =
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 6bcf4d3e0a2..bb520db75b9 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -906,14 +906,6 @@ pub(crate) struct TakesNoArguments<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_proc_macro_attribute_only_be_used_on_bare_functions)]
-pub(crate) struct AttributeOnlyBeUsedOnBareFunctions<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub path: &'a str,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_proc_macro_attribute_only_usable_with_crate_type)]
 pub(crate) struct AttributeOnlyUsableWithCrateType<'a> {
     #[primary_span]
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index f440adf6cf0..6ac3e17503d 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -231,12 +231,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
         let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind {
             fn_.ident
         } else {
-            self.dcx
-                .create_err(errors::AttributeOnlyBeUsedOnBareFunctions {
-                    span: attr.span,
-                    path: &pprust::path_to_string(&attr.get_normal_item().path),
-                })
-                .emit();
+            // Error handled by general target checking logic
             return;
         };
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0518.md b/compiler/rustc_error_codes/src/error_codes/E0518.md
index f04329bc4e6..87dc231578a 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0518.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0518.md
@@ -1,9 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 An `#[inline(..)]` attribute was incorrectly placed on something other than a
 function or method.
 
 Example of erroneous code:
 
-```compile_fail,E0518
+```ignore (no longer emitted)
 #[inline(always)]
 struct Foo;
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0701.md b/compiler/rustc_error_codes/src/error_codes/E0701.md
index 4965e643105..e1be0e915f4 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0701.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0701.md
@@ -1,9 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed
 on something other than a struct or enum.
 
 Erroneous code example:
 
-```compile_fail,E0701
+```ignore (no longer emitted)
 #[non_exhaustive]
 trait Foo { }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0739.md b/compiler/rustc_error_codes/src/error_codes/E0739.md
index 406d3d52779..5403405ca9d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0739.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0739.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `#[track_caller]` must  be applied to a function
 
 Erroneous code example:
 
-```compile_fail,E0739
+```ignore (no longer emitted)
 #[track_caller]
 struct Bar {
     a: u8,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0755.md b/compiler/rustc_error_codes/src/error_codes/E0755.md
index b67f078c78e..bd93626a8db 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0755.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0755.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 The `ffi_pure` attribute was used on a non-foreign function.
 
 Erroneous code example:
 
-```compile_fail,E0755
+```ignore (no longer emitted)
 #![feature(ffi_pure)]
 
 #[unsafe(ffi_pure)] // error!
diff --git a/compiler/rustc_error_codes/src/error_codes/E0756.md b/compiler/rustc_error_codes/src/error_codes/E0756.md
index aadde038d12..daafc2a5ac0 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0756.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0756.md
@@ -1,9 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 The `ffi_const` attribute was used on something other than a foreign function
 declaration.
 
 Erroneous code example:
 
-```compile_fail,E0756
+```ignore (no longer emitted)
 #![feature(ffi_const)]
 
 #[unsafe(ffi_const)] // error!
diff --git a/compiler/rustc_error_codes/src/error_codes/E0788.md b/compiler/rustc_error_codes/src/error_codes/E0788.md
index ba138aed2d1..1afa961f9b7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0788.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0788.md
@@ -1,3 +1,5 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 A `#[coverage(off|on)]` attribute was found in a position where it is not
 allowed.
 
@@ -10,7 +12,7 @@ Coverage attributes can be applied to:
 
 Example of erroneous code:
 
-```compile_fail,E0788
+```ignore (no longer emitted)
 unsafe extern "C" {
     #[coverage(off)]
     fn foreign_fn();
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 0cc03ef7b5b..2c8986b7c7d 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1232,6 +1232,13 @@ impl Attribute {
             _ => None,
         }
     }
+
+    pub fn is_parsed_attr(&self) -> bool {
+        match self {
+            Attribute::Parsed(_) => true,
+            Attribute::Unparsed(_) => false,
+        }
+    }
 }
 
 impl AttributeExt for Attribute {
@@ -1302,13 +1309,8 @@ impl AttributeExt for Attribute {
         match &self {
             Attribute::Unparsed(u) => u.span,
             // FIXME: should not be needed anymore when all attrs are parsed
-            Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span,
             Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
-            Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => *span,
-            Attribute::Parsed(AttributeKind::MayDangle(span)) => *span,
-            Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span,
-            Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span,
-            Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span,
+            Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span,
             Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span,
             Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span,
             a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs
index c55a41eb2b7..e3cde2d3bb6 100644
--- a/compiler/rustc_hir/src/lints.rs
+++ b/compiler/rustc_hir/src/lints.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_macros::HashStable_Generic;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 
-use crate::HirId;
+use crate::{HirId, Target};
 
 #[derive(Debug)]
 pub struct DelayedLints {
@@ -34,4 +34,5 @@ pub enum AttributeLintKind {
     UnusedDuplicate { this: Span, other: Span, warning: bool },
     IllFormedAttributeInput { suggestions: Vec<String> },
     EmptyAttribute { first_span: Span },
+    InvalidTarget { name: Symbol, target: Target, applied: String, only: &'static str },
 }
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index d617f44f8d8..f68dad3a5e8 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -6,23 +6,34 @@
 
 use std::fmt::{self, Display};
 
+use rustc_ast::visit::AssocCtxt;
+use rustc_ast::{AssocItemKind, ForeignItemKind, ast};
+use rustc_macros::HashStable_Generic;
+
 use crate::def::DefKind;
 use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir};
 
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
 pub enum GenericParamKind {
     Type,
     Lifetime,
     Const,
 }
 
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
 pub enum MethodKind {
-    Trait { body: bool },
+    /// Method in a `trait Trait` block
+    Trait {
+        /// Whether a default is provided for this method
+        body: bool,
+    },
+    /// Method in a `impl Trait for Type` block
+    TraitImpl,
+    /// Method in a `impl Type` block
     Inherent,
 }
 
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
 pub enum Target {
     ExternCrate,
     Use,
@@ -57,6 +68,9 @@ pub enum Target {
     PatField,
     ExprField,
     WherePredicate,
+    MacroCall,
+    Crate,
+    Delegation { mac: bool },
 }
 
 impl Display for Target {
@@ -98,7 +112,10 @@ impl Target {
             | Target::Param
             | Target::PatField
             | Target::ExprField
-            | Target::WherePredicate => false,
+            | Target::MacroCall
+            | Target::Crate
+            | Target::WherePredicate
+            | Target::Delegation { .. } => false,
         }
     }
 
@@ -146,6 +163,39 @@ impl Target {
         }
     }
 
+    pub fn from_ast_item(item: &ast::Item) -> Target {
+        match item.kind {
+            ast::ItemKind::ExternCrate(..) => Target::ExternCrate,
+            ast::ItemKind::Use(..) => Target::Use,
+            ast::ItemKind::Static { .. } => Target::Static,
+            ast::ItemKind::Const(..) => Target::Const,
+            ast::ItemKind::Fn { .. } => Target::Fn,
+            ast::ItemKind::Mod(..) => Target::Mod,
+            ast::ItemKind::ForeignMod { .. } => Target::ForeignMod,
+            ast::ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
+            ast::ItemKind::TyAlias(..) => Target::TyAlias,
+            ast::ItemKind::Enum(..) => Target::Enum,
+            ast::ItemKind::Struct(..) => Target::Struct,
+            ast::ItemKind::Union(..) => Target::Union,
+            ast::ItemKind::Trait(..) => Target::Trait,
+            ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
+            ast::ItemKind::Impl(ref i) => Target::Impl { of_trait: i.of_trait.is_some() },
+            ast::ItemKind::MacCall(..) => Target::MacroCall,
+            ast::ItemKind::MacroDef(..) => Target::MacroDef,
+            ast::ItemKind::Delegation(..) => Target::Delegation { mac: false },
+            ast::ItemKind::DelegationMac(..) => Target::Delegation { mac: true },
+        }
+    }
+
+    pub fn from_foreign_item_kind(kind: &ast::ForeignItemKind) -> Target {
+        match kind {
+            ForeignItemKind::Static(_) => Target::ForeignStatic,
+            ForeignItemKind::Fn(_) => Target::ForeignFn,
+            ForeignItemKind::TyAlias(_) => Target::ForeignTy,
+            ForeignItemKind::MacCall(_) => Target::MacroCall,
+        }
+    }
+
     pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
         match trait_item.kind {
             TraitItemKind::Const(..) => Target::AssocConst,
@@ -183,12 +233,40 @@ impl Target {
         }
     }
 
+    pub fn from_assoc_item_kind(kind: &ast::AssocItemKind, assoc_ctxt: AssocCtxt) -> Target {
+        match kind {
+            AssocItemKind::Const(_) => Target::AssocConst,
+            AssocItemKind::Fn(f) => Target::Method(match assoc_ctxt {
+                AssocCtxt::Trait => MethodKind::Trait { body: f.body.is_some() },
+                AssocCtxt::Impl { of_trait } => {
+                    if of_trait {
+                        MethodKind::TraitImpl
+                    } else {
+                        MethodKind::Inherent
+                    }
+                }
+            }),
+            AssocItemKind::Type(_) => Target::AssocTy,
+            AssocItemKind::Delegation(_) => Target::Delegation { mac: false },
+            AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true },
+            AssocItemKind::MacCall(_) => Target::MacroCall,
+        }
+    }
+
+    pub fn from_expr(expr: &ast::Expr) -> Self {
+        match &expr.kind {
+            ast::ExprKind::Closure(..) | ast::ExprKind::Gen(..) => Self::Closure,
+            ast::ExprKind::Paren(e) => Self::from_expr(&e),
+            _ => Self::Expression,
+        }
+    }
+
     pub fn name(self) -> &'static str {
         match self {
             Target::ExternCrate => "extern crate",
             Target::Use => "use",
-            Target::Static => "static item",
-            Target::Const => "constant item",
+            Target::Static => "static",
+            Target::Const => "constant",
             Target::Fn => "function",
             Target::Closure => "closure",
             Target::Mod => "module",
@@ -202,8 +280,7 @@ impl Target {
             Target::Union => "union",
             Target::Trait => "trait",
             Target::TraitAlias => "trait alias",
-            Target::Impl { of_trait: false } => "inherent implementation block",
-            Target::Impl { of_trait: true } => "trait implementation block",
+            Target::Impl { .. } => "implementation block",
             Target::Expression => "expression",
             Target::Statement => "statement",
             Target::Arm => "match arm",
@@ -212,12 +289,13 @@ impl Target {
                 MethodKind::Inherent => "inherent method",
                 MethodKind::Trait { body: false } => "required trait method",
                 MethodKind::Trait { body: true } => "provided trait method",
+                MethodKind::TraitImpl => "trait method in an impl block",
             },
             Target::AssocTy => "associated type",
             Target::ForeignFn => "foreign function",
             Target::ForeignStatic => "foreign static item",
             Target::ForeignTy => "foreign type",
-            Target::GenericParam { kind, has_default: _ } => match kind {
+            Target::GenericParam { kind, .. } => match kind {
                 GenericParamKind::Type => "type parameter",
                 GenericParamKind::Lifetime => "lifetime parameter",
                 GenericParamKind::Const => "const parameter",
@@ -227,6 +305,60 @@ impl Target {
             Target::PatField => "pattern field",
             Target::ExprField => "struct field",
             Target::WherePredicate => "where predicate",
+            Target::MacroCall => "macro call",
+            Target::Crate => "crate",
+            Target::Delegation { .. } => "delegation",
+        }
+    }
+
+    pub fn plural_name(self) -> &'static str {
+        match self {
+            Target::ExternCrate => "extern crates",
+            Target::Use => "use statements",
+            Target::Static => "statics",
+            Target::Const => "constants",
+            Target::Fn => "functions",
+            Target::Closure => "closures",
+            Target::Mod => "modules",
+            Target::ForeignMod => "foreign modules",
+            Target::GlobalAsm => "global asms",
+            Target::TyAlias => "type aliases",
+            Target::Enum => "enums",
+            Target::Variant => "enum variants",
+            Target::Struct => "structs",
+            Target::Field => "struct fields",
+            Target::Union => "unions",
+            Target::Trait => "traits",
+            Target::TraitAlias => "trait aliases",
+            Target::Impl { of_trait: false } => "inherent impl blocks",
+            Target::Impl { of_trait: true } => "trait impl blocks",
+            Target::Expression => "expressions",
+            Target::Statement => "statements",
+            Target::Arm => "match arms",
+            Target::AssocConst => "associated consts",
+            Target::Method(kind) => match kind {
+                MethodKind::Inherent => "inherent methods",
+                MethodKind::Trait { body: false } => "required trait methods",
+                MethodKind::Trait { body: true } => "provided trait methods",
+                MethodKind::TraitImpl => "trait methods in impl blocks",
+            },
+            Target::AssocTy => "associated types",
+            Target::ForeignFn => "foreign functions",
+            Target::ForeignStatic => "foreign statics",
+            Target::ForeignTy => "foreign types",
+            Target::GenericParam { kind, has_default: _ } => match kind {
+                GenericParamKind::Type => "type parameters",
+                GenericParamKind::Lifetime => "lifetime parameters",
+                GenericParamKind::Const => "const parameters",
+            },
+            Target::MacroDef => "macro defs",
+            Target::Param => "function params",
+            Target::PatField => "pattern fields",
+            Target::ExprField => "struct fields",
+            Target::WherePredicate => "where predicates",
+            Target::MacroCall => "macro calls",
+            Target::Crate => "crates",
+            Target::Delegation { .. } => "delegations",
         }
     }
 }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index eb03235de0c..7481b0ea960 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -13,22 +13,6 @@ passes_abi_ne =
 passes_abi_of =
     fn_abi_of({$fn_name}) = {$fn_abi}
 
-passes_align_attr_application =
-    `#[rustc_align(...)]` should be applied to a function item
-    .label = not a function item
-
-passes_align_on_fields =
-    attribute should be applied to a function or method
-    .warn = {-passes_previously_accepted}
-
-passes_align_should_be_repr_align =
-    `#[rustc_align(...)]` is not supported on {$item} items
-    .suggestion = use `#[repr(align(...))]` instead
-
-passes_allow_incoherent_impl =
-    `rustc_allow_incoherent_impl` attribute should be applied to impl items
-    .label = the only currently supported targets are inherent methods
-
 passes_macro_only_attribute =
     attribute should be applied to a macro
     .label = not a macro
@@ -78,18 +62,10 @@ passes_change_fields_to_be_of_unit_type =
      *[other] fields
     }
 
-passes_cold =
-    {passes_should_be_applied_to_fn}
-    .warn = {-passes_previously_accepted}
-    .label = {passes_should_be_applied_to_fn.label}
-
 passes_collapse_debuginfo =
     `collapse_debuginfo` attribute should be applied to macro definitions
     .label = not a macro definition
 
-passes_confusables = attribute should be applied to an inherent method
-    .label = not an inherent method
-
 passes_const_continue_attr =
     `#[const_continue]` should be applied to a break expression
     .label = not a break expression
@@ -98,16 +74,6 @@ passes_const_stable_not_stable =
     attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
     .label = attribute specified here
 
-passes_coroutine_on_non_closure =
-    attribute should be applied to closures
-    .label = not a closure
-
-passes_coverage_attribute_not_allowed =
-    coverage attribute not allowed here
-    .not_fn_impl_mod = not a function, impl block, or module
-    .no_body = function has no body
-    .help = coverage attribute can be applied to a function (with body), impl block, or module
-
 passes_dead_codes =
     { $multiple ->
       *[true] multiple {$descr}s are
@@ -129,9 +95,6 @@ passes_debug_visualizer_placement =
 passes_debug_visualizer_unreadable =
     couldn't read {$file}: {$error}
 
-passes_deprecated =
-    attribute is ignored here
-
 passes_deprecated_annotation_has_no_effect =
     this `#[deprecated]` annotation has no effect
     .suggestion = remove the unnecessary deprecation attribute
@@ -304,10 +267,6 @@ passes_duplicate_lang_item_crate_depends =
 passes_enum_variant_same_name =
     it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name
 
-passes_export_name =
-    attribute should be applied to a free function, impl method or static
-    .label = not a free function, impl method or static
-
 passes_extern_main =
     the `main` function cannot be declared in an `extern` block
 
@@ -317,21 +276,10 @@ passes_feature_previously_declared =
 passes_feature_stable_twice =
     feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
 
-passes_ffi_const_invalid_target =
-    `#[ffi_const]` may only be used on foreign functions
-
-passes_ffi_pure_invalid_target =
-    `#[ffi_pure]` may only be used on foreign functions
-
 passes_has_incoherent_inherent_impl =
     `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits
     .label = only adts, extern types and traits are supported
 
-passes_ignored_attr =
-    `#[{$sym}]` is ignored on struct fields and match arms
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "80564")}
-
 passes_ignored_attr_with_macro =
     `#[{$sym}]` is ignored on struct fields, match arms and macro defs
     .warn = {-passes_previously_accepted}
@@ -373,22 +321,10 @@ passes_incorrect_target =
 passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
     .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
 
-passes_inline_ignored_constants =
-    `#[inline]` is ignored on constants
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "65833")}
-
 passes_inline_ignored_for_exported =
     `#[inline]` is ignored on externally exported functions
     .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`
 
-passes_inline_ignored_function_prototype =
-    `#[inline]` is ignored on function prototypes
-
-passes_inline_not_fn_or_closure =
-    attribute should be applied to function or closure
-    .label = not a function or closure
-
 passes_inner_crate_level_attr =
     crate-level attribute should be in the root module
 
@@ -438,25 +374,6 @@ passes_link =
     .warn = {-passes_previously_accepted}
     .label = not an `extern` block
 
-passes_link_name =
-    attribute should be applied to a foreign function or static
-    .warn = {-passes_previously_accepted}
-    .label = not a foreign function or static
-    .help = try `#[link(name = "{$value}")]` instead
-
-passes_link_ordinal =
-    attribute should be applied to a foreign function or static
-    .label = not a foreign function or static
-
-passes_link_section =
-    attribute should be applied to a function or static
-    .warn = {-passes_previously_accepted}
-    .label = not a function or static
-
-passes_linkage =
-    attribute should be applied to a function or static
-    .label = not a function definition or static
-
 passes_loop_match_attr =
     `#[loop_match]` should be applied to a loop
     .label = not a loop
@@ -468,9 +385,6 @@ passes_macro_export_on_decl_macro =
     `#[macro_export]` has no effect on declarative macro definitions
     .note = declarative macros follow the same exporting rules as regular items
 
-passes_macro_use =
-    `#[{$name}]` only has an effect on `extern crate` and modules
-
 passes_may_dangle =
     `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
 
@@ -509,7 +423,7 @@ passes_must_not_suspend =
     .label = is not a struct, enum, union, or trait
 
 passes_must_use_no_effect =
-    `#[must_use]` has no effect when applied to {$article} {$target}
+    `#[must_use]` has no effect when applied to {$target}
     .suggestion = remove the attribute
 
 passes_no_link =
@@ -530,18 +444,6 @@ passes_no_main_function =
     .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
     .non_function_main = non-function item at `crate::main` is found
 
-passes_no_mangle =
-    attribute should be applied to a free function, impl method or static
-    .warn = {-passes_previously_accepted}
-    .label = not a free function, impl method or static
-
-passes_no_mangle_foreign =
-    `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
-    .warn = {-passes_previously_accepted}
-    .label = foreign {$foreign_item_kind}
-    .note = symbol names in extern blocks are not mangled
-    .suggestion = remove this attribute
-
 passes_no_sanitize =
     `#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind}
     .label = not {$accepted_kind}
@@ -557,19 +459,6 @@ passes_non_exported_macro_invalid_attrs =
 passes_object_lifetime_err =
     {$repr}
 
-passes_only_has_effect_on =
-    `#[{$attr_name}]` only has an effect on {$target_name ->
-        [function] functions
-        [module] modules
-        [trait_implementation_block] trait implementation blocks
-        [inherent_implementation_block] inherent implementation blocks
-        *[unspecified] (unspecified--this is a compiler bug)
-    }
-
-passes_optimize_invalid_target =
-    attribute applied to an invalid target
-    .label = invalid target
-
 passes_outer_crate_level_attr =
     crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
 
@@ -585,10 +474,6 @@ passes_parent_info =
      *[other] {$descr}s
     } in this {$parent_descr}
 
-passes_pass_by_value =
-    `pass_by_value` attribute should be applied to a struct, enum or type alias
-    .label = is not a struct, enum or type alias
-
 passes_proc_macro_bad_sig = {$kind} has incorrect signature
 
 passes_remove_fields =
@@ -605,7 +490,7 @@ passes_repr_align_greater_than_target_max =
     .note = `isize::MAX` is {$size} for the current target
 
 passes_repr_align_should_be_align =
-    `#[repr(align(...))]` is not supported on {$item} items
+    `#[repr(align(...))]` is not supported on {$item}
     .help = use `#[rustc_align(...)]` instead
 
 passes_repr_conflicting =
@@ -620,18 +505,10 @@ passes_rustc_const_stable_indirect_pairing =
 passes_rustc_dirty_clean =
     attribute requires -Z query-dep-graph to be enabled
 
-passes_rustc_force_inline =
-    attribute should be applied to a function
-    .label = not a function definition
-
 passes_rustc_force_inline_coro =
     attribute cannot be applied to a `async`, `gen` or `async gen` function
     .label = `async`, `gen` or `async gen` function
 
-passes_rustc_layout_scalar_valid_range_not_struct =
-    attribute should be applied to a struct
-    .label = not a struct
-
 passes_rustc_legacy_const_generics_index =
     #[rustc_legacy_const_generics] must have one index for each generic parameter
     .label = generic parameters
@@ -665,14 +542,6 @@ passes_rustc_pub_transparent =
     attribute should be applied to `#[repr(transparent)]` types
     .label = not a `#[repr(transparent)]` type
 
-passes_rustc_std_internal_symbol =
-    attribute should be applied to functions or statics
-    .label = not a function or static
-
-passes_rustc_unstable_feature_bound =
-    attribute should be applied to `impl`, trait or free function
-    .label = not an `impl`, trait or free function
-
 passes_should_be_applied_to_fn =
     attribute should be applied to a function definition
     .label = {$on_crate ->
@@ -684,24 +553,12 @@ passes_should_be_applied_to_static =
     attribute should be applied to a static
     .label = not a static
 
-passes_should_be_applied_to_struct_enum =
-    attribute should be applied to a struct or enum
-    .label = not a struct or enum
-
 passes_should_be_applied_to_trait =
     attribute should be applied to a trait
     .label = not a trait
 
-passes_stability_promotable =
-    attribute cannot be applied to an expression
-
 passes_string_interpolation_only_works = string interpolation only works in `format!` invocations
 
-passes_target_feature_on_statement =
-    {passes_should_be_applied_to_fn}
-    .warn = {-passes_previously_accepted}
-    .label = {passes_should_be_applied_to_fn.label}
-
 passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait
 passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable...
 passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable...
@@ -826,11 +683,6 @@ passes_unused_variable_try_prefix = unused variable: `{$name}`
     .label = unused variable
     .suggestion = if this is intentional, prefix it with an underscore
 
-
-passes_used_static =
-    attribute must be applied to a `static` variable
-    .label = but this is a {$target}
-
 passes_useless_assignment =
     useless assignment of {$is_field_assign ->
         [true] field
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index df1db65c06e..0e28c51e981 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,7 +10,7 @@ use std::collections::hash_map::Entry;
 use std::slice;
 
 use rustc_abi::{Align, ExternAbi, Size};
-use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms};
+use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast};
 use rustc_attr_parsing::{AttributeParser, Late};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
@@ -40,7 +40,6 @@ use rustc_session::lint;
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
     MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
-    USELESS_DEPRECATED,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::edition::Edition;
@@ -50,7 +49,6 @@ use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
 use rustc_trait_selection::traits::ObligationCtxt;
 use tracing::debug;
 
-use crate::errors::AlignOnFields;
 use crate::{errors, fluent_generated as fluent};
 
 #[derive(LintDiagnostic)]
@@ -134,56 +132,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 Attribute::Parsed(AttributeKind::ProcMacroAttribute(_)) => {
                     self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
                 }
-                Attribute::Parsed(AttributeKind::ProcMacroDerive { span: attr_span, .. }) => {
-                    self.check_generic_attr(
-                        hir_id,
-                        sym::proc_macro_derive,
-                        *attr_span,
-                        target,
-                        Target::Fn,
-                    );
+                Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => {
                     self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
                 }
-                Attribute::Parsed(
-                    AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. }
-                    | AttributeKind::Coinductive(attr_span)
-                    | AttributeKind::ConstTrait(attr_span)
-                    | AttributeKind::DenyExplicitImpl(attr_span)
-                    | AttributeKind::DoNotImplementViaObject(attr_span),
-                ) => {
-                    self.check_must_be_applied_to_trait(*attr_span, span, target);
-                }
-                &Attribute::Parsed(
-                    AttributeKind::SpecializationTrait(attr_span)
-                    | AttributeKind::UnsafeSpecializationMarker(attr_span)
-                    | AttributeKind::ParenSugar(attr_span),
-                ) => {
-                    // FIXME: more validation is needed
-                    self.check_must_be_applied_to_trait(attr_span, span, target);
-                }
                 &Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => {
                     self.check_type_const(hir_id, attr_span, target)
                 }
-                &Attribute::Parsed(AttributeKind::Marker(attr_span)) => {
-                    self.check_marker(hir_id, attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::Fundamental | AttributeKind::CoherenceIsCore) => {
-                    // FIXME: add validation
-                }
-                &Attribute::Parsed(AttributeKind::AllowIncoherentImpl(attr_span)) => {
-                    self.check_allow_incoherent_impl(attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
-                    self.check_confusables(*first_span, target);
-                }
-                Attribute::Parsed(AttributeKind::AutomaticallyDerived(attr_span)) => self
-                    .check_generic_attr(
-                        hir_id,
-                        sym::automatically_derived,
-                        *attr_span,
-                        target,
-                        Target::Impl { of_trait: true },
-                    ),
                 Attribute::Parsed(
                     AttributeKind::Stability {
                         span: attr_span,
@@ -193,13 +147,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         span: attr_span,
                         stability: PartialConstStability { level, feature, .. },
                     },
-                ) => self.check_stability(*attr_span, span, level, *feature, target),
+                ) => self.check_stability(*attr_span, span, level, *feature),
                 Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
                 Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
-                    self.check_inline(hir_id, *attr_span, span, kind, target)
-                }
-                Attribute::Parsed(AttributeKind::Optimize(_, attr_span)) => {
-                    self.check_optimize(hir_id, *attr_span, span, target)
+                    self.check_inline(hir_id, *attr_span, kind, target)
                 }
                 Attribute::Parsed(AttributeKind::LoopMatch(attr_span)) => {
                     self.check_loop_match(hir_id, *attr_span, target)
@@ -207,11 +158,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => {
                     self.check_const_continue(hir_id, *attr_span, target)
                 }
-                Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => {
-                    self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs)
-                }
-                Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => {
-                    self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs)
+                Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span)) => {
+                    self.check_macro_only_attr(*attr_span, span, target, attrs)
                 }
                 Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => {
                     self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target)
@@ -220,11 +168,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     self.check_deprecated(hir_id, attr, span, target)
                 }
                 Attribute::Parsed(AttributeKind::TargetFeature(_, attr_span)) => {
-                    self.check_target_feature(hir_id, *attr_span, span, target, attrs)
-                }
-                Attribute::Parsed(AttributeKind::DocComment { .. }) => { /* `#[doc]` is actually a lot more than just doc comments, so is checked below*/
-                }
-                Attribute::Parsed(AttributeKind::Repr { .. }) => { /* handled below this loop and elsewhere */
+                    self.check_target_feature(hir_id, *attr_span, target, attrs)
                 }
                 Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => {
                     self.check_object_lifetime_default(hir_id);
@@ -232,59 +176,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 &Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => {
                     self.check_rustc_pub_transparent(attr_span, span, attrs)
                 }
-                Attribute::Parsed(AttributeKind::Cold(attr_span)) => {
-                    self.check_cold(hir_id, *attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => {
-                    self.check_export_name(hir_id, *attr_span, span, target)
-                }
                 Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => {
-                    self.check_align(span, hir_id, target, *align, *attr_span)
-                }
-                Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => {
-                    self.check_link_section(hir_id, *attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => {
-                    self.check_macro_use(hir_id, sym::macro_use, *span, target)
+                    self.check_align(*align, *attr_span)
                 }
-                Attribute::Parsed(AttributeKind::MacroEscape(span)) => {
-                    self.check_macro_use(hir_id, sym::macro_escape, *span, target)
-                }
-                Attribute::Parsed(AttributeKind::Naked(attr_span)) => {
-                    self.check_naked(hir_id, *attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::NoImplicitPrelude(attr_span)) => self
-                    .check_generic_attr(
-                        hir_id,
-                        sym::no_implicit_prelude,
-                        *attr_span,
-                        target,
-                        Target::Mod,
-                    ),
-                Attribute::Parsed(AttributeKind::Path(_, attr_span)) => {
-                    self.check_generic_attr(hir_id, sym::path, *attr_span, target, Target::Mod)
+                Attribute::Parsed(AttributeKind::Naked(..)) => {
+                    self.check_naked(hir_id, target)
                 }
                 Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
-                    self.check_track_caller(hir_id, *attr_span, attrs, span, target)
+                    self.check_track_caller(hir_id, *attr_span, attrs, target)
                 }
                 Attribute::Parsed(AttributeKind::NonExhaustive(attr_span)) => {
-                    self.check_non_exhaustive(hir_id, *attr_span, span, target, item)
-                }
-                Attribute::Parsed(
-                    AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span)
-                    | AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span),
-                ) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target),
-                Attribute::Parsed(AttributeKind::ExportStable) => {
-                    // handled in `check_export`
-                }
-                &Attribute::Parsed(AttributeKind::FfiConst(attr_span)) => {
-                    self.check_ffi_const(attr_span, target)
+                    self.check_non_exhaustive(*attr_span, span, target, item)
                 }
                 &Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => {
-                    self.check_ffi_pure(attr_span, attrs, target)
+                    self.check_ffi_pure(attr_span, attrs)
                 }
-                Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => {
-                    self.check_unstable_feature_bound(syms.first().unwrap().1, span, target)
+                Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
+                    self.check_may_dangle(hir_id, *attr_span)
+                }
+                Attribute::Parsed(AttributeKind::MustUse { span, .. }) => {
+                    self.check_must_use(hir_id, *span, target)
                 }
                 Attribute::Parsed(
                     AttributeKind::BodyStability { .. }
@@ -292,49 +203,52 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::MacroTransparency(_)
                     | AttributeKind::Pointee(..)
                     | AttributeKind::Dummy
-                    | AttributeKind::RustcBuiltinMacro { .. },
+                    | AttributeKind::RustcBuiltinMacro { .. }
+                    | AttributeKind::Ignore { .. }
+                    | AttributeKind::Path(..)
+                    | AttributeKind::NoImplicitPrelude(..)
+                    | AttributeKind::AutomaticallyDerived(..)
+                    | AttributeKind::Marker(..)
+                    | AttributeKind::SkipDuringMethodDispatch { .. }
+                    | AttributeKind::Coinductive(..)
+                    | AttributeKind::ConstTrait(..)
+                    | AttributeKind::DenyExplicitImpl(..)
+                    | AttributeKind::DoNotImplementViaObject(..)
+                    | AttributeKind::SpecializationTrait(..)
+                    | AttributeKind::UnsafeSpecializationMarker(..)
+                    | AttributeKind::ParenSugar(..)
+                    | AttributeKind::AllowIncoherentImpl(..)
+                    | AttributeKind::Confusables { .. }
+                    // `#[doc]` is actually a lot more than just doc comments, so is checked below
+                    | AttributeKind::DocComment {..}
+                    // handled below this loop and elsewhere
+                    | AttributeKind::Repr { .. }
+                    | AttributeKind::Cold(..)
+                    | AttributeKind::ExportName { .. }
+                    | AttributeKind::CoherenceIsCore
+                    | AttributeKind::Fundamental
+                    | AttributeKind::Optimize(..)
+                    | AttributeKind::LinkSection { .. }
+                    | AttributeKind::MacroUse { .. }
+                    | AttributeKind::MacroEscape( .. )
+                    | AttributeKind::RustcLayoutScalarValidRangeStart(..)
+                    | AttributeKind::RustcLayoutScalarValidRangeEnd(..)
+                    | AttributeKind::ExportStable
+                    | AttributeKind::FfiConst(..)
+                    | AttributeKind::UnstableFeatureBound(..)
+                    | AttributeKind::AsPtr(..)
+                    | AttributeKind::LinkName { .. }
+                    | AttributeKind::LinkOrdinal { .. }
+                    | AttributeKind::NoMangle(..)
+                    | AttributeKind::Used { .. }
+                    | AttributeKind::PassByValue (..)
+                    | AttributeKind::StdInternalSymbol (..)
+                    | AttributeKind::Coverage (..)
+                    | AttributeKind::ShouldPanic { .. }
+                    | AttributeKind::Coroutine(..)
+                    | AttributeKind::Linkage(..),
                 ) => { /* do nothing  */ }
-                Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
-                    self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => {
-                    self.check_link_name(hir_id, *attr_span, *name, span, target)
-                }
-                Attribute::Parsed(AttributeKind::LinkOrdinal { span: attr_span, .. }) => {
-                    self.check_link_ordinal(*attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
-                    self.check_may_dangle(hir_id, *attr_span)
-                }
-                Attribute::Parsed(AttributeKind::Ignore { span, .. }) => {
-                    self.check_generic_attr(hir_id, sym::ignore, *span, target, Target::Fn)
-                }
-                Attribute::Parsed(AttributeKind::MustUse { span, .. }) => {
-                    self.check_must_use(hir_id, *span, target)
-                }
-                Attribute::Parsed(AttributeKind::NoMangle(attr_span)) => {
-                    self.check_no_mangle(hir_id, *attr_span, span, target)
-                }
-                Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => {
-                    self.check_used(*attr_span, target, span);
-                }
-                Attribute::Parsed(AttributeKind::ShouldPanic { span: attr_span, .. }) => self
-                    .check_generic_attr(hir_id, sym::should_panic, *attr_span, target, Target::Fn),
-                &Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => {
-                    self.check_pass_by_value(attr_span, span, target)
-                }
-                &Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => {
-                    self.check_rustc_std_internal_symbol(attr_span, span, target)
-                }
-                &Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => {
-                    self.check_coverage(attr_span, span, target)
-                }
-                &Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => {
-                    self.check_coroutine(attr_span, target)
-                }
-                &Attribute::Parsed(AttributeKind::Linkage(_, attr_span)) => {
-                    self.check_linkage(attr_span, span, target);
-                }
+
                 Attribute::Unparsed(attr_item) => {
                     style = Some(attr_item.style);
                     match attr.path().as_slice() {
@@ -390,10 +304,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::rustc_has_incoherent_inherent_impls, ..] => {
                             self.check_has_incoherent_inherent_impls(attr, span, target)
                         }
-                        [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target),
-                        [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target),
                         [sym::link, ..] => self.check_link(hir_id, attr, span, target),
-                        [sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod),
                         [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
                         [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
                             self.check_autodiff(hir_id, attr, span, target)
@@ -485,7 +396,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
 
         self.check_repr(attrs, span, target, item, hir_id);
-        self.check_rustc_force_inline(hir_id, attrs, span, target);
+        self.check_rustc_force_inline(hir_id, attrs, target);
         self.check_mix_no_mangle_export(hir_id, attrs);
     }
 
@@ -498,15 +409,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         );
     }
 
-    fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr_span: Span, sym: &str) {
-        self.tcx.emit_node_span_lint(
-            UNUSED_ATTRIBUTES,
-            hir_id,
-            attr_span,
-            errors::IgnoredAttr { sym },
-        );
-    }
-
     /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl and that it has no
     /// arguments.
     fn check_do_not_recommend(
@@ -554,14 +456,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     /// Checks if an `#[inline]` is applied to a function or a closure.
-    fn check_inline(
-        &self,
-        hir_id: HirId,
-        attr_span: Span,
-        defn_span: Span,
-        kind: &InlineAttr,
-        target: Target,
-    ) {
+    fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) {
         match target {
             Target::Fn
             | Target::Closure
@@ -583,81 +478,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     }
                 }
             }
-            Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::IgnoredInlineAttrFnProto,
-                )
-            }
-            // FIXME(#65833): We permit associated consts to have an `#[inline]` 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::AssocConst => self.tcx.emit_node_span_lint(
-                UNUSED_ATTRIBUTES,
-                hir_id,
-                attr_span,
-                errors::IgnoredInlineAttrConstants,
-            ),
-            // FIXME(#80564): Same for fields, arms, and macro defs
-            Target::Field | Target::Arm | Target::MacroDef => {
-                self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "inline")
-            }
-            _ => {
-                self.dcx().emit_err(errors::InlineNotFnOrClosure { attr_span, defn_span });
-            }
-        }
-    }
-
-    /// Checks that `#[coverage(..)]` is applied to a function/closure/method,
-    /// or to an impl block or module.
-    fn check_coverage(&self, attr_span: Span, target_span: Span, target: Target) {
-        let mut not_fn_impl_mod = None;
-        let mut no_body = None;
-
-        match target {
-            Target::Fn
-            | Target::Closure
-            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
-            | Target::Impl { .. }
-            | Target::Mod => return,
-
-            // These are "functions", but they aren't allowed because they don't
-            // have a body, so the usual explanation would be confusing.
-            Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
-                no_body = Some(target_span);
-            }
-
-            _ => {
-                not_fn_impl_mod = Some(target_span);
-            }
-        }
-
-        self.dcx().emit_err(errors::CoverageAttributeNotAllowed {
-            attr_span,
-            not_fn_impl_mod,
-            no_body,
-            help: (),
-        });
-    }
-
-    /// Checks that `#[optimize(..)]` is applied to a function/closure/method,
-    /// or to an impl block or module.
-    fn check_optimize(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
-        let is_valid = matches!(
-            target,
-            Target::Fn
-                | Target::Closure
-                | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
-        );
-        if !is_valid {
-            self.dcx().emit_err(errors::OptimizeInvalidTarget {
-                attr_span,
-                defn_span: span,
-                on_crate: hir_id == CRATE_HIR_ID,
-            });
+            _ => {}
         }
     }
 
@@ -697,51 +518,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// FIXME: Remove when all attributes are ported to the new parser
-    fn check_generic_attr_unparsed(
-        &self,
-        hir_id: HirId,
-        attr: &Attribute,
-        target: Target,
-        allowed_target: Target,
-    ) {
-        if target != allowed_target {
-            let attr_name = join_path_syms(attr.path());
-            self.tcx.emit_node_span_lint(
-                UNUSED_ATTRIBUTES,
-                hir_id,
-                attr.span(),
-                errors::OnlyHasEffectOn {
-                    attr_name,
-                    target_name: allowed_target.name().replace(' ', "_"),
-                },
-            );
-        }
-    }
-
-    fn check_generic_attr(
-        &self,
-        hir_id: HirId,
-        attr_name: Symbol,
-        attr_span: Span,
-        target: Target,
-        allowed_target: Target,
-    ) {
-        if target != allowed_target {
-            self.tcx.emit_node_span_lint(
-                UNUSED_ATTRIBUTES,
-                hir_id,
-                attr_span,
-                errors::OnlyHasEffectOn {
-                    attr_name: attr_name.to_string(),
-                    target_name: allowed_target.name().replace(' ', "_"),
-                },
-            );
-        }
-    }
-
     /// Checks if `#[naked]` is applied to a function definition.
-    fn check_naked(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
+    fn check_naked(&self, hir_id: HirId, target: Target) {
         match target {
             Target::Fn
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
@@ -760,13 +538,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     .emit();
                 }
             }
-            _ => {
-                self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
-                    attr_span,
-                    defn_span: span,
-                    on_crate: hir_id == CRATE_HIR_ID,
-                });
-            }
+            _ => {}
         }
     }
 
@@ -809,7 +581,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         hir_id: HirId,
         attr_span: Span,
         attrs: &[Attribute],
-        span: Span,
         target: Target,
     ) {
         match target {
@@ -829,28 +600,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     });
                 }
             }
-            Target::Method(..) | Target::ForeignFn | Target::Closure => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[track_caller]` 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, "track_caller");
-            }
-            _ => {
-                self.dcx().emit_err(errors::TrackedCallerWrongLocation {
-                    attr_span,
-                    defn_span: span,
-                    on_crate: hir_id == CRATE_HIR_ID,
-                });
-            }
+            _ => {}
         }
     }
 
     /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid.
     fn check_non_exhaustive(
         &self,
-        hir_id: HirId,
         attr_span: Span,
         span: Span,
         target: Target,
@@ -871,36 +627,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     });
                 }
             }
-            Target::Enum | Target::Variant => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[non_exhaustive]` 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, "non_exhaustive");
-            }
-            _ => {
-                self.dcx()
-                    .emit_err(errors::NonExhaustiveWrongLocation { attr_span, defn_span: span });
-            }
-        }
-    }
-
-    /// Checks if the `#[marker]` attribute on an `item` is valid.
-    fn check_marker(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Trait => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[marker]` 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, "marker");
-            }
-            _ => {
-                self.dcx()
-                    .emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span: span });
-            }
+            _ => {}
         }
     }
 
@@ -909,7 +636,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         &self,
         hir_id: HirId,
         attr_span: Span,
-        span: Span,
         target: Target,
         attrs: &[Attribute],
     ) {
@@ -932,30 +658,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     });
                 }
             }
-            // FIXME: #[target_feature] was previously erroneously allowed on statements and some
-            // crates used this, so only emit a warning.
-            Target::Statement => {
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::TargetFeatureOnStatement,
-                );
-            }
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[target_feature]` 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, "target_feature");
-            }
-            _ => {
-                self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
-                    attr_span,
-                    defn_span: span,
-                    on_crate: hir_id == CRATE_HIR_ID,
-                });
-            }
+            _ => {}
         }
     }
 
@@ -1059,7 +762,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             | Target::GenericParam { .. }
             | Target::MacroDef
             | Target::PatField
-            | Target::ExprField => None,
+            | Target::ExprField
+            | Target::Crate
+            | Target::MacroCall
+            | Target::Delegation { .. } => None,
         } {
             tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location });
             return;
@@ -1535,25 +1241,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Warns against some misuses of `#[pass_by_value]`
-    fn check_pass_by_value(&self, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Struct | Target::Enum | Target::TyAlias => {}
-            _ => {
-                self.dcx().emit_err(errors::PassByValue { attr_span, span });
-            }
-        }
-    }
-
-    fn check_allow_incoherent_impl(&self, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Method(MethodKind::Inherent) => {}
-            _ => {
-                self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span, span });
-            }
-        }
-    }
-
     fn check_has_incoherent_inherent_impls(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
             Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => {}
@@ -1565,23 +1252,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) {
-        if target != Target::ForeignFn {
-            self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span });
-            return;
-        }
+    fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute]) {
         if find_attr!(attrs, AttributeKind::FfiConst(_)) {
             // `#[ffi_const]` functions cannot be `#[ffi_pure]`
             self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span });
         }
     }
 
-    fn check_ffi_const(&self, attr_span: Span, target: Target) {
-        if target != Target::ForeignFn {
-            self.dcx().emit_err(errors::FfiConstInvalidTarget { attr_span });
-        }
-    }
-
     /// Warns against some misuses of `#[must_use]`
     fn check_must_use(&self, hir_id: HirId, attr_span: Span, target: Target) {
         if matches!(
@@ -1609,22 +1286,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             return;
         }
 
-        let article = match target {
-            Target::ExternCrate
-            | Target::Enum
-            | Target::Impl { .. }
-            | Target::Expression
-            | Target::Arm
-            | Target::AssocConst
-            | Target::AssocTy => "an",
-            _ => "a",
-        };
-
         self.tcx.emit_node_span_lint(
             UNUSED_ATTRIBUTES,
             hir_id,
             attr_span,
-            errors::MustUseNoEffect { article, target, attr_span },
+            errors::MustUseNoEffect { target: target.plural_name(), attr_span },
         );
     }
 
@@ -1659,30 +1325,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         self.dcx().emit_err(errors::InvalidMayDangle { attr_span });
     }
 
-    /// Checks if `#[cold]` is applied to a non-function.
-    fn check_cold(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[cold]` 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, "cold");
-            }
-            _ => {
-                // FIXME: #[cold] was previously allowed on non-functions and some crates used
-                // this, so only emit a warning.
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID },
-                );
-            }
-        }
-    }
-
     /// Checks if `#[link]` is applied to an item other than a foreign module.
     fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
         if target == Target::ForeignMod
@@ -1701,38 +1343,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         );
     }
 
-    /// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
-    fn check_link_name(
-        &self,
-        hir_id: HirId,
-        attr_span: Span,
-        name: Symbol,
-        span: Span,
-        target: Target,
-    ) {
-        match target {
-            Target::ForeignFn | Target::ForeignStatic => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[link_name]` 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, "link_name");
-            }
-            _ => {
-                // FIXME: #[link_name] was previously allowed on non-functions/statics and some crates
-                // used this, so only emit a warning.
-                let help_span = matches!(target, Target::ForeignMod).then_some(attr_span);
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::LinkName { span, help_span, value: name.as_str() },
-                );
-            }
-        }
-    }
-
     /// Checks if `#[no_link]` is applied to an `extern crate`.
     fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
         match target {
@@ -1750,35 +1360,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn is_impl_item(&self, hir_id: HirId) -> bool {
-        matches!(self.tcx.hir_node(hir_id), hir::Node::ImplItem(..))
-    }
-
-    /// Checks if `#[export_name]` is applied to a function or static.
-    fn check_export_name(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Static | Target::Fn => {}
-            Target::Method(..) if self.is_impl_item(hir_id) => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[export_name]` 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, "export_name");
-            }
-            _ => {
-                self.dcx().emit_err(errors::ExportName { attr_span, span });
-            }
-        }
-    }
-
-    fn check_rustc_layout_scalar_valid_range(&self, attr_span: Span, span: Span, target: Target) {
-        if target != Target::Struct {
-            self.dcx().emit_err(errors::RustcLayoutScalarValidRangeNotStruct { attr_span, span });
-            return;
-        }
-    }
-
     /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
     fn check_rustc_legacy_const_generics(
         &self,
@@ -1913,106 +1494,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Checks if `#[link_section]` is applied to a function or static.
-    fn check_link_section(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Static | Target::Fn | Target::Method(..) => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[link_section]` 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, "link_section");
-            }
-            _ => {
-                // FIXME: #[link_section] was previously allowed on non-functions/statics and some
-                // crates used this, so only emit a warning.
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::LinkSection { span },
-                );
-            }
-        }
-    }
-
-    /// Checks if `#[no_mangle]` is applied to a function or static.
-    fn check_no_mangle(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Static | Target::Fn => {}
-            Target::Method(..) if self.is_impl_item(hir_id) => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[no_mangle]` 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, "no_mangle");
-            }
-            // FIXME: #[no_mangle] was previously allowed on non-functions/statics, this should be an error
-            // The error should specify that the item that is wrong is specifically a *foreign* fn/static
-            // otherwise the error seems odd
-            Target::ForeignFn | Target::ForeignStatic => {
-                let foreign_item_kind = match target {
-                    Target::ForeignFn => "function",
-                    Target::ForeignStatic => "static",
-                    _ => unreachable!(),
-                };
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::NoMangleForeign { span, attr_span, foreign_item_kind },
-                );
-            }
-            _ => {
-                // FIXME: #[no_mangle] was previously allowed on non-functions/statics and some
-                // crates used this, so only emit a warning.
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::NoMangle { span },
-                );
-            }
-        }
-    }
-
-    /// Checks if the `#[align]` attributes on `item` are valid.
-    // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
-    fn check_align(
-        &self,
-        span: Span,
-        hir_id: HirId,
-        target: Target,
-        align: Align,
-        attr_span: Span,
-    ) {
-        match target {
-            Target::Fn | Target::Method(_) | Target::ForeignFn => {}
-            Target::Field => {
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    AlignOnFields { span },
-                );
-            }
-            Target::Struct | Target::Union | Target::Enum => {
-                self.dcx().emit_err(errors::AlignShouldBeReprAlign {
-                    span: attr_span,
-                    item: target.name(),
-                    align_bytes: align.bytes(),
-                });
-            }
-            _ => {
-                self.dcx().emit_err(errors::AlignAttrApplication { hint_span: attr_span, span });
-            }
-        }
-
-        self.check_align_value(align, attr_span);
-    }
-
     /// Checks if the `#[repr]` attributes on `item` are valid.
     fn check_repr(
         &self,
@@ -2067,7 +1548,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         Target::Fn | Target::Method(_) => {
                             self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
                                 span: *repr_span,
-                                item: target.name(),
+                                item: target.plural_name(),
                             });
                         }
                         _ => {
@@ -2078,7 +1559,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         }
                     }
 
-                    self.check_align_value(*align, *repr_span);
+                    self.check_align(*align, *repr_span);
                 }
                 ReprAttr::ReprPacked(_) => {
                     if target != Target::Struct && target != Target::Union {
@@ -2137,7 +1618,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 Target::Fn | Target::Method(_) => {
                     self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
                         span: first_attr_span,
-                        item: target.name(),
+                        item: target.plural_name(),
                     });
                 }
                 _ => {
@@ -2184,7 +1665,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_align_value(&self, align: Align, span: Span) {
+    fn check_align(&self, align: Align, span: Span) {
         if align.bytes() > 2_u64.pow(29) {
             // for values greater than 2^29, a different error will be emitted, make sure that happens
             self.dcx().span_delayed_bug(
@@ -2203,61 +1684,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_used(&self, attr_span: Span, target: Target, target_span: Span) {
-        if target != Target::Static {
-            self.dcx().emit_err(errors::UsedStatic {
-                attr_span,
-                span: target_span,
-                target: target.name(),
-            });
-        }
-    }
-
-    /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
-    /// (Allows proc_macro functions)
-    fn check_allow_internal_unstable(
-        &self,
-        hir_id: HirId,
-        attr_span: Span,
-        span: Span,
-        target: Target,
-        attrs: &[Attribute],
-    ) {
-        self.check_macro_only_attr(
-            hir_id,
-            attr_span,
-            span,
-            target,
-            attrs,
-            "allow_internal_unstable",
-        )
-    }
-
-    /// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros.
-    /// (Allows proc_macro functions)
-    fn check_allow_internal_unsafe(
-        &self,
-        hir_id: HirId,
-        attr_span: Span,
-        span: Span,
-        target: Target,
-        attrs: &[Attribute],
-    ) {
-        self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe")
-    }
-
     /// Outputs an error for attributes that can only be applied to macros, such as
     /// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`.
     /// (Allows proc_macro functions)
     // FIXME(jdonszelmann): if possible, move to attr parsing
     fn check_macro_only_attr(
         &self,
-        hir_id: HirId,
         attr_span: Span,
         span: Span,
         target: Target,
         attrs: &[Attribute],
-        attr_name: &str,
     ) {
         match target {
             Target::Fn => {
@@ -2267,23 +1703,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         return;
                     }
                 }
-                // continue out of the match
-            }
-            // return on decl macros
-            Target::MacroDef => return,
-            // FIXME(#80564): We permit struct fields and match arms to have an
-            // `#[allow_internal_unstable]` 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 => {
-                self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name);
-                return;
+                self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span });
             }
-            // otherwise continue out of the match
             _ => {}
         }
-
-        self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span });
     }
 
     /// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
@@ -2310,66 +1733,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         target: Target,
     ) {
         match target {
-            Target::Fn | Target::Method(_)
-                if self.tcx.is_const_fn(hir_id.expect_owner().to_def_id()) => {}
-            // FIXME(#80564): We permit struct fields and match arms to have an
-            // `#[allow_internal_unstable]` 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, "allow_internal_unstable"),
-            _ => {
-                self.tcx.dcx().emit_err(errors::RustcAllowConstFnUnstable { attr_span, span });
-            }
-        }
-    }
-
-    fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Target) {
-        match target {
-            // FIXME(staged_api): There's no reason we can't support more targets here. We're just
-            // being conservative to begin with.
-            Target::Fn | Target::Impl { .. } | Target::Trait => {}
-            Target::ExternCrate
-            | Target::Use
-            | Target::Static
-            | Target::Const
-            | Target::Closure
-            | Target::Mod
-            | Target::ForeignMod
-            | Target::GlobalAsm
-            | Target::TyAlias
-            | Target::Enum
-            | Target::Variant
-            | Target::Struct
-            | Target::Field
-            | Target::Union
-            | Target::TraitAlias
-            | Target::Expression
-            | Target::Statement
-            | Target::Arm
-            | Target::AssocConst
-            | Target::Method(_)
-            | Target::AssocTy
-            | Target::ForeignFn
-            | Target::ForeignStatic
-            | Target::ForeignTy
-            | Target::GenericParam { .. }
-            | Target::MacroDef
-            | Target::Param
-            | Target::PatField
-            | Target::ExprField
-            | Target::WherePredicate => {
-                self.tcx.dcx().emit_err(errors::RustcUnstableFeatureBound { attr_span, span });
-            }
-        }
-    }
-
-    fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {}
-            _ => {
-                self.tcx.dcx().emit_err(errors::RustcStdInternalSymbol { attr_span, span });
+            Target::Fn | Target::Method(_) => {
+                if !self.tcx.is_const_fn(hir_id.expect_owner().to_def_id()) {
+                    self.tcx.dcx().emit_err(errors::RustcAllowConstFnUnstable { attr_span, span });
+                }
             }
+            _ => {}
         }
     }
 
@@ -2379,15 +1748,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         item_span: Span,
         level: &StabilityLevel,
         feature: Symbol,
-        target: Target,
     ) {
-        match target {
-            Target::Expression => {
-                self.dcx().emit_err(errors::StabilityPromotable { attr_span });
-            }
-            _ => {}
-        }
-
         // Stable *language* features shouldn't be used as unstable library features.
         // (Not doing this for stable library features is checked by tidy.)
         if level.is_unstable()
@@ -2399,40 +1760,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) {
-        match target {
-            Target::ForeignFn | Target::ForeignStatic => {}
-            _ => {
-                self.dcx().emit_err(errors::LinkOrdinal { attr_span });
-            }
-        }
-    }
-
-    fn check_confusables(&self, span: Span, target: Target) {
-        if !matches!(target, Target::Method(MethodKind::Inherent)) {
-            self.dcx().emit_err(errors::Confusables { attr_span: span });
-        }
-    }
-
     fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target: Target) {
         match target {
-            Target::Closure | Target::Expression | Target::Statement | Target::Arm => {
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr.span(),
-                    errors::Deprecated,
-                );
-            }
-            Target::Impl { of_trait: true }
-            | Target::GenericParam { has_default: false, kind: _ } => {
-                self.tcx.emit_node_span_lint(
-                    USELESS_DEPRECATED,
-                    hir_id,
-                    attr.span(),
-                    errors::DeprecatedAnnotationHasNoEffect { span: attr.span() },
-                );
-            }
             Target::AssocConst | Target::Method(..) | Target::AssocTy
                 if matches!(
                     self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id)),
@@ -2440,7 +1769,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 ) =>
             {
                 self.tcx.emit_node_span_lint(
-                    USELESS_DEPRECATED,
+                    UNUSED_ATTRIBUTES,
                     hir_id,
                     attr.span(),
                     errors::DeprecatedAnnotationHasNoEffect { span: attr.span() },
@@ -2450,20 +1779,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_macro_use(&self, hir_id: HirId, name: Symbol, attr_span: Span, target: Target) {
-        match target {
-            Target::ExternCrate | Target::Mod => {}
-            _ => {
-                self.tcx.emit_node_span_lint(
-                    UNUSED_ATTRIBUTES,
-                    hir_id,
-                    attr_span,
-                    errors::MacroUse { name },
-                );
-            }
-        }
-    }
-
     fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
         if target != Target::MacroDef {
             self.tcx.emit_node_span_lint(
@@ -2683,15 +1998,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_coroutine(&self, attr_span: Span, target: Target) {
-        match target {
-            Target::Closure => return,
-            _ => {
-                self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr_span });
-            }
-        }
-    }
-
     fn check_type_const(&self, hir_id: HirId, attr_span: Span, target: Target) {
         let tcx = self.tcx;
         if target == Target::AssocConst
@@ -2709,19 +2015,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_linkage(&self, attr_span: Span, span: Span, target: Target) {
-        match target {
-            Target::Fn
-            | Target::Method(..)
-            | Target::Static
-            | Target::ForeignStatic
-            | Target::ForeignFn => {}
-            _ => {
-                self.dcx().emit_err(errors::Linkage { attr_span, span });
-            }
-        }
-    }
-
     fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) {
         if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent))
             .unwrap_or(false)
@@ -2730,43 +2023,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    fn check_rustc_force_inline(
-        &self,
-        hir_id: HirId,
-        attrs: &[Attribute],
-        span: Span,
-        target: Target,
-    ) {
-        match (
+    fn check_rustc_force_inline(&self, hir_id: HirId, attrs: &[Attribute], target: Target) {
+        if let (Target::Closure, None) = (
             target,
             find_attr!(attrs, AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span),
         ) {
-            (Target::Closure, None) => {
-                let is_coro = matches!(
-                    self.tcx.hir_expect_expr(hir_id).kind,
-                    hir::ExprKind::Closure(hir::Closure {
-                        kind: hir::ClosureKind::Coroutine(..)
-                            | hir::ClosureKind::CoroutineClosure(..),
-                        ..
-                    })
-                );
-                let parent_did = self.tcx.hir_get_parent_item(hir_id).to_def_id();
-                let parent_span = self.tcx.def_span(parent_did);
+            let is_coro = matches!(
+                self.tcx.hir_expect_expr(hir_id).kind,
+                hir::ExprKind::Closure(hir::Closure {
+                    kind: hir::ClosureKind::Coroutine(..) | hir::ClosureKind::CoroutineClosure(..),
+                    ..
+                })
+            );
+            let parent_did = self.tcx.hir_get_parent_item(hir_id).to_def_id();
+            let parent_span = self.tcx.def_span(parent_did);
 
-                if let Some(attr_span) = find_attr!(
-                    self.tcx.get_all_attrs(parent_did),
-                    AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span
-                ) && is_coro
-                {
-                    self.dcx()
-                        .emit_err(errors::RustcForceInlineCoro { attr_span, span: parent_span });
-                }
-            }
-            (Target::Fn, _) => (),
-            (_, Some(attr_span)) => {
-                self.dcx().emit_err(errors::RustcForceInline { attr_span, span });
+            if let Some(attr_span) = find_attr!(
+                self.tcx.get_all_attrs(parent_did),
+                AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span
+            ) && is_coro
+            {
+                self.dcx().emit_err(errors::RustcForceInlineCoro { attr_span, span: parent_span });
             }
-            (_, None) => (),
         }
     }
 
@@ -2816,8 +2094,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let node_span = self.tcx.hir_span(hir_id);
 
         if !matches!(target, Target::Expression) {
-            self.dcx().emit_err(errors::LoopMatchAttr { attr_span, node_span });
-            return;
+            return; // Handled in target checking during attr parse
         }
 
         if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Loop(..)) {
@@ -2829,8 +2106,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let node_span = self.tcx.hir_span(hir_id);
 
         if !matches!(target, Target::Expression) {
-            self.dcx().emit_err(errors::ConstContinueAttr { attr_span, node_span });
-            return;
+            return; // Handled in target checking during attr parse
         }
 
         if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Break(..)) {
@@ -2873,6 +2149,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
             .hir_attrs(where_predicate.hir_id)
             .iter()
             .filter(|attr| !ATTRS_ALLOWED.iter().any(|&sym| attr.has_name(sym)))
+            .filter(|attr| !attr.is_parsed_attr())
             .map(|attr| attr.span())
             .collect::<Vec<_>>();
         if !spans.is_empty() {
@@ -3003,10 +2280,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         }) = attr
         {
             (*first_attr_span, sym::repr)
-        } else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr {
-            (*span, sym::path)
-        } else if let Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) = attr {
-            (*span, sym::automatically_derived)
         } else {
             continue;
         };
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 37216656e57..c5d5155d0e5 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -75,58 +75,6 @@ pub(crate) struct IgnoredAttrWithMacro<'a> {
     pub sym: &'a str,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(passes_ignored_attr)]
-pub(crate) struct IgnoredAttr<'a> {
-    pub sym: &'a str,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(passes_inline_ignored_function_prototype)]
-pub(crate) struct IgnoredInlineAttrFnProto;
-
-#[derive(LintDiagnostic)]
-#[diag(passes_inline_ignored_constants)]
-#[warning]
-#[note]
-pub(crate) struct IgnoredInlineAttrConstants;
-
-#[derive(Diagnostic)]
-#[diag(passes_inline_not_fn_or_closure, code = E0518)]
-pub(crate) struct InlineNotFnOrClosure {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub defn_span: Span,
-}
-
-/// "coverage attribute not allowed here"
-#[derive(Diagnostic)]
-#[diag(passes_coverage_attribute_not_allowed, code = E0788)]
-pub(crate) struct CoverageAttributeNotAllowed {
-    #[primary_span]
-    pub attr_span: Span,
-    /// "not a function, impl block, or module"
-    #[label(passes_not_fn_impl_mod)]
-    pub not_fn_impl_mod: Option<Span>,
-    /// "function has no body"
-    #[label(passes_no_body)]
-    pub no_body: Option<Span>,
-    /// "coverage attribute can be applied to a function (with body), impl block, or module"
-    #[help]
-    pub help: (),
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_optimize_invalid_target)]
-pub(crate) struct OptimizeInvalidTarget {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub defn_span: Span,
-    pub on_crate: bool,
-}
-
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_fn)]
 pub(crate) struct AttrShouldBeAppliedToFn {
@@ -138,25 +86,6 @@ pub(crate) struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_should_be_applied_to_fn, code = E0739)]
-pub(crate) struct TrackedCallerWrongLocation {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub defn_span: Span,
-    pub on_crate: bool,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_should_be_applied_to_struct_enum, code = E0701)]
-pub(crate) struct NonExhaustiveWrongLocation {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub defn_span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_non_exhaustive_with_default_field_values)]
 pub(crate) struct NonExhaustiveWithDefaultFieldValues {
     #[primary_span]
@@ -174,10 +103,6 @@ pub(crate) struct AttrShouldBeAppliedToTrait {
     pub defn_span: Span,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(passes_target_feature_on_statement)]
-pub(crate) struct TargetFeatureOnStatement;
-
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_static)]
 pub(crate) struct AttrShouldBeAppliedToStatic {
@@ -417,24 +342,6 @@ pub(crate) struct DocTestUnknownInclude {
 pub(crate) struct DocInvalid;
 
 #[derive(Diagnostic)]
-#[diag(passes_pass_by_value)]
-pub(crate) struct PassByValue {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_allow_incoherent_impl)]
-pub(crate) struct AllowIncoherentImpl {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_has_incoherent_inherent_impl)]
 pub(crate) struct HasIncoherentInherentImpl {
     #[primary_span]
@@ -450,25 +357,10 @@ pub(crate) struct BothFfiConstAndPure {
     pub attr_span: Span,
 }
 
-#[derive(Diagnostic)]
-#[diag(passes_ffi_pure_invalid_target, code = E0755)]
-pub(crate) struct FfiPureInvalidTarget {
-    #[primary_span]
-    pub attr_span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_ffi_const_invalid_target, code = E0756)]
-pub(crate) struct FfiConstInvalidTarget {
-    #[primary_span]
-    pub attr_span: Span,
-}
-
 #[derive(LintDiagnostic)]
 #[diag(passes_must_use_no_effect)]
 pub(crate) struct MustUseNoEffect {
-    pub article: &'static str,
-    pub target: rustc_hir::Target,
+    pub target: &'static str,
     #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
     pub attr_span: Span,
 }
@@ -483,15 +375,6 @@ pub(crate) struct MustNotSuspend {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes_cold)]
-#[warning]
-pub(crate) struct Cold {
-    #[label]
-    pub span: Span,
-    pub on_crate: bool,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(passes_link)]
 #[warning]
 pub(crate) struct Link {
@@ -499,17 +382,6 @@ pub(crate) struct Link {
     pub span: Option<Span>,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(passes_link_name)]
-#[warning]
-pub(crate) struct LinkName<'a> {
-    #[help]
-    pub help_span: Option<Span>,
-    #[label]
-    pub span: Span,
-    pub value: &'a str,
-}
-
 #[derive(Diagnostic)]
 #[diag(passes_no_link)]
 pub(crate) struct NoLink {
@@ -520,24 +392,6 @@ pub(crate) struct NoLink {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_export_name)]
-pub(crate) struct ExportName {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_rustc_layout_scalar_valid_range_not_struct)]
-pub(crate) struct RustcLayoutScalarValidRangeNotStruct {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_rustc_legacy_const_generics_only)]
 pub(crate) struct RustcLegacyConstGenericsOnly {
     #[primary_span]
@@ -578,42 +432,6 @@ pub(crate) struct RustcDirtyClean {
     pub span: Span,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(passes_link_section)]
-#[warning]
-pub(crate) struct LinkSection {
-    #[label]
-    pub span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(passes_no_mangle_foreign)]
-#[warning]
-#[note]
-pub(crate) struct NoMangleForeign {
-    #[label]
-    pub span: Span,
-    #[suggestion(code = "", applicability = "machine-applicable")]
-    pub attr_span: Span,
-    pub foreign_item_kind: &'static str,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(passes_no_mangle)]
-#[warning]
-pub(crate) struct NoMangle {
-    #[label]
-    pub span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(passes_align_on_fields)]
-#[warning]
-pub(crate) struct AlignOnFields {
-    #[label]
-    pub span: Span,
-}
-
 #[derive(Diagnostic)]
 #[diag(passes_repr_conflicting, code = E0566)]
 pub(crate) struct ReprConflicting {
@@ -635,16 +453,6 @@ pub(crate) struct InvalidReprAlignForTarget {
 pub(crate) struct ReprConflictingLint;
 
 #[derive(Diagnostic)]
-#[diag(passes_used_static)]
-pub(crate) struct UsedStatic {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-    pub target: &'static str,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_macro_only_attribute)]
 pub(crate) struct MacroOnlyAttribute {
     #[primary_span]
@@ -689,24 +497,6 @@ pub(crate) struct RustcAllowConstFnUnstable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_rustc_unstable_feature_bound)]
-pub(crate) struct RustcUnstableFeatureBound {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_rustc_std_internal_symbol)]
-pub(crate) struct RustcStdInternalSymbol {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_rustc_pub_transparent)]
 pub(crate) struct RustcPubTransparent {
     #[primary_span]
@@ -716,15 +506,6 @@ pub(crate) struct RustcPubTransparent {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_rustc_force_inline)]
-pub(crate) struct RustcForceInline {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_rustc_force_inline_coro)]
 pub(crate) struct RustcForceInlineCoro {
     #[primary_span]
@@ -733,53 +514,6 @@ pub(crate) struct RustcForceInlineCoro {
     pub span: Span,
 }
 
-#[derive(Diagnostic)]
-#[diag(passes_link_ordinal)]
-pub(crate) struct LinkOrdinal {
-    #[primary_span]
-    pub attr_span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_confusables)]
-pub(crate) struct Confusables {
-    #[primary_span]
-    pub attr_span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_coroutine_on_non_closure)]
-pub(crate) struct CoroutineOnNonClosure {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_linkage)]
-pub(crate) struct Linkage {
-    #[primary_span]
-    pub attr_span: Span,
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_stability_promotable)]
-pub(crate) struct StabilityPromotable {
-    #[primary_span]
-    pub attr_span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(passes_deprecated)]
-pub(crate) struct Deprecated;
-
-#[derive(LintDiagnostic)]
-#[diag(passes_macro_use)]
-pub(crate) struct MacroUse {
-    pub name: Symbol,
-}
-
 #[derive(LintDiagnostic)]
 pub(crate) enum MacroExport {
     #[diag(passes_macro_export)]
@@ -1283,13 +1017,6 @@ pub(crate) struct UselessAssignment<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes_only_has_effect_on)]
-pub(crate) struct OnlyHasEffectOn {
-    pub attr_name: String,
-    pub target_name: String,
-}
-
-#[derive(LintDiagnostic)]
 #[diag(passes_inline_ignored_for_exported)]
 #[help]
 pub(crate) struct InlineIgnoredForExported {}
@@ -1843,26 +1570,3 @@ pub(crate) struct ReprAlignShouldBeAlign {
     pub span: Span,
     pub item: &'static str,
 }
-
-#[derive(Diagnostic)]
-#[diag(passes_align_should_be_repr_align)]
-pub(crate) struct AlignShouldBeReprAlign {
-    #[primary_span]
-    #[suggestion(
-        style = "verbose",
-        applicability = "machine-applicable",
-        code = "#[repr(align({align_bytes}))]"
-    )]
-    pub span: Span,
-    pub item: &'static str,
-    pub align_bytes: u64,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_align_attr_application)]
-pub(crate) struct AlignAttrApplication {
-    #[primary_span]
-    pub hint_span: Span,
-    #[label]
-    pub span: Span,
-}
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 6fac01827a4..141a60a8ec3 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -329,7 +329,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
                     match &self.parent_item.unwrap().kind {
                         ast::ItemKind::Impl(i) => {
                             if i.of_trait.is_some() {
-                                Target::Method(MethodKind::Trait { body })
+                                Target::Method(MethodKind::TraitImpl)
                             } else {
                                 Target::Method(MethodKind::Inherent)
                             }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 1e4513eb787..14538df8187 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -5,6 +5,7 @@ use rustc_ast::*;
 use rustc_attr_parsing::{AttributeParser, Early, OmitDoc, ShouldEmit};
 use rustc_expand::expand::AstFragment;
 use rustc_hir as hir;
+use rustc_hir::Target;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::span_bug;
@@ -138,6 +139,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                     &i.attrs,
                     i.span,
                     i.id,
+                    Target::MacroDef,
                     OmitDoc::Skip,
                     std::convert::identity,
                     |_l| {
diff --git a/tests/crashes/138510.rs b/tests/crashes/138510.rs
deleted file mode 100644
index f429e8bb33b..00000000000
--- a/tests/crashes/138510.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: #138510
-fn main()
-where
-    #[repr()]
-    _: Sized,
-{
-}
diff --git a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr
index 9d3ce5e63ef..85c9516236c 100644
--- a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr
+++ b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr
@@ -4,13 +4,13 @@ error: `#[doc(alias = "...")]` isn't allowed on foreign module
 LL | #[doc(alias = "foo")]
    |       ^^^^^^^^^^^^^
 
-error: `#[doc(alias = "...")]` isn't allowed on inherent implementation block
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
   --> $DIR/check-doc-alias-attr-location.rs:10:7
    |
 LL | #[doc(alias = "bar")]
    |       ^^^^^^^^^^^^^
 
-error: `#[doc(alias = "...")]` isn't allowed on trait implementation block
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
   --> $DIR/check-doc-alias-attr-location.rs:16:7
    |
 LL | #[doc(alias = "foobar")]
diff --git a/tests/ui/asm/naked-invalid-attr.rs b/tests/ui/asm/naked-invalid-attr.rs
index 6ac9cb9e3a9..c9e0949abfb 100644
--- a/tests/ui/asm/naked-invalid-attr.rs
+++ b/tests/ui/asm/naked-invalid-attr.rs
@@ -1,25 +1,25 @@
 // Checks that the #[unsafe(naked)] attribute can be placed on function definitions only.
 //
 //@ needs-asm-support
-#![unsafe(naked)] //~ ERROR should be applied to a function definition
+#![unsafe(naked)] //~ ERROR attribute cannot be used on
 
 use std::arch::naked_asm;
 
 extern "C" {
-    #[unsafe(naked)] //~ ERROR should be applied to a function definition
+    #[unsafe(naked)] //~ ERROR attribute cannot be used on
     fn f();
 }
 
-#[unsafe(naked)] //~ ERROR should be applied to a function definition
+#[unsafe(naked)] //~ ERROR attribute cannot be used on
 #[repr(C)]
 struct S {
-    #[unsafe(naked)] //~ ERROR should be applied to a function definition
+    #[unsafe(naked)] //~ ERROR attribute cannot be used on
     a: u32,
     b: u32,
 }
 
 trait Invoke {
-    #[unsafe(naked)] //~ ERROR should be applied to a function definition
+    #[unsafe(naked)] //~ ERROR attribute cannot be used on
     extern "C" fn invoke(&self);
 }
 
@@ -48,7 +48,7 @@ impl S {
 }
 
 fn main() {
-    #[unsafe(naked)] //~ ERROR should be applied to a function definition
+    #[unsafe(naked)] //~ ERROR attribute cannot be used on
     || {};
 }
 
diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr
index 2571c8fa989..936a36cd92e 100644
--- a/tests/ui/asm/naked-invalid-attr.stderr
+++ b/tests/ui/asm/naked-invalid-attr.stderr
@@ -4,65 +4,62 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a`
 LL | #[::a]
    |     ^ use of unresolved module or unlinked crate `a`
 
-error[E0736]: attribute incompatible with `#[unsafe(naked)]`
-  --> $DIR/naked-invalid-attr.rs:56:3
+error: `#[naked]` attribute cannot be used on crates
+  --> $DIR/naked-invalid-attr.rs:4:1
    |
-LL | #[::a]
-   |   ^^^ the `::a` attribute is incompatible with `#[unsafe(naked)]`
-...
-LL | #[unsafe(naked)]
-   | ---------------- function marked with `#[unsafe(naked)]` here
-
-error: attribute should be applied to a function definition
-  --> $DIR/naked-invalid-attr.rs:13:1
+LL | #![unsafe(naked)]
+   | ^^^^^^^^^^^^^^^^^
    |
-LL |   #[unsafe(naked)]
-   |   ^^^^^^^^^^^^^^^^
-LL |   #[repr(C)]
-LL | / struct S {
-LL | |     #[unsafe(naked)]
-LL | |     a: u32,
-LL | |     b: u32,
-LL | | }
-   | |_- not a function definition
+   = help: `#[naked]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/naked-invalid-attr.rs:16:5
+error: `#[naked]` attribute cannot be used on foreign functions
+  --> $DIR/naked-invalid-attr.rs:9:5
    |
 LL |     #[unsafe(naked)]
    |     ^^^^^^^^^^^^^^^^
-LL |     a: u32,
-   |     ------ not a function definition
+   |
+   = help: `#[naked]` can be applied to methods, functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/naked-invalid-attr.rs:51:5
+error: `#[naked]` attribute cannot be used on structs
+  --> $DIR/naked-invalid-attr.rs:13:1
+   |
+LL | #[unsafe(naked)]
+   | ^^^^^^^^^^^^^^^^
+   |
+   = help: `#[naked]` can only be applied to functions
+
+error: `#[naked]` attribute cannot be used on struct fields
+  --> $DIR/naked-invalid-attr.rs:16:5
    |
 LL |     #[unsafe(naked)]
    |     ^^^^^^^^^^^^^^^^
-LL |     || {};
-   |     ----- not a function definition
+   |
+   = help: `#[naked]` can only be applied to functions
 
-error: attribute should be applied to a function definition
+error: `#[naked]` attribute cannot be used on required trait methods
   --> $DIR/naked-invalid-attr.rs:22:5
    |
 LL |     #[unsafe(naked)]
    |     ^^^^^^^^^^^^^^^^
-LL |     extern "C" fn invoke(&self);
-   |     ---------------------------- not a function definition
+   |
+   = help: `#[naked]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks
 
-error: attribute should be applied to a function definition
-  --> $DIR/naked-invalid-attr.rs:9:5
+error: `#[naked]` attribute cannot be used on closures
+  --> $DIR/naked-invalid-attr.rs:51:5
    |
 LL |     #[unsafe(naked)]
    |     ^^^^^^^^^^^^^^^^
-LL |     fn f();
-   |     ------- not a function definition
+   |
+   = help: `#[naked]` can be applied to methods, functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/naked-invalid-attr.rs:4:1
+error[E0736]: attribute incompatible with `#[unsafe(naked)]`
+  --> $DIR/naked-invalid-attr.rs:56:3
    |
-LL | #![unsafe(naked)]
-   | ^^^^^^^^^^^^^^^^^ cannot be applied to crates
+LL | #[::a]
+   |   ^^^ the `::a` attribute is incompatible with `#[unsafe(naked)]`
+...
+LL | #[unsafe(naked)]
+   | ---------------- function marked with `#[unsafe(naked)]` here
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs
index 158a4500bde..c8e9810327c 100644
--- a/tests/ui/attributes/attrs-on-params.rs
+++ b/tests/ui/attributes/attrs-on-params.rs
@@ -1,7 +1,7 @@
 // This checks that incorrect params on function parameters are caught
 
 fn function(#[inline] param: u32) {
-    //~^ ERROR attribute should be applied to function or closure
+    //~^ ERROR attribute cannot be used on
     //~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes
 }
 
diff --git a/tests/ui/attributes/attrs-on-params.stderr b/tests/ui/attributes/attrs-on-params.stderr
index 306e862cb58..91f87a954c5 100644
--- a/tests/ui/attributes/attrs-on-params.stderr
+++ b/tests/ui/attributes/attrs-on-params.stderr
@@ -4,14 +4,13 @@ error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed
 LL | fn function(#[inline] param: u32) {
    |             ^^^^^^^^^
 
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on function params
   --> $DIR/attrs-on-params.rs:3:13
    |
 LL | fn function(#[inline] param: u32) {
-   |             ^^^^^^^^^-----------
-   |             |
-   |             not a function or closure
+   |             ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0518`.
diff --git a/tests/ui/attributes/cold-attribute-application-54044.rs b/tests/ui/attributes/cold-attribute-application-54044.rs
index 2e644b91c07..cf027ac02b0 100644
--- a/tests/ui/attributes/cold-attribute-application-54044.rs
+++ b/tests/ui/attributes/cold-attribute-application-54044.rs
@@ -2,13 +2,13 @@
 #![deny(unused_attributes)] //~ NOTE lint level is defined here
 
 #[cold]
-//~^ ERROR attribute should be applied to a function
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-struct Foo; //~ NOTE not a function
+//~^ ERROR attribute cannot be used on
+//~| WARN previously accepted
+struct Foo;
 
 fn main() {
     #[cold]
-    //~^ ERROR attribute should be applied to a function
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    5; //~ NOTE not a function
+    //~^ ERROR attribute cannot be used on
+    //~| WARN previously accepted
+    5;
 }
diff --git a/tests/ui/attributes/cold-attribute-application-54044.stderr b/tests/ui/attributes/cold-attribute-application-54044.stderr
index efdf5e0de52..367686f02cb 100644
--- a/tests/ui/attributes/cold-attribute-application-54044.stderr
+++ b/tests/ui/attributes/cold-attribute-application-54044.stderr
@@ -1,29 +1,25 @@
-error: attribute should be applied to a function definition
+error: `#[cold]` attribute cannot be used on structs
   --> $DIR/cold-attribute-application-54044.rs:4:1
    |
 LL | #[cold]
    | ^^^^^^^
-...
-LL | struct Foo;
-   | ----------- not a function definition
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
 note: the lint level is defined here
   --> $DIR/cold-attribute-application-54044.rs:2:9
    |
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: attribute should be applied to a function definition
+error: `#[cold]` attribute cannot be used on expressions
   --> $DIR/cold-attribute-application-54044.rs:10:5
    |
 LL |     #[cold]
    |     ^^^^^^^
-...
-LL |     5;
-   |     - not a function definition
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/attributes/empty-repr.rs b/tests/ui/attributes/empty-repr.rs
new file mode 100644
index 00000000000..e6ba1baf031
--- /dev/null
+++ b/tests/ui/attributes/empty-repr.rs
@@ -0,0 +1,14 @@
+// Regression test for https://github.com/rust-lang/rust/issues/138510
+
+#![feature(where_clause_attrs)]
+#![deny(unused_attributes)]
+
+fn main() {
+}
+
+fn test() where
+#[repr()]
+//~^ ERROR unused attribute
+(): Sized {
+
+}
diff --git a/tests/ui/attributes/empty-repr.stderr b/tests/ui/attributes/empty-repr.stderr
new file mode 100644
index 00000000000..92901fa170c
--- /dev/null
+++ b/tests/ui/attributes/empty-repr.stderr
@@ -0,0 +1,14 @@
+error: unused attribute
+  --> $DIR/empty-repr.rs:10:1
+   |
+LL | #[repr()]
+   | ^^^^^^^^^ help: remove this attribute
+   |
+note: the lint level is defined here
+  --> $DIR/empty-repr.rs:4:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/inline-attribute-enum-variant-error.rs b/tests/ui/attributes/inline-attribute-enum-variant-error.rs
index 305b285d2a4..fd2cd49be16 100644
--- a/tests/ui/attributes/inline-attribute-enum-variant-error.rs
+++ b/tests/ui/attributes/inline-attribute-enum-variant-error.rs
@@ -2,7 +2,7 @@
 
 enum Foo {
     #[inline]
-    //~^ ERROR attribute should be applied
+    //~^ ERROR attribute cannot be used on
     Variant,
 }
 
diff --git a/tests/ui/attributes/inline-attribute-enum-variant-error.stderr b/tests/ui/attributes/inline-attribute-enum-variant-error.stderr
index a4564d8f722..03954388c2e 100644
--- a/tests/ui/attributes/inline-attribute-enum-variant-error.stderr
+++ b/tests/ui/attributes/inline-attribute-enum-variant-error.stderr
@@ -1,12 +1,10 @@
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on enum variants
   --> $DIR/inline-attribute-enum-variant-error.rs:4:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
-LL |
-LL |     Variant,
-   |     ------- not a function or closure
+   |
+   = help: `#[inline]` can only be applied to functions
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0518`.
diff --git a/tests/ui/attributes/inline/attr-usage-inline.rs b/tests/ui/attributes/inline/attr-usage-inline.rs
index d8ca0fce163..8217b9834ff 100644
--- a/tests/ui/attributes/inline/attr-usage-inline.rs
+++ b/tests/ui/attributes/inline/attr-usage-inline.rs
@@ -4,7 +4,7 @@
 #[inline]
 fn f() {}
 
-#[inline] //~ ERROR: attribute should be applied to function or closure
+#[inline] //~ ERROR: attribute cannot be used on
 struct S;
 
 struct I {
diff --git a/tests/ui/attributes/inline/attr-usage-inline.stderr b/tests/ui/attributes/inline/attr-usage-inline.stderr
index 2123438032c..9fca17d90ca 100644
--- a/tests/ui/attributes/inline/attr-usage-inline.stderr
+++ b/tests/ui/attributes/inline/attr-usage-inline.stderr
@@ -1,10 +1,10 @@
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on structs
   --> $DIR/attr-usage-inline.rs:7:1
    |
 LL | #[inline]
    | ^^^^^^^^^
-LL | struct S;
-   | --------- not a function or closure
+   |
+   = help: `#[inline]` can only be applied to functions
 
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/attr-usage-inline.rs:21:1
diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
index cb196471fd7..f9e01cd1507 100644
--- a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
+++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
@@ -3,5 +3,5 @@
 
 fn main() {}
 
-#[track_caller] //~ ERROR attribute should be applied to a function
+#[track_caller] //~ ERROR attribute cannot be used on
 static _A: () = ();
diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
index 1248967c47b..337d3808d28 100644
--- a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
+++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
@@ -1,11 +1,10 @@
-error[E0739]: attribute should be applied to a function definition
+error: `#[track_caller]` attribute cannot be used on statics
   --> $DIR/issue-105594-invalid-attr-validation.rs:6:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
-LL | static _A: () = ();
-   | ------------------- not a function definition
+   |
+   = help: `#[track_caller]` can only be applied to functions
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0739`.
diff --git a/tests/ui/attributes/linkage.rs b/tests/ui/attributes/linkage.rs
index 0d5ce699fa8..932bfa88fc5 100644
--- a/tests/ui/attributes/linkage.rs
+++ b/tests/ui/attributes/linkage.rs
@@ -3,16 +3,16 @@
 #![deny(unused_attributes)]
 #![allow(dead_code)]
 
-#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+#[linkage = "weak"] //~ ERROR attribute cannot be used on
 type InvalidTy = ();
 
-#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+#[linkage = "weak"] //~ ERROR attribute cannot be used on
 mod invalid_module {}
 
-#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+#[linkage = "weak"] //~ ERROR attribute cannot be used on
 struct F;
 
-#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+#[linkage = "weak"] //~ ERROR attribute cannot be used on
 impl F {
     #[linkage = "weak"]
     fn valid(&self) {}
@@ -24,7 +24,7 @@ fn f() {
     {
         1
     };
-    //~^^^^ ERROR attribute should be applied to a function or static
+    //~^^^^ ERROR attribute cannot be used on
 }
 
 extern "C" {
@@ -38,5 +38,5 @@ extern "C" {
 fn main() {
     let _ = #[linkage = "weak"]
     (|| 1);
-    //~^^ ERROR attribute should be applied to a function or static
+    //~^^ ERROR attribute cannot be used on
 }
diff --git a/tests/ui/attributes/linkage.stderr b/tests/ui/attributes/linkage.stderr
index d5595529f40..2e7ff0e7936 100644
--- a/tests/ui/attributes/linkage.stderr
+++ b/tests/ui/attributes/linkage.stderr
@@ -1,55 +1,50 @@
-error: attribute should be applied to a function or static
+error: `#[linkage]` attribute cannot be used on type aliases
   --> $DIR/linkage.rs:6:1
    |
 LL | #[linkage = "weak"]
    | ^^^^^^^^^^^^^^^^^^^
-LL | type InvalidTy = ();
-   | -------------------- not a function definition or static
+   |
+   = help: `#[linkage]` can be applied to functions, statics, foreign statics
 
-error: attribute should be applied to a function or static
+error: `#[linkage]` attribute cannot be used on modules
   --> $DIR/linkage.rs:9:1
    |
 LL | #[linkage = "weak"]
    | ^^^^^^^^^^^^^^^^^^^
-LL | mod invalid_module {}
-   | --------------------- not a function definition or static
+   |
+   = help: `#[linkage]` can be applied to functions, statics, foreign statics
 
-error: attribute should be applied to a function or static
+error: `#[linkage]` attribute cannot be used on structs
   --> $DIR/linkage.rs:12:1
    |
 LL | #[linkage = "weak"]
    | ^^^^^^^^^^^^^^^^^^^
-LL | struct F;
-   | --------- not a function definition or static
+   |
+   = help: `#[linkage]` can be applied to functions, statics, foreign statics
 
-error: attribute should be applied to a function or static
+error: `#[linkage]` attribute cannot be used on inherent impl blocks
   --> $DIR/linkage.rs:15:1
    |
-LL |   #[linkage = "weak"]
-   |   ^^^^^^^^^^^^^^^^^^^
-LL | / impl F {
-LL | |     #[linkage = "weak"]
-LL | |     fn valid(&self) {}
-LL | | }
-   | |_- not a function definition or static
+LL | #[linkage = "weak"]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[linkage]` can be applied to functions, statics, foreign statics
 
-error: attribute should be applied to a function or static
+error: `#[linkage]` attribute cannot be used on expressions
   --> $DIR/linkage.rs:23:5
    |
-LL |       #[linkage = "weak"]
-   |       ^^^^^^^^^^^^^^^^^^^
-LL | /     {
-LL | |         1
-LL | |     };
-   | |_____- not a function definition or static
+LL |     #[linkage = "weak"]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[linkage]` can be applied to functions, statics, foreign statics
 
-error: attribute should be applied to a function or static
+error: `#[linkage]` attribute cannot be used on closures
   --> $DIR/linkage.rs:39:13
    |
 LL |     let _ = #[linkage = "weak"]
    |             ^^^^^^^^^^^^^^^^^^^
-LL |     (|| 1);
-   |     ------ not a function definition or static
+   |
+   = help: `#[linkage]` can be applied to methods, functions, statics, foreign statics, foreign functions
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/attributes/lint_on_root.rs b/tests/ui/attributes/lint_on_root.rs
index 9029da7dc97..bafdb46883f 100644
--- a/tests/ui/attributes/lint_on_root.rs
+++ b/tests/ui/attributes/lint_on_root.rs
@@ -3,5 +3,6 @@
 #![inline = ""]
 //~^ ERROR: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` [ill_formed_attribute_input]
 //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~| ERROR attribute cannot be used on
 
 fn main() {}
diff --git a/tests/ui/attributes/lint_on_root.stderr b/tests/ui/attributes/lint_on_root.stderr
index 91b72730530..9d8d1495c1b 100644
--- a/tests/ui/attributes/lint_on_root.stderr
+++ b/tests/ui/attributes/lint_on_root.stderr
@@ -1,3 +1,11 @@
+error: `#[inline]` attribute cannot be used on crates
+  --> $DIR/lint_on_root.rs:3:1
+   |
+LL | #![inline = ""]
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
   --> $DIR/lint_on_root.rs:3:1
    |
@@ -8,7 +16,7 @@ LL | #![inline = ""]
    = 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 1 previous error
+error: aborting due to 2 previous errors
 
 Future incompatibility report: Future breakage diagnostic:
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs
index 3261b29fe7e..3293f75fba9 100644
--- a/tests/ui/attributes/malformed-attrs.rs
+++ b/tests/ui/attributes/malformed-attrs.rs
@@ -35,6 +35,7 @@
 //~^ ERROR `allow_internal_unstable` expects a list of feature names
 #[rustc_confusables]
 //~^ ERROR malformed
+//~| ERROR attribute cannot be used on
 #[deprecated = 5]
 //~^ ERROR malformed
 #[doc]
@@ -42,9 +43,10 @@
 //~| WARN this was previously accepted by the compiler
 #[rustc_macro_transparency]
 //~^ ERROR malformed
+//~| ERROR attribute cannot be used on
 #[repr]
 //~^ ERROR malformed
-//~| ERROR is not supported on function items
+//~| ERROR is not supported on functions
 #[rustc_as_ptr = 5]
 //~^ ERROR malformed
 #[inline = 5]
@@ -68,6 +70,7 @@
 //~^ ERROR malformed
 #[used()]
 //~^ ERROR malformed
+//~| ERROR attribute cannot be used on
 #[crate_name]
 //~^ ERROR malformed
 #[doc]
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index aa4891459aa..9c31765149b 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -1,5 +1,5 @@
 error[E0539]: malformed `cfg` attribute input
-  --> $DIR/malformed-attrs.rs:99:1
+  --> $DIR/malformed-attrs.rs:102:1
    |
 LL | #[cfg]
    | ^^^^^^
@@ -10,7 +10,7 @@ LL | #[cfg]
    = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
 
 error: malformed `cfg_attr` attribute input
-  --> $DIR/malformed-attrs.rs:101:1
+  --> $DIR/malformed-attrs.rs:104:1
    |
 LL | #[cfg_attr]
    | ^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | #[cfg_attr(condition, attribute, other_attribute, ...)]
    |           ++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0463]: can't find crate for `wloop`
-  --> $DIR/malformed-attrs.rs:208:1
+  --> $DIR/malformed-attrs.rs:211:1
    |
 LL | extern crate wloop;
    | ^^^^^^^^^^^^^^^^^^^ can't find crate
@@ -42,7 +42,7 @@ LL | #![windows_subsystem = "windows"]
    |                      +++++++++++
 
 error: malformed `crate_name` attribute input
-  --> $DIR/malformed-attrs.rs:71:1
+  --> $DIR/malformed-attrs.rs:74:1
    |
 LL | #[crate_name]
    | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
@@ -50,13 +50,13 @@ LL | #[crate_name]
    = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
 
 error: malformed `no_sanitize` attribute input
-  --> $DIR/malformed-attrs.rs:89:1
+  --> $DIR/malformed-attrs.rs:92:1
    |
 LL | #[no_sanitize]
    | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]`
 
 error: malformed `instruction_set` attribute input
-  --> $DIR/malformed-attrs.rs:103:1
+  --> $DIR/malformed-attrs.rs:106:1
    |
 LL | #[instruction_set]
    | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]`
@@ -64,13 +64,13 @@ LL | #[instruction_set]
    = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute>
 
 error: malformed `patchable_function_entry` attribute input
-  --> $DIR/malformed-attrs.rs:105:1
+  --> $DIR/malformed-attrs.rs:108:1
    |
 LL | #[patchable_function_entry]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
 
 error: malformed `must_not_suspend` attribute input
-  --> $DIR/malformed-attrs.rs:129:1
+  --> $DIR/malformed-attrs.rs:132:1
    |
 LL | #[must_not_suspend()]
    | ^^^^^^^^^^^^^^^^^^^^^
@@ -85,13 +85,13 @@ LL + #[must_not_suspend]
    |
 
 error: malformed `cfi_encoding` attribute input
-  --> $DIR/malformed-attrs.rs:131:1
+  --> $DIR/malformed-attrs.rs:134:1
    |
 LL | #[cfi_encoding]
    | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
 
 error: malformed `allow` attribute input
-  --> $DIR/malformed-attrs.rs:175:1
+  --> $DIR/malformed-attrs.rs:178:1
    |
 LL | #[allow]
    | ^^^^^^^^
@@ -107,7 +107,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")]
    |        +++++++++++++++++++++++++++++++++++++
 
 error: malformed `expect` attribute input
-  --> $DIR/malformed-attrs.rs:177:1
+  --> $DIR/malformed-attrs.rs:180:1
    |
 LL | #[expect]
    | ^^^^^^^^^
@@ -123,7 +123,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")]
    |         +++++++++++++++++++++++++++++++++++++
 
 error: malformed `warn` attribute input
-  --> $DIR/malformed-attrs.rs:179:1
+  --> $DIR/malformed-attrs.rs:182:1
    |
 LL | #[warn]
    | ^^^^^^^
@@ -139,7 +139,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")]
    |       +++++++++++++++++++++++++++++++++++++
 
 error: malformed `deny` attribute input
-  --> $DIR/malformed-attrs.rs:181:1
+  --> $DIR/malformed-attrs.rs:184:1
    |
 LL | #[deny]
    | ^^^^^^^
@@ -155,7 +155,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")]
    |       +++++++++++++++++++++++++++++++++++++
 
 error: malformed `forbid` attribute input
-  --> $DIR/malformed-attrs.rs:183:1
+  --> $DIR/malformed-attrs.rs:186:1
    |
 LL | #[forbid]
    | ^^^^^^^^^
@@ -171,7 +171,7 @@ LL | #[forbid(lint1, lint2, lint3, reason = "...")]
    |         +++++++++++++++++++++++++++++++++++++
 
 error: malformed `debugger_visualizer` attribute input
-  --> $DIR/malformed-attrs.rs:185:1
+  --> $DIR/malformed-attrs.rs:188:1
    |
 LL | #[debugger_visualizer]
    | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]`
@@ -179,13 +179,13 @@ LL | #[debugger_visualizer]
    = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute>
 
 error: malformed `thread_local` attribute input
-  --> $DIR/malformed-attrs.rs:200:1
+  --> $DIR/malformed-attrs.rs:203:1
    |
 LL | #[thread_local()]
    | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]`
 
 error: malformed `no_link` attribute input
-  --> $DIR/malformed-attrs.rs:204:1
+  --> $DIR/malformed-attrs.rs:207:1
    |
 LL | #[no_link()]
    | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]`
@@ -193,7 +193,7 @@ LL | #[no_link()]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute>
 
 error: malformed `macro_export` attribute input
-  --> $DIR/malformed-attrs.rs:211:1
+  --> $DIR/malformed-attrs.rs:214:1
    |
 LL | #[macro_export = 18]
    | ^^^^^^^^^^^^^^^^^^^^
@@ -209,25 +209,25 @@ LL + #[macro_export]
    |
 
 error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/malformed-attrs.rs:96:1
+  --> $DIR/malformed-attrs.rs:99:1
    |
 LL | #[proc_macro = 18]
    | ^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/malformed-attrs.rs:113:1
+  --> $DIR/malformed-attrs.rs:116:1
    |
 LL | #[proc_macro_attribute = 19]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/malformed-attrs.rs:120:1
+  --> $DIR/malformed-attrs.rs:123:1
    |
 LL | #[proc_macro_derive]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
-  --> $DIR/malformed-attrs.rs:213:1
+  --> $DIR/malformed-attrs.rs:216:1
    |
 LL | #[allow_internal_unsafe = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL | #[allow_internal_unsafe = 1]
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]`
-  --> $DIR/malformed-attrs.rs:40:1
+  --> $DIR/malformed-attrs.rs:41:1
    |
 LL | #[doc]
    | ^^^^^^
@@ -247,7 +247,7 @@ LL | #[doc]
    = note: `#[deny(ill_formed_attribute_input)]` on by default
 
 error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]`
-  --> $DIR/malformed-attrs.rs:73:1
+  --> $DIR/malformed-attrs.rs:76:1
    |
 LL | #[doc]
    | ^^^^^^
@@ -257,7 +257,7 @@ LL | #[doc]
    = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html>
 
 error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-attrs.rs:80:1
+  --> $DIR/malformed-attrs.rs:83:1
    |
 LL | #[link]
    | ^^^^^^^
@@ -267,7 +267,7 @@ LL | #[link]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
 
 error: invalid argument
-  --> $DIR/malformed-attrs.rs:185:1
+  --> $DIR/malformed-attrs.rs:188:1
    |
 LL | #[debugger_visualizer]
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -303,8 +303,16 @@ LL | #[rustc_confusables]
    | expected this to be a list
    | help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]`
 
+error: `#[rustc_confusables]` attribute cannot be used on functions
+  --> $DIR/malformed-attrs.rs:36:1
+   |
+LL | #[rustc_confusables]
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_confusables]` can only be applied to inherent methods
+
 error[E0539]: malformed `deprecated` attribute input
-  --> $DIR/malformed-attrs.rs:38:1
+  --> $DIR/malformed-attrs.rs:39:1
    |
 LL | #[deprecated = 5]
    | ^^^^^^^^^^^^^^^-^
@@ -328,7 +336,7 @@ LL + #[deprecated(since = "version", note = "reason")]
    = and 1 other candidate
 
 error[E0539]: malformed `rustc_macro_transparency` attribute input
-  --> $DIR/malformed-attrs.rs:43:1
+  --> $DIR/malformed-attrs.rs:44:1
    |
 LL | #[rustc_macro_transparency]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -342,8 +350,16 @@ LL | #[rustc_macro_transparency = "semitransparent"]
 LL | #[rustc_macro_transparency = "transparent"]
    |                            +++++++++++++++
 
+error: `#[rustc_macro_transparency]` attribute cannot be used on functions
+  --> $DIR/malformed-attrs.rs:44:1
+   |
+LL | #[rustc_macro_transparency]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_macro_transparency]` can only be applied to macro defs
+
 error[E0539]: malformed `repr` attribute input
-  --> $DIR/malformed-attrs.rs:45:1
+  --> $DIR/malformed-attrs.rs:47:1
    |
 LL | #[repr]
    | ^^^^^^^ expected this to be a list
@@ -362,7 +378,7 @@ LL | #[repr(align(...))]
    = and 2 other candidates
 
 error[E0565]: malformed `rustc_as_ptr` attribute input
-  --> $DIR/malformed-attrs.rs:48:1
+  --> $DIR/malformed-attrs.rs:50:1
    |
 LL | #[rustc_as_ptr = 5]
    | ^^^^^^^^^^^^^^^---^
@@ -371,7 +387,7 @@ LL | #[rustc_as_ptr = 5]
    | help: must be of the form: `#[rustc_as_ptr]`
 
 error[E0539]: malformed `rustc_align` attribute input
-  --> $DIR/malformed-attrs.rs:53:1
+  --> $DIR/malformed-attrs.rs:55:1
    |
 LL | #[rustc_align]
    | ^^^^^^^^^^^^^^
@@ -380,7 +396,7 @@ LL | #[rustc_align]
    | help: must be of the form: `#[rustc_align(<alignment in bytes>)]`
 
 error[E0539]: malformed `optimize` attribute input
-  --> $DIR/malformed-attrs.rs:55:1
+  --> $DIR/malformed-attrs.rs:57:1
    |
 LL | #[optimize]
    | ^^^^^^^^^^^ expected this to be a list
@@ -395,7 +411,7 @@ LL | #[optimize(speed)]
    |           +++++++
 
 error[E0565]: malformed `cold` attribute input
-  --> $DIR/malformed-attrs.rs:57:1
+  --> $DIR/malformed-attrs.rs:59:1
    |
 LL | #[cold = 1]
    | ^^^^^^^---^
@@ -404,13 +420,13 @@ LL | #[cold = 1]
    | help: must be of the form: `#[cold]`
 
 error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]`
-  --> $DIR/malformed-attrs.rs:59:1
+  --> $DIR/malformed-attrs.rs:61:1
    |
 LL | #[must_use()]
    | ^^^^^^^^^^^^^
 
 error[E0565]: malformed `no_mangle` attribute input
-  --> $DIR/malformed-attrs.rs:61:1
+  --> $DIR/malformed-attrs.rs:63:1
    |
 LL | #[no_mangle = 1]
    | ^^^^^^^^^^^^---^
@@ -419,7 +435,7 @@ LL | #[no_mangle = 1]
    | help: must be of the form: `#[no_mangle]`
 
 error[E0565]: malformed `naked` attribute input
-  --> $DIR/malformed-attrs.rs:63:1
+  --> $DIR/malformed-attrs.rs:65:1
    |
 LL | #[unsafe(naked())]
    | ^^^^^^^^^^^^^^--^^
@@ -428,7 +444,7 @@ LL | #[unsafe(naked())]
    | help: must be of the form: `#[naked]`
 
 error[E0565]: malformed `track_caller` attribute input
-  --> $DIR/malformed-attrs.rs:65:1
+  --> $DIR/malformed-attrs.rs:67:1
    |
 LL | #[track_caller()]
    | ^^^^^^^^^^^^^^--^
@@ -437,13 +453,13 @@ LL | #[track_caller()]
    | help: must be of the form: `#[track_caller]`
 
 error[E0539]: malformed `export_name` attribute input
-  --> $DIR/malformed-attrs.rs:67:1
+  --> $DIR/malformed-attrs.rs:69:1
    |
 LL | #[export_name()]
    | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_name = "name"]`
 
 error[E0805]: malformed `used` attribute input
-  --> $DIR/malformed-attrs.rs:69:1
+  --> $DIR/malformed-attrs.rs:71:1
    |
 LL | #[used()]
    | ^^^^^^--^
@@ -460,8 +476,16 @@ LL - #[used()]
 LL + #[used]
    |
 
+error: `#[used]` attribute cannot be used on functions
+  --> $DIR/malformed-attrs.rs:71:1
+   |
+LL | #[used()]
+   | ^^^^^^^^^
+   |
+   = help: `#[used]` can only be applied to statics
+
 error[E0539]: malformed `target_feature` attribute input
-  --> $DIR/malformed-attrs.rs:76:1
+  --> $DIR/malformed-attrs.rs:79:1
    |
 LL | #[target_feature]
    | ^^^^^^^^^^^^^^^^^
@@ -470,7 +494,7 @@ LL | #[target_feature]
    | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]`
 
 error[E0565]: malformed `export_stable` attribute input
-  --> $DIR/malformed-attrs.rs:78:1
+  --> $DIR/malformed-attrs.rs:81:1
    |
 LL | #[export_stable = 1]
    | ^^^^^^^^^^^^^^^^---^
@@ -479,7 +503,7 @@ LL | #[export_stable = 1]
    | help: must be of the form: `#[export_stable]`
 
 error[E0539]: malformed `link_name` attribute input
-  --> $DIR/malformed-attrs.rs:83:1
+  --> $DIR/malformed-attrs.rs:86:1
    |
 LL | #[link_name]
    | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]`
@@ -487,7 +511,7 @@ LL | #[link_name]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute>
 
 error[E0539]: malformed `link_section` attribute input
-  --> $DIR/malformed-attrs.rs:85:1
+  --> $DIR/malformed-attrs.rs:88:1
    |
 LL | #[link_section]
    | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]`
@@ -495,7 +519,7 @@ LL | #[link_section]
    = note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute>
 
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/malformed-attrs.rs:87:1
+  --> $DIR/malformed-attrs.rs:90:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -508,7 +532,7 @@ LL | #[coverage(on)]
    |           ++++
 
 error[E0565]: malformed `no_implicit_prelude` attribute input
-  --> $DIR/malformed-attrs.rs:94:1
+  --> $DIR/malformed-attrs.rs:97:1
    |
 LL | #[no_implicit_prelude = 23]
    | ^^^^^^^^^^^^^^^^^^^^^^----^
@@ -517,7 +541,7 @@ LL | #[no_implicit_prelude = 23]
    | help: must be of the form: `#[no_implicit_prelude]`
 
 error[E0565]: malformed `proc_macro` attribute input
-  --> $DIR/malformed-attrs.rs:96:1
+  --> $DIR/malformed-attrs.rs:99:1
    |
 LL | #[proc_macro = 18]
    | ^^^^^^^^^^^^^----^
@@ -526,7 +550,7 @@ LL | #[proc_macro = 18]
    | help: must be of the form: `#[proc_macro]`
 
 error[E0565]: malformed `coroutine` attribute input
-  --> $DIR/malformed-attrs.rs:108:5
+  --> $DIR/malformed-attrs.rs:111:5
    |
 LL |     #[coroutine = 63] || {}
    |     ^^^^^^^^^^^^----^
@@ -535,7 +559,7 @@ LL |     #[coroutine = 63] || {}
    |     help: must be of the form: `#[coroutine]`
 
 error[E0565]: malformed `proc_macro_attribute` attribute input
-  --> $DIR/malformed-attrs.rs:113:1
+  --> $DIR/malformed-attrs.rs:116:1
    |
 LL | #[proc_macro_attribute = 19]
    | ^^^^^^^^^^^^^^^^^^^^^^^----^
@@ -544,7 +568,7 @@ LL | #[proc_macro_attribute = 19]
    | help: must be of the form: `#[proc_macro_attribute]`
 
 error[E0539]: malformed `must_use` attribute input
-  --> $DIR/malformed-attrs.rs:116:1
+  --> $DIR/malformed-attrs.rs:119:1
    |
 LL | #[must_use = 1]
    | ^^^^^^^^^^^^^-^
@@ -562,7 +586,7 @@ LL + #[must_use]
    |
 
 error[E0539]: malformed `proc_macro_derive` attribute input
-  --> $DIR/malformed-attrs.rs:120:1
+  --> $DIR/malformed-attrs.rs:123:1
    |
 LL | #[proc_macro_derive]
    | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list
@@ -576,7 +600,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |                    ++++++++++++++++++++++++++++++++++++++++++
 
 error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
-  --> $DIR/malformed-attrs.rs:125:1
+  --> $DIR/malformed-attrs.rs:128:1
    |
 LL | #[rustc_layout_scalar_valid_range_start]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -585,7 +609,7 @@ LL | #[rustc_layout_scalar_valid_range_start]
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
 
 error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input
-  --> $DIR/malformed-attrs.rs:127:1
+  --> $DIR/malformed-attrs.rs:130:1
    |
 LL | #[rustc_layout_scalar_valid_range_end]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -594,7 +618,7 @@ LL | #[rustc_layout_scalar_valid_range_end]
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
 
 error[E0565]: malformed `marker` attribute input
-  --> $DIR/malformed-attrs.rs:152:1
+  --> $DIR/malformed-attrs.rs:155:1
    |
 LL | #[marker = 3]
    | ^^^^^^^^^---^
@@ -603,7 +627,7 @@ LL | #[marker = 3]
    | help: must be of the form: `#[marker]`
 
 error[E0565]: malformed `fundamental` attribute input
-  --> $DIR/malformed-attrs.rs:154:1
+  --> $DIR/malformed-attrs.rs:157:1
    |
 LL | #[fundamental()]
    | ^^^^^^^^^^^^^--^
@@ -612,7 +636,7 @@ LL | #[fundamental()]
    | help: must be of the form: `#[fundamental]`
 
 error[E0565]: malformed `ffi_pure` attribute input
-  --> $DIR/malformed-attrs.rs:162:5
+  --> $DIR/malformed-attrs.rs:165:5
    |
 LL |     #[unsafe(ffi_pure = 1)]
    |     ^^^^^^^^^^^^^^^^^^---^^
@@ -621,7 +645,7 @@ LL |     #[unsafe(ffi_pure = 1)]
    |     help: must be of the form: `#[ffi_pure]`
 
 error[E0539]: malformed `link_ordinal` attribute input
-  --> $DIR/malformed-attrs.rs:164:5
+  --> $DIR/malformed-attrs.rs:167:5
    |
 LL |     #[link_ordinal]
    |     ^^^^^^^^^^^^^^^
@@ -632,7 +656,7 @@ LL |     #[link_ordinal]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute>
 
 error[E0565]: malformed `ffi_const` attribute input
-  --> $DIR/malformed-attrs.rs:168:5
+  --> $DIR/malformed-attrs.rs:171:5
    |
 LL |     #[unsafe(ffi_const = 1)]
    |     ^^^^^^^^^^^^^^^^^^^---^^
@@ -641,7 +665,7 @@ LL |     #[unsafe(ffi_const = 1)]
    |     help: must be of the form: `#[ffi_const]`
 
 error[E0539]: malformed `linkage` attribute input
-  --> $DIR/malformed-attrs.rs:170:5
+  --> $DIR/malformed-attrs.rs:173:5
    |
 LL |     #[linkage]
    |     ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
@@ -659,7 +683,7 @@ LL |     #[linkage = "external"]
    = and 5 other candidates
 
 error[E0565]: malformed `automatically_derived` attribute input
-  --> $DIR/malformed-attrs.rs:188:1
+  --> $DIR/malformed-attrs.rs:191:1
    |
 LL | #[automatically_derived = 18]
    | ^^^^^^^^^^^^^^^^^^^^^^^^----^
@@ -668,7 +692,7 @@ LL | #[automatically_derived = 18]
    | help: must be of the form: `#[automatically_derived]`
 
 error[E0565]: malformed `non_exhaustive` attribute input
-  --> $DIR/malformed-attrs.rs:194:1
+  --> $DIR/malformed-attrs.rs:197:1
    |
 LL | #[non_exhaustive = 1]
    | ^^^^^^^^^^^^^^^^^---^
@@ -677,13 +701,13 @@ LL | #[non_exhaustive = 1]
    | help: must be of the form: `#[non_exhaustive]`
 
 error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
-  --> $DIR/malformed-attrs.rs:206:1
+  --> $DIR/malformed-attrs.rs:209:1
    |
 LL | #[macro_use = 1]
    | ^^^^^^^^^^^^^^^^
 
 error[E0565]: malformed `allow_internal_unsafe` attribute input
-  --> $DIR/malformed-attrs.rs:213:1
+  --> $DIR/malformed-attrs.rs:216:1
    |
 LL | #[allow_internal_unsafe = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^---^
@@ -692,7 +716,7 @@ LL | #[allow_internal_unsafe = 1]
    | help: must be of the form: `#[allow_internal_unsafe]`
 
 error[E0565]: malformed `type_const` attribute input
-  --> $DIR/malformed-attrs.rs:140:5
+  --> $DIR/malformed-attrs.rs:143:5
    |
 LL |     #[type_const = 1]
    |     ^^^^^^^^^^^^^---^
@@ -712,20 +736,20 @@ LL | |     #[coroutine = 63] || {}
 LL | | }
    | |_- not a `const fn`
 
-error: `#[repr(align(...))]` is not supported on function items
-  --> $DIR/malformed-attrs.rs:45:1
+error: `#[repr(align(...))]` is not supported on functions
+  --> $DIR/malformed-attrs.rs:47:1
    |
 LL | #[repr]
    | ^^^^^^^
    |
 help: use `#[rustc_align(...)]` instead
-  --> $DIR/malformed-attrs.rs:45:1
+  --> $DIR/malformed-attrs.rs:47:1
    |
 LL | #[repr]
    | ^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/malformed-attrs.rs:146:1
+  --> $DIR/malformed-attrs.rs:149:1
    |
 LL | #[diagnostic::do_not_recommend()]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -733,7 +757,7 @@ LL | #[diagnostic::do_not_recommend()]
    = note: `#[warn(malformed_diagnostic_attributes)]` on by default
 
 warning: missing options for `on_unimplemented` attribute
-  --> $DIR/malformed-attrs.rs:135:1
+  --> $DIR/malformed-attrs.rs:138:1
    |
 LL | #[diagnostic::on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -741,7 +765,7 @@ LL | #[diagnostic::on_unimplemented]
    = help: at least one of the `message`, `note` and `label` options are expected
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/malformed-attrs.rs:137:1
+  --> $DIR/malformed-attrs.rs:140:1
    |
 LL | #[diagnostic::on_unimplemented = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -749,7 +773,7 @@ LL | #[diagnostic::on_unimplemented = 1]
    = help: only `message`, `note` and `label` are allowed as options
 
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
-  --> $DIR/malformed-attrs.rs:50:1
+  --> $DIR/malformed-attrs.rs:52:1
    |
 LL | #[inline = 5]
    | ^^^^^^^^^^^^^
@@ -758,7 +782,7 @@ LL | #[inline = 5]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:91:1
+  --> $DIR/malformed-attrs.rs:94:1
    |
 LL | #[ignore()]
    | ^^^^^^^^^^^
@@ -767,7 +791,7 @@ LL | #[ignore()]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:220:1
+  --> $DIR/malformed-attrs.rs:223:1
    |
 LL | #[ignore = 1]
    | ^^^^^^^^^^^^^
@@ -776,7 +800,7 @@ LL | #[ignore = 1]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 error[E0308]: mismatched types
-  --> $DIR/malformed-attrs.rs:108:23
+  --> $DIR/malformed-attrs.rs:111:23
    |
 LL | fn test() {
    |          - help: a return type might be missing here: `-> _`
@@ -784,15 +808,15 @@ LL |     #[coroutine = 63] || {}
    |                       ^^^^^ expected `()`, found coroutine
    |
    = note: expected unit type `()`
-              found coroutine `{coroutine@$DIR/malformed-attrs.rs:108:23: 108:25}`
+              found coroutine `{coroutine@$DIR/malformed-attrs.rs:111:23: 111:25}`
 
-error: aborting due to 74 previous errors; 3 warnings emitted
+error: aborting due to 77 previous errors; 3 warnings emitted
 
 Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805.
 For more information about an error, try `rustc --explain E0308`.
 Future incompatibility report: Future breakage diagnostic:
 error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]`
-  --> $DIR/malformed-attrs.rs:40:1
+  --> $DIR/malformed-attrs.rs:41:1
    |
 LL | #[doc]
    | ^^^^^^
@@ -804,7 +828,7 @@ LL | #[doc]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]`
-  --> $DIR/malformed-attrs.rs:73:1
+  --> $DIR/malformed-attrs.rs:76:1
    |
 LL | #[doc]
    | ^^^^^^
@@ -816,7 +840,7 @@ LL | #[doc]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-attrs.rs:80:1
+  --> $DIR/malformed-attrs.rs:83:1
    |
 LL | #[link]
    | ^^^^^^^
@@ -828,7 +852,7 @@ LL | #[link]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
-  --> $DIR/malformed-attrs.rs:50:1
+  --> $DIR/malformed-attrs.rs:52:1
    |
 LL | #[inline = 5]
    | ^^^^^^^^^^^^^
@@ -839,7 +863,7 @@ LL | #[inline = 5]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:91:1
+  --> $DIR/malformed-attrs.rs:94:1
    |
 LL | #[ignore()]
    | ^^^^^^^^^^^
@@ -850,7 +874,7 @@ LL | #[ignore()]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:220:1
+  --> $DIR/malformed-attrs.rs:223:1
    |
 LL | #[ignore = 1]
    | ^^^^^^^^^^^^^
diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs
index cf143b28e54..adce84763ab 100644
--- a/tests/ui/attributes/malformed-fn-align.rs
+++ b/tests/ui/attributes/malformed-fn-align.rs
@@ -23,7 +23,7 @@ fn f2() {}
 #[rustc_align(0)] //~ ERROR invalid alignment value: not a power of two
 fn f3() {}
 
-#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on function items
+#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on functions
 fn f4() {}
 
 #[rustc_align(-1)] //~ ERROR expected unsuffixed literal, found `-`
@@ -41,14 +41,14 @@ fn f7() {}
 #[rustc_align(16)]
 fn f8() {}
 
-#[rustc_align(16)] //~ ERROR `#[rustc_align(...)]` is not supported on struct items
+#[rustc_align(16)] //~ ERROR attribute cannot be used on
 struct S1;
 
-#[rustc_align(32)] //~ ERROR `#[rustc_align(...)]` should be applied to a function item
+#[rustc_align(32)] //~ ERROR attribute cannot be used on
 const FOO: i32 = 42;
 
-#[rustc_align(32)] //~ ERROR `#[rustc_align(...)]` should be applied to a function item
+#[rustc_align(32)] //~ ERROR attribute cannot be used on
 mod test {}
 
-#[rustc_align(32)] //~ ERROR `#[rustc_align(...)]` should be applied to a function item
+#[rustc_align(32)] //~ ERROR attribute cannot be used on
 use ::std::iter;
diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr
index d995a7bf070..346fe2b4b7f 100644
--- a/tests/ui/attributes/malformed-fn-align.stderr
+++ b/tests/ui/attributes/malformed-fn-align.stderr
@@ -69,53 +69,49 @@ error[E0589]: invalid alignment value: not a power of two
 LL | #[rustc_align(3)]
    |               ^
 
-error: `#[repr(align(...))]` is not supported on function items
-  --> $DIR/malformed-fn-align.rs:26:8
-   |
-LL | #[repr(align(16))]
-   |        ^^^^^^^^^
-   |
-help: use `#[rustc_align(...)]` instead
-  --> $DIR/malformed-fn-align.rs:26:8
-   |
-LL | #[repr(align(16))]
-   |        ^^^^^^^^^
-
-error: `#[rustc_align(...)]` is not supported on struct items
+error: `#[rustc_align]` attribute cannot be used on structs
   --> $DIR/malformed-fn-align.rs:44:1
    |
 LL | #[rustc_align(16)]
    | ^^^^^^^^^^^^^^^^^^
    |
-help: use `#[repr(align(...))]` instead
-   |
-LL - #[rustc_align(16)]
-LL + #[repr(align(16))]
-   |
+   = help: `#[rustc_align]` can only be applied to functions
 
-error: `#[rustc_align(...)]` should be applied to a function item
+error: `#[rustc_align]` attribute cannot be used on constants
   --> $DIR/malformed-fn-align.rs:47:1
    |
 LL | #[rustc_align(32)]
    | ^^^^^^^^^^^^^^^^^^
-LL | const FOO: i32 = 42;
-   | -------------------- not a function item
+   |
+   = help: `#[rustc_align]` can only be applied to functions
 
-error: `#[rustc_align(...)]` should be applied to a function item
+error: `#[rustc_align]` attribute cannot be used on modules
   --> $DIR/malformed-fn-align.rs:50:1
    |
 LL | #[rustc_align(32)]
    | ^^^^^^^^^^^^^^^^^^
-LL | mod test {}
-   | ----------- not a function item
+   |
+   = help: `#[rustc_align]` can only be applied to functions
 
-error: `#[rustc_align(...)]` should be applied to a function item
+error: `#[rustc_align]` attribute cannot be used on use statements
   --> $DIR/malformed-fn-align.rs:53:1
    |
 LL | #[rustc_align(32)]
    | ^^^^^^^^^^^^^^^^^^
-LL | use ::std::iter;
-   | ---------------- not a function item
+   |
+   = help: `#[rustc_align]` can only be applied to functions
+
+error: `#[repr(align(...))]` is not supported on functions
+  --> $DIR/malformed-fn-align.rs:26:8
+   |
+LL | #[repr(align(16))]
+   |        ^^^^^^^^^
+   |
+help: use `#[rustc_align(...)]` instead
+  --> $DIR/malformed-fn-align.rs:26:8
+   |
+LL | #[repr(align(16))]
+   |        ^^^^^^^^^
 
 error: aborting due to 15 previous errors
 
diff --git a/tests/ui/attributes/multiple-invalid.rs b/tests/ui/attributes/multiple-invalid.rs
index ae044eb843b..49d1aeed604 100644
--- a/tests/ui/attributes/multiple-invalid.rs
+++ b/tests/ui/attributes/multiple-invalid.rs
@@ -2,9 +2,9 @@
 // on an item.
 
 #[inline]
-//~^ ERROR attribute should be applied to function or closure [E0518]
+//~^ ERROR attribute cannot be used on
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 const FOO: u8 = 0;
 
 fn main() { }
diff --git a/tests/ui/attributes/multiple-invalid.stderr b/tests/ui/attributes/multiple-invalid.stderr
index f4f7dd7c4f1..182d39b14bc 100644
--- a/tests/ui/attributes/multiple-invalid.stderr
+++ b/tests/ui/attributes/multiple-invalid.stderr
@@ -1,21 +1,18 @@
-error: attribute should be applied to a function definition
+error: `#[inline]` attribute cannot be used on constants
+  --> $DIR/multiple-invalid.rs:4:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[target_feature]` attribute cannot be used on constants
   --> $DIR/multiple-invalid.rs:6:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | const FOO: u8 = 0;
-   | ------------------ not a function definition
-
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/multiple-invalid.rs:4:1
    |
-LL | #[inline]
-   | ^^^^^^^^^
-...
-LL | const FOO: u8 = 0;
-   | ------------------ not a function or closure
+   = help: `#[target_feature]` can only be applied to functions
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0518`.
diff --git a/tests/ui/attributes/optimize.rs b/tests/ui/attributes/optimize.rs
index 7a1cc1be9ee..78e05f111e7 100644
--- a/tests/ui/attributes/optimize.rs
+++ b/tests/ui/attributes/optimize.rs
@@ -5,11 +5,11 @@
 
 //@ edition: 2018
 
-#[optimize(speed)] //~ ERROR attribute applied to an invalid target
+#[optimize(speed)] //~ ERROR attribute cannot be used on
 struct F;
 
 fn invalid() {
-    #[optimize(speed)] //~ ERROR attribute applied to an invalid target
+    #[optimize(speed)] //~ ERROR attribute cannot be used on
     {
         1
     };
@@ -18,10 +18,10 @@ fn invalid() {
 #[optimize(speed)]
 fn valid() {}
 
-#[optimize(speed)] //~ ERROR attribute applied to an invalid target
+#[optimize(speed)] //~ ERROR attribute cannot be used on
 mod valid_module {}
 
-#[optimize(speed)] //~ ERROR attribute applied to an invalid target
+#[optimize(speed)] //~ ERROR attribute cannot be used on
 impl F {}
 
 fn main() {
diff --git a/tests/ui/attributes/optimize.stderr b/tests/ui/attributes/optimize.stderr
index ad9309d27a5..2ded1a973f3 100644
--- a/tests/ui/attributes/optimize.stderr
+++ b/tests/ui/attributes/optimize.stderr
@@ -1,36 +1,34 @@
-error: attribute applied to an invalid target
+error: `#[optimize]` attribute cannot be used on structs
   --> $DIR/optimize.rs:8:1
    |
 LL | #[optimize(speed)]
    | ^^^^^^^^^^^^^^^^^^
-LL | struct F;
-   | --------- invalid target
+   |
+   = help: `#[optimize]` can only be applied to functions
 
-error: attribute applied to an invalid target
+error: `#[optimize]` attribute cannot be used on expressions
   --> $DIR/optimize.rs:12:5
    |
-LL |       #[optimize(speed)]
-   |       ^^^^^^^^^^^^^^^^^^
-LL | /     {
-LL | |         1
-LL | |     };
-   | |_____- invalid target
+LL |     #[optimize(speed)]
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[optimize]` can only be applied to functions
 
-error: attribute applied to an invalid target
+error: `#[optimize]` attribute cannot be used on modules
   --> $DIR/optimize.rs:21:1
    |
 LL | #[optimize(speed)]
    | ^^^^^^^^^^^^^^^^^^
-LL | mod valid_module {}
-   | ------------------- invalid target
+   |
+   = help: `#[optimize]` can only be applied to functions
 
-error: attribute applied to an invalid target
+error: `#[optimize]` attribute cannot be used on inherent impl blocks
   --> $DIR/optimize.rs:24:1
    |
 LL | #[optimize(speed)]
    | ^^^^^^^^^^^^^^^^^^
-LL | impl F {}
-   | --------- invalid target
+   |
+   = help: `#[optimize]` can only be applied to functions
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/attributes/positions/used.rs b/tests/ui/attributes/positions/used.rs
index 7950fa773a1..7e106d278f2 100644
--- a/tests/ui/attributes/positions/used.rs
+++ b/tests/ui/attributes/positions/used.rs
@@ -4,20 +4,20 @@
 #[used]
 static FOO: u32 = 0; // OK
 
-#[used] //~ ERROR attribute must be applied to a `static` variable
+#[used] //~ ERROR attribute cannot be used on
 fn foo() {}
 
-#[used] //~ ERROR attribute must be applied to a `static` variable
+#[used] //~ ERROR attribute cannot be used on
 struct Foo {}
 
-#[used] //~ ERROR attribute must be applied to a `static` variable
+#[used] //~ ERROR attribute cannot be used on
 trait Bar {}
 
-#[used] //~ ERROR attribute must be applied to a `static` variable
+#[used] //~ ERROR attribute cannot be used on
 impl Bar for Foo {}
 
 // Regression test for <https://github.com/rust-lang/rust/issues/126789>.
 extern "C" {
-    #[used] //~ ERROR attribute must be applied to a `static` variable
+    #[used] //~ ERROR attribute cannot be used on
     static BAR: i32;
 }
diff --git a/tests/ui/attributes/positions/used.stderr b/tests/ui/attributes/positions/used.stderr
index 64460c178cb..79011f3a758 100644
--- a/tests/ui/attributes/positions/used.stderr
+++ b/tests/ui/attributes/positions/used.stderr
@@ -1,42 +1,42 @@
-error: attribute must be applied to a `static` variable
+error: `#[used]` attribute cannot be used on functions
   --> $DIR/used.rs:7:1
    |
 LL | #[used]
    | ^^^^^^^
-LL | fn foo() {}
-   | ----------- but this is a function
+   |
+   = help: `#[used]` can only be applied to statics
 
-error: attribute must be applied to a `static` variable
+error: `#[used]` attribute cannot be used on structs
   --> $DIR/used.rs:10:1
    |
 LL | #[used]
    | ^^^^^^^
-LL | struct Foo {}
-   | ------------- but this is a struct
+   |
+   = help: `#[used]` can only be applied to statics
 
-error: attribute must be applied to a `static` variable
+error: `#[used]` attribute cannot be used on traits
   --> $DIR/used.rs:13:1
    |
 LL | #[used]
    | ^^^^^^^
-LL | trait Bar {}
-   | ------------ but this is a trait
+   |
+   = help: `#[used]` can only be applied to statics
 
-error: attribute must be applied to a `static` variable
+error: `#[used]` attribute cannot be used on trait impl blocks
   --> $DIR/used.rs:16:1
    |
 LL | #[used]
    | ^^^^^^^
-LL | impl Bar for Foo {}
-   | ------------------- but this is a trait implementation block
+   |
+   = help: `#[used]` can only be applied to statics
 
-error: attribute must be applied to a `static` variable
+error: `#[used]` attribute cannot be used on foreign statics
   --> $DIR/used.rs:21:5
    |
 LL |     #[used]
    |     ^^^^^^^
-LL |     static BAR: i32;
-   |     ---------------- but this is a foreign static item
+   |
+   = help: `#[used]` can only be applied to statics
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/attributes/rustc_confusables.rs b/tests/ui/attributes/rustc_confusables.rs
index a8095936cff..91c66a75cc3 100644
--- a/tests/ui/attributes/rustc_confusables.rs
+++ b/tests/ui/attributes/rustc_confusables.rs
@@ -43,5 +43,6 @@ impl Bar {
 }
 
 #[rustc_confusables("blah")]
-//~^ ERROR attribute should be applied to an inherent method
+//~^ ERROR attribute cannot be used on
+//~| HELP can only be applied to
 fn not_inherent_impl_method() {}
diff --git a/tests/ui/attributes/rustc_confusables.stderr b/tests/ui/attributes/rustc_confusables.stderr
index 3ed4efeb4db..c714257ee77 100644
--- a/tests/ui/attributes/rustc_confusables.stderr
+++ b/tests/ui/attributes/rustc_confusables.stderr
@@ -22,11 +22,13 @@ 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
+error: `#[rustc_confusables]` attribute cannot be used on functions
   --> $DIR/rustc_confusables.rs:45:1
    |
 LL | #[rustc_confusables("blah")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_confusables]` can only be applied to inherent methods
 
 error[E0599]: no method named `inser` found for struct `rustc_confusables_across_crate::BTreeSet` in the current scope
   --> $DIR/rustc_confusables.rs:12:7
diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.rs b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs
index 25b473d5a58..e1bd0ca3896 100644
--- a/tests/ui/attributes/rustc_skip_during_method_dispatch.rs
+++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs
@@ -32,7 +32,7 @@ trait String {}
 trait OK {}
 
 #[rustc_skip_during_method_dispatch(array)]
-//~^ ERROR: attribute should be applied to a trait
+//~^ ERROR: attribute cannot be used on
 impl OK for () {}
 
 fn main() {}
diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
index 2f5d7968489..094987e944f 100644
--- a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
+++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
@@ -61,14 +61,13 @@ LL | #[rustc_skip_during_method_dispatch("array")]
    | |                                   didn't expect a literal here
    | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
 
-error: attribute should be applied to a trait
+error: `#[rustc_skip_during_method_dispatch]` attribute cannot be used on trait impl blocks
   --> $DIR/rustc_skip_during_method_dispatch.rs:34:1
    |
 LL | #[rustc_skip_during_method_dispatch(array)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | impl OK for () {}
-   | ----------------- not a trait
+   |
+   = help: `#[rustc_skip_during_method_dispatch]` can only be applied to traits
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/coroutine/invalid_attr_usage.rs b/tests/ui/coroutine/invalid_attr_usage.rs
index 995a3aa3100..5081c17de4b 100644
--- a/tests/ui/coroutine/invalid_attr_usage.rs
+++ b/tests/ui/coroutine/invalid_attr_usage.rs
@@ -3,9 +3,9 @@
 #![feature(coroutines)]
 
 #[coroutine]
-//~^ ERROR: attribute should be applied to closures
+//~^ ERROR: attribute cannot be used on
 struct Foo;
 
 #[coroutine]
-//~^ ERROR: attribute should be applied to closures
+//~^ ERROR: attribute cannot be used on
 fn main() {}
diff --git a/tests/ui/coroutine/invalid_attr_usage.stderr b/tests/ui/coroutine/invalid_attr_usage.stderr
index 316a0117e5d..46fc80c1bad 100644
--- a/tests/ui/coroutine/invalid_attr_usage.stderr
+++ b/tests/ui/coroutine/invalid_attr_usage.stderr
@@ -1,14 +1,18 @@
-error: attribute should be applied to closures
+error: `#[coroutine]` attribute cannot be used on structs
   --> $DIR/invalid_attr_usage.rs:5:1
    |
 LL | #[coroutine]
    | ^^^^^^^^^^^^
+   |
+   = help: `#[coroutine]` can only be applied to closures
 
-error: attribute should be applied to closures
+error: `#[coroutine]` attribute cannot be used on functions
   --> $DIR/invalid_attr_usage.rs:9:1
    |
 LL | #[coroutine]
    | ^^^^^^^^^^^^
+   |
+   = help: `#[coroutine]` can only be applied to closures
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coverage-attr/allowed-positions.rs b/tests/ui/coverage-attr/allowed-positions.rs
index f1169fa6570..cfbc7f5e6c0 100644
--- a/tests/ui/coverage-attr/allowed-positions.rs
+++ b/tests/ui/coverage-attr/allowed-positions.rs
@@ -11,24 +11,24 @@
 #[coverage(off)]
 mod submod {}
 
-#[coverage(off)] //~ ERROR coverage attribute not allowed here [E0788]
+#[coverage(off)] //~ ERROR attribute cannot be used on
 type MyTypeAlias = ();
 
-#[coverage(off)] //~ ERROR [E0788]
+#[coverage(off)] //~ ERROR attribute cannot be used on
 trait MyTrait {
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     const TRAIT_ASSOC_CONST: u32;
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     type TraitAssocType;
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     fn trait_method(&self);
 
     #[coverage(off)]
     fn trait_method_with_default(&self) {}
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     fn trait_assoc_fn();
 }
 
@@ -36,7 +36,7 @@ trait MyTrait {
 impl MyTrait for () {
     const TRAIT_ASSOC_CONST: u32 = 0;
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     type TraitAssocType = Self;
 
     #[coverage(off)]
@@ -53,14 +53,14 @@ trait HasAssocType {
 }
 
 impl HasAssocType for () {
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     type T = impl Copy;
     fn constrain_assoc_type() -> Self::T {}
 }
 
-#[coverage(off)] //~ ERROR [E0788]
+#[coverage(off)] //~ ERROR attribute cannot be used on
 struct MyStruct {
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     field: u32,
 }
 
@@ -73,25 +73,25 @@ impl MyStruct {
 }
 
 extern "C" {
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     static X: u32;
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     type T;
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     fn foreign_fn();
 }
 
 #[coverage(off)]
 fn main() {
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     let _ = ();
 
     // Currently not allowed on let statements, even if they bind to a closure.
     // It might be nice to support this as a special case someday, but trying
     // to define the precise boundaries of that special case might be tricky.
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     let _let_closure = || ();
 
     // In situations where attributes can already be applied to expressions,
@@ -107,10 +107,10 @@ fn main() {
     //~^ ERROR attributes on expressions are experimental [E0658]
 
     match () {
-        #[coverage(off)] //~ ERROR [E0788]
+        #[coverage(off)] //~ ERROR attribute cannot be used on
         () => (),
     }
 
-    #[coverage(off)] //~ ERROR [E0788]
+    #[coverage(off)] //~ ERROR attribute cannot be used on
     return ();
 }
diff --git a/tests/ui/coverage-attr/allowed-positions.stderr b/tests/ui/coverage-attr/allowed-positions.stderr
index 34562a4da1b..aaef3ad0203 100644
--- a/tests/ui/coverage-attr/allowed-positions.stderr
+++ b/tests/ui/coverage-attr/allowed-positions.stderr
@@ -8,185 +8,142 @@ LL |     let _closure_expr = #[coverage(off)] || ();
    = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0788]: coverage attribute not allowed here
+error: `#[coverage]` attribute cannot be used on type aliases
   --> $DIR/allowed-positions.rs:14:1
    |
 LL | #[coverage(off)]
    | ^^^^^^^^^^^^^^^^
-LL | type MyTypeAlias = ();
-   | ---------------------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
+error: `#[coverage]` attribute cannot be used on traits
   --> $DIR/allowed-positions.rs:17:1
    |
-LL |   #[coverage(off)]
-   |   ^^^^^^^^^^^^^^^^
-LL | / trait MyTrait {
-LL | |     #[coverage(off)]
-LL | |     const TRAIT_ASSOC_CONST: u32;
-...  |
-LL | |     fn trait_assoc_fn();
-LL | | }
-   | |_- not a function, impl block, or module
+LL | #[coverage(off)]
+   | ^^^^^^^^^^^^^^^^
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:61:1
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/allowed-positions.rs:19:5
    |
-LL |   #[coverage(off)]
-   |   ^^^^^^^^^^^^^^^^
-LL | / struct MyStruct {
-LL | |     #[coverage(off)]
-LL | |     field: u32,
-LL | | }
-   | |_- not a function, impl block, or module
+LL |     #[coverage(off)]
+   |     ^^^^^^^^^^^^^^^^
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:63:5
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/allowed-positions.rs:22:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     field: u32,
-   |     ---------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:88:5
+error: `#[coverage]` attribute cannot be used on required trait methods
+  --> $DIR/allowed-positions.rs:25:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     let _ = ();
-   |     ----------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:94:5
+error: `#[coverage]` attribute cannot be used on required trait methods
+  --> $DIR/allowed-positions.rs:31:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     let _let_closure = || ();
-   |     ------------------------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:110:9
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/allowed-positions.rs:39:5
    |
-LL |         #[coverage(off)]
-   |         ^^^^^^^^^^^^^^^^
-LL |         () => (),
-   |         -------- not a function, impl block, or module
+LL |     #[coverage(off)]
+   |     ^^^^^^^^^^^^^^^^
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:114:5
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/allowed-positions.rs:56:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     return ();
-   |     --------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:19:5
+error: `#[coverage]` attribute cannot be used on structs
+  --> $DIR/allowed-positions.rs:61:1
    |
-LL |     #[coverage(off)]
-   |     ^^^^^^^^^^^^^^^^
-LL |     const TRAIT_ASSOC_CONST: u32;
-   |     ----------------------------- not a function, impl block, or module
+LL | #[coverage(off)]
+   | ^^^^^^^^^^^^^^^^
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:22:5
+error: `#[coverage]` attribute cannot be used on struct fields
+  --> $DIR/allowed-positions.rs:63:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     type TraitAssocType;
-   |     -------------------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:25:5
+error: `#[coverage]` attribute cannot be used on foreign statics
+  --> $DIR/allowed-positions.rs:76:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     fn trait_method(&self);
-   |     ----------------------- function has no body
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:31:5
+error: `#[coverage]` attribute cannot be used on foreign types
+  --> $DIR/allowed-positions.rs:79:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     fn trait_assoc_fn();
-   |     -------------------- function has no body
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:39:5
+error: `#[coverage]` attribute cannot be used on foreign functions
+  --> $DIR/allowed-positions.rs:82:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     type TraitAssocType = Self;
-   |     --------------------------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to methods, impl blocks, functions, closures, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:56:5
+error: `#[coverage]` attribute cannot be used on statements
+  --> $DIR/allowed-positions.rs:88:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     type T = impl Copy;
-   |     ------------------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:76:5
+error: `#[coverage]` attribute cannot be used on statements
+  --> $DIR/allowed-positions.rs:94:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     static X: u32;
-   |     -------------- not a function, impl block, or module
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:79:5
+error: `#[coverage]` attribute cannot be used on match arms
+  --> $DIR/allowed-positions.rs:110:9
    |
-LL |     #[coverage(off)]
-   |     ^^^^^^^^^^^^^^^^
-LL |     type T;
-   |     ------- not a function, impl block, or module
+LL |         #[coverage(off)]
+   |         ^^^^^^^^^^^^^^^^
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/allowed-positions.rs:82:5
+error: `#[coverage]` attribute cannot be used on expressions
+  --> $DIR/allowed-positions.rs:114:5
    |
 LL |     #[coverage(off)]
    |     ^^^^^^^^^^^^^^^^
-LL |     fn foreign_fn();
-   |     ---------------- function has no body
    |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
 
 error: aborting due to 18 previous errors
 
-Some errors have detailed explanations: E0658, E0788.
-For more information about an error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs
index 8171dbbf692..6e81ab89616 100644
--- a/tests/ui/coverage-attr/name-value.rs
+++ b/tests/ui/coverage-attr/name-value.rs
@@ -20,6 +20,7 @@ mod my_mod_inner {
 
 #[coverage = "off"]
 //~^ ERROR malformed `coverage` attribute input
+//~| ERROR attribute cannot be used on
 struct MyStruct;
 
 #[coverage = "off"]
@@ -27,18 +28,22 @@ struct MyStruct;
 impl MyStruct {
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     const X: u32 = 7;
 }
 
 #[coverage = "off"]
 //~^ ERROR malformed `coverage` attribute input
+//~| ERROR attribute cannot be used on
 trait MyTrait {
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     const X: u32;
 
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     type T;
 }
 
@@ -47,10 +52,12 @@ trait MyTrait {
 impl MyTrait for MyStruct {
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     const X: u32 = 8;
 
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     type T = ();
 }
 
diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr
index a838ec5df8e..2dac2401e3c 100644
--- a/tests/ui/coverage-attr/name-value.stderr
+++ b/tests/ui/coverage-attr/name-value.stderr
@@ -43,8 +43,16 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on structs
+  --> $DIR/name-value.rs:21:1
+   |
+LL | #[coverage = "off"]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:25:1
+  --> $DIR/name-value.rs:26:1
    |
 LL | #[coverage = "off"]
    | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -59,7 +67,7 @@ LL + #[coverage(on)]
    |
 
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:28:5
+  --> $DIR/name-value.rs:29:5
    |
 LL |     #[coverage = "off"]
    |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -73,8 +81,16 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/name-value.rs:29:5
+   |
+LL |     #[coverage = "off"]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:33:1
+  --> $DIR/name-value.rs:35:1
    |
 LL | #[coverage = "off"]
    | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -88,8 +104,16 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on traits
+  --> $DIR/name-value.rs:35:1
+   |
+LL | #[coverage = "off"]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:36:5
+  --> $DIR/name-value.rs:39:5
    |
 LL |     #[coverage = "off"]
    |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -103,8 +127,16 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/name-value.rs:39:5
+   |
+LL |     #[coverage = "off"]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:40:5
+  --> $DIR/name-value.rs:44:5
    |
 LL |     #[coverage = "off"]
    |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -118,8 +150,16 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/name-value.rs:44:5
+   |
+LL |     #[coverage = "off"]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:45:1
+  --> $DIR/name-value.rs:50:1
    |
 LL | #[coverage = "off"]
    | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -134,7 +174,7 @@ LL + #[coverage(on)]
    |
 
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:48:5
+  --> $DIR/name-value.rs:53:5
    |
 LL |     #[coverage = "off"]
    |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -148,8 +188,16 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/name-value.rs:53:5
+   |
+LL |     #[coverage = "off"]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:52:5
+  --> $DIR/name-value.rs:58:5
    |
 LL |     #[coverage = "off"]
    |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -163,8 +211,16 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/name-value.rs:58:5
+   |
+LL |     #[coverage = "off"]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:57:1
+  --> $DIR/name-value.rs:64:1
    |
 LL | #[coverage = "off"]
    | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -178,6 +234,6 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error: aborting due to 12 previous errors
+error: aborting due to 19 previous errors
 
 For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs
index 81bd558b8b0..e47279f74ca 100644
--- a/tests/ui/coverage-attr/word-only.rs
+++ b/tests/ui/coverage-attr/word-only.rs
@@ -20,6 +20,7 @@ mod my_mod_inner {
 
 #[coverage]
 //~^ ERROR malformed `coverage` attribute input
+//~| ERROR attribute cannot be used on
 struct MyStruct;
 
 #[coverage]
@@ -27,18 +28,22 @@ struct MyStruct;
 impl MyStruct {
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     const X: u32 = 7;
 }
 
 #[coverage]
 //~^ ERROR malformed `coverage` attribute input
+//~| ERROR attribute cannot be used on
 trait MyTrait {
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     const X: u32;
 
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     type T;
 }
 
@@ -47,10 +52,12 @@ trait MyTrait {
 impl MyTrait for MyStruct {
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     const X: u32 = 8;
 
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
+    //~| ERROR attribute cannot be used on
     type T = ();
 }
 
diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr
index dd161360a5c..e916a817e36 100644
--- a/tests/ui/coverage-attr/word-only.stderr
+++ b/tests/ui/coverage-attr/word-only.stderr
@@ -39,8 +39,16 @@ LL | #[coverage(off)]
 LL | #[coverage(on)]
    |           ++++
 
+error: `#[coverage]` attribute cannot be used on structs
+  --> $DIR/word-only.rs:21:1
+   |
+LL | #[coverage]
+   | ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:25:1
+  --> $DIR/word-only.rs:26:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -53,7 +61,7 @@ LL | #[coverage(on)]
    |           ++++
 
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:28:5
+  --> $DIR/word-only.rs:29:5
    |
 LL |     #[coverage]
    |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -65,8 +73,16 @@ LL |     #[coverage(off)]
 LL |     #[coverage(on)]
    |               ++++
 
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/word-only.rs:29:5
+   |
+LL |     #[coverage]
+   |     ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:33:1
+  --> $DIR/word-only.rs:35:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -78,8 +94,16 @@ LL | #[coverage(off)]
 LL | #[coverage(on)]
    |           ++++
 
+error: `#[coverage]` attribute cannot be used on traits
+  --> $DIR/word-only.rs:35:1
+   |
+LL | #[coverage]
+   | ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:36:5
+  --> $DIR/word-only.rs:39:5
    |
 LL |     #[coverage]
    |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -91,8 +115,16 @@ LL |     #[coverage(off)]
 LL |     #[coverage(on)]
    |               ++++
 
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/word-only.rs:39:5
+   |
+LL |     #[coverage]
+   |     ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:40:5
+  --> $DIR/word-only.rs:44:5
    |
 LL |     #[coverage]
    |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -104,8 +136,16 @@ LL |     #[coverage(off)]
 LL |     #[coverage(on)]
    |               ++++
 
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/word-only.rs:44:5
+   |
+LL |     #[coverage]
+   |     ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:45:1
+  --> $DIR/word-only.rs:50:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -118,7 +158,7 @@ LL | #[coverage(on)]
    |           ++++
 
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:48:5
+  --> $DIR/word-only.rs:53:5
    |
 LL |     #[coverage]
    |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -130,8 +170,16 @@ LL |     #[coverage(off)]
 LL |     #[coverage(on)]
    |               ++++
 
+error: `#[coverage]` attribute cannot be used on associated consts
+  --> $DIR/word-only.rs:53:5
+   |
+LL |     #[coverage]
+   |     ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:52:5
+  --> $DIR/word-only.rs:58:5
    |
 LL |     #[coverage]
    |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -143,8 +191,16 @@ LL |     #[coverage(off)]
 LL |     #[coverage(on)]
    |               ++++
 
+error: `#[coverage]` attribute cannot be used on associated types
+  --> $DIR/word-only.rs:58:5
+   |
+LL |     #[coverage]
+   |     ^^^^^^^^^^^
+   |
+   = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
+
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:57:1
+  --> $DIR/word-only.rs:64:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -156,6 +212,6 @@ LL | #[coverage(off)]
 LL | #[coverage(on)]
    |           ++++
 
-error: aborting due to 12 previous errors
+error: aborting due to 19 previous errors
 
 For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs
index 80198ab8196..9698a376025 100644
--- a/tests/ui/deprecation/deprecation-sanity.rs
+++ b/tests/ui/deprecation/deprecation-sanity.rs
@@ -1,3 +1,5 @@
+#![deny(unused_attributes)]
+
 // Various checks that deprecation attributes are used correctly
 
 mod bogus_attribute_types_1 {
@@ -32,7 +34,8 @@ fn f1() { }
 
 struct X;
 
-#[deprecated = "hello"] //~ ERROR this `#[deprecated]` annotation has no effect
+#[deprecated = "hello"] //~ ERROR attribute cannot be used on
+//~| WARN previously accepted
 impl Default for X {
     fn default() -> Self {
         X
diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr
index 856f51a4b24..1d44215731d 100644
--- a/tests/ui/deprecation/deprecation-sanity.stderr
+++ b/tests/ui/deprecation/deprecation-sanity.stderr
@@ -1,11 +1,11 @@
 error[E0541]: unknown meta item 'reason'
-  --> $DIR/deprecation-sanity.rs:4:43
+  --> $DIR/deprecation-sanity.rs:6:43
    |
 LL |     #[deprecated(since = "a", note = "a", reason)]
    |                                           ^^^^^^ expected one of `since`, `note`
 
 error[E0539]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:7:5
+  --> $DIR/deprecation-sanity.rs:9:5
    |
 LL |     #[deprecated(since = "a", note)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^----^^
@@ -29,7 +29,7 @@ LL +     #[deprecated(since = "version", note = "reason")]
    = and 1 other candidate
 
 error[E0539]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:10:5
+  --> $DIR/deprecation-sanity.rs:12:5
    |
 LL |     #[deprecated(since, note = "a")]
    |     ^^^^^^^^^^^^^-----^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL +     #[deprecated(since = "version", note = "reason")]
    = and 1 other candidate
 
 error[E0539]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:13:5
+  --> $DIR/deprecation-sanity.rs:15:5
    |
 LL |     #[deprecated(since = "a", note(b))]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
@@ -77,7 +77,7 @@ LL +     #[deprecated(since = "version", note = "reason")]
    = and 1 other candidate
 
 error[E0539]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:16:5
+  --> $DIR/deprecation-sanity.rs:18:5
    |
 LL |     #[deprecated(since(b), note = "a")]
    |     ^^^^^^^^^^^^^--------^^^^^^^^^^^^^^
@@ -101,7 +101,7 @@ LL +     #[deprecated(since = "version", note = "reason")]
    = and 1 other candidate
 
 error[E0539]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:19:5
+  --> $DIR/deprecation-sanity.rs:21:5
    |
 LL |     #[deprecated(note = b"test")]
    |     ^^^^^^^^^^^^^^^^^^^^-^^^^^^^^
@@ -111,7 +111,7 @@ LL |     #[deprecated(note = b"test")]
    = note: expected a normal string literal, not a byte string literal
 
 error[E0565]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:22:5
+  --> $DIR/deprecation-sanity.rs:24:5
    |
 LL |     #[deprecated("test")]
    |     ^^^^^^^^^^^^^------^^
@@ -135,19 +135,19 @@ LL +     #[deprecated(since = "version", note = "reason")]
    = and 1 other candidate
 
 error: multiple `deprecated` attributes
-  --> $DIR/deprecation-sanity.rs:27:1
+  --> $DIR/deprecation-sanity.rs:29:1
    |
 LL | #[deprecated(since = "a", note = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/deprecation-sanity.rs:26:1
+  --> $DIR/deprecation-sanity.rs:28:1
    |
 LL | #[deprecated(since = "a", note = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0538]: malformed `deprecated` attribute input
-  --> $DIR/deprecation-sanity.rs:30:1
+  --> $DIR/deprecation-sanity.rs:32:1
    |
 LL | #[deprecated(since = "a", since = "b", note = "c")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^
@@ -170,12 +170,14 @@ LL + #[deprecated(since = "version", note = "reason")]
    |
    = and 1 other candidate
 
-error: this `#[deprecated]` annotation has no effect
-  --> $DIR/deprecation-sanity.rs:35:1
+error: `#[deprecated]` attribute cannot be used on trait impl blocks
+  --> $DIR/deprecation-sanity.rs:37:1
    |
 LL | #[deprecated = "hello"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove the unnecessary deprecation attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates
    = note: `#[deny(useless_deprecated)]` on by default
 
 error: aborting due to 10 previous errors
diff --git a/tests/ui/error-codes/E0518.rs b/tests/ui/error-codes/E0518.rs
deleted file mode 100644
index 9c99702ada8..00000000000
--- a/tests/ui/error-codes/E0518.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#[inline(always)] //~ ERROR: E0518
-struct Foo;
-
-#[inline(never)] //~ ERROR: E0518
-impl Foo {
-}
-
-fn main() {
-}
diff --git a/tests/ui/error-codes/E0518.stderr b/tests/ui/error-codes/E0518.stderr
deleted file mode 100644
index 561446f8175..00000000000
--- a/tests/ui/error-codes/E0518.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/E0518.rs:1:1
-   |
-LL | #[inline(always)]
-   | ^^^^^^^^^^^^^^^^^
-LL | struct Foo;
-   | ----------- not a function or closure
-
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/E0518.rs:4:1
-   |
-LL |   #[inline(never)]
-   |   ^^^^^^^^^^^^^^^^
-LL | / impl Foo {
-LL | | }
-   | |_- not a function or closure
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0518`.
diff --git a/tests/ui/error-codes/E0718.stderr b/tests/ui/error-codes/E0718.stderr
index ec7462765f8..e7784d193ba 100644
--- a/tests/ui/error-codes/E0718.stderr
+++ b/tests/ui/error-codes/E0718.stderr
@@ -2,7 +2,7 @@ error[E0718]: `owned_box` lang item must be applied to a struct
   --> $DIR/E0718.rs:4:1
    |
 LL | #[lang = "owned_box"]
-   | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
+   | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/extern/extern-no-mangle.rs b/tests/ui/extern/extern-no-mangle.rs
index dba9689a075..6f2d125b923 100644
--- a/tests/ui/extern/extern-no-mangle.rs
+++ b/tests/ui/extern/extern-no-mangle.rs
@@ -9,21 +9,21 @@
 
 extern "C" {
     #[no_mangle]
-    //~^ WARNING `#[no_mangle]` has no effect on a foreign static
-    //~^^ WARNING this was previously accepted by the compiler
+    //~^ WARNING attribute cannot be used on
+    //~| WARN previously accepted
     pub static FOO: u8;
 
     #[no_mangle]
-    //~^ WARNING `#[no_mangle]` has no effect on a foreign function
-    //~^^ WARNING this was previously accepted by the compiler
+    //~^ WARNING attribute cannot be used on
+    //~| WARN previously accepted
     pub fn bar();
 }
 
 fn no_new_warn() {
     // Should emit the generic "not a function or static" warning
     #[no_mangle]
-    //~^ WARNING attribute should be applied to a free function, impl method or static
-    //~^^ WARNING this was previously accepted by the compiler
+    //~^ WARNING attribute cannot be used on
+    //~| WARN previously accepted
     let x = 0_u8;
 }
 
diff --git a/tests/ui/extern/extern-no-mangle.stderr b/tests/ui/extern/extern-no-mangle.stderr
index f20ee158ac4..b07cf0d4b4d 100644
--- a/tests/ui/extern/extern-no-mangle.stderr
+++ b/tests/ui/extern/extern-no-mangle.stderr
@@ -1,42 +1,34 @@
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/extern-no-mangle.rs:24:5
+warning: `#[no_mangle]` attribute cannot be used on foreign statics
+  --> $DIR/extern-no-mangle.rs:11:5
    |
 LL |     #[no_mangle]
    |     ^^^^^^^^^^^^
-...
-LL |     let x = 0_u8;
-   |     ------------- not a free function, impl method or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics
 note: the lint level is defined here
   --> $DIR/extern-no-mangle.rs:1:9
    |
 LL | #![warn(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-warning: `#[no_mangle]` has no effect on a foreign static
-  --> $DIR/extern-no-mangle.rs:11:5
+warning: `#[no_mangle]` attribute cannot be used on foreign functions
+  --> $DIR/extern-no-mangle.rs:16:5
    |
 LL |     #[no_mangle]
-   |     ^^^^^^^^^^^^ help: remove this attribute
-...
-LL |     pub static FOO: u8;
-   |     ------------------- foreign static
+   |     ^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: symbol names in extern blocks are not mangled
+   = help: `#[no_mangle]` can be applied to methods, functions, statics
 
-warning: `#[no_mangle]` has no effect on a foreign function
-  --> $DIR/extern-no-mangle.rs:16:5
+warning: `#[no_mangle]` attribute cannot be used on statements
+  --> $DIR/extern-no-mangle.rs:24:5
    |
 LL |     #[no_mangle]
-   |     ^^^^^^^^^^^^ help: remove this attribute
-...
-LL |     pub fn bar();
-   |     ------------- foreign function
+   |     ^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: symbol names in extern blocks are not mangled
+   = help: `#[no_mangle]` can be applied to functions, statics
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/extern/issue-47725.rs b/tests/ui/extern/issue-47725.rs
index 8ac866dc7d9..b0a0af930de 100644
--- a/tests/ui/extern/issue-47725.rs
+++ b/tests/ui/extern/issue-47725.rs
@@ -1,22 +1,25 @@
 #![warn(unused_attributes)] //~ NOTE lint level is defined here
 
 #[link_name = "foo"]
-//~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-struct Foo; //~ NOTE not a foreign function or static
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
+struct Foo;
 
 #[link_name = "foobar"]
-//~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-//~| HELP try `#[link(name = "foobar")]` instead
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 extern "C" {
     fn foo() -> u32;
 }
-//~^^^ NOTE not a foreign function or static
 
 #[link_name]
 //~^ ERROR malformed `link_name` attribute input
 //~| HELP must be of the form
+//~| WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 //~| NOTE for more information, visit
 extern "C" {
     fn bar() -> u32;
diff --git a/tests/ui/extern/issue-47725.stderr b/tests/ui/extern/issue-47725.stderr
index c5af54b8029..704b1d81b63 100644
--- a/tests/ui/extern/issue-47725.stderr
+++ b/tests/ui/extern/issue-47725.stderr
@@ -6,40 +6,38 @@ LL | #[link_name]
    |
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute>
 
-warning: attribute should be applied to a foreign function or static
+warning: `#[link_name]` attribute cannot be used on structs
   --> $DIR/issue-47725.rs:3:1
    |
 LL | #[link_name = "foo"]
    | ^^^^^^^^^^^^^^^^^^^^
-...
-LL | struct Foo;
-   | ----------- not a foreign function or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
 note: the lint level is defined here
   --> $DIR/issue-47725.rs:1:9
    |
 LL | #![warn(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-47725.rs:8:1
+warning: `#[link_name]` attribute cannot be used on foreign modules
+  --> $DIR/issue-47725.rs:9:1
    |
-LL |   #[link_name = "foobar"]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | / extern "C" {
-LL | |     fn foo() -> u32;
-LL | | }
-   | |_- not a foreign function or static
+LL | #[link_name = "foobar"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-help: try `#[link(name = "foobar")]` instead
-  --> $DIR/issue-47725.rs:8:1
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on foreign modules
+  --> $DIR/issue-47725.rs:17:1
    |
-LL | #[link_name = "foobar"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[link_name]
+   | ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
 
-error: aborting due to 1 previous error; 2 warnings emitted
+error: aborting due to 1 previous error; 3 warnings emitted
 
 For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs
index 81b7fe3db2b..91caba81cb6 100644
--- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs
+++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs
@@ -4,7 +4,7 @@
 // FIXME(jdonszelmann): empty attributes are currently ignored, since when its empty no actual
 // change is applied. This should be fixed when later moving this check to attribute parsing.
 #[allow_internal_unstable(something)] //~ ERROR allow_internal_unstable side-steps
-//~| ERROR attribute should
+//~| ERROR attribute cannot be used on
 struct S;
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr
index 076f2df28e3..cb8cf29e99d 100644
--- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr
+++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr
@@ -7,14 +7,13 @@ LL | #[allow_internal_unstable(something)]
    = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: attribute should be applied to a macro
+error: `#[allow_internal_unstable]` attribute cannot be used on structs
   --> $DIR/feature-gate-allow-internal-unstable-struct.rs:6:1
    |
 LL | #[allow_internal_unstable(something)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | struct S;
-   | --------- not a macro
+   |
+   = help: `#[allow_internal_unstable]` can be applied to macro defs, functions
 
 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 7fb11b7bde7..130dd48b0fe 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
@@ -1,6 +1,4 @@
 //~ NOTE: not an `extern crate` item
-//~^ NOTE: not a free function, impl method or static
-//~^^ NOTE: not a function or closure
 // This is testing whether various builtin attributes signals an
 // error or warning when put in "weird" places.
 //
@@ -19,29 +17,25 @@
 #![repr()]
 //~^ ERROR: `repr` attribute cannot be used at crate level
 #![path = "3800"]
-//~^ ERROR: `path` attribute cannot be used at crate level
+//~^ ERROR: attribute cannot be used on
 #![automatically_derived]
-//~^ ERROR: `automatically_derived` attribute cannot be used at crate level
+//~^ ERROR: attribute cannot be used on
 #![no_mangle]
 #![no_link]
 //~^ ERROR: attribute should be applied to an `extern crate` item
 #![export_name = "2200"]
-//~^ ERROR: attribute should be applied to a free function, impl method or static
+//~^ ERROR: attribute cannot be used on
 #![inline]
-//~^ ERROR: attribute should be applied to function or closure
+//~^ ERROR: attribute cannot be used on
 #[inline]
-//~^ ERROR attribute should be applied to function or closure
+//~^ ERROR attribute cannot be used on
 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
-    //~| NOTE not a function or closure
+    //~^ ERROR attribute cannot be used on
 
     #[inline = "2100"] fn f() { }
     //~^ ERROR valid forms for the attribute are
@@ -50,16 +44,13 @@ mod inline {
     //~| NOTE for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
     #[inline] struct S;
-    //~^ ERROR attribute should be applied to function or closure
-    //~| NOTE not a function or closure
+    //~^ ERROR attribute cannot be used on
 
     #[inline] type T = S;
-    //~^ ERROR attribute should be applied to function or closure
-    //~| NOTE not a function or closure
+    //~^ ERROR attribute cannot be used on
 
     #[inline] impl S { }
-    //~^ ERROR attribute should be applied to function or closure
-    //~| NOTE not a function or closure
+    //~^ ERROR attribute cannot be used on
 }
 
 #[no_link]
@@ -89,36 +80,27 @@ mod no_link {
 }
 
 #[export_name = "2200"]
-//~^ ERROR attribute should be applied to a free function, impl method or static
+//~^ ERROR attribute cannot be used on
 mod export_name {
-    //~^ NOTE not a free function, impl method or static
-
     mod inner { #![export_name="2200"] }
-    //~^ ERROR attribute should be applied to a free function, impl method or static
-    //~| NOTE not a free function, impl method or static
+    //~^ ERROR attribute cannot be used on
 
     #[export_name = "2200"] fn f() { }
 
     #[export_name = "2200"] struct S;
-    //~^ ERROR attribute should be applied to a free function, impl method or static
-    //~| NOTE not a free function, impl method or static
+    //~^ ERROR attribute cannot be used on
 
     #[export_name = "2200"] type T = S;
-    //~^ ERROR attribute should be applied to a free function, impl method or static
-    //~| NOTE not a free function, impl method or static
+    //~^ ERROR attribute cannot be used on
 
     #[export_name = "2200"] impl S { }
-    //~^ ERROR attribute should be applied to a free function, impl method or static
-    //~| NOTE not a free function, impl method or static
+    //~^ ERROR attribute cannot be used on
 
     trait Tr {
         #[export_name = "2200"] fn foo();
-        //~^ ERROR attribute should be applied to a free function, impl method or static
-        //~| NOTE not a free function, impl method or static
+        //~^ ERROR attribute cannot be used on
 
         #[export_name = "2200"] fn bar() {}
-        //~^ ERROR attribute should be applied to a free function, impl method or static
-        //~| NOTE not a free function, impl method or static
     }
 }
 
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 7550e26f4a7..13dce72a882 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
@@ -1,5 +1,5 @@
 error[E0658]: use of an internal attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
    |
 LL | #![rustc_main]
    | ^^^^^^^^^^^^^^
@@ -8,19 +8,128 @@ 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[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1
+error: `#[path]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1
    |
-LL |   #[inline]
-   |   ^^^^^^^^^
-LL |
-LL | / mod inline {
-...  |
-LL | | }
-   | |_- not a function or closure
+LL | #![path = "3800"]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[path]` can only be applied to modules
+
+error: `#[automatically_derived]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1
+   |
+LL | #![automatically_derived]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+error: `#[export_name]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1
+   |
+LL | #![export_name = "2200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to functions, statics
+
+error: `#[inline]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1
+   |
+LL | #![inline]
+   | ^^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[inline]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1
+   |
+LL | #[inline]
+   | ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[inline]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:37:17
+   |
+LL |     mod inner { #![inline] }
+   |                 ^^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[inline]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
+   |
+LL |     #[inline] struct S;
+   |     ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[inline]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:49:5
+   |
+LL |     #[inline] type T = S;
+   |     ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[inline]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:52:5
+   |
+LL |     #[inline] impl S { }
+   |     ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[export_name]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:82:1
+   |
+LL | #[export_name = "2200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to functions, statics
+
+error: `#[export_name]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:17
+   |
+LL |     mod inner { #![export_name="2200"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to functions, statics
+
+error: `#[export_name]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:5
+   |
+LL |     #[export_name = "2200"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to functions, statics
+
+error: `#[export_name]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:93:5
+   |
+LL |     #[export_name = "2200"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to functions, statics
+
+error: `#[export_name]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5
+   |
+LL |     #[export_name = "2200"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to functions, statics
+
+error: `#[export_name]` attribute cannot be used on required trait methods
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:9
+   |
+LL |         #[export_name = "2200"] fn foo();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[export_name]` can be applied to statics, functions, inherent methods, provided trait methods, trait methods in impl blocks
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:56:1
    |
 LL |   #[no_link]
    |   ^^^^^^^^^^
@@ -33,22 +142,8 @@ LL | |     mod inner { #![no_link] }
 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:91:1
-   |
-LL |   #[export_name = "2200"]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / mod export_name {
-LL | |
-LL | |
-LL | |     mod inner { #![export_name="2200"] }
-...  |
-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:125:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:107:8
    |
 LL |   #[repr(C)]
    |          ^
@@ -61,7 +156,7 @@ LL | | }
    | |_- 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:149:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131:8
    |
 LL |   #[repr(Rust)]
    |          ^^^^
@@ -74,25 +169,13 @@ LL | | }
    | |_- not a struct, enum, or union
 
 error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:24:1
    |
 LL | #![no_link]
    | ^^^^^^^^^^^ 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:28:1
-   |
-LL | #![export_name = "2200"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static
-
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1
-   |
-LL | #![inline]
-   | ^^^^^^^^^^ not a function or closure
-
 error: `macro_export` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:10:1
    |
 LL | #![macro_export]
    | ^^^^^^^^^^^^^^^^
@@ -107,7 +190,7 @@ LL + #[macro_export]
    |
 
 error: `rustc_main` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
    |
 LL | #![rustc_main]
    | ^^^^^^^^^^^^^^
@@ -122,7 +205,7 @@ LL + #[rustc_main]
    |
 
 error: `repr` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1
    |
 LL | #![repr()]
    | ^^^^^^^^^^
@@ -136,176 +219,86 @@ LL - #![repr()]
 LL + #[repr()]
    |
 
-error: `path` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1
-   |
-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"]
-   |
-
-error: `automatically_derived` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1
-   |
-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]
-   |
-
-error[E0518]: attribute should be applied to function or closure
-  --> $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: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: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: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:70:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:61: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:74:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65: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:78:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:69: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:82:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:73: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:86:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:77: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: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: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: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: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: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: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:129:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:111: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:133:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:115: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:139:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:121: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:143:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:125:12
    |
 LL |     #[repr(C)] impl 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:153:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:135:25
    |
 LL |     mod inner { #![repr(Rust)] }
    |     --------------------^^^^---- 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:157:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:12
    |
 LL |     #[repr(Rust)] 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:163:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12
    |
 LL |     #[repr(Rust)] 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:167:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:149:12
    |
 LL |     #[repr(Rust)] impl S { }
    |            ^^^^   ---------- not a struct, enum, or union
 
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5
    |
 LL |     #[inline = "2100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
@@ -314,13 +307,13 @@ LL |     #[inline = "2100"] fn f() { }
    = 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
+error: aborting due to 37 previous errors
 
-Some errors have detailed explanations: E0517, E0518, E0658.
+Some errors have detailed explanations: E0517, E0658.
 For more information about an error, try `rustc --explain E0517`.
 Future incompatibility report: Future breakage diagnostic:
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5
    |
 LL |     #[inline = "2100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index c91fd600068..8702d852a89 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -1,7 +1,4 @@
-//~ NOTE not a function
-//~| NOTE not a foreign function or static
-//~| NOTE cannot be applied to crates
-//~| NOTE not an `extern` block
+//~ NOTE not an `extern` block
 // This test enumerates as many compiler-builtin ungated attributes as
 // possible (that is, all the mutually compatible ones), and checks
 // that we get "expected" (*) warnings for each in the various weird
@@ -50,25 +47,34 @@
 #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs)
 // skipping testing of cfg
 // skipping testing of cfg_attr
-#![should_panic] //~ WARN `#[should_panic]` only has an effect
-#![ignore] //~ WARN `#[ignore]` only has an effect on functions
+#![should_panic] //~ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
+#![ignore] //~ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 #![no_implicit_prelude]
 #![reexport_test_harness_main = "2900"]
 // see gated-link-args.rs
 // see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700"
 // (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600")
-#![proc_macro_derive(Test)] //~ WARN `#[proc_macro_derive]` only has an effect
+#![proc_macro_derive(Test)] //~ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 #![doc = "2400"]
-#![cold] //~ WARN attribute should be applied to a function
-//~^ WARN this was previously accepted
+#![cold] //~ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 #![link()] //~ WARN attribute should be applied to an `extern` block
 //~^ WARN this was previously accepted
 #![link_name = "1900"]
-//~^ WARN attribute should be applied to a foreign function
-//~^^ WARN this was previously accepted by the compiler
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 #![link_section = "1800"]
-//~^ WARN attribute should be applied to a function or static
-//~^^ WARN this was previously accepted by the compiler
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 #![must_use]
 //~^ WARN `#[must_use]` has no effect
 //~| HELP remove the attribute
@@ -175,16 +181,24 @@ mod macro_use {
     mod inner { #![macro_use] }
 
     #[macro_use] fn f() { }
-    //~^ WARN `#[macro_use]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[macro_use] struct S;
-    //~^ WARN `#[macro_use]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[macro_use] type T = S;
-    //~^ WARN `#[macro_use]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[macro_use] impl S { }
-    //~^ WARN `#[macro_use]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 }
 
 #[macro_export]
@@ -243,116 +257,158 @@ mod path {
     mod inner { #![path="3800"] }
 
     #[path = "3800"] fn f() { }
-    //~^ WARN `#[path]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[path = "3800"]  struct S;
-    //~^ WARN `#[path]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[path = "3800"] type T = S;
-    //~^ WARN `#[path]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[path = "3800"] impl S { }
-    //~^ WARN `#[path]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 }
 
 #[automatically_derived]
-//~^ WARN `#[automatically_derived]` only has an effect
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 mod automatically_derived {
     mod inner { #![automatically_derived] }
-    //~^ WARN `#[automatically_derived]
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[automatically_derived] fn f() { }
-    //~^ WARN `#[automatically_derived]
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[automatically_derived] struct S;
-    //~^ WARN `#[automatically_derived]
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[automatically_derived] type T = S;
-    //~^ WARN `#[automatically_derived]
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[automatically_derived] trait W { }
-    //~^ WARN `#[automatically_derived]
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[automatically_derived] impl S { }
-    //~^ WARN `#[automatically_derived]
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[automatically_derived] impl W for S { }
 }
 
 #[no_mangle]
-//~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 mod no_mangle {
-    //~^ NOTE not a free function, impl method or static
     mod inner { #![no_mangle] }
-    //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a free function, impl method or static
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[no_mangle] fn f() { }
 
     #[no_mangle] struct S;
-    //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a free function, impl method or static
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[no_mangle] type T = S;
-    //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a free function, impl method or static
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[no_mangle] impl S { }
-    //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a free function, impl method or static
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     trait Tr {
         #[no_mangle] fn foo();
-        //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-        //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-        //~| NOTE not a free function, impl method or static
+        //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+        //~| HELP can be applied to
 
         #[no_mangle] fn bar() {}
-        //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes]
-        //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-        //~| NOTE not a free function, impl method or static
+        //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+        //~| HELP can be applied to
     }
 }
 
 #[should_panic]
-//~^ WARN `#[should_panic]` only has an effect on
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 mod should_panic {
     mod inner { #![should_panic] }
-    //~^ WARN `#[should_panic]` only has an effect on
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[should_panic] fn f() { }
 
     #[should_panic] struct S;
-    //~^ WARN `#[should_panic]` only has an effect on
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[should_panic] type T = S;
-    //~^ WARN `#[should_panic]` only has an effect on
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[should_panic] impl S { }
-    //~^ WARN `#[should_panic]` only has an effect on
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 }
 
 #[ignore]
-//~^ WARN `#[ignore]` only has an effect on functions
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 mod ignore {
     mod inner { #![ignore] }
-    //~^ WARN `#[ignore]` only has an effect on functions
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[ignore] fn f() { }
 
     #[ignore] struct S;
-    //~^ WARN `#[ignore]` only has an effect on functions
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[ignore] type T = S;
-    //~^ WARN `#[ignore]` only has an effect on functions
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[ignore] impl S { }
-    //~^ WARN `#[ignore]` only has an effect on functions
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can only be applied to
 }
 
 #[no_implicit_prelude]
@@ -360,16 +416,24 @@ mod no_implicit_prelude {
     mod inner { #![no_implicit_prelude] }
 
     #[no_implicit_prelude] fn f() { }
-    //~^ WARN `#[no_implicit_prelude]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[no_implicit_prelude] struct S;
-    //~^ WARN `#[no_implicit_prelude]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[no_implicit_prelude] type T = S;
-    //~^ WARN `#[no_implicit_prelude]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[no_implicit_prelude] impl S { }
-    //~^ WARN `#[no_implicit_prelude]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 }
 
 #[reexport_test_harness_main = "2900"]
@@ -400,16 +464,24 @@ mod macro_escape {
     //~| HELP try an outer attribute: `#[macro_use]`
 
     #[macro_escape] fn f() { }
-    //~^ WARN `#[macro_escape]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[macro_escape] struct S;
-    //~^ WARN `#[macro_escape]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[macro_escape] type T = S;
-    //~^ WARN `#[macro_escape]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[macro_escape] impl S { }
-    //~^ WARN `#[macro_escape]` only has an effect
+    //~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+    //~| HELP can be applied to
 }
 
 #[no_std]
@@ -449,100 +521,97 @@ mod doc {
 }
 
 #[cold]
-//~^ WARN attribute should be applied to a function
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can only be applied to
 mod cold {
-    //~^ NOTE not a function
 
     mod inner { #![cold] }
-    //~^ WARN attribute should be applied to a function
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[cold] fn f() { }
 
     #[cold] struct S;
-    //~^ WARN attribute should be applied to a function
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[cold] type T = S;
-    //~^ WARN attribute should be applied to a function
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 
     #[cold] impl S { }
-    //~^ WARN attribute should be applied to a function
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can only be applied to
 }
 
 #[link_name = "1900"]
-//~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 mod link_name {
-    //~^ NOTE not a foreign function or static
-
     #[link_name = "1900"]
-    //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| HELP try `#[link(name = "1900")]` instead
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
     extern "C" { }
-    //~^ NOTE not a foreign function or static
 
     mod inner { #![link_name="1900"] }
-    //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a foreign function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_name = "1900"] fn f() { }
-    //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a foreign function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_name = "1900"] struct S;
-    //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a foreign function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_name = "1900"] type T = S;
-    //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a foreign function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_name = "1900"] impl S { }
-    //~^ WARN attribute should be applied to a foreign function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a foreign function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 }
 
 #[link_section = "1800"]
-//~^ WARN attribute should be applied to a function or static [unused_attributes]
-//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~^ WARN attribute cannot be used on
+//~| WARN previously accepted
+//~| HELP can be applied to
 mod link_section {
-    //~^ NOTE not a function or static
-
     mod inner { #![link_section="1800"] }
-    //~^ WARN attribute should be applied to a function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_section = "1800"] fn f() { }
 
     #[link_section = "1800"] struct S;
-    //~^ WARN attribute should be applied to a function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_section = "1800"] type T = S;
-    //~^ WARN attribute should be applied to a function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 
     #[link_section = "1800"] impl S { }
-    //~^ WARN attribute should be applied to a function or static [unused_attributes]
-    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    //~| NOTE not a function or static
+    //~^ WARN attribute cannot be used on
+    //~| WARN previously accepted
+    //~| HELP can be applied to
 }
 
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index e0ea5382faa..8e2bffb91ca 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,5 +1,5 @@
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -7,292 +7,211 @@ LL |     mod inner { #![macro_escape] }
    = help: try an outer attribute: `#[macro_use]`
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:459:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:43:9
    |
 LL | #![warn(x5400)]
    |         ^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:28
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:37:28
    |
 LL | #![warn(unused_attributes, unknown_lints)]
    |                            ^^^^^^^^^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:10
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:10
    |
 LL | #![allow(x5300)]
    |          ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:48:11
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:11
    |
 LL | #![forbid(x5200)]
    |           ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:9
    |
 LL | #![deny(x5100)]
    |         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:97:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:103:8
    |
 LL | #[warn(x5400)]
    |        ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:100:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:106:25
    |
 LL |     mod inner { #![warn(x5400)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:103:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:109:12
    |
 LL |     #[warn(x5400)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:106:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:12
    |
 LL |     #[warn(x5400)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:109:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:12
    |
 LL |     #[warn(x5400)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:12
    |
 LL |     #[warn(x5400)] impl S { }
    |            ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:9
    |
 LL | #[allow(x5300)]
    |         ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:26
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:26
    |
 LL |     mod inner { #![allow(x5300)] }
    |                          ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:13
    |
 LL |     #[allow(x5300)] fn f() { }
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:131:13
    |
 LL |     #[allow(x5300)] struct S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:13
    |
 LL |     #[allow(x5300)] type T = S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:131:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:13
    |
 LL |     #[allow(x5300)] impl S { }
    |             ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:10
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:10
    |
 LL | #[forbid(x5200)]
    |          ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:27
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:27
    |
 LL |     mod inner { #![forbid(x5200)] }
    |                           ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:14
    |
 LL |     #[forbid(x5200)] fn f() { }
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:150:14
    |
 LL |     #[forbid(x5200)] struct S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:14
    |
 LL |     #[forbid(x5200)] type T = S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:150:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:14
    |
 LL |     #[forbid(x5200)] impl S { }
    |              ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:8
    |
 LL | #[deny(x5100)]
    |        ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:25
    |
 LL |     mod inner { #![deny(x5100)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:12
    |
 LL |     #[deny(x5100)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:169:12
    |
 LL |     #[deny(x5100)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:172:12
    |
 LL |     #[deny(x5100)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:169:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:175:12
    |
 LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:1
    |
 LL | #[macro_export]
    | ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:37:9
    |
 LL | #![warn(unused_attributes, unknown_lints)]
    |         ^^^^^^^^^^^^^^^^^
 
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:1
-   |
-LL | #[automatically_derived]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:282:1
-   |
-LL |   #[no_mangle]
-   |   ^^^^^^^^^^^^
-...
-LL | / mod no_mangle {
-LL | |
-LL | |     mod inner { #![no_mangle] }
-...  |
-LL | | }
-   | |_- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:322:1
-   |
-LL | #[should_panic]
-   | ^^^^^^^^^^^^^^^
-
-warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:340:1
-   |
-LL | #[ignore]
-   | ^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:375:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:415:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:1
    |
 LL | #[no_std]
    | ^^^^^^^^^
 
-warning: attribute should be applied to a function definition
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:1
-   |
-LL |   #[cold]
-   |   ^^^^^^^
-...
-LL | / mod cold {
-LL | |
-LL | |
-LL | |     mod inner { #![cold] }
-...  |
-LL | | }
-   | |_- not a function definition
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:1
-   |
-LL |   #[link_name = "1900"]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-...
-LL | / mod link_name {
-LL | |
-LL | |
-LL | |     #[link_name = "1900"]
-...  |
-LL | | }
-   | |_- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:1
-   |
-LL |   #[link_section = "1800"]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | / mod link_section {
-LL | |
-LL | |
-LL | |     mod inner { #![link_section="1800"] }
-...  |
-LL | | }
-   | |_- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:1
    |
 LL |   #[link()]
    |   ^^^^^^^^^
@@ -307,564 +226,174 @@ LL | | }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:602:1
+warning: `#[must_use]` has no effect when applied to modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:619:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
    |
 LL | #[windows_subsystem = "windows"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:640:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:698:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:1
    |
 LL | #[no_builtins]
    | ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:824:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
    |
 LL | #![link()]
    | ^^^^^^^^^^ not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1
-   |
-LL | #![ignore]
-   | ^^^^^^^^^^
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
-   |
-LL | #![link_name = "1900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
-   |
-LL | #![link_section = "1800"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
+warning: `#[must_use]` has no effect when applied to modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1
    |
 LL | #![must_use]
    | ^^^^^^^^^^^^
 
-warning: `#[proc_macro_derive]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
-   |
-LL | #![proc_macro_derive(Test)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
-   |
-LL | #![should_panic]
-   | ^^^^^^^^^^^^^^^^
-
-warning: attribute should be applied to a function definition
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
-   |
-LL | #![cold]
-   | ^^^^^^^^ cannot be applied to crates
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
 warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:86:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:92:12
    |
 LL | #![feature(rust1)]
    |            ^^^^^
    |
    = note: `#[warn(stable_features)]` on by default
 
-warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:5
-   |
-LL |     #[macro_use] fn f() { }
-   |     ^^^^^^^^^^^^
-
-warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:5
-   |
-LL |     #[macro_use] struct S;
-   |     ^^^^^^^^^^^^
-
-warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:5
-   |
-LL |     #[macro_use] type T = S;
-   |     ^^^^^^^^^^^^
-
-warning: `#[macro_use]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:5
-   |
-LL |     #[macro_use] impl S { }
-   |     ^^^^^^^^^^^^
-
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:17
    |
 LL |     mod inner { #![macro_export] }
    |                 ^^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5
    |
 LL |     #[macro_export] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
    |
 LL |     #[macro_export] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5
    |
 LL |     #[macro_export] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: `#[macro_export]` only has an effect on macro definitions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5
    |
 LL |     #[macro_export] impl S { }
    |     ^^^^^^^^^^^^^^^
 
-warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:5
-   |
-LL |     #[path = "3800"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^
-
-warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:5
-   |
-LL |     #[path = "3800"]  struct S;
-   |     ^^^^^^^^^^^^^^^^
-
-warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:251:5
-   |
-LL |     #[path = "3800"] type T = S;
-   |     ^^^^^^^^^^^^^^^^
-
-warning: `#[path]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:254:5
-   |
-LL |     #[path = "3800"] impl S { }
-   |     ^^^^^^^^^^^^^^^^
-
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:261:17
-   |
-LL |     mod inner { #![automatically_derived] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:264:5
-   |
-LL |     #[automatically_derived] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:267:5
-   |
-LL |     #[automatically_derived] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:5
-   |
-LL |     #[automatically_derived] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5
-   |
-LL |     #[automatically_derived] trait W { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[automatically_derived]` only has an effect on trait implementation blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5
-   |
-LL |     #[automatically_derived] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:287:17
-   |
-LL |     mod inner { #![no_mangle] }
-   |     ------------^^^^^^^^^^^^^-- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:5
-   |
-LL |     #[no_mangle] struct S;
-   |     ^^^^^^^^^^^^ --------- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:299:5
-   |
-LL |     #[no_mangle] type T = S;
-   |     ^^^^^^^^^^^^ ----------- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:304:5
-   |
-LL |     #[no_mangle] impl S { }
-   |     ^^^^^^^^^^^^ ---------- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:9
-   |
-LL |         #[no_mangle] fn foo();
-   |         ^^^^^^^^^^^^ --------- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:315:9
-   |
-LL |         #[no_mangle] fn bar() {}
-   |         ^^^^^^^^^^^^ ----------- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:17
-   |
-LL |     mod inner { #![should_panic] }
-   |                 ^^^^^^^^^^^^^^^^
-
-warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:5
-   |
-LL |     #[should_panic] struct S;
-   |     ^^^^^^^^^^^^^^^
-
-warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:5
-   |
-LL |     #[should_panic] type T = S;
-   |     ^^^^^^^^^^^^^^^
-
-warning: `#[should_panic]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5
-   |
-LL |     #[should_panic] impl S { }
-   |     ^^^^^^^^^^^^^^^
-
-warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:343:17
-   |
-LL |     mod inner { #![ignore] }
-   |                 ^^^^^^^^^^
-
-warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:348:5
-   |
-LL |     #[ignore] struct S;
-   |     ^^^^^^^^^
-
-warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:5
-   |
-LL |     #[ignore] type T = S;
-   |     ^^^^^^^^^
-
-warning: `#[ignore]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:5
-   |
-LL |     #[ignore] impl S { }
-   |     ^^^^^^^^^
-
-warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:362:5
-   |
-LL |     #[no_implicit_prelude] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:5
-   |
-LL |     #[no_implicit_prelude] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:5
-   |
-LL |     #[no_implicit_prelude] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: `#[no_implicit_prelude]` only has an effect on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
-   |
-LL |     #[no_implicit_prelude] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:378:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:381:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:5
-   |
-LL |     #[macro_escape] fn f() { }
-   |     ^^^^^^^^^^^^^^^
-
-warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:5
-   |
-LL |     #[macro_escape] struct S;
-   |     ^^^^^^^^^^^^^^^
-
-warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5
-   |
-LL |     #[macro_escape] type T = S;
-   |     ^^^^^^^^^^^^^^^
-
-warning: `#[macro_escape]` only has an effect on `extern crate` and modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5
-   |
-LL |     #[macro_escape] impl S { }
-   |     ^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:17
    |
 LL |     mod inner { #![no_std] }
    |                 ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
 
-warning: attribute should be applied to a function definition
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:17
-   |
-LL |     mod inner { #![cold] }
-   |     ------------^^^^^^^^-- not a function definition
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function definition
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
-   |
-LL |     #[cold] struct S;
-   |     ^^^^^^^ --------- not a function definition
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function definition
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5
-   |
-LL |     #[cold] type T = S;
-   |     ^^^^^^^ ----------- not a function definition
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function definition
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:5
-   |
-LL |     #[cold] impl S { }
-   |     ^^^^^^^ ---------- not a function definition
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
-   |
-LL |     #[link_name = "1900"]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     extern "C" { }
-   |     -------------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-help: try `#[link(name = "1900")]` instead
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
-   |
-LL |     #[link_name = "1900"]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:17
-   |
-LL |     mod inner { #![link_name="1900"] }
-   |     ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:498:5
-   |
-LL |     #[link_name = "1900"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:5
-   |
-LL |     #[link_name = "1900"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
-   |
-LL |     #[link_name = "1900"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:5
-   |
-LL |     #[link_name = "1900"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:17
-   |
-LL |     mod inner { #![link_section="1800"] }
-   |     ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5
-   |
-LL |     #[link_section = "1800"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:537:5
-   |
-LL |     #[link_section = "1800"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:542:5
-   |
-LL |     #[link_section = "1800"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:557:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:17
    |
 LL |     mod inner { #![link()] }
    |     ------------^^^^^^^^^^-- not an `extern` block
@@ -872,7 +401,7 @@ LL |     mod inner { #![link()] }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:562:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:5
    |
 LL |     #[link()] fn f() { }
    |     ^^^^^^^^^ ---------- not an `extern` block
@@ -880,7 +409,7 @@ LL |     #[link()] 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!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5
    |
 LL |     #[link()] struct S;
    |     ^^^^^^^^^ --------- not an `extern` block
@@ -888,7 +417,7 @@ LL |     #[link()] struct S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:572:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5
    |
 LL |     #[link()] type T = S;
    |     ^^^^^^^^^ ----------- not an `extern` block
@@ -896,7 +425,7 @@ LL |     #[link()] type T = S;
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:577:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
    |
 LL |     #[link()] impl S { }
    |     ^^^^^^^^^ ---------- not an `extern` block
@@ -904,270 +433,837 @@ LL |     #[link()] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:582:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
    |
 LL |     #[link()] extern "Rust" {}
    |     ^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:17
+warning: `#[must_use]` has no effect when applied to modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:17
    |
 LL |     mod inner { #![must_use] }
    |                 ^^^^^^^^^^^^
 
-warning: `#[must_use]` has no effect when applied to a type alias
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:612:5
+warning: `#[must_use]` has no effect when applied to type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:5
    |
 LL |     #[must_use] type T = S;
    |     ^^^^^^^^^^^
 
-warning: `#[must_use]` has no effect when applied to an inherent implementation block
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:5
+warning: `#[must_use]` has no effect when applied to inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5
    |
 LL |     #[must_use] impl S { }
    |     ^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:622:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17
    |
 LL |     mod inner { #![windows_subsystem="windows"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:625:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:5
    |
 LL |     #[windows_subsystem = "windows"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:628:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5
    |
 LL |     #[windows_subsystem = "windows"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
    |
 LL |     #[windows_subsystem = "windows"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5
    |
 LL |     #[windows_subsystem = "windows"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:662:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:17
    |
 LL |     mod inner { #![no_builtins] }
    |                 ^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:792:5
    |
 LL |     #[no_builtins] fn f() { }
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
    |
 LL |     #[no_builtins] struct S;
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:5
    |
 LL |     #[no_builtins] type T = S;
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5
    |
 LL |     #[no_builtins] impl S { }
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:820:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+warning: `#[macro_use]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:5
+   |
+LL |     #[macro_use] 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!
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
+
+warning: `#[macro_use]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:188:5
+   |
+LL |     #[macro_use] struct S;
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
+
+warning: `#[macro_use]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:5
+   |
+LL |     #[macro_use] type T = S;
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
+
+warning: `#[macro_use]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5
+   |
+LL |     #[macro_use] impl S { }
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
+
+warning: `#[path]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5
+   |
+LL |     #[path = "3800"] 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!
+   = help: `#[path]` can only be applied to modules
+
+warning: `#[path]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:264:5
+   |
+LL |     #[path = "3800"]  struct S;
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[path]` can only be applied to modules
+
+warning: `#[path]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:5
+   |
+LL |     #[path = "3800"] type T = S;
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[path]` can only be applied to modules
+
+warning: `#[path]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
+   |
+LL |     #[path = "3800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[path]` can only be applied to modules
+
+warning: `#[automatically_derived]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1
+   |
+LL | #[automatically_derived]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[automatically_derived]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:285:17
+   |
+LL |     mod inner { #![automatically_derived] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[automatically_derived]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:290:5
+   |
+LL |     #[automatically_derived] 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!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[automatically_derived]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5
+   |
+LL |     #[automatically_derived] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[automatically_derived]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:300:5
+   |
+LL |     #[automatically_derived] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[automatically_derived]` attribute cannot be used on traits
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:305:5
+   |
+LL |     #[automatically_derived] trait W { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[automatically_derived]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:5
+   |
+LL |     #[automatically_derived] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[no_mangle]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:1
+   |
+LL | #[no_mangle]
+   | ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics
+
+warning: `#[no_mangle]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:17
+   |
+LL |     mod inner { #![no_mangle] }
+   |                 ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics
+
+warning: `#[no_mangle]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:5
+   |
+LL |     #[no_mangle] struct S;
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics
+
+warning: `#[no_mangle]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5
+   |
+LL |     #[no_mangle] type T = S;
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics
+
+warning: `#[no_mangle]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:340:5
+   |
+LL |     #[no_mangle] impl S { }
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics
+
+warning: `#[no_mangle]` attribute cannot be used on required trait methods
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:346:9
+   |
+LL |         #[no_mangle] fn foo();
+   |         ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics, inherent methods, trait methods in impl blocks
+
+warning: `#[no_mangle]` attribute cannot be used on provided trait methods
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:9
+   |
+LL |         #[no_mangle] fn bar() {}
+   |         ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions, statics, inherent methods, trait methods in impl blocks
+
+warning: `#[should_panic]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:1
+   |
+LL | #[should_panic]
+   | ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: `#[should_panic]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:17
+   |
+LL |     mod inner { #![should_panic] }
+   |                 ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: `#[should_panic]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5
+   |
+LL |     #[should_panic] struct S;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: `#[should_panic]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:375:5
+   |
+LL |     #[should_panic] type T = S;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: `#[should_panic]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
+   |
+LL |     #[should_panic] impl S { }
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: `#[ignore]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:1
+   |
+LL | #[ignore]
+   | ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[ignore]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:17
+   |
+LL |     mod inner { #![ignore] }
+   |                 ^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[ignore]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5
+   |
+LL |     #[ignore] struct S;
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[ignore]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5
+   |
+LL |     #[ignore] type T = S;
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[ignore]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5
+   |
+LL |     #[ignore] impl S { }
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[no_implicit_prelude]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5
+   |
+LL |     #[no_implicit_prelude] 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!
+   = help: `#[no_implicit_prelude]` can be applied to modules, crates
+
+warning: `#[no_implicit_prelude]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
+   |
+LL |     #[no_implicit_prelude] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_implicit_prelude]` can be applied to modules, crates
+
+warning: `#[no_implicit_prelude]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428:5
+   |
+LL |     #[no_implicit_prelude] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_implicit_prelude]` can be applied to modules, crates
+
+warning: `#[no_implicit_prelude]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5
+   |
+LL |     #[no_implicit_prelude] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_implicit_prelude]` can be applied to modules, crates
+
+warning: `#[macro_escape]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5
+   |
+LL |     #[macro_escape] 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!
+   = help: `#[macro_escape]` can be applied to modules, extern crates, crates
+
+warning: `#[macro_escape]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:5
+   |
+LL |     #[macro_escape] struct S;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_escape]` can be applied to modules, extern crates, crates
+
+warning: `#[macro_escape]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5
+   |
+LL |     #[macro_escape] type T = S;
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_escape]` can be applied to modules, extern crates, crates
+
+warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:5
+   |
+LL |     #[macro_escape] impl S { }
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_escape]` can be applied to modules, extern crates, crates
+
+warning: `#[cold]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:1
+   |
+LL | #[cold]
+   | ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:529:17
+   |
+LL |     mod inner { #![cold] }
+   |                 ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:5
+   |
+LL |     #[cold] struct S;
+   |     ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+   |
+LL |     #[cold] type T = S;
+   |     ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:546:5
+   |
+LL |     #[cold] impl S { }
+   |     ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[link_name]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:1
+   |
+LL | #[link_name = "1900"]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on foreign modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:557:5
+   |
+LL |     #[link_name = "1900"]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:17
+   |
+LL |     mod inner { #![link_name="1900"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:568:5
+   |
+LL |     #[link_name = "1900"] 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!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:573:5
+   |
+LL |     #[link_name = "1900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:578:5
+   |
+LL |     #[link_name = "1900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_name]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:583:5
+   |
+LL |     #[link_name = "1900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_section]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:589:1
+   |
+LL | #[link_section = "1800"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics, functions
+
+warning: `#[link_section]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:594:17
+   |
+LL |     mod inner { #![link_section="1800"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics, functions
+
+warning: `#[link_section]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:601:5
+   |
+LL |     #[link_section = "1800"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics, functions
+
+warning: `#[link_section]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:606:5
+   |
+LL |     #[link_section = "1800"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics, functions
+
+warning: `#[link_section]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
+   |
+LL |     #[link_section = "1800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics, functions
+
+warning: `#[should_panic]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1
+   |
+LL | #![should_panic]
+   | ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: `#[ignore]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
+   |
+LL | #![ignore]
+   | ^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[proc_macro_derive]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1
+   |
+LL | #![proc_macro_derive(Test)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[proc_macro_derive]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
+   |
+LL | #![cold]
+   | ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[link_name]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
+   |
+LL | #![link_name = "1900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions, foreign statics
+
+warning: `#[link_section]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:74:1
+   |
+LL | #![link_section = "1800"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics, functions
+
 warning: 173 warnings emitted
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
index 392880e1b3b..35392b4eff6 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
@@ -1,34 +1,29 @@
-// At time of authorship, #[proc_macro_derive = "2500"] will emit an
-// error when it occurs on a mod (apart from crate-level), but will
-// not descend further into the mod for other occurrences of the same
-// error.
-//
-// This file sits on its own because the "weird" occurrences here
+// This file sits on its own because the occurrences here
 // signal errors, making it incompatible with the "warnings only"
 // nature of issue-43106-gating-of-builtin-attrs.rs
 
 #[proc_macro_derive(Test)]
-//~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+//~^ ERROR attribute cannot be used on
 mod proc_macro_derive1 {
     mod inner { #![proc_macro_derive(Test)] }
-    // (no error issued here if there was one on outer module)
+    //~^ ERROR attribute cannot be used on
 }
 
 mod proc_macro_derive2 {
     mod inner { #![proc_macro_derive(Test)] }
-    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+    //~^ ERROR attribute cannot be used on
 
     #[proc_macro_derive(Test)] fn f() { }
     //~^ ERROR the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro`
 
     #[proc_macro_derive(Test)] struct S;
-    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+    //~^ ERROR attribute cannot be used on
 
     #[proc_macro_derive(Test)] type T = S;
-    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+    //~^ ERROR attribute cannot be used on
 
     #[proc_macro_derive(Test)] impl S { }
-    //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
+    //~^ ERROR attribute cannot be used on
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
index 537032d777f..753e3e2f21d 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
@@ -1,38 +1,56 @@
-error: the `#[proc_macro_derive]` attribute may only be used on bare functions
-  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:10:1
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:16:5
+   |
+LL |     #[proc_macro_derive(Test)] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[proc_macro_derive]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:5:1
    |
 LL | #[proc_macro_derive(Test)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
-error: the `#[proc_macro_derive]` attribute may only be used on bare functions
-  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:18:17
+error: `#[proc_macro_derive]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:8:17
    |
 LL |     mod inner { #![proc_macro_derive(Test)] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
-error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:21:5
+error: `#[proc_macro_derive]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:13:17
    |
-LL |     #[proc_macro_derive(Test)] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![proc_macro_derive(Test)] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
-error: the `#[proc_macro_derive]` attribute may only be used on bare functions
-  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:24:5
+error: `#[proc_macro_derive]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:19:5
    |
 LL |     #[proc_macro_derive(Test)] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
-error: the `#[proc_macro_derive]` attribute may only be used on bare functions
-  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:27:5
+error: `#[proc_macro_derive]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:22:5
    |
 LL |     #[proc_macro_derive(Test)] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
-error: the `#[proc_macro_derive]` attribute may only be used on bare functions
-  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:30:5
+error: `#[proc_macro_derive]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:25:5
    |
 LL |     #[proc_macro_derive(Test)] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/ffi-attrs/ffi_const.rs b/tests/ui/ffi-attrs/ffi_const.rs
index dddc862b0fa..caeaf8a25a9 100644
--- a/tests/ui/ffi-attrs/ffi_const.rs
+++ b/tests/ui/ffi-attrs/ffi_const.rs
@@ -1,16 +1,16 @@
 #![feature(ffi_const)]
 #![crate_type = "lib"]
 
-#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+#[unsafe(ffi_const)] //~ ERROR attribute cannot be used on
 pub fn foo() {}
 
-#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+#[unsafe(ffi_const)] //~ ERROR attribute cannot be used on
 macro_rules! bar {
     () => {};
 }
 
 extern "C" {
-    #[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+    #[unsafe(ffi_const)] //~ ERROR attribute cannot be used on
     static INT: i32;
 
     #[ffi_const] //~ ERROR unsafe attribute used without unsafe
diff --git a/tests/ui/ffi-attrs/ffi_const.stderr b/tests/ui/ffi-attrs/ffi_const.stderr
index 7f31237539d..f3be9254318 100644
--- a/tests/ui/ffi-attrs/ffi_const.stderr
+++ b/tests/ui/ffi-attrs/ffi_const.stderr
@@ -9,24 +9,29 @@ help: wrap the attribute in `unsafe(...)`
 LL |     #[unsafe(ffi_const)]
    |       +++++++         +
 
-error[E0756]: `#[ffi_const]` may only be used on foreign functions
+error: `#[ffi_const]` attribute cannot be used on functions
   --> $DIR/ffi_const.rs:4:1
    |
 LL | #[unsafe(ffi_const)]
    | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[ffi_const]` can only be applied to foreign functions
 
-error[E0756]: `#[ffi_const]` may only be used on foreign functions
+error: `#[ffi_const]` attribute cannot be used on macro defs
   --> $DIR/ffi_const.rs:7:1
    |
 LL | #[unsafe(ffi_const)]
    | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[ffi_const]` can only be applied to foreign functions
 
-error[E0756]: `#[ffi_const]` may only be used on foreign functions
+error: `#[ffi_const]` attribute cannot be used on foreign statics
   --> $DIR/ffi_const.rs:13:5
    |
 LL |     #[unsafe(ffi_const)]
    |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[ffi_const]` can only be applied to foreign functions
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0756`.
diff --git a/tests/ui/ffi-attrs/ffi_pure.rs b/tests/ui/ffi-attrs/ffi_pure.rs
index 1f4812f55cf..c56be793919 100644
--- a/tests/ui/ffi-attrs/ffi_pure.rs
+++ b/tests/ui/ffi-attrs/ffi_pure.rs
@@ -1,16 +1,16 @@
 #![feature(ffi_pure)]
 #![crate_type = "lib"]
 
-#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+#[unsafe(ffi_pure)] //~ ERROR attribute cannot be used on
 pub fn foo() {}
 
-#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+#[unsafe(ffi_pure)] //~ ERROR attribute cannot be used on
 macro_rules! bar {
     () => {};
 }
 
 extern "C" {
-    #[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+    #[unsafe(ffi_pure)] //~ ERROR attribute cannot be used on
     static INT: i32;
 
     #[ffi_pure] //~ ERROR unsafe attribute used without unsafe
diff --git a/tests/ui/ffi-attrs/ffi_pure.stderr b/tests/ui/ffi-attrs/ffi_pure.stderr
index bd1177c01e2..da1eae975ac 100644
--- a/tests/ui/ffi-attrs/ffi_pure.stderr
+++ b/tests/ui/ffi-attrs/ffi_pure.stderr
@@ -9,24 +9,29 @@ help: wrap the attribute in `unsafe(...)`
 LL |     #[unsafe(ffi_pure)]
    |       +++++++        +
 
-error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+error: `#[ffi_pure]` attribute cannot be used on functions
   --> $DIR/ffi_pure.rs:4:1
    |
 LL | #[unsafe(ffi_pure)]
    | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[ffi_pure]` can only be applied to foreign functions
 
-error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+error: `#[ffi_pure]` attribute cannot be used on macro defs
   --> $DIR/ffi_pure.rs:7:1
    |
 LL | #[unsafe(ffi_pure)]
    | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[ffi_pure]` can only be applied to foreign functions
 
-error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+error: `#[ffi_pure]` attribute cannot be used on foreign statics
   --> $DIR/ffi_pure.rs:13:5
    |
 LL |     #[unsafe(ffi_pure)]
    |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[ffi_pure]` can only be applied to foreign functions
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0755`.
diff --git a/tests/ui/force-inlining/invalid.rs b/tests/ui/force-inlining/invalid.rs
index e9f5712413e..6047739992f 100644
--- a/tests/ui/force-inlining/invalid.rs
+++ b/tests/ui/force-inlining/invalid.rs
@@ -28,110 +28,110 @@ pub fn forced4() {
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 extern crate std as other_std;
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 use std::collections::HashMap;
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 static _FOO: &'static str = "FOO";
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 const _BAR: u32 = 3;
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 mod foo { }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 unsafe extern "C" {
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     static X: &'static u32;
 
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     type Y;
 
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     fn foo();
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 type Foo = u32;
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 enum Bar<#[rustc_force_inline] T> {
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     Baz(std::marker::PhantomData<T>),
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 struct Qux {
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     field: u32,
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 union FooBar {
     x: u32,
     y: u32,
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 trait FooBaz {
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     type Foo;
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     const Bar: i32;
 
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     fn foo() {}
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 trait FooQux = FooBaz;
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 impl<T> Bar<T> {
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     fn foo() {}
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 impl<T> FooBaz for Bar<T> {
     type Foo = u32;
     const Bar: i32 = 3;
 }
 
 #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 macro_rules! barqux { ($foo:tt) => { $foo }; }
 
 fn barqux(#[rustc_force_inline] _x: u32) {}
 //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
-//~^^ ERROR attribute should be applied to a function
+//~^^ ERROR attribute cannot be used on
 
 #[rustc_force_inline]
 //~^ ERROR attribute cannot be applied to a `async`, `gen` or `async gen` function
@@ -147,16 +147,16 @@ async gen fn async_gen_foo() {}
 
 fn main() {
     let _x = #[rustc_force_inline] || { };
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     let _y = #[rustc_force_inline] 3 + 4;
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
     let _z = 3;
 
     match _z {
         #[rustc_force_inline]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
         1 => (),
         _ => (),
     }
diff --git a/tests/ui/force-inlining/invalid.stderr b/tests/ui/force-inlining/invalid.stderr
index 3b3da00ae88..299a3ed4a46 100644
--- a/tests/ui/force-inlining/invalid.stderr
+++ b/tests/ui/force-inlining/invalid.stderr
@@ -64,322 +64,272 @@ LL - #[rustc_force_inline = 2]
 LL + #[rustc_force_inline]
    |
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on extern crates
   --> $DIR/invalid.rs:30:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | extern crate std as other_std;
-   | ------------------------------ not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on use statements
   --> $DIR/invalid.rs:34:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | use std::collections::HashMap;
-   | ------------------------------ not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on statics
   --> $DIR/invalid.rs:38:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | static _FOO: &'static str = "FOO";
-   | ---------------------------------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on constants
   --> $DIR/invalid.rs:42:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | const _BAR: u32 = 3;
-   | -------------------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on modules
   --> $DIR/invalid.rs:46:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | mod foo { }
-   | ----------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on foreign modules
   --> $DIR/invalid.rs:50:1
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / unsafe extern "C" {
-LL | |     #[rustc_force_inline]
-LL | |
-LL | |     static X: &'static u32;
-...  |
-LL | |     fn foo();
-LL | | }
-   | |_- not a function definition
-
-error: attribute should be applied to a function
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on foreign statics
+  --> $DIR/invalid.rs:53:5
+   |
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on foreign types
+  --> $DIR/invalid.rs:57:5
+   |
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on foreign functions
+  --> $DIR/invalid.rs:61:5
+   |
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on type aliases
   --> $DIR/invalid.rs:66:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | type Foo = u32;
-   | --------------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on enums
   --> $DIR/invalid.rs:70:1
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / enum Bar<#[rustc_force_inline] T> {
-LL | |
-LL | |     #[rustc_force_inline]
-...  |
-LL | | }
-   | |_- not a function definition
-
-error: attribute should be applied to a function
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on function params
   --> $DIR/invalid.rs:72:10
    |
 LL | enum Bar<#[rustc_force_inline] T> {
-   |          ^^^^^^^^^^^^^^^^^^^^^ - not a function definition
+   |          ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on enum variants
   --> $DIR/invalid.rs:74:5
    |
 LL |     #[rustc_force_inline]
    |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     Baz(std::marker::PhantomData<T>),
-   |     -------------------------------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on structs
   --> $DIR/invalid.rs:79:1
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / struct Qux {
-LL | |     #[rustc_force_inline]
-LL | |
-LL | |     field: u32,
-LL | | }
-   | |_- not a function definition
-
-error: attribute should be applied to a function
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on struct fields
   --> $DIR/invalid.rs:82:5
    |
 LL |     #[rustc_force_inline]
    |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     field: u32,
-   |     ---------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on unions
   --> $DIR/invalid.rs:87:1
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / union FooBar {
-LL | |     x: u32,
-LL | |     y: u32,
-LL | | }
-   | |_- not a function definition
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on traits
   --> $DIR/invalid.rs:94:1
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / trait FooBaz {
-LL | |     #[rustc_force_inline]
-LL | |
-LL | |     type Foo;
-...  |
-LL | |     fn foo() {}
-LL | | }
-   | |_- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:109:1
-   |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | trait FooQux = FooBaz;
-   | ---------------------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:113:1
+error: `#[rustc_force_inline]` attribute cannot be used on associated types
+  --> $DIR/invalid.rs:97:5
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / impl<T> Bar<T> {
-LL | |     #[rustc_force_inline]
-LL | |
-LL | |     fn foo() {}
-LL | | }
-   | |_- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:121:1
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
-LL |   #[rustc_force_inline]
-   |   ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / impl<T> FooBaz for Bar<T> {
-LL | |     type Foo = u32;
-LL | |     const Bar: i32 = 3;
-LL | | }
-   | |_- not a function definition
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:128:1
+error: `#[rustc_force_inline]` attribute cannot be used on associated consts
+  --> $DIR/invalid.rs:100:5
+   |
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on provided trait methods
+  --> $DIR/invalid.rs:104:5
+   |
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on trait aliases
+  --> $DIR/invalid.rs:109:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | macro_rules! barqux { ($foo:tt) => { $foo }; }
-   | ---------------------------------------------- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:132:11
    |
-LL | fn barqux(#[rustc_force_inline] _x: u32) {}
-   |           ^^^^^^^^^^^^^^^^^^^^^--------
-   |           |
-   |           not a function definition
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute cannot be applied to a `async`, `gen` or `async gen` function
-  --> $DIR/invalid.rs:136:1
+error: `#[rustc_force_inline]` attribute cannot be used on inherent impl blocks
+  --> $DIR/invalid.rs:113:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | async fn async_foo() {}
-   | -------------------- `async`, `gen` or `async gen` function
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute cannot be applied to a `async`, `gen` or `async gen` function
-  --> $DIR/invalid.rs:140:1
+error: `#[rustc_force_inline]` attribute cannot be used on inherent methods
+  --> $DIR/invalid.rs:116:5
+   |
+LL |     #[rustc_force_inline]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on trait impl blocks
+  --> $DIR/invalid.rs:121:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | gen fn gen_foo() {}
-   | ---------------- `async`, `gen` or `async gen` function
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute cannot be applied to a `async`, `gen` or `async gen` function
-  --> $DIR/invalid.rs:144:1
+error: `#[rustc_force_inline]` attribute cannot be used on macro defs
+  --> $DIR/invalid.rs:128:1
    |
 LL | #[rustc_force_inline]
    | ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | async gen fn async_gen_foo() {}
-   | ---------------------------- `async`, `gen` or `async gen` function
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on function params
+  --> $DIR/invalid.rs:132:11
+   |
+LL | fn barqux(#[rustc_force_inline] _x: u32) {}
+   |           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
+
+error: `#[rustc_force_inline]` attribute cannot be used on closures
   --> $DIR/invalid.rs:149:14
    |
 LL |     let _x = #[rustc_force_inline] || { };
-   |              ^^^^^^^^^^^^^^^^^^^^^ ------ not a function definition
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on expressions
   --> $DIR/invalid.rs:151:14
    |
 LL |     let _y = #[rustc_force_inline] 3 + 4;
-   |              ^^^^^^^^^^^^^^^^^^^^^ - not a function definition
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on statements
   --> $DIR/invalid.rs:153:5
    |
 LL |     #[rustc_force_inline]
    |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     let _z = 3;
-   |     ----------- not a function definition
+   |
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
+error: `#[rustc_force_inline]` attribute cannot be used on match arms
   --> $DIR/invalid.rs:158:9
    |
 LL |         #[rustc_force_inline]
    |         ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |         1 => (),
-   |         ------- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:97:5
-   |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     type Foo;
-   |     --------- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:100:5
-   |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     const Bar: i32;
-   |     --------------- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:104:5
-   |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     fn foo() {}
-   |     ----------- not a function definition
-
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:116:5
    |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     fn foo() {}
-   |     ----------- not a function definition
+   = help: `#[rustc_force_inline]` can only be applied to functions
 
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:53:5
+error: attribute cannot be applied to a `async`, `gen` or `async gen` function
+  --> $DIR/invalid.rs:136:1
    |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
 LL |
-LL |     static X: &'static u32;
-   |     ----------------------- not a function definition
+LL | async fn async_foo() {}
+   | -------------------- `async`, `gen` or `async gen` function
 
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:57:5
+error: attribute cannot be applied to a `async`, `gen` or `async gen` function
+  --> $DIR/invalid.rs:140:1
    |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
 LL |
-LL |     type Y;
-   |     ------- not a function definition
+LL | gen fn gen_foo() {}
+   | ---------------- `async`, `gen` or `async gen` function
 
-error: attribute should be applied to a function
-  --> $DIR/invalid.rs:61:5
+error: attribute cannot be applied to a `async`, `gen` or `async gen` function
+  --> $DIR/invalid.rs:144:1
    |
-LL |     #[rustc_force_inline]
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_force_inline]
+   | ^^^^^^^^^^^^^^^^^^^^^
 LL |
-LL |     fn foo();
-   |     --------- not a function definition
+LL | async gen fn async_gen_foo() {}
+   | ---------------------------- `async`, `gen` or `async gen` function
 
 error: aborting due to 37 previous errors
 
diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
index 8b9ad78db37..6d5a22e4ced 100644
--- a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
+++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr
@@ -25,6 +25,14 @@ LL | #[rustc_layout_scalar_valid_range_end(a = "a")]
    | |                                     expected an integer literal here
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
 
+error: `#[rustc_layout_scalar_valid_range_end]` attribute cannot be used on enums
+  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1
+   |
+LL | #[rustc_layout_scalar_valid_range_end(1)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_layout_scalar_valid_range_end]` can only be applied to structs
+
 error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
   --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:18:1
    |
@@ -34,17 +42,6 @@ LL | #[rustc_layout_scalar_valid_range_start(rustc_layout_scalar_valid_range_sta
    | |                                       expected an integer literal here
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
 
-error: attribute should be applied to a struct
-  --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1
-   |
-LL |   #[rustc_layout_scalar_valid_range_end(1)]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL | / enum E {
-LL | |     X = 1,
-LL | |     Y = 14,
-LL | | }
-   | |_- not a struct
-
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0539, E0805.
diff --git a/tests/ui/issues/issue-31769.rs b/tests/ui/issues/issue-31769.rs
index f56c6ea5656..354c1be9ed5 100644
--- a/tests/ui/issues/issue-31769.rs
+++ b/tests/ui/issues/issue-31769.rs
@@ -1,4 +1,4 @@
 fn main() {
-    #[inline] struct Foo;  //~ ERROR attribute should be applied to function or closure
+    #[inline] struct Foo;  //~ ERROR attribute cannot be used on
     #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to a struct, enum, or union
 }
diff --git a/tests/ui/issues/issue-31769.stderr b/tests/ui/issues/issue-31769.stderr
index 03e2f931c84..0f75e84f2a7 100644
--- a/tests/ui/issues/issue-31769.stderr
+++ b/tests/ui/issues/issue-31769.stderr
@@ -1,8 +1,10 @@
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on structs
   --> $DIR/issue-31769.rs:2:5
    |
 LL |     #[inline] struct Foo;
-   |     ^^^^^^^^^ ----------- not a function or closure
+   |     ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
 
 error[E0517]: attribute should be applied to a struct, enum, or union
   --> $DIR/issue-31769.rs:3:12
@@ -12,5 +14,4 @@ LL |     #[repr(C)] fn foo() {}
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0517, E0518.
-For more information about an error, try `rustc --explain E0517`.
+For more information about this error, try `rustc --explain E0517`.
diff --git a/tests/ui/issues/issue-43988.rs b/tests/ui/issues/issue-43988.rs
index 5fea5576b7f..bd23e0e2457 100644
--- a/tests/ui/issues/issue-43988.rs
+++ b/tests/ui/issues/issue-43988.rs
@@ -4,12 +4,13 @@ fn main() {
 
     #[inline]
     let _a = 4;
-    //~^^ ERROR attribute should be applied to function or closure
+    //~^^ ERROR attribute cannot be used on
 
 
     #[inline(XYZ)]
     let _b = 4;
     //~^^ ERROR malformed `inline` attribute
+    //~| ERROR attribute cannot be used on
 
     #[repr(nothing)]
     let _x = 0;
@@ -30,6 +31,7 @@ fn main() {
     #[inline(ABC)]
     foo();
     //~^^ ERROR malformed `inline` attribute
+    //~| ERROR attribute cannot be used on
 
     let _z = #[repr] 1;
     //~^ ERROR malformed `repr` attribute
diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr
index b50d691e685..0219eeb693e 100644
--- a/tests/ui/issues/issue-43988.stderr
+++ b/tests/ui/issues/issue-43988.stderr
@@ -1,3 +1,11 @@
+error: `#[inline]` attribute cannot be used on statements
+  --> $DIR/issue-43988.rs:5:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
 error[E0539]: malformed `inline` attribute input
   --> $DIR/issue-43988.rs:10:5
    |
@@ -19,8 +27,16 @@ LL -     #[inline(XYZ)]
 LL +     #[inline]
    |
 
+error: `#[inline]` attribute cannot be used on statements
+  --> $DIR/issue-43988.rs:10:5
+   |
+LL |     #[inline(XYZ)]
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
 error[E0552]: unrecognized representation hint
-  --> $DIR/issue-43988.rs:14:12
+  --> $DIR/issue-43988.rs:15:12
    |
 LL |     #[repr(nothing)]
    |            ^^^^^^^
@@ -29,7 +45,7 @@ LL |     #[repr(nothing)]
    = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
 
 error[E0552]: unrecognized representation hint
-  --> $DIR/issue-43988.rs:18:12
+  --> $DIR/issue-43988.rs:19:12
    |
 LL |     #[repr(something_not_real)]
    |            ^^^^^^^^^^^^^^^^^^
@@ -38,7 +54,7 @@ LL |     #[repr(something_not_real)]
    = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations>
 
 error[E0539]: malformed `repr` attribute input
-  --> $DIR/issue-43988.rs:24:5
+  --> $DIR/issue-43988.rs:25:5
    |
 LL |     #[repr]
    |     ^^^^^^^ expected this to be a list
@@ -57,7 +73,7 @@ LL |     #[repr(align(...))]
    = and 2 other candidates
 
 error[E0539]: malformed `inline` attribute input
-  --> $DIR/issue-43988.rs:30:5
+  --> $DIR/issue-43988.rs:31:5
    |
 LL |     #[inline(ABC)]
    |     ^^^^^^^^^---^^
@@ -77,8 +93,16 @@ LL -     #[inline(ABC)]
 LL +     #[inline]
    |
 
+error: `#[inline]` attribute cannot be used on expressions
+  --> $DIR/issue-43988.rs:31:5
+   |
+LL |     #[inline(ABC)]
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
+
 error[E0539]: malformed `repr` attribute input
-  --> $DIR/issue-43988.rs:34:14
+  --> $DIR/issue-43988.rs:36:14
    |
 LL |     let _z = #[repr] 1;
    |              ^^^^^^^ expected this to be a list
@@ -96,15 +120,7 @@ LL |     let _z = #[repr(align(...))] 1;
    |                    ++++++++++++
    = and 2 other candidates
 
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-43988.rs:5:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
-LL |     let _a = 4;
-   |     ----------- not a function or closure
-
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0518, E0539, E0552.
-For more information about an error, try `rustc --explain E0518`.
+Some errors have detailed explanations: E0539, E0552.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/issues/issue-78957.rs b/tests/ui/issues/issue-78957.rs
index 567c59fd560..2ff92612e18 100644
--- a/tests/ui/issues/issue-78957.rs
+++ b/tests/ui/issues/issue-78957.rs
@@ -3,26 +3,26 @@
 use std::marker::PhantomData;
 
 pub struct Foo<#[inline] const N: usize>;
-//~^ ERROR attribute should be applied to function or closure
+//~^ ERROR attribute cannot be used on
 pub struct Bar<#[cold] const N: usize>;
-//~^ ERROR attribute should be applied to a function
-//~| WARN this was previously accepted
+//~^ ERROR attribute cannot be used on
+//~| WARN previously accepted
 pub struct Baz<#[repr(C)] const N: usize>;
 //~^ ERROR attribute should be applied to a struct, enum, or union
 //
 pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
-//~^ ERROR attribute should be applied to function or closure
+//~^ ERROR attribute cannot be used on
 pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
-//~^ ERROR attribute should be applied to a function
-//~| WARN this was previously accepted
+//~^ ERROR attribute cannot be used on
+//~| WARN previously accepted
 pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
 //~^ ERROR attribute should be applied to a struct, enum, or union
 //
 pub struct Foo3<#[inline] T>(PhantomData<T>);
-//~^ ERROR attribute should be applied to function or closure
+//~^ ERROR attribute cannot be used on
 pub struct Bar3<#[cold] T>(PhantomData<T>);
-//~^ ERROR attribute should be applied to a function
-//~| WARN this was previously accepted
+//~^ ERROR attribute cannot be used on
+//~| WARN previously accepted
 pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
 //~^ ERROR attribute should be applied to a struct, enum, or union
 
diff --git a/tests/ui/issues/issue-78957.stderr b/tests/ui/issues/issue-78957.stderr
index 6de22d6bf79..d271b1840fb 100644
--- a/tests/ui/issues/issue-78957.stderr
+++ b/tests/ui/issues/issue-78957.stderr
@@ -1,21 +1,26 @@
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on function params
   --> $DIR/issue-78957.rs:5:16
    |
 LL | pub struct Foo<#[inline] const N: usize>;
-   |                ^^^^^^^^^ -------------- not a function or closure
+   |                ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/issue-78957.rs:7:16
+error: `#[inline]` attribute cannot be used on function params
+  --> $DIR/issue-78957.rs:13:17
    |
-LL | pub struct Bar<#[cold] const N: usize>;
-   |                ^^^^^^^ -------------- not a function definition
+LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
+   |                 ^^^^^^^^^
    |
-   = 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/issue-78957.rs:1:9
+   = help: `#[inline]` can only be applied to functions
+
+error: `#[inline]` attribute cannot be used on function params
+  --> $DIR/issue-78957.rs:21:17
    |
-LL | #![deny(unused_attributes)]
-   |         ^^^^^^^^^^^^^^^^^
+LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
+   |                 ^^^^^^^^^
+   |
+   = help: `#[inline]` can only be applied to functions
 
 error[E0517]: attribute should be applied to a struct, enum, or union
   --> $DIR/issue-78957.rs:10:23
@@ -23,47 +28,50 @@ error[E0517]: attribute should be applied to a struct, enum, or union
 LL | pub struct Baz<#[repr(C)] const N: usize>;
    |                       ^   -------------- not a struct, enum, or union
 
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-78957.rs:13:17
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-78957.rs:18:24
    |
-LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
-   |                 ^^^^^^^^^ -- not a function or closure
+LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
+   |                        ^   -- not a struct, enum, or union
 
-error: attribute should be applied to a function definition
-  --> $DIR/issue-78957.rs:15:17
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-78957.rs:26:24
    |
-LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
-   |                 ^^^^^^^ -- not a function definition
+LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
+   |                        ^   - not a struct, enum, or union
+
+error: `#[cold]` attribute cannot be used on function params
+  --> $DIR/issue-78957.rs:7:16
+   |
+LL | pub struct Bar<#[cold] const N: usize>;
+   |                ^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-78957.rs:18:24
+   = help: `#[cold]` can only be applied to functions
+note: the lint level is defined here
+  --> $DIR/issue-78957.rs:1:9
    |
-LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
-   |                        ^   -- not a struct, enum, or union
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
 
-error[E0518]: attribute should be applied to function or closure
-  --> $DIR/issue-78957.rs:21:17
+error: `#[cold]` attribute cannot be used on function params
+  --> $DIR/issue-78957.rs:15:17
    |
-LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
-   |                 ^^^^^^^^^ - not a function or closure
+LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
+   |                 ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
 
-error: attribute should be applied to a function definition
+error: `#[cold]` attribute cannot be used on function params
   --> $DIR/issue-78957.rs:23:17
    |
 LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
-   |                 ^^^^^^^ - not a function definition
+   |                 ^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-78957.rs:26:24
-   |
-LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
-   |                        ^   - not a struct, enum, or union
+   = help: `#[cold]` can only be applied to functions
 
 error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0517, E0518.
-For more information about an error, try `rustc --explain E0517`.
+For more information about this error, try `rustc --explain E0517`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
index 5982c771033..301e690be38 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
@@ -1,13 +1,13 @@
 #[link_ordinal(123)]
-//~^ ERROR attribute should be applied to a foreign function or static
+//~^ ERROR attribute cannot be used on
 struct Foo {}
 
 #[link_ordinal(123)]
-//~^ ERROR attribute should be applied to a foreign function or static
+//~^ ERROR attribute cannot be used on
 fn test() {}
 
 #[link_ordinal(42)]
-//~^ ERROR attribute should be applied to a foreign function or static
+//~^ ERROR attribute cannot be used on
 static mut imported_val: i32 = 123;
 
 #[link(name = "exporter", kind = "raw-dylib")]
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr
index 8f279508720..c561373db77 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr
@@ -1,20 +1,26 @@
-error: attribute should be applied to a foreign function or static
+error: `#[link_ordinal]` attribute cannot be used on structs
   --> $DIR/link-ordinal-not-foreign-fn.rs:1:1
    |
 LL | #[link_ordinal(123)]
    | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[link_ordinal]` can be applied to foreign functions, foreign statics
 
-error: attribute should be applied to a foreign function or static
+error: `#[link_ordinal]` attribute cannot be used on functions
   --> $DIR/link-ordinal-not-foreign-fn.rs:5:1
    |
 LL | #[link_ordinal(123)]
    | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[link_ordinal]` can be applied to foreign functions, foreign statics
 
-error: attribute should be applied to a foreign function or static
+error: `#[link_ordinal]` attribute cannot be used on statics
   --> $DIR/link-ordinal-not-foreign-fn.rs:9:1
    |
 LL | #[link_ordinal(42)]
    | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[link_ordinal]` can be applied to foreign functions, foreign statics
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/lint/inline-trait-and-foreign-items.rs b/tests/ui/lint/inline-trait-and-foreign-items.rs
index 39bc01f71b5..d41a09dee96 100644
--- a/tests/ui/lint/inline-trait-and-foreign-items.rs
+++ b/tests/ui/lint/inline-trait-and-foreign-items.rs
@@ -4,33 +4,33 @@
 #![warn(unused_attributes)]
 
 trait Trait {
-    #[inline] //~ WARN `#[inline]` is ignored on constants
-    //~^ WARN this was previously accepted
+    #[inline] //~ WARN attribute cannot be used on
+//~| WARN previously accepted
     const X: u32;
 
-    #[inline] //~ ERROR attribute should be applied to function or closure
+    #[inline] //~ ERROR attribute cannot be used on
     type T;
 
     type U;
 }
 
 impl Trait for () {
-    #[inline] //~ WARN `#[inline]` is ignored on constants
-    //~^ WARN this was previously accepted
+    #[inline] //~ WARN attribute cannot be used on
+//~| WARN previously accepted
     const X: u32 = 0;
 
-    #[inline] //~ ERROR attribute should be applied to function or closure
+    #[inline] //~ ERROR attribute cannot be used on
     type T = Self;
 
-    #[inline] //~ ERROR attribute should be applied to function or closure
+    #[inline] //~ ERROR attribute cannot be used on
     type U = impl Trait; //~ ERROR unconstrained opaque type
 }
 
 extern "C" {
-    #[inline] //~ ERROR attribute should be applied to function or closure
+    #[inline] //~ ERROR attribute cannot be used on
     static X: u32;
 
-    #[inline] //~ ERROR attribute should be applied to function or closure
+    #[inline] //~ ERROR attribute cannot be used on
     type T;
 }
 
diff --git a/tests/ui/lint/inline-trait-and-foreign-items.stderr b/tests/ui/lint/inline-trait-and-foreign-items.stderr
index 2f1fb4c46c0..4bde4bc590a 100644
--- a/tests/ui/lint/inline-trait-and-foreign-items.stderr
+++ b/tests/ui/lint/inline-trait-and-foreign-items.stderr
@@ -1,65 +1,42 @@
-warning: `#[inline]` is ignored on constants
-  --> $DIR/inline-trait-and-foreign-items.rs:7:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information
-note: the lint level is defined here
-  --> $DIR/inline-trait-and-foreign-items.rs:4:9
-   |
-LL | #![warn(unused_attributes)]
-   |         ^^^^^^^^^^^^^^^^^
-
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on associated types
   --> $DIR/inline-trait-and-foreign-items.rs:11:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
-LL |     type T;
-   |     ------- not a function or closure
-
-warning: `#[inline]` is ignored on constants
-  --> $DIR/inline-trait-and-foreign-items.rs:18:5
-   |
-LL |     #[inline]
-   |     ^^^^^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information
+   = help: `#[inline]` can only be applied to functions
 
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on associated types
   --> $DIR/inline-trait-and-foreign-items.rs:22:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
-LL |     type T = Self;
-   |     -------------- not a function or closure
+   |
+   = help: `#[inline]` can only be applied to functions
 
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on associated types
   --> $DIR/inline-trait-and-foreign-items.rs:25:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
-LL |     type U = impl Trait;
-   |     -------------------- not a function or closure
+   |
+   = help: `#[inline]` can only be applied to functions
 
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on foreign statics
   --> $DIR/inline-trait-and-foreign-items.rs:30:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
-LL |     static X: u32;
-   |     -------------- not a function or closure
+   |
+   = help: `#[inline]` can only be applied to functions
 
-error[E0518]: attribute should be applied to function or closure
+error: `#[inline]` attribute cannot be used on foreign types
   --> $DIR/inline-trait-and-foreign-items.rs:33:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
-LL |     type T;
-   |     ------- not a function or closure
+   |
+   = help: `#[inline]` can only be applied to functions
 
 error: unconstrained opaque type
   --> $DIR/inline-trait-and-foreign-items.rs:26:14
@@ -69,6 +46,28 @@ LL |     type U = impl Trait;
    |
    = note: `U` must be used in combination with a concrete type within the same impl
 
+warning: `#[inline]` attribute cannot be used on associated consts
+  --> $DIR/inline-trait-and-foreign-items.rs:7:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can only be applied to functions
+note: the lint level is defined here
+  --> $DIR/inline-trait-and-foreign-items.rs:4:9
+   |
+LL | #![warn(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: `#[inline]` attribute cannot be used on associated consts
+  --> $DIR/inline-trait-and-foreign-items.rs:18:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can only be applied to functions
+
 error: aborting due to 6 previous errors; 2 warnings emitted
 
-For more information about this error, try `rustc --explain E0518`.
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs
index 7a8a1bb1ae5..96f2834a296 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.rs
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs
@@ -4,8 +4,10 @@
 
 // A sample of various built-in attributes.
 #[macro_export]
-#[macro_use] //~ ERROR `#[macro_use]` only has an effect
-#[path="foo"] //~ ERROR #[path]` only has an effect
+#[macro_use] //~ ERROR attribute cannot be used on
+//~| WARN previously accepted
+#[path="foo"] //~ ERROR attribute cannot be used on
+//~| WARN previously accepted
 #[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute
 macro_rules! foo {
     () => {};
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
index 1e1211af5e2..0c55ae678e9 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -1,5 +1,5 @@
 error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/unused-attr-macro-rules.rs:9:1
+  --> $DIR/unused-attr-macro-rules.rs:11:1
    |
 LL | #[recursion_limit="1"]
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -10,17 +10,23 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: `#[macro_use]` only has an effect on `extern crate` and modules
+error: `#[macro_use]` attribute cannot be used on macro defs
   --> $DIR/unused-attr-macro-rules.rs:7:1
    |
 LL | #[macro_use]
    | ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
 
-error: `#[path]` only has an effect on modules
-  --> $DIR/unused-attr-macro-rules.rs:8:1
+error: `#[path]` attribute cannot be used on macro defs
+  --> $DIR/unused-attr-macro-rules.rs:9:1
    |
 LL | #[path="foo"]
    | ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[path]` can only be applied to modules
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
index 27927cf37e9..9e37f6504cc 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -15,127 +15,127 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes, unused_must_use)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to an extern crate
+error: `#[must_use]` has no effect when applied to extern crates
   --> $DIR/unused_attributes-must_use.rs:7:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a module
+error: `#[must_use]` has no effect when applied to modules
   --> $DIR/unused_attributes-must_use.rs:10:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a use
+error: `#[must_use]` has no effect when applied to use statements
   --> $DIR/unused_attributes-must_use.rs:13:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a constant item
+error: `#[must_use]` has no effect when applied to constants
   --> $DIR/unused_attributes-must_use.rs:16:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a static item
+error: `#[must_use]` has no effect when applied to statics
   --> $DIR/unused_attributes-must_use.rs:18:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to an inherent implementation block
+error: `#[must_use]` has no effect when applied to inherent impl blocks
   --> $DIR/unused_attributes-must_use.rs:35:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a foreign module
+error: `#[must_use]` has no effect when applied to foreign modules
   --> $DIR/unused_attributes-must_use.rs:49:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a type alias
+error: `#[must_use]` has no effect when applied to type aliases
   --> $DIR/unused_attributes-must_use.rs:63:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a type parameter
+error: `#[must_use]` has no effect when applied to type parameters
   --> $DIR/unused_attributes-must_use.rs:66:8
    |
 LL | fn qux<#[must_use] T>(_: T) {}
    |        ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to an trait implementation block
+error: `#[must_use]` has no effect when applied to trait impl blocks
   --> $DIR/unused_attributes-must_use.rs:81:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a trait alias
+error: `#[must_use]` has no effect when applied to trait aliases
   --> $DIR/unused_attributes-must_use.rs:91:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a macro def
+error: `#[must_use]` has no effect when applied to macro defs
   --> $DIR/unused_attributes-must_use.rs:94:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a statement
+error: `#[must_use]` has no effect when applied to statements
   --> $DIR/unused_attributes-must_use.rs:102:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a closure
+error: `#[must_use]` has no effect when applied to closures
   --> $DIR/unused_attributes-must_use.rs:106:13
    |
 LL |     let x = #[must_use]
    |             ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to an match arm
+error: `#[must_use]` has no effect when applied to match arms
   --> $DIR/unused_attributes-must_use.rs:128:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a struct field
+error: `#[must_use]` has no effect when applied to struct fields
   --> $DIR/unused_attributes-must_use.rs:136:28
    |
 LL |     let s = PatternField { #[must_use]  foo: 123 };
    |                            ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a pattern field
+error: `#[must_use]` has no effect when applied to pattern fields
   --> $DIR/unused_attributes-must_use.rs:137:24
    |
 LL |     let PatternField { #[must_use] foo } = s;
    |                        ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to an associated const
+error: `#[must_use]` has no effect when applied to associated consts
   --> $DIR/unused_attributes-must_use.rs:70:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to an associated type
+error: `#[must_use]` has no effect when applied to associated types
   --> $DIR/unused_attributes-must_use.rs:72:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a provided trait method
+error: `#[must_use]` has no effect when applied to provided trait methods
   --> $DIR/unused_attributes-must_use.rs:85:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
-error: `#[must_use]` has no effect when applied to a foreign static item
+error: `#[must_use]` has no effect when applied to foreign statics
   --> $DIR/unused_attributes-must_use.rs:52:5
    |
 LL |     #[must_use]
diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs
index 4684fe14577..bef607a4ec5 100644
--- a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs
+++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs
@@ -1,12 +1,14 @@
 #![deny(unused_attributes)]
 
 trait Trait {
-    #[inline] //~ ERROR `#[inline]` is ignored on function prototypes
+    #[inline] //~ ERROR attribute cannot be used on
+    //~^ WARN previously accepted
     fn foo();
 }
 
 extern "C" {
-    #[inline] //~ ERROR `#[inline]` is ignored on function prototypes
+    #[inline] //~ ERROR attribute cannot be used on
+    //~^ WARN previously accepted
     fn foo();
 }
 
diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
index ab19d80e732..336366042f9 100644
--- a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
+++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr
@@ -1,20 +1,25 @@
-error: `#[inline]` is ignored on function prototypes
+error: `#[inline]` attribute cannot be used on required trait methods
   --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
    |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks, closures
 note: the lint level is defined here
   --> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9
    |
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: `#[inline]` is ignored on function prototypes
-  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5
+error: `#[inline]` attribute cannot be used on foreign functions
+  --> $DIR/warn-unused-inline-on-fn-prototypes.rs:10:5
    |
 LL |     #[inline]
    |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can be applied to methods, functions, closures
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/loop-match/invalid-attribute.rs b/tests/ui/loop-match/invalid-attribute.rs
index d8d2f605eb4..a5d7daac583 100644
--- a/tests/ui/loop-match/invalid-attribute.rs
+++ b/tests/ui/loop-match/invalid-attribute.rs
@@ -3,17 +3,17 @@
 
 #![allow(incomplete_features)]
 #![feature(loop_match)]
-#![loop_match] //~ ERROR should be applied to a loop
-#![const_continue] //~ ERROR should be applied to a break expression
+#![loop_match] //~ ERROR attribute cannot be used on
+#![const_continue] //~ ERROR attribute cannot be used on
 
 extern "C" {
-    #[loop_match] //~ ERROR should be applied to a loop
-    #[const_continue] //~ ERROR should be applied to a break expression
+    #[loop_match] //~ ERROR attribute cannot be used on
+    #[const_continue] //~ ERROR attribute cannot be used on
     fn f();
 }
 
-#[loop_match] //~ ERROR should be applied to a loop
-#[const_continue] //~ ERROR should be applied to a break expression
+#[loop_match] //~ ERROR attribute cannot be used on
+#[const_continue] //~ ERROR attribute cannot be used on
 #[repr(C)]
 struct S {
     a: u32,
@@ -21,18 +21,18 @@ struct S {
 }
 
 trait Invoke {
-    #[loop_match] //~ ERROR should be applied to a loop
-    #[const_continue] //~ ERROR should be applied to a break expression
+    #[loop_match] //~ ERROR attribute cannot be used on
+    #[const_continue] //~ ERROR attribute cannot be used on
     extern "C" fn invoke(&self);
 }
 
-#[loop_match] //~ ERROR should be applied to a loop
-#[const_continue] //~ ERROR should be applied to a break expression
+#[loop_match] //~ ERROR attribute cannot be used on
+#[const_continue] //~ ERROR attribute cannot be used on
 extern "C" fn ok() {}
 
 fn main() {
-    #[loop_match] //~ ERROR should be applied to a loop
-    #[const_continue] //~ ERROR should be applied to a break expression
+    #[loop_match] //~ ERROR attribute cannot be used on
+    #[const_continue] //~ ERROR attribute cannot be used on
     || {};
 
     {
diff --git a/tests/ui/loop-match/invalid-attribute.stderr b/tests/ui/loop-match/invalid-attribute.stderr
index 07015311f9c..ddb68aea31b 100644
--- a/tests/ui/loop-match/invalid-attribute.stderr
+++ b/tests/ui/loop-match/invalid-attribute.stderr
@@ -1,54 +1,98 @@
-error: `#[const_continue]` should be applied to a break expression
-  --> $DIR/invalid-attribute.rs:16:1
+error: `#[loop_match]` attribute cannot be used on crates
+  --> $DIR/invalid-attribute.rs:6:1
    |
-LL | #[const_continue]
-   | ^^^^^^^^^^^^^^^^^
-LL | #[repr(C)]
-LL | struct S {
-   | -------- not a break expression
+LL | #![loop_match]
+   | ^^^^^^^^^^^^^^
+   |
+   = help: `#[loop_match]` can be applied to 
 
-error: `#[loop_match]` should be applied to a loop
+error: `#[const_continue]` attribute cannot be used on crates
+  --> $DIR/invalid-attribute.rs:7:1
+   |
+LL | #![const_continue]
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[const_continue]` can be applied to 
+
+error: `#[loop_match]` attribute cannot be used on foreign functions
+  --> $DIR/invalid-attribute.rs:10:5
+   |
+LL |     #[loop_match]
+   |     ^^^^^^^^^^^^^
+   |
+   = help: `#[loop_match]` can be applied to 
+
+error: `#[const_continue]` attribute cannot be used on foreign functions
+  --> $DIR/invalid-attribute.rs:11:5
+   |
+LL |     #[const_continue]
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[const_continue]` can be applied to 
+
+error: `#[loop_match]` attribute cannot be used on structs
   --> $DIR/invalid-attribute.rs:15:1
    |
 LL | #[loop_match]
    | ^^^^^^^^^^^^^
-...
-LL | struct S {
-   | -------- not a loop
+   |
+   = help: `#[loop_match]` can be applied to 
 
-error: `#[const_continue]` should be applied to a break expression
-  --> $DIR/invalid-attribute.rs:30:1
+error: `#[const_continue]` attribute cannot be used on structs
+  --> $DIR/invalid-attribute.rs:16:1
    |
 LL | #[const_continue]
    | ^^^^^^^^^^^^^^^^^
-LL | extern "C" fn ok() {}
-   | ------------------ not a break expression
+   |
+   = help: `#[const_continue]` can be applied to 
 
-error: `#[loop_match]` should be applied to a loop
+error: `#[loop_match]` attribute cannot be used on required trait methods
+  --> $DIR/invalid-attribute.rs:24:5
+   |
+LL |     #[loop_match]
+   |     ^^^^^^^^^^^^^
+   |
+   = help: `#[loop_match]` can be applied to 
+
+error: `#[const_continue]` attribute cannot be used on required trait methods
+  --> $DIR/invalid-attribute.rs:25:5
+   |
+LL |     #[const_continue]
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[const_continue]` can be applied to 
+
+error: `#[loop_match]` attribute cannot be used on functions
   --> $DIR/invalid-attribute.rs:29:1
    |
 LL | #[loop_match]
    | ^^^^^^^^^^^^^
-LL | #[const_continue]
-LL | extern "C" fn ok() {}
-   | ------------------ not a loop
+   |
+   = help: `#[loop_match]` can be applied to 
 
-error: `#[const_continue]` should be applied to a break expression
-  --> $DIR/invalid-attribute.rs:35:5
+error: `#[const_continue]` attribute cannot be used on functions
+  --> $DIR/invalid-attribute.rs:30:1
    |
-LL |     #[const_continue]
-   |     ^^^^^^^^^^^^^^^^^
-LL |     || {};
-   |     -- not a break expression
+LL | #[const_continue]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[const_continue]` can be applied to 
 
-error: `#[loop_match]` should be applied to a loop
+error: `#[loop_match]` attribute cannot be used on closures
   --> $DIR/invalid-attribute.rs:34:5
    |
 LL |     #[loop_match]
    |     ^^^^^^^^^^^^^
+   |
+   = help: `#[loop_match]` can be applied to 
+
+error: `#[const_continue]` attribute cannot be used on closures
+  --> $DIR/invalid-attribute.rs:35:5
+   |
 LL |     #[const_continue]
-LL |     || {};
-   |     -- not a loop
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[const_continue]` can be applied to 
 
 error: `#[const_continue]` should be applied to a break expression
   --> $DIR/invalid-attribute.rs:40:9
@@ -67,65 +111,5 @@ LL |         #[const_continue]
 LL |         5
    |         - not a loop
 
-error: `#[const_continue]` should be applied to a break expression
-  --> $DIR/invalid-attribute.rs:25:5
-   |
-LL |     #[const_continue]
-   |     ^^^^^^^^^^^^^^^^^
-LL |     extern "C" fn invoke(&self);
-   |     ---------------------------- not a break expression
-
-error: `#[loop_match]` should be applied to a loop
-  --> $DIR/invalid-attribute.rs:24:5
-   |
-LL |     #[loop_match]
-   |     ^^^^^^^^^^^^^
-LL |     #[const_continue]
-LL |     extern "C" fn invoke(&self);
-   |     ---------------------------- not a loop
-
-error: `#[const_continue]` should be applied to a break expression
-  --> $DIR/invalid-attribute.rs:11:5
-   |
-LL |     #[const_continue]
-   |     ^^^^^^^^^^^^^^^^^
-LL |     fn f();
-   |     ------- not a break expression
-
-error: `#[loop_match]` should be applied to a loop
-  --> $DIR/invalid-attribute.rs:10:5
-   |
-LL |     #[loop_match]
-   |     ^^^^^^^^^^^^^
-LL |     #[const_continue]
-LL |     fn f();
-   |     ------- not a loop
-
-error: `#[const_continue]` should be applied to a break expression
-  --> $DIR/invalid-attribute.rs:7:1
-   |
-LL | / #![allow(incomplete_features)]
-LL | | #![feature(loop_match)]
-LL | | #![loop_match]
-LL | | #![const_continue]
-   | | ^^^^^^^^^^^^^^^^^^
-...  |
-LL | |     };
-LL | | }
-   | |_- not a break expression
-
-error: `#[loop_match]` should be applied to a loop
-  --> $DIR/invalid-attribute.rs:6:1
-   |
-LL | / #![allow(incomplete_features)]
-LL | | #![feature(loop_match)]
-LL | | #![loop_match]
-   | | ^^^^^^^^^^^^^^
-LL | | #![const_continue]
-...  |
-LL | |     };
-LL | | }
-   | |_- not a loop
-
 error: aborting due to 14 previous errors
 
diff --git a/tests/ui/macros/issue-68060.rs b/tests/ui/macros/issue-68060.rs
index 4eddb96848c..2edf9861743 100644
--- a/tests/ui/macros/issue-68060.rs
+++ b/tests/ui/macros/issue-68060.rs
@@ -2,13 +2,12 @@ fn main() {
     (0..)
         .map(
             #[target_feature(enable = "")]
-            //~^ ERROR: attribute should be applied to a function
+            //~^ ERROR: attribute cannot be used on
             #[track_caller]
             //~^ ERROR: `#[track_caller]` on closures is currently unstable
             //~| NOTE: see issue #87417
             //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
             |_| (),
-            //~^ NOTE: not a function
         )
         .next();
 }
diff --git a/tests/ui/macros/issue-68060.stderr b/tests/ui/macros/issue-68060.stderr
index ef2246d5bd6..c701e50f054 100644
--- a/tests/ui/macros/issue-68060.stderr
+++ b/tests/ui/macros/issue-68060.stderr
@@ -1,11 +1,10 @@
-error: attribute should be applied to a function definition
+error: `#[target_feature]` attribute cannot be used on closures
   --> $DIR/issue-68060.rs:4:13
    |
 LL |             #[target_feature(enable = "")]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |             |_| (),
-   |             ------ not a function definition
+   |
+   = help: `#[target_feature]` can be applied to methods, functions
 
 error[E0658]: `#[track_caller]` on closures is currently unstable
   --> $DIR/issue-68060.rs:6:13
diff --git a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs
index 0bf620934ec..1fb206d628f 100644
--- a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs
+++ b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs
@@ -1,23 +1,23 @@
 #![feature(marker_trait_attr)]
 
-#[marker] //~ ERROR attribute should be applied to a trait
+#[marker] //~ ERROR attribute cannot be used on
 struct Struct {}
 
-#[marker] //~ ERROR attribute should be applied to a trait
+#[marker] //~ ERROR attribute cannot be used on
 impl Struct {}
 
-#[marker] //~ ERROR attribute should be applied to a trait
+#[marker] //~ ERROR attribute cannot be used on
 union Union {
     x: i32,
 }
 
-#[marker] //~ ERROR attribute should be applied to a trait
+#[marker] //~ ERROR attribute cannot be used on
 const CONST: usize = 10;
 
-#[marker] //~ ERROR attribute should be applied to a trait
+#[marker] //~ ERROR attribute cannot be used on
 fn function() {}
 
-#[marker] //~ ERROR attribute should be applied to a trait
+#[marker] //~ ERROR attribute cannot be used on
 type Type = ();
 
 fn main() {}
diff --git a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr
index 19a5290dd7e..71abe7f39df 100644
--- a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr
+++ b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr
@@ -1,52 +1,50 @@
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on structs
   --> $DIR/marker-attribute-on-non-trait.rs:3:1
    |
 LL | #[marker]
    | ^^^^^^^^^
-LL | struct Struct {}
-   | ---------------- not a trait
+   |
+   = help: `#[marker]` can only be applied to traits
 
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on inherent impl blocks
   --> $DIR/marker-attribute-on-non-trait.rs:6:1
    |
 LL | #[marker]
    | ^^^^^^^^^
-LL | impl Struct {}
-   | -------------- not a trait
+   |
+   = help: `#[marker]` can only be applied to traits
 
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on unions
   --> $DIR/marker-attribute-on-non-trait.rs:9:1
    |
-LL |   #[marker]
-   |   ^^^^^^^^^
-LL | / union Union {
-LL | |     x: i32,
-LL | | }
-   | |_- not a trait
+LL | #[marker]
+   | ^^^^^^^^^
+   |
+   = help: `#[marker]` can only be applied to traits
 
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on constants
   --> $DIR/marker-attribute-on-non-trait.rs:14:1
    |
 LL | #[marker]
    | ^^^^^^^^^
-LL | const CONST: usize = 10;
-   | ------------------------ not a trait
+   |
+   = help: `#[marker]` can only be applied to traits
 
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on functions
   --> $DIR/marker-attribute-on-non-trait.rs:17:1
    |
 LL | #[marker]
    | ^^^^^^^^^
-LL | fn function() {}
-   | ---------------- not a trait
+   |
+   = help: `#[marker]` can only be applied to traits
 
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on type aliases
   --> $DIR/marker-attribute-on-non-trait.rs:20:1
    |
 LL | #[marker]
    | ^^^^^^^^^
-LL | type Type = ();
-   | --------------- not a trait
+   |
+   = help: `#[marker]` can only be applied to traits
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.stderr b/tests/ui/panic-handler/panic-handler-wrong-location.stderr
index 66ee91aa4c1..9b361bf8d60 100644
--- a/tests/ui/panic-handler/panic-handler-wrong-location.stderr
+++ b/tests/ui/panic-handler/panic-handler-wrong-location.stderr
@@ -2,7 +2,7 @@ error[E0718]: `panic_impl` lang item must be applied to a function
   --> $DIR/panic-handler-wrong-location.rs:6:1
    |
 LL | #[panic_handler]
-   | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static item
+   | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static
 
 error: `#[panic_handler]` function required, but not found
 
diff --git a/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs b/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs
index 4efd9e952fc..19473fb2caf 100644
--- a/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs
+++ b/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs
@@ -8,7 +8,7 @@ pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
 
 // Issue #37590
 #[proc_macro_derive(Foo)]
-//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions
+//~^ ERROR: attribute cannot be used on
 pub struct Foo {
 }
 
diff --git a/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr
index c0930ab7102..f01619b9195 100644
--- a/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr
+++ b/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr
@@ -4,11 +4,13 @@ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `p
 LL | #[proc_macro_derive(Foo)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+error: `#[proc_macro_derive]` attribute cannot be used on structs
   --> $DIR/illegal-proc-macro-derive-use.rs:10:1
    |
 LL | #[proc_macro_derive(Foo)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[proc_macro_derive]` can only be applied to functions
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs
index 143f9a3009b..b538a97280d 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs
@@ -3,11 +3,11 @@
 struct Foo;
 
 #[non_exhaustive]
-//~^ ERROR attribute should be applied to a struct or enum [E0701]
+//~^ ERROR attribute cannot be used on
 trait Bar { }
 
 #[non_exhaustive]
-//~^ ERROR attribute should be applied to a struct or enum [E0701]
+//~^ ERROR attribute cannot be used on
 union Baz {
     f1: u16,
     f2: u16
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr
index 1ac017aa08b..3522c459977 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr
@@ -7,28 +7,22 @@ LL | #[non_exhaustive(anything)]
    | |               didn't expect any arguments here
    | help: must be of the form: `#[non_exhaustive]`
 
-error[E0701]: attribute should be applied to a struct or enum
+error: `#[non_exhaustive]` attribute cannot be used on traits
   --> $DIR/invalid-attribute.rs:5:1
    |
 LL | #[non_exhaustive]
    | ^^^^^^^^^^^^^^^^^
-LL |
-LL | trait Bar { }
-   | ------------- not a struct or enum
+   |
+   = help: `#[non_exhaustive]` can be applied to data types, enum variants
 
-error[E0701]: attribute should be applied to a struct or enum
+error: `#[non_exhaustive]` attribute cannot be used on unions
   --> $DIR/invalid-attribute.rs:9:1
    |
-LL |   #[non_exhaustive]
-   |   ^^^^^^^^^^^^^^^^^
-LL |
-LL | / union Baz {
-LL | |     f1: u16,
-LL | |     f2: u16
-LL | | }
-   | |_- not a struct or enum
+LL | #[non_exhaustive]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[non_exhaustive]` can be applied to data types, enum variants
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0565, E0701.
-For more information about an error, try `rustc --explain E0565`.
+For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs
index 2d2b01b6f94..53a856e0df3 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs
+++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs
@@ -1,5 +1,5 @@
 #[track_caller]
 struct S;
-//~^^ ERROR attribute should be applied to a function definition
+//~^^ ERROR attribute cannot be used on
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr
index f976b7f5210..6ff66be4e5c 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr
+++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr
@@ -1,11 +1,10 @@
-error[E0739]: attribute should be applied to a function definition
+error: `#[track_caller]` attribute cannot be used on structs
   --> $DIR/only-for-fns.rs:1:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
-LL | struct S;
-   | --------- not a function definition
+   |
+   = help: `#[track_caller]` can only be applied to functions
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0739`.
diff --git a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr
index 4244c11eb3e..23c93a4ed8b 100644
--- a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr
+++ b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr
@@ -10,13 +10,13 @@ error: `#[doc(alias = "...")]` isn't allowed on foreign module
 LL | #[doc(alias = "foo")]
    |       ^^^^^^^^^^^^^
 
-error: `#[doc(alias = "...")]` isn't allowed on inherent implementation block
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
   --> $DIR/check-doc-alias-attr-location.rs:12:7
    |
 LL | #[doc(alias = "bar")]
    |       ^^^^^^^^^^^^^
 
-error: `#[doc(alias = "...")]` isn't allowed on trait implementation block
+error: `#[doc(alias = "...")]` isn't allowed on implementation block
   --> $DIR/check-doc-alias-attr-location.rs:18:7
    |
 LL | #[doc(alias = "foobar")]
diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs
index d13098c3a6a..b34a48aba26 100644
--- a/tests/ui/target-feature/invalid-attribute.rs
+++ b/tests/ui/target-feature/invalid-attribute.rs
@@ -3,19 +3,16 @@
 #![warn(unused_attributes)]
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 extern crate alloc;
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 use alloc::alloc::alloc;
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 extern "Rust" {}
-//~^ NOTE not a function
 
 #[target_feature = "+sse2"]
 //~^ ERROR malformed `target_feature` attribute
@@ -32,42 +29,35 @@ extern "Rust" {}
 unsafe fn foo() {}
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 mod another {}
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 const FOO: usize = 7;
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 struct Foo;
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 enum Bar {}
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 union Qux {
-    //~^ NOTE not a function
-    f1: u16,
+        f1: u16,
     f2: u16,
 }
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 type Uwu = ();
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 trait Baz {}
-//~^ NOTE not a function
 
 #[inline(always)]
 //~^ ERROR: cannot use `#[inline(always)]`
@@ -75,21 +65,18 @@ trait Baz {}
 unsafe fn test() {}
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 static A: () = ();
-//~^ NOTE not a function
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 impl Quux for u8 {}
-//~^ NOTE not a function
-//~| NOTE missing `foo` in implementation
+//~^ NOTE missing `foo` in implementation
 //~| ERROR missing: `foo`
 
 #[target_feature(enable = "sse2")]
-//~^ ERROR attribute should be applied to a function
+//~^ ERROR attribute cannot be used on
 impl Foo {}
-//~^ NOTE not a function
 
 trait Quux {
     fn foo(); //~ NOTE `foo` from trait
@@ -109,17 +96,15 @@ impl Quux for Foo {
 
 fn main() {
     #[target_feature(enable = "sse2")]
-    //~^ ERROR attribute should be applied to a function
+    //~^ ERROR attribute cannot be used on
     unsafe {
         foo();
     }
-    //~^^^ NOTE not a function
 
     #[target_feature(enable = "sse2")]
-    //~^ ERROR attribute should be applied to a function
+    //~^ ERROR attribute cannot be used on
     || {};
-    //~^ NOTE not a function
-}
+    }
 
 #[target_feature(enable = "+sse2")]
 //~^ ERROR `+sse2` is not valid for this target
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index 113c0c3695a..a0117649a57 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -1,5 +1,29 @@
+error: `#[target_feature]` attribute cannot be used on extern crates
+  --> $DIR/invalid-attribute.rs:5:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[target_feature]` can only be applied to functions
+
+error: `#[target_feature]` attribute cannot be used on use statements
+  --> $DIR/invalid-attribute.rs:9:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[target_feature]` can only be applied to functions
+
+error: `#[target_feature]` attribute cannot be used on foreign modules
+  --> $DIR/invalid-attribute.rs:13:1
+   |
+LL | #[target_feature(enable = "sse2")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[target_feature]` can only be applied to functions
+
 error[E0539]: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:20:1
+  --> $DIR/invalid-attribute.rs:17:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +32,7 @@ LL | #[target_feature = "+sse2"]
    | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]`
 
 error[E0539]: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:26:1
+  --> $DIR/invalid-attribute.rs:23:1
    |
 LL | #[target_feature(bar)]
    | ^^^^^^^^^^^^^^^^^---^^
@@ -17,7 +41,7 @@ LL | #[target_feature(bar)]
    | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]`
 
 error[E0539]: malformed `target_feature` attribute input
-  --> $DIR/invalid-attribute.rs:29:1
+  --> $DIR/invalid-attribute.rs:26:1
    |
 LL | #[target_feature(disable = "baz")]
    | ^^^^^^^^^^^^^^^^^-------^^^^^^^^^^
@@ -25,161 +49,116 @@ LL | #[target_feature(disable = "baz")]
    | |                expected this to be of the form `enable = "..."`
    | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]`
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:5:1
+error: `#[target_feature]` attribute cannot be used on modules
+  --> $DIR/invalid-attribute.rs:31:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | extern crate alloc;
-   | ------------------- not a function definition
-
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:10:1
    |
-LL | #[target_feature(enable = "sse2")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | use alloc::alloc::alloc;
-   | ------------------------ not a function definition
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:15:1
+error: `#[target_feature]` attribute cannot be used on constants
+  --> $DIR/invalid-attribute.rs:35:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | extern "Rust" {}
-   | ---------------- not a function definition
-
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:34:1
    |
-LL | #[target_feature(enable = "sse2")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | mod another {}
-   | -------------- not a function definition
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
+error: `#[target_feature]` attribute cannot be used on structs
   --> $DIR/invalid-attribute.rs:39:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | const FOO: usize = 7;
-   | --------------------- not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:44:1
+error: `#[target_feature]` attribute cannot be used on enums
+  --> $DIR/invalid-attribute.rs:43:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | struct Foo;
-   | ----------- not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:49:1
+error: `#[target_feature]` attribute cannot be used on unions
+  --> $DIR/invalid-attribute.rs:47:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | enum Bar {}
-   | ----------- not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
+error: `#[target_feature]` attribute cannot be used on type aliases
   --> $DIR/invalid-attribute.rs:54:1
    |
-LL |   #[target_feature(enable = "sse2")]
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | / union Qux {
-LL | |
-LL | |     f1: u16,
-LL | |     f2: u16,
-LL | | }
-   | |_- not a function definition
-
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:62:1
-   |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | type Uwu = ();
-   | -------------- not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:67:1
+error: `#[target_feature]` attribute cannot be used on traits
+  --> $DIR/invalid-attribute.rs:58:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | trait Baz {}
-   | ------------ not a function definition
-
-error: cannot use `#[inline(always)]` with `#[target_feature]`
-  --> $DIR/invalid-attribute.rs:72:1
    |
-LL | #[inline(always)]
-   | ^^^^^^^^^^^^^^^^^
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:77:1
+error: `#[target_feature]` attribute cannot be used on statics
+  --> $DIR/invalid-attribute.rs:67:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | static A: () = ();
-   | ------------------ not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:82:1
+error: `#[target_feature]` attribute cannot be used on trait impl blocks
+  --> $DIR/invalid-attribute.rs:71:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | impl Quux for u8 {}
-   | ------------------- not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:89:1
+error: `#[target_feature]` attribute cannot be used on inherent impl blocks
+  --> $DIR/invalid-attribute.rs:77:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | impl Foo {}
-   | ----------- not a function definition
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:111:5
+error: `#[target_feature]` attribute cannot be used on expressions
+  --> $DIR/invalid-attribute.rs:98:5
    |
-LL |       #[target_feature(enable = "sse2")]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | /     unsafe {
-LL | |         foo();
-LL | |     }
-   | |_____- not a function definition
+LL |     #[target_feature(enable = "sse2")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[target_feature]` can only be applied to functions
 
-error: attribute should be applied to a function definition
-  --> $DIR/invalid-attribute.rs:118:5
+error: `#[target_feature]` attribute cannot be used on closures
+  --> $DIR/invalid-attribute.rs:104:5
    |
 LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     || {};
-   |     ----- not a function definition
+   |
+   = help: `#[target_feature]` can be applied to methods, functions
+
+error: cannot use `#[inline(always)]` with `#[target_feature]`
+  --> $DIR/invalid-attribute.rs:62:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/invalid-attribute.rs:23:18
+  --> $DIR/invalid-attribute.rs:20:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^ `foo` is not valid for this target
 
 error[E0046]: not all trait items implemented, missing: `foo`
-  --> $DIR/invalid-attribute.rs:84:1
+  --> $DIR/invalid-attribute.rs:73:1
    |
 LL | impl Quux for u8 {}
    | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
@@ -188,7 +167,7 @@ LL |     fn foo();
    |     --------- `foo` from trait
 
 error: `#[target_feature(..)]` cannot be applied to safe trait method
-  --> $DIR/invalid-attribute.rs:100:5
+  --> $DIR/invalid-attribute.rs:87:5
    |
 LL |     #[target_feature(enable = "sse2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
@@ -197,13 +176,13 @@ LL |     fn foo() {}
    |     -------- not an `unsafe` function
 
 error[E0053]: method `foo` has an incompatible type for trait
-  --> $DIR/invalid-attribute.rs:103:5
+  --> $DIR/invalid-attribute.rs:90:5
    |
 LL |     fn foo() {}
    |     ^^^^^^^^ expected safe fn, found unsafe fn
    |
 note: type in trait
-  --> $DIR/invalid-attribute.rs:95:5
+  --> $DIR/invalid-attribute.rs:82:5
    |
 LL |     fn foo();
    |     ^^^^^^^^^
@@ -211,7 +190,7 @@ LL |     fn foo();
               found signature `#[target_features] fn()`
 
 error: the feature named `+sse2` is not valid for this target
-  --> $DIR/invalid-attribute.rs:124:18
+  --> $DIR/invalid-attribute.rs:109:18
    |
 LL | #[target_feature(enable = "+sse2")]
    |                  ^^^^^^^^^^^^^^^^ `+sse2` is not valid for this target
diff --git a/tests/ui/traits/alias/not-a-marker.rs b/tests/ui/traits/alias/not-a-marker.rs
index b004b9ff9ae..633cc60554d 100644
--- a/tests/ui/traits/alias/not-a-marker.rs
+++ b/tests/ui/traits/alias/not-a-marker.rs
@@ -1,7 +1,7 @@
 #![feature(trait_alias, marker_trait_attr)]
 
 #[marker]
-//~^ ERROR attribute should be applied to a trait
+//~^ ERROR attribute cannot be used on
 trait Foo = Send;
 
 fn main() {}
diff --git a/tests/ui/traits/alias/not-a-marker.stderr b/tests/ui/traits/alias/not-a-marker.stderr
index 2f3f6fea30f..8b0eba65b95 100644
--- a/tests/ui/traits/alias/not-a-marker.stderr
+++ b/tests/ui/traits/alias/not-a-marker.stderr
@@ -1,11 +1,10 @@
-error: attribute should be applied to a trait
+error: `#[marker]` attribute cannot be used on trait aliases
   --> $DIR/not-a-marker.rs:3:1
    |
 LL | #[marker]
    | ^^^^^^^^^
-LL |
-LL | trait Foo = Send;
-   | ----------------- not a trait
+   |
+   = help: `#[marker]` can only be applied to traits
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/const-traits/attr-misuse.rs b/tests/ui/traits/const-traits/attr-misuse.rs
index 01ac74feff7..70dfcbf47d2 100644
--- a/tests/ui/traits/const-traits/attr-misuse.rs
+++ b/tests/ui/traits/const-traits/attr-misuse.rs
@@ -2,9 +2,9 @@
 
 #[const_trait]
 trait A {
-    #[const_trait] //~ ERROR attribute should be applied
+    #[const_trait] //~ ERROR attribute cannot be used on
     fn foo(self);
 }
 
-#[const_trait] //~ ERROR attribute should be applied
+#[const_trait] //~ ERROR attribute cannot be used on
 fn main() {}
diff --git a/tests/ui/traits/const-traits/attr-misuse.stderr b/tests/ui/traits/const-traits/attr-misuse.stderr
index 998958cedf7..2f86efac4c9 100644
--- a/tests/ui/traits/const-traits/attr-misuse.stderr
+++ b/tests/ui/traits/const-traits/attr-misuse.stderr
@@ -1,18 +1,18 @@
-error: attribute should be applied to a trait
+error: `#[const_trait]` attribute cannot be used on required trait methods
+  --> $DIR/attr-misuse.rs:5:5
+   |
+LL |     #[const_trait]
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: `#[const_trait]` can only be applied to traits
+
+error: `#[const_trait]` attribute cannot be used on functions
   --> $DIR/attr-misuse.rs:9:1
    |
 LL | #[const_trait]
    | ^^^^^^^^^^^^^^
-LL | fn main() {}
-   | ------------ not a trait
-
-error: attribute should be applied to a trait
-  --> $DIR/attr-misuse.rs:5:5
    |
-LL |     #[const_trait]
-   |     ^^^^^^^^^^^^^^
-LL |     fn foo(self);
-   |     ------------- not a trait
+   = help: `#[const_trait]` can only be applied to traits
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs
index 0d6e4ebb408..cdd4178fc87 100644
--- a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs
+++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs
@@ -9,14 +9,14 @@
 pub trait Trait {
     #[unstable(feature = "feat", issue = "none" )]
     #[unstable_feature_bound(foo)]
-    //~^ ERROR: attribute should be applied to `impl`, trait or free function
+    //~^ ERROR: attribute cannot be used on
     fn foo();
 }
 
 #[stable(feature = "a", since = "1.1.1" )]
 impl Trait for u8 {
     #[unstable_feature_bound(foo)]
-    //~^ ERROR: attribute should be applied to `impl`, trait or free function
+    //~^ ERROR: attribute cannot be used on
     fn foo() {}
 }
 
diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr
index 90cbb32df7c..2a1ae936cfe 100644
--- a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr
+++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr
@@ -1,20 +1,18 @@
-error: attribute should be applied to `impl`, trait or free function
+error: `#[unstable_feature_bound]` attribute cannot be used on required trait methods
   --> $DIR/unstable_inherent_method.rs:11:5
    |
 LL |     #[unstable_feature_bound(foo)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     fn foo();
-   |     --------- not an `impl`, trait or free function
+   |
+   = help: `#[unstable_feature_bound]` can be applied to functions, trait impl blocks, traits
 
-error: attribute should be applied to `impl`, trait or free function
+error: `#[unstable_feature_bound]` attribute cannot be used on trait methods in impl blocks
   --> $DIR/unstable_inherent_method.rs:18:5
    |
 LL |     #[unstable_feature_bound(foo)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL |     fn foo() {}
-   |     ----------- not an `impl`, trait or free function
+   |
+   = help: `#[unstable_feature_bound]` can be applied to functions, trait impl blocks, traits
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/where-clauses/unsupported_attribute.rs b/tests/ui/where-clauses/unsupported_attribute.rs
index 33128b383b9..75213e17661 100644
--- a/tests/ui/where-clauses/unsupported_attribute.rs
+++ b/tests/ui/where-clauses/unsupported_attribute.rs
@@ -13,18 +13,18 @@ fn foo<'a, T>()
 where
     #[doc = "doc"] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
     #[doc = "doc"] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
-    #[ignore] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
-    #[ignore] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
-    #[should_panic] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
-    #[should_panic] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
-    #[macro_use] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
-    #[macro_use] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[ignore] T: Trait, //~ ERROR attribute cannot be used on
+    #[ignore] 'a: 'static, //~ ERROR attribute cannot be used on
+    #[should_panic] T: Trait, //~ ERROR attribute cannot be used on
+    #[should_panic] 'a: 'static, //~ ERROR attribute cannot be used on
+    #[macro_use] T: Trait, //~ ERROR attribute cannot be used on
+    #[macro_use] 'a: 'static, //~ ERROR attribute cannot be used on
     #[allow(unused)] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
     #[allow(unused)] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
-    #[deprecated] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
-    #[deprecated] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
-    #[automatically_derived] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
-    #[automatically_derived] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
+    #[deprecated] T: Trait, //~ ERROR attribute cannot be used on
+    #[deprecated] 'a: 'static, //~ ERROR attribute cannot be used on
+    #[automatically_derived] T: Trait, //~ ERROR attribute cannot be used on
+    #[automatically_derived] 'a: 'static, //~ ERROR attribute cannot be used on
     #[derive(Clone)] T: Trait,
     //~^ ERROR most attributes are not supported in `where` clauses
     //~| ERROR expected non-macro attribute, found attribute macro `derive`
diff --git a/tests/ui/where-clauses/unsupported_attribute.stderr b/tests/ui/where-clauses/unsupported_attribute.stderr
index ecb28039f88..411c895ed87 100644
--- a/tests/ui/where-clauses/unsupported_attribute.stderr
+++ b/tests/ui/where-clauses/unsupported_attribute.stderr
@@ -10,115 +10,115 @@ error: expected non-macro attribute, found attribute macro `derive`
 LL |     #[derive(Clone)] 'a: 'static,
    |       ^^^^^^ not a non-macro attribute
 
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:14:5
-   |
-LL |     #[doc = "doc"] T: Trait,
-   |     ^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:15:5
-   |
-LL |     #[doc = "doc"] 'a: 'static,
-   |     ^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
+error: `#[ignore]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:16:5
    |
 LL |     #[ignore] T: Trait,
    |     ^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[ignore]` can only be applied to functions
 
-error: most attributes are not supported in `where` clauses
+error: `#[ignore]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:17:5
    |
 LL |     #[ignore] 'a: 'static,
    |     ^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[ignore]` can only be applied to functions
 
-error: most attributes are not supported in `where` clauses
+error: `#[should_panic]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:18:5
    |
 LL |     #[should_panic] T: Trait,
    |     ^^^^^^^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[should_panic]` can only be applied to functions
 
-error: most attributes are not supported in `where` clauses
+error: `#[should_panic]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:19:5
    |
 LL |     #[should_panic] 'a: 'static,
    |     ^^^^^^^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[should_panic]` can only be applied to functions
 
-error: most attributes are not supported in `where` clauses
+error: `#[macro_use]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:20:5
    |
 LL |     #[macro_use] T: Trait,
    |     ^^^^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
 
-error: most attributes are not supported in `where` clauses
+error: `#[macro_use]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:21:5
    |
 LL |     #[macro_use] 'a: 'static,
    |     ^^^^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[macro_use]` can be applied to modules, extern crates, crates
 
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:22:5
+error: `#[deprecated]` attribute cannot be used on where predicates
+  --> $DIR/unsupported_attribute.rs:24:5
    |
-LL |     #[allow(unused)] T: Trait,
-   |     ^^^^^^^^^^^^^^^^
+LL |     #[deprecated] T: Trait,
+   |     ^^^^^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates
 
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:23:5
+error: `#[deprecated]` attribute cannot be used on where predicates
+  --> $DIR/unsupported_attribute.rs:25:5
    |
-LL |     #[allow(unused)] 'a: 'static,
-   |     ^^^^^^^^^^^^^^^^
+LL |     #[deprecated] 'a: 'static,
+   |     ^^^^^^^^^^^^^
    |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+   = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates
+
+error: `#[automatically_derived]` attribute cannot be used on where predicates
+  --> $DIR/unsupported_attribute.rs:26:5
+   |
+LL |     #[automatically_derived] T: Trait,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+error: `#[automatically_derived]` attribute cannot be used on where predicates
+  --> $DIR/unsupported_attribute.rs:27:5
+   |
+LL |     #[automatically_derived] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:24:5
+  --> $DIR/unsupported_attribute.rs:14:5
    |
-LL |     #[deprecated] T: Trait,
-   |     ^^^^^^^^^^^^^
+LL |     #[doc = "doc"] T: Trait,
+   |     ^^^^^^^^^^^^^^
    |
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:25:5
+  --> $DIR/unsupported_attribute.rs:15:5
    |
-LL |     #[deprecated] 'a: 'static,
-   |     ^^^^^^^^^^^^^
+LL |     #[doc = "doc"] 'a: 'static,
+   |     ^^^^^^^^^^^^^^
    |
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:26:5
+  --> $DIR/unsupported_attribute.rs:22:5
    |
-LL |     #[automatically_derived] T: Trait,
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[allow(unused)] T: Trait,
+   |     ^^^^^^^^^^^^^^^^
    |
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:27:5
+  --> $DIR/unsupported_attribute.rs:23:5
    |
-LL |     #[automatically_derived] 'a: 'static,
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[allow(unused)] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^
    |
    = help: only `#[cfg]` and `#[cfg_attr]` are supported