Rollup merge of #150072 - Bryntet:parse_no_link, r=JonathanBrouwer

Port #[no_link] to use attribute parser

Adds `#[no_link]` to the attribute parser, as well as adds tests making sure to FCW warn on `field`, `arm`, and `macrodef `
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 64f29a4..f7290bd 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -47,6 +47,7 @@
 pub(crate) mod macro_attrs;
 pub(crate) mod must_use;
 pub(crate) mod no_implicit_prelude;
+pub(crate) mod no_link;
 pub(crate) mod non_exhaustive;
 pub(crate) mod path;
 pub(crate) mod pin_v2;
diff --git a/compiler/rustc_attr_parsing/src/attributes/no_link.rs b/compiler/rustc_attr_parsing/src/attributes/no_link.rs
new file mode 100644
index 0000000..43cd1c5
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/no_link.rs
@@ -0,0 +1,14 @@
+use super::prelude::*;
+
+pub(crate) struct NoLinkParser;
+impl<S: Stage> NoArgsAttributeParser<S> for NoLinkParser {
+    const PATH: &[Symbol] = &[sym::no_link];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::ExternCrate),
+        Warn(Target::Field),
+        Warn(Target::Arm),
+        Warn(Target::MacroDef),
+    ]);
+    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoLink;
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 242e0c0..9e83ea4 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -50,6 +50,7 @@
 };
 use crate::attributes::must_use::MustUseParser;
 use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
+use crate::attributes::no_link::NoLinkParser;
 use crate::attributes::non_exhaustive::NonExhaustiveParser;
 use crate::attributes::path::PathParser as PathAttributeParser;
 use crate::attributes::pin_v2::PinV2Parser;
@@ -241,6 +242,7 @@ mod late {
         Single<WithoutArgs<MayDangleParser>>,
         Single<WithoutArgs<NoCoreParser>>,
         Single<WithoutArgs<NoImplicitPreludeParser>>,
+        Single<WithoutArgs<NoLinkParser>>,
         Single<WithoutArgs<NoMangleParser>>,
         Single<WithoutArgs<NoStdParser>>,
         Single<WithoutArgs<NonExhaustiveParser>>,
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index 177a424..fb3d9a6 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -803,6 +803,9 @@ pub enum AttributeKind {
     /// Represents `#[no_implicit_prelude]`
     NoImplicitPrelude(Span),
 
+    /// Represents `#[no_link]`
+    NoLink,
+
     /// Represents `#[no_mangle]`
     NoMangle(Span),
 
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 10b7af1..56446e8 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -70,6 +70,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
             Naked(..) => No,
             NoCore(..) => No,
             NoImplicitPrelude(..) => No,
+            NoLink => No,
             NoMangle(..) => Yes, // Needed for rustdoc
             NoStd(..) => No,
             NonExhaustive(..) => Yes, // Needed for rustdoc
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 0f206ed..dfa7826 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -240,11 +240,6 @@
     `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_with_macro =
-    `#[{$sym}]` is ignored on struct fields, match arms and macro defs
-    .warn = {-passes_previously_accepted}
-    .note = {-passes_see_issue(issue: "80564")}
-
 passes_ignored_derived_impls =
     `{$name}` has {$trait_list_len ->
       [one] a derived impl
@@ -379,10 +374,6 @@
     `must_not_suspend` attribute should be applied to a struct, enum, union, or trait
     .label = is not a struct, enum, union, or trait
 
-passes_no_link =
-    attribute should be applied to an `extern crate` item
-    .label = not an `extern crate` item
-
 passes_no_main_function =
     `main` function not found in crate `{$crate_name}`
     .here_is_main = here is a function named `main`
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index f4896a8..d8ecbbc 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -254,6 +254,7 @@ fn check_attributes(
                     | AttributeKind::LinkSection { .. }
                     | AttributeKind::MacroUse { .. }
                     | AttributeKind::MacroEscape( .. )
+                    | AttributeKind::NoLink
                     | AttributeKind::RustcLayoutScalarValidRangeStart(..)
                     | AttributeKind::RustcLayoutScalarValidRangeEnd(..)
                     | AttributeKind::RustcScalableVector { .. }
@@ -303,7 +304,6 @@ fn check_attributes(
                             self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
                         }
                         [sym::thread_local, ..] => self.check_thread_local(attr, span, target),
-                        [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target),
                         [sym::rustc_no_implicit_autorefs, ..] => {
                             self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
                         }
@@ -457,15 +457,6 @@ fn check_attributes(
         self.check_mix_no_mangle_export(hir_id, attrs);
     }
 
-    fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr_span: Span, sym: &str) {
-        self.tcx.emit_node_span_lint(
-            UNUSED_ATTRIBUTES,
-            hir_id,
-            attr_span,
-            errors::IgnoredAttrWithMacro { sym },
-        );
-    }
-
     fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
         for EiiImpl { span, inner_span, eii_macro, impl_marked_unsafe, is_default: _ } in impls {
             match target {
@@ -1199,23 +1190,6 @@ fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target)
         );
     }
 
-    /// 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 {
-            Target::ExternCrate => {}
-            // FIXME(#80564): We permit struct fields, match arms and macro defs to have an
-            // `#[no_link]` 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_link");
-            }
-            _ => {
-                self.dcx().emit_err(errors::NoLink { attr_span: attr.span(), span });
-            }
-        }
-    }
-
     /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
     fn check_rustc_legacy_const_generics(
         &self,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 8ead69d..6b3c2bd 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -80,12 +80,6 @@ pub(crate) struct OuterCrateLevelAttrSuggestion {
 #[diag(passes_inner_crate_level_attr)]
 pub(crate) struct InnerCrateLevelAttr;
 
-#[derive(LintDiagnostic)]
-#[diag(passes_ignored_attr_with_macro)]
-pub(crate) struct IgnoredAttrWithMacro<'a> {
-    pub sym: &'a str,
-}
-
 #[derive(Diagnostic)]
 #[diag(passes_should_be_applied_to_fn)]
 pub(crate) struct AttrShouldBeAppliedToFn {
@@ -255,15 +249,6 @@ pub(crate) struct Link {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_no_link)]
-pub(crate) struct NoLink {
-    #[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]
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 0cd88e2..228ea12 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -147,14 +147,6 @@
 LL | #[thread_local()]
    | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]`
 
-error: malformed `no_link` attribute input
-  --> $DIR/malformed-attrs.rs:214:1
-   |
-LL | #[no_link()]
-   | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute>
-
 error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
   --> $DIR/malformed-attrs.rs:105:1
    |
@@ -626,6 +618,15 @@
    | |                didn't expect any arguments here
    | help: must be of the form: `#[non_exhaustive]`
 
+error[E0565]: malformed `no_link` attribute input
+  --> $DIR/malformed-attrs.rs:214:1
+   |
+LL | #[no_link()]
+   | ^^^^^^^^^--^
+   | |        |
+   | |        didn't expect any arguments here
+   | help: must be of the form: `#[no_link]`
+
 error[E0539]: malformed `macro_use` attribute input
   --> $DIR/malformed-attrs.rs:216:1
    |
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 0b0dd80..1560f2b 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,4 +1,3 @@
-//~ NOTE: not an `extern crate` item
 // This is testing whether various builtin attributes signals an
 // error or warning when put in "weird" places.
 //
@@ -29,7 +28,7 @@
 //~| WARN cannot be used on crates
 //~| WARN previously accepted
 #![no_link]
-//~^ ERROR: attribute should be applied to an `extern crate` item
+//~^ ERROR: `#[no_link]` attribute cannot be used on crates
 #![export_name = "2200"]
 //~^ ERROR: attribute cannot be used on
 //~| NOTE takes precedence
@@ -60,29 +59,40 @@ mod inner { #![inline] }
 }
 
 #[no_link]
-//~^ ERROR attribute should be applied to an `extern crate` item
+//~^ ERROR `#[no_link]` attribute cannot be used on modules
 mod no_link {
-    //~^ NOTE not an `extern crate` item
-
     mod inner { #![no_link] }
-    //~^ ERROR attribute should be applied to an `extern crate` item
-    //~| NOTE not an `extern crate` item
+    //~^ ERROR `#[no_link]` attribute cannot be used on modules
 
-    #[no_link] fn f() { }
-    //~^ ERROR attribute should be applied to an `extern crate` item
-    //~| NOTE not an `extern crate` item
+    #[no_link] fn f() {
+        //~^ ERROR `#[no_link]` attribute cannot be used on functions
+        match () {
+            #[no_link]
+            //~^ WARN `#[no_link]` attribute cannot be used on match arms [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!
+            _ => ()
+        }
+    }
 
-    #[no_link] struct S;
-    //~^ ERROR attribute should be applied to an `extern crate` item
-    //~| NOTE not an `extern crate` item
+    #[no_link]
+    //~^ ERROR `#[no_link]` attribute cannot be used on structs
+    struct S {
+        #[no_link]
+        //~^ WARN `#[no_link]` attribute cannot be used on struct fields [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!
+        field: ()
+    }
 
     #[no_link]type T = S;
-    //~^ ERROR attribute should be applied to an `extern crate` item
-    //~| NOTE not an `extern crate` item
+    //~^ ERROR `#[no_link]` attribute cannot be used on type aliases
 
     #[no_link] impl S { }
-    //~^ ERROR attribute should be applied to an `extern crate` item
-    //~| NOTE not an `extern crate` item
+    //~^ ERROR `#[no_link]` attribute cannot be used on inherent impl blocks
+
+    #[no_link]
+    //~^ WARN `#[no_link]` attribute cannot be used on macro defs
+    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    macro_rules! m{() => {}}
 }
 
 #[export_name = "2200"]
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 013e529..662776e 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:12:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:1
    |
 LL | #![rustc_main]
    | ^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@
    = note: the `#[rustc_main]` attribute is used internally to specify test entry point function
 
 error: `#[macro_export]` attribute cannot be used on crates
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:10:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:9:1
    |
 LL | #![macro_export]
    | ^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@
    = help: `#[macro_export]` can only be applied to macro defs
 
 error: `#[rustc_main]` attribute cannot be used on crates
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:11:1
    |
 LL | #![rustc_main]
    | ^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@
    = help: `#[rustc_main]` can only be applied to functions
 
 error: `#[path]` attribute cannot be used on crates
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:20:1
    |
 LL | #![path = "3800"]
    | ^^^^^^^^^^^^^^^^^
@@ -33,15 +33,23 @@
    = 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:23:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:22:1
    |
 LL | #![automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: `#[automatically_derived]` can only be applied to trait impl blocks
 
+error: `#[no_link]` attribute cannot be used on crates
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1
+   |
+LL | #![no_link]
+   | ^^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
 error: `#[export_name]` attribute cannot be used on crates
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:33:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1
    |
 LL | #![export_name = "2200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +57,7 @@
    = help: `#[export_name]` can be applied to functions and statics
 
 error: `#[inline]` attribute cannot be used on crates
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:35:1
    |
 LL | #![inline]
    | ^^^^^^^^^^
@@ -57,7 +65,7 @@
    = 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:38:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:37:1
    |
 LL | #[inline]
    | ^^^^^^^^^
@@ -65,7 +73,7 @@
    = 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:43:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:42:17
    |
 LL |     mod inner { #![inline] }
    |                 ^^^^^^^^^^
@@ -73,7 +81,7 @@
    = 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:52:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:51:5
    |
 LL |     #[inline] struct S;
    |     ^^^^^^^^^
@@ -81,7 +89,7 @@
    = 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:55:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:5
    |
 LL |     #[inline] type T = S;
    |     ^^^^^^^^^
@@ -89,15 +97,63 @@
    = 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:58:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:57:5
    |
 LL |     #[inline] impl S { }
    |     ^^^^^^^^^
    |
    = help: `#[inline]` can only be applied to functions
 
+error: `#[no_link]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:61:1
+   |
+LL | #[no_link]
+   | ^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
+error: `#[no_link]` attribute cannot be used on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:64:17
+   |
+LL |     mod inner { #![no_link] }
+   |                 ^^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
+error: `#[no_link]` attribute cannot be used on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:67:5
+   |
+LL |     #[no_link] fn f() {
+   |     ^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
+error: `#[no_link]` attribute cannot be used on structs
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:77:5
+   |
+LL |     #[no_link]
+   |     ^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
+error: `#[no_link]` attribute cannot be used on type aliases
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:86:5
+   |
+LL |     #[no_link]type T = S;
+   |     ^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
+error: `#[no_link]` attribute cannot be used on inherent impl blocks
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:89:5
+   |
+LL |     #[no_link] impl S { }
+   |     ^^^^^^^^^^
+   |
+   = help: `#[no_link]` can only be applied to extern crates
+
 error: `#[export_name]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:88:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:98:1
    |
 LL | #[export_name = "2200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^
@@ -105,7 +161,7 @@
    = help: `#[export_name]` can be applied to functions and statics
 
 error: `#[export_name]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:101:17
    |
 LL |     mod inner { #![export_name="2200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^
@@ -113,7 +169,7 @@
    = help: `#[export_name]` can be applied to functions and statics
 
 error: `#[export_name]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:5
    |
 LL |     #[export_name = "2200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -121,7 +177,7 @@
    = help: `#[export_name]` can be applied to functions and statics
 
 error: `#[export_name]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:99:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:5
    |
 LL |     #[export_name = "2200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -129,7 +185,7 @@
    = help: `#[export_name]` can be applied to functions and statics
 
 error: `#[export_name]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:102:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:112:5
    |
 LL |     #[export_name = "2200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -137,29 +193,15 @@
    = help: `#[export_name]` can be applied to functions and statics
 
 error: `#[export_name]` attribute cannot be used on required trait methods
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:116:9
    |
 LL |         #[export_name = "2200"] fn foo();
    |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: `#[export_name]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks
 
-error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:62:1
-   |
-LL |   #[no_link]
-   |   ^^^^^^^^^^
-LL |
-LL | / mod no_link {
-LL | |
-LL | |
-LL | |     mod inner { #![no_link] }
-...  |
-LL | | }
-   | |_- not an `extern crate` item
-
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:8
    |
 LL |   #[repr(C)]
    |          ^
@@ -172,7 +214,7 @@
    | |_- 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:137:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:147:8
    |
 LL |   #[repr(Rust)]
    |          ^^^^
@@ -184,20 +226,14 @@
 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:31:1
-   |
-LL | #![no_link]
-   | ^^^^^^^^^^^ not an `extern crate` item
-
 warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:24:1
    |
 LL | #![no_mangle]
    | ^^^^^^^^^^^^^ `#[no_mangle]` is ignored
    |
 note: `#[export_name]` takes precedence
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:33:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1
    |
 LL | #![export_name = "2200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -208,7 +244,7 @@
    |
 
 error: `repr` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
    |
 LL | #![repr()]
    | ^^^^^^^^^^
@@ -222,86 +258,56 @@
 LL + #[repr()]
    |
 
-error: attribute should be applied to an `extern crate` item
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:67: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:71: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:75: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:79: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:83:5
-   |
-LL |     #[no_link] impl S { }
-   |     ^^^^^^^^^^ ---------- not an `extern crate` item
-
 error[E0517]: attribute should be applied to a struct, enum, or union
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127: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:121:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131: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:127:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137: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:131:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141: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:141:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151: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:145:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155: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:151:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:161: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:155:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:165: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:45:5
    |
 LL |     #[inline = "2100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
@@ -310,8 +316,35 @@
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
 
+warning: `#[no_link]` attribute cannot be used on match arms
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:70:13
+   |
+LL |             #[no_link]
+   |             ^^^^^^^^^^
+   |
+   = 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_link]` can only be applied to extern crates
+
+warning: `#[no_link]` attribute cannot be used on struct fields
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:9
+   |
+LL |         #[no_link]
+   |         ^^^^^^^^^^
+   |
+   = 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_link]` can only be applied to extern crates
+
+warning: `#[no_link]` attribute cannot be used on macro defs
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:92:5
+   |
+LL |     #[no_link]
+   |     ^^^^^^^^^^
+   |
+   = 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_link]` can only be applied to extern crates
+
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
    |
 LL | #![repr()]
    | ^^^^^^^^^^ help: remove this attribute
@@ -319,7 +352,7 @@
    = note: using `repr` with an empty list has no effect
 
 warning: `#[no_mangle]` attribute cannot be used on crates
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:24:1
    |
 LL | #![no_mangle]
    | ^^^^^^^^^^^^^
@@ -327,13 +360,13 @@
    = 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 and statics
 
-error: aborting due to 37 previous errors; 3 warnings emitted
+error: aborting due to 37 previous errors; 6 warnings emitted
 
 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:45:5
    |
 LL |     #[inline = "2100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 86506db..54ed351 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -17,18 +17,6 @@
    |         ^^^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:37:1
-   |
-LL | #[no_link]
-   | ^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:36:1
-   |
-LL | #[no_link]
-   | ^^^^^^^^^^
-
-error: unused attribute
   --> $DIR/unused-attr-duplicate.rs:34:1
    |
 LL | #![no_builtins]
@@ -41,6 +29,18 @@
    | ^^^^^^^^^^^^^^^
 
 error: unused attribute
+  --> $DIR/unused-attr-duplicate.rs:37:1
+   |
+LL | #[no_link]
+   | ^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/unused-attr-duplicate.rs:36:1
+   |
+LL | #[no_link]
+   | ^^^^^^^^^^
+
+error: unused attribute
   --> $DIR/unused-attr-duplicate.rs:41:1
    |
 LL | #[macro_use]