about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-26 22:03:48 +0000
committerbors <bors@rust-lang.org>2025-08-26 22:03:48 +0000
commit176d8dbce6a7a7a4541d1c980d4a85dfb76ce1f1 (patch)
tree5308d6f394ed0437b622d36f9ecbf6ed03d4ed55
parent160e7623e8cbbf1feab2b6e2a24733a98c7bde9c (diff)
parentcefa84aeac6eafe0593fa2dae8b26a56606addea (diff)
downloadrust-176d8dbce6a7a7a4541d1c980d4a85dfb76ce1f1.tar.gz
rust-176d8dbce6a7a7a4541d1c980d4a85dfb76ce1f1.zip
Auto merge of #145906 - samueltardieu:rollup-p8ibzhz, r=samueltardieu
Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#144499 (ci: Begin running ui tests with `rust.debuginfo-level-tests=1`)
 - rust-lang/rust#145790 (Improve dist for gnullvm hosts)
 - rust-lang/rust#145792 (Use attribute name in message for "outer attr used as inner attr" errors)
 - rust-lang/rust#145840 (rustc_codegen_ssa: More comprehensive RISC-V ELF flags)
 - rust-lang/rust#145876 (Enable building/disting standard library in stage 0)
 - rust-lang/rust#145887 (bootstrap: Don't panic if codegen-backends is set to empty)
 - rust-lang/rust#145888 (platform-support: Fix LoongArch32 host column)
 - rust-lang/rust#145892 (add a flag to codegen fn attrs for foreign items)
 - rust-lang/rust#145901 (Fix typo in comment of library/alloc/src/raw_vec/mod.rs)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl6
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/crate_level.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs17
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs18
-rw-r--r--compiler/rustc_attr_parsing/src/interface.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/lints.rs14
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs12
-rw-r--r--compiler/rustc_attr_parsing/src/target_checking.rs33
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_hir/src/lints.rs1
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs7
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs2
-rw-r--r--compiler/rustc_mir_transform/src/cross_crate_inline.rs2
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs71
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs12
-rw-r--r--compiler/rustc_passes/src/reachable.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--library/alloc/src/raw_vec/mod.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs13
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs2
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs7
-rw-r--r--src/bootstrap/src/core/builder/mod.rs28
-rw-r--r--src/bootstrap/src/core/builder/tests.rs28
-rw-r--r--src/bootstrap/src/core/config/config.rs40
-rw-r--r--src/bootstrap/src/core/config/toml/rust.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile17
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile17
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile5
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--src/tools/miri/src/helpers.rs3
-rw-r--r--tests/ui/attributes/crate-only-as-outer.rs10
-rw-r--r--tests/ui/attributes/crate-only-as-outer.stderr26
-rw-r--r--tests/ui/diagnostic-flags/colored-session-opt-error.rs4
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs52
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr589
-rw-r--r--tests/ui/issues/issue-29466.rs3
-rw-r--r--tests/ui/limits/huge-enum.rs3
-rw-r--r--tests/ui/limits/huge-enum.stderr2
-rw-r--r--tests/ui/lint/linker-warning.stderr6
-rw-r--r--tests/ui/lint/lint-misplaced-attr.stderr7
-rw-r--r--tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs2
-rw-r--r--tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr10
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.stderr6
-rw-r--r--tests/ui/panics/issue-47429-short-backtraces.rs3
-rw-r--r--tests/ui/panics/issue-47429-short-backtraces.run.stderr2
-rw-r--r--tests/ui/panics/runtime-switch.rs3
-rw-r--r--tests/ui/panics/runtime-switch.run.stderr2
55 files changed, 838 insertions, 304 deletions
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index 40e9d597530..8f24b51f1d9 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -86,6 +86,12 @@ attr_parsing_invalid_repr_hint_no_value =
 attr_parsing_invalid_since =
     'since' must be a Rust version number, such as "1.31.0"
 
+attr_parsing_invalid_style = {$is_used_as_inner ->
+        [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]`
+        *[other] the `#![{$name}]` attribute can only be used at the crate root
+    }
+    .note = This attribute does not have an `!`, which means it is applied to this {$target}
+
 attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
     .note = the value may not exceed `u16::MAX`
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
index 9175d7479e1..2fed09b85e8 100644
--- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -1,3 +1,5 @@
+use rustc_feature::AttributeType;
+
 use super::prelude::*;
 
 pub(crate) struct CrateNameParser;
@@ -7,6 +9,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
+    const TYPE: AttributeType = AttributeType::CrateLevel;
 
     // FIXME: crate name is allowed on all targets and ignored,
     //        even though it should only be valid on crates of course
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 9dad9c893f0..043bc925eac 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -12,11 +12,15 @@
 //! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
 //! contents of attributes, if an attribute appear multiple times in a list
 //!
+//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
+//! at the crate root, consider setting the `TYPE` in the parser trait to
+//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
+//!
 //! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
 
 use std::marker::PhantomData;
 
-use rustc_feature::{AttributeTemplate, template};
+use rustc_feature::{AttributeTemplate, AttributeType, template};
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol};
 use thin_vec::ThinVec;
@@ -88,6 +92,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
 
     const ALLOWED_TARGETS: AllowedTargets;
 
+    const TYPE: AttributeType = AttributeType::Normal;
+
     /// The parser has gotten a chance to accept the attributes on an item,
     /// here it can produce an attribute.
     ///
@@ -129,6 +135,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
+    const TYPE: AttributeType = AttributeType::Normal;
+
     /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
 }
@@ -175,6 +183,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
     )];
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
 
+    const TYPE: AttributeType = T::TYPE;
+
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         Some(self.1?.0)
     }
@@ -259,6 +269,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
     const PATH: &[Symbol];
     const ON_DUPLICATE: OnDuplicate<S>;
     const ALLOWED_TARGETS: AllowedTargets;
+    const TYPE: AttributeType = AttributeType::Normal;
 
     /// Create the [`AttributeKind`] given attribute's [`Span`].
     const CREATE: fn(Span) -> AttributeKind;
@@ -278,6 +289,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
     const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(Word);
+    const TYPE: AttributeType = T::TYPE;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         if let Err(span) = args.no_args() {
@@ -311,6 +323,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
+    const TYPE: AttributeType = AttributeType::Normal;
+
     /// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
     fn extend<'c>(
         cx: &'c mut AcceptContext<'_, '_, S>,
@@ -346,6 +360,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
             group.items.extend(T::extend(cx, args))
         })];
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
+    const TYPE: AttributeType = T::TYPE;
 
     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/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index 89ac1b07d16..fbd9a480fbb 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -1,5 +1,7 @@
 use std::mem;
 
+use rustc_feature::AttributeType;
+
 use super::prelude::*;
 use crate::attributes::{
     AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
@@ -154,6 +156,7 @@ 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 TYPE: AttributeType = AttributeType::CrateLevel;
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
 }
 
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index d4b9cfe00ad..b16ef7edd64 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -4,12 +4,12 @@ use std::ops::{Deref, DerefMut};
 use std::sync::LazyLock;
 
 use private::Sealed;
-use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
+use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
 use rustc_errors::{Diag, Diagnostic, Level};
-use rustc_feature::AttributeTemplate;
+use rustc_feature::{AttributeTemplate, AttributeType};
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{AttrPath, HirId};
+use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
 use rustc_session::Session;
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
@@ -80,6 +80,7 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
     pub(super) template: AttributeTemplate,
     pub(super) accept_fn: AcceptFn<S>,
     pub(super) allowed_targets: AllowedTargets,
+    pub(super) attribute_type: AttributeType,
 }
 
 type AcceptFn<S> =
@@ -129,6 +130,7 @@ macro_rules! attribute_parsers {
                                 })
                             }),
                             allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
+                            attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
                         });
                     }
 
@@ -250,6 +252,8 @@ pub trait Stage: Sized + 'static + Sealed {
     ) -> ErrorGuaranteed;
 
     fn should_emit(&self) -> ShouldEmit;
+
+    fn id_is_crate_root(id: Self::Id) -> bool;
 }
 
 // allow because it's a sealed trait
@@ -271,6 +275,10 @@ impl Stage for Early {
     fn should_emit(&self) -> ShouldEmit {
         self.emit_errors
     }
+
+    fn id_is_crate_root(id: Self::Id) -> bool {
+        id == CRATE_NODE_ID
+    }
 }
 
 // allow because it's a sealed trait
@@ -292,6 +300,10 @@ impl Stage for Late {
     fn should_emit(&self) -> ShouldEmit {
         ShouldEmit::ErrorsAndLints
     }
+
+    fn id_is_crate_root(id: Self::Id) -> bool {
+        id == CRATE_HIR_ID
+    }
 }
 
 /// used when parsing attributes for miscellaneous things *before* ast lowering
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index 60523c2877c..a3558850ef3 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -271,8 +271,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
                             };
 
                             (accept.accept_fn)(&mut cx, args);
-
-                            if !matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
+                            if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
+                                Self::check_type(accept.attribute_type, target, &mut cx);
                                 self.check_target(
                                     path.get_attribute_path(),
                                     attr.span,
diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs
index 84ae19c4fc6..b1a971eec32 100644
--- a/compiler/rustc_attr_parsing/src/lints.rs
+++ b/compiler/rustc_attr_parsing/src/lints.rs
@@ -66,5 +66,19 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
                     attr_span: *span,
                 },
             ),
+
+        &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => {
+            lint_emitter.emit_node_span_lint(
+                rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
+                *id,
+                *span,
+                session_diagnostics::InvalidAttrStyle {
+                    name: name.clone(),
+                    is_used_as_inner,
+                    target_span: (!is_used_as_inner).then_some(target_span),
+                    target,
+                },
+            )
+        }
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 72bee0ddfbf..a639b55e81f 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
 };
 use rustc_feature::AttributeTemplate;
-use rustc_hir::AttrPath;
+use rustc_hir::{AttrPath, Target};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Span, Symbol};
 
@@ -826,3 +826,13 @@ pub(crate) struct SuffixedLiteralInAttribute {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(attr_parsing_invalid_style)]
+pub(crate) struct InvalidAttrStyle {
+    pub name: AttrPath,
+    pub is_used_as_inner: bool,
+    #[note]
+    pub target_span: Option<Span>,
+    pub target: Target,
+}
diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs
index 9568b791b3f..6f4dd76fa81 100644
--- a/compiler/rustc_attr_parsing/src/target_checking.rs
+++ b/compiler/rustc_attr_parsing/src/target_checking.rs
@@ -1,13 +1,14 @@
 use std::borrow::Cow;
 
+use rustc_ast::AttrStyle;
 use rustc_errors::DiagArgValue;
-use rustc_feature::Features;
+use rustc_feature::{AttributeType, Features};
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
 use rustc_hir::{AttrPath, MethodKind, Target};
 use rustc_span::Span;
 
 use crate::AttributeParser;
-use crate::context::Stage;
+use crate::context::{AcceptContext, Stage};
 use crate::session_diagnostics::InvalidTarget;
 
 #[derive(Debug)]
@@ -68,7 +69,7 @@ pub(crate) enum Policy {
     Error(Target),
 }
 
-impl<S: Stage> AttributeParser<'_, S> {
+impl<'sess, S: Stage> AttributeParser<'sess, S> {
     pub(crate) fn check_target(
         &self,
         attr_name: AttrPath,
@@ -111,6 +112,32 @@ impl<S: Stage> AttributeParser<'_, S> {
             }
         }
     }
+
+    pub(crate) fn check_type(
+        attribute_type: AttributeType,
+        target: Target,
+        cx: &mut AcceptContext<'_, 'sess, S>,
+    ) {
+        let is_crate_root = S::id_is_crate_root(cx.target_id);
+
+        if is_crate_root {
+            return;
+        }
+
+        if attribute_type != AttributeType::CrateLevel {
+            return;
+        }
+
+        let lint = AttributeLintKind::InvalidStyle {
+            name: cx.attr_path.clone(),
+            is_used_as_inner: cx.attr_style == AttrStyle::Inner,
+            target,
+            target_span: cx.target_span,
+        };
+        let attr_span = cx.attr_span;
+
+        cx.emit_lint(lint, attr_span);
+    }
 }
 
 /// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index bf38c02e908..10aaadd5688 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -329,12 +329,18 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
             // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
             let mut e_flags: u32 = 0x0;
 
-            // Check if compressed is enabled
-            // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
-            if sess.unstable_target_features.contains(&sym::c) {
+            // Check if compression is enabled
+            // `unstable_target_features` is used here because "zca" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::zca) {
                 e_flags |= elf::EF_RISCV_RVC;
             }
 
+            // Check if RVTSO is enabled
+            // `unstable_target_features` is used here because "ztso" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::ztso) {
+                e_flags |= elf::EF_RISCV_TSO;
+            }
+
             // Set the appropriate flag based on ABI
             // This needs to match LLVM `RISCVELFStreamer.cpp`
             match &*sess.target.llvm_abiname {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 77096822fdc..13419bcb22c 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -570,7 +570,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
     // core/std/allocators/etc. For example symbols used to hook up allocation
     // are not considered for export
     let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
-    let is_extern = codegen_fn_attrs.contains_extern_indicator(tcx, sym_def_id);
+    let is_extern = codegen_fn_attrs.contains_extern_indicator();
     let std_internal =
         codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 6b0bd64102c..961bb788149 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -385,6 +385,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
 
     // Foreign items by default use no mangling for their symbol name.
     if tcx.is_foreign_item(did) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::FOREIGN_ITEM;
+
         // There's a few exceptions to this rule though:
         if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
             // * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs
index 061ec786dc8..0b24052b453 100644
--- a/compiler/rustc_hir/src/lints.rs
+++ b/compiler/rustc_hir/src/lints.rs
@@ -35,4 +35,5 @@ pub enum AttributeLintKind {
     IllFormedAttributeInput { suggestions: Vec<String> },
     EmptyAttribute { first_span: Span },
     InvalidTarget { name: AttrPath, target: Target, applied: Vec<String>, only: &'static str },
+    InvalidStyle { name: AttrPath, is_used_as_inner: bool, target: Target, target_span: Span },
 }
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 78cafe8566b..866736f74a0 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -2,7 +2,6 @@ use std::borrow::Cow;
 
 use rustc_abi::Align;
 use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
-use rustc_hir::def_id::DefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::Symbol;
 use rustc_target::spec::SanitizerSet;
@@ -161,6 +160,8 @@ bitflags::bitflags! {
         const ALLOCATOR_ZEROED          = 1 << 14;
         /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
         const NO_BUILTINS               = 1 << 15;
+        /// Marks foreign items, to make `contains_extern_indicator` cheaper.
+        const FOREIGN_ITEM              = 1 << 16;
     }
 }
 rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
@@ -194,8 +195,8 @@ impl CodegenFnAttrs {
     /// * `#[linkage]` is present
     ///
     /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
-    pub fn contains_extern_indicator(&self, tcx: TyCtxt<'_>, did: DefId) -> bool {
-        if tcx.is_foreign_item(did) {
+    pub fn contains_extern_indicator(&self) -> bool {
+        if self.flags.contains(CodegenFnAttrFlags::FOREIGN_ITEM) {
             return false;
         }
 
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 533066bdef9..6b45b2dc3ff 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -149,7 +149,7 @@ impl<'tcx> MonoItem<'tcx> {
         // instantiation:
         // We emit an unused_attributes lint for this case, which should be kept in sync if possible.
         let codegen_fn_attrs = tcx.codegen_instance_attrs(instance.def);
-        if codegen_fn_attrs.contains_extern_indicator(tcx, instance.def.def_id())
+        if codegen_fn_attrs.contains_extern_indicator()
             || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
         {
             return InstantiationMode::GloballyShared { may_conflict: false };
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 03fdf9fbac5..b186c2bd775 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -18,7 +18,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
     // If this has an extern indicator, then this function is globally shared and thus will not
     // generate cgu-internal copies which would make it cross-crate inlinable.
-    if codegen_fn_attrs.contains_extern_indicator(tcx, def_id.into()) {
+    if codegen_fn_attrs.contains_extern_indicator() {
         return false;
     }
 
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 00a41e31a02..3be06a3704c 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -462,8 +462,10 @@ passes_object_lifetime_err =
     {$repr}
 
 passes_outer_crate_level_attr =
-    crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+    crate-level attribute should be an inner attribute
 
+passes_outer_crate_level_attr_suggestion =
+    add a `!`
 
 passes_panic_unwind_without_std =
     unwinding panics are not supported without std
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 7aef60b7b91..3a79176f914 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -369,24 +369,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
             if hir_id != CRATE_HIR_ID {
                 match attr {
-                    // FIXME(jdonszelmann) move to attribute parsing when validation gets better there
-                    &Attribute::Parsed(AttributeKind::CrateName {
-                        attr_span: span, style, ..
-                    }) => match style {
-                        ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
-                            UNUSED_ATTRIBUTES,
-                            hir_id,
-                            span,
-                            errors::OuterCrateLevelAttr,
-                        ),
-                        ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
-                            UNUSED_ATTRIBUTES,
-                            hir_id,
-                            span,
-                            errors::InnerCrateLevelAttr,
-                        ),
-                    },
-                    Attribute::Parsed(_) => { /* not crate-level */ }
+                    Attribute::Parsed(_) => { /* Already validated. */ }
                     Attribute::Unparsed(attr) => {
                         // FIXME(jdonszelmann): remove once all crate-level attrs are parsed and caught by
                         // the above
@@ -397,12 +380,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                                 .and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
                         {
                             match attr.style {
-                                ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
-                                    UNUSED_ATTRIBUTES,
-                                    hir_id,
-                                    attr.span,
-                                    errors::OuterCrateLevelAttr,
-                                ),
+                                ast::AttrStyle::Outer => {
+                                    let attr_span = attr.span;
+                                    let bang_position = self
+                                        .tcx
+                                        .sess
+                                        .source_map()
+                                        .span_until_char(attr_span, '[')
+                                        .shrink_to_hi();
+
+                                    self.tcx.emit_node_span_lint(
+                                        UNUSED_ATTRIBUTES,
+                                        hir_id,
+                                        attr.span,
+                                        errors::OuterCrateLevelAttr {
+                                            suggestion: errors::OuterCrateLevelAttrSuggestion {
+                                                bang_position,
+                                            },
+                                        },
+                                    )
+                                }
                                 ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
                                     UNUSED_ATTRIBUTES,
                                     hir_id,
@@ -495,7 +492,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 {
                     let attrs = self.tcx.codegen_fn_attrs(did);
                     // Not checking naked as `#[inline]` is forbidden for naked functions anyways.
-                    if attrs.contains_extern_indicator(self.tcx, did.into()) {
+                    if attrs.contains_extern_indicator() {
                         self.tcx.emit_node_span_lint(
                             UNUSED_ATTRIBUTES,
                             hir_id,
@@ -1851,12 +1848,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         {
             if hir_id != CRATE_HIR_ID {
                 match style {
-                    Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
-                        UNUSED_ATTRIBUTES,
-                        hir_id,
-                        attr.span(),
-                        errors::OuterCrateLevelAttr,
-                    ),
+                    Some(ast::AttrStyle::Outer) => {
+                        let attr_span = attr.span();
+                        let bang_position = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_until_char(attr_span, '[')
+                            .shrink_to_hi();
+
+                        self.tcx.emit_node_span_lint(
+                            UNUSED_ATTRIBUTES,
+                            hir_id,
+                            attr_span,
+                            errors::OuterCrateLevelAttr {
+                                suggestion: errors::OuterCrateLevelAttrSuggestion { bang_position },
+                            },
+                        )
+                    }
                     Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
                         UNUSED_ATTRIBUTES,
                         hir_id,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 10cd9df4816..fc33405d455 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -706,7 +706,7 @@ fn has_allow_dead_code_or_lang_attr(
 
             // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
             // forcefully, e.g., for placing it in a specific section.
-            cg_attrs.contains_extern_indicator(tcx, def_id.into())
+            cg_attrs.contains_extern_indicator()
                 || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
                 || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
         }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 4fec6b0798a..01972067978 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -64,7 +64,17 @@ pub(crate) struct MixedExportNameAndNoMangle {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_outer_crate_level_attr)]
-pub(crate) struct OuterCrateLevelAttr;
+pub(crate) struct OuterCrateLevelAttr {
+    #[subdiagnostic]
+    pub suggestion: OuterCrateLevelAttrSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(passes_outer_crate_level_attr_suggestion, style = "verbose")]
+pub(crate) struct OuterCrateLevelAttrSuggestion {
+    #[suggestion_part(code = "!")]
+    pub bang_position: Span,
+}
 
 #[derive(LintDiagnostic)]
 #[diag(passes_inner_crate_level_attr)]
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 6cd8a54ecf4..d1a703fc5d8 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -183,7 +183,7 @@ impl<'tcx> ReachableContext<'tcx> {
             } else {
                 CodegenFnAttrs::EMPTY
             };
-            let is_extern = codegen_attrs.contains_extern_indicator(self.tcx, search_item.into());
+            let is_extern = codegen_attrs.contains_extern_indicator();
             if is_extern {
                 self.reachable_symbols.insert(search_item);
             }
@@ -425,7 +425,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     }
 
     let codegen_attrs = tcx.codegen_fn_attrs(def_id);
-    codegen_attrs.contains_extern_indicator(tcx, def_id.into())
+    codegen_attrs.contains_extern_indicator()
         // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
         // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
         // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5d140cc6117..585968044bf 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2419,9 +2419,11 @@ symbols! {
         yield_expr,
         ymm_reg,
         yreg,
+        zca,
         zfh,
         zfhmin,
         zmm_reg,
+        ztso,
         // tidy-alphabetical-end
     }
 }
diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs
index 40716755aad..fd05f9ca464 100644
--- a/library/alloc/src/raw_vec/mod.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -155,7 +155,7 @@ impl RawVecInner<Global> {
 }
 
 // Tiny Vecs are dumb. Skip to:
-// - 8 if the element size is 1, because any heap allocators is likely
+// - 8 if the element size is 1, because any heap allocator is likely
 //   to round up a request of less than 8 bytes to at least 8 bytes.
 // - 4 if elements are moderate-sized (<= 1 KiB).
 // - 1 otherwise, to avoid wasting too much space for very short Vecs.
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index a4976139fe9..d30005c8d51 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -167,8 +167,13 @@ impl Step for Std {
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let target = self.target;
 
-        // We already have std ready to be used for stage 0.
-        if self.build_compiler.stage == 0 {
+        // In most cases, we already have the std ready to be used for stage 0.
+        // However, if we are doing a local rebuild (so the build compiler can compile the standard
+        // library even on stage 0), and we're cross-compiling (so the stage0 standard library for
+        // *target* is not available), we still allow the stdlib to be built here.
+        if self.build_compiler.stage == 0
+            && !(builder.local_rebuild && target != builder.host_target)
+        {
             let compiler = self.build_compiler;
             builder.ensure(StdLink::from_std(self, compiler));
 
@@ -1332,9 +1337,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
         cargo.env("CFG_OMIT_GIT_HASH", "1");
     }
 
-    if let Some(backend) = builder.config.default_codegen_backend(target) {
-        cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
-    }
+    cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
 
     let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
     let target_config = builder.config.target_config.get(&target);
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index a6156cad6fc..abe79405984 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1850,7 +1850,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}
             // Tells compiletest which codegen backend to use.
             // It is used to e.g. ignore tests that don't support that codegen backend.
             cmd.arg("--default-codegen-backend")
-                .arg(builder.config.default_codegen_backend(compiler.host).unwrap().name());
+                .arg(builder.config.default_codegen_backend(compiler.host).name());
         }
 
         if builder.build.config.llvm_enzyme {
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 9c417952a5f..cdf6fe573e5 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1323,12 +1323,7 @@ impl Builder<'_> {
 
             if let Some(limit) = limit
                 && (build_compiler_stage == 0
-                    || self
-                        .config
-                        .default_codegen_backend(target)
-                        .cloned()
-                        .unwrap_or_default()
-                        .is_llvm())
+                    || self.config.default_codegen_backend(target).is_llvm())
             {
                 rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
             }
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 27e416359a9..f794f4e079a 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1435,22 +1435,30 @@ impl<'a> Builder<'a> {
         // FIXME: make the `Std` step return some type-level "proof" that std was indeed built,
         // and then require passing that to all Cargo invocations that we do.
 
-        // The "stage 0" std is always precompiled and comes with the stage0 compiler, so we have
-        // special logic for it, to avoid creating needless and confusing Std steps that don't
+        // The "stage 0" std is almost always precompiled and comes with the stage0 compiler, so we
+        // have special logic for it, to avoid creating needless and confusing Std steps that don't
         // actually build anything.
+        // We only allow building the stage0 stdlib if we do a local rebuild, so the stage0 compiler
+        // actually comes from in-tree sources, and we're cross-compiling, so the stage0 for the
+        // given `target` is not available.
         if compiler.stage == 0 {
             if target != compiler.host {
-                panic!(
-                    r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
+                if self.local_rebuild {
+                    self.ensure(Std::new(compiler, target))
+                } else {
+                    panic!(
+                        r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
 You have to build a stage1 compiler for `{}` first, and then use it to build a standard library for `{target}`.
+Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler built from in-tree sources.
 ",
-                    compiler.host
-                )
+                        compiler.host
+                    )
+                }
+            } else {
+                // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
+                self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
+                None
             }
-
-            // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
-            self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
-            None
         } else {
             // This step both compiles the std and links it into the compiler's sysroot.
             // Yes, it's quite magical and side-effecty.. would be nice to refactor later.
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index f7067d11450..3c2cb782850 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -854,6 +854,18 @@ mod snapshot {
     }
 
     #[test]
+    fn build_library_stage_0_local_rebuild() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("build")
+                .path("library")
+                .stage(0)
+                .targets(&[TEST_TRIPLE_1])
+                .args(&["--set", "build.local-rebuild=true"])
+                .render_steps(), @"[build] rustc 0 <host> -> std 0 <target1>");
+    }
+
+    #[test]
     fn build_library_stage_1() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
@@ -1697,6 +1709,22 @@ mod snapshot {
     }
 
     #[test]
+    fn dist_library_stage_0_local_rebuild() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("dist")
+                .path("rust-std")
+                .stage(0)
+                .targets(&[TEST_TRIPLE_1])
+                .args(&["--set", "build.local-rebuild=true"])
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> std 0 <target1>
+        [build] rustc 0 <host> -> RustInstaller 1 <host>
+        [dist] rustc 0 <host> -> std 0 <target1>
+        ");
+    }
+
+    #[test]
     fn check_compiler_no_explicit_stage() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 3e9c8ccb4fa..a8eb563015f 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -969,31 +969,38 @@ impl Config {
             | Subcommand::Vendor { .. } => flags_stage.unwrap_or(0),
         };
 
-        // Now check that the selected stage makes sense, and if not, print a warning and end
+        let local_rebuild = build_local_rebuild.unwrap_or(false);
+
+        let check_stage0 = |kind: &str| {
+            if local_rebuild {
+                eprintln!("WARNING: running {kind} in stage 0. This might not work as expected.");
+            } else {
+                eprintln!(
+                    "ERROR: cannot {kind} anything on stage 0. Use at least stage 1 or set build.local-rebuild=true and use a stage0 compiler built from in-tree sources."
+                );
+                exit!(1);
+            }
+        };
+
+        // Now check that the selected stage makes sense, and if not, print an error and end
         match (stage, &flags_cmd) {
             (0, Subcommand::Build { .. }) => {
-                eprintln!("ERROR: cannot build anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("build");
             }
             (0, Subcommand::Check { .. }) => {
-                eprintln!("ERROR: cannot check anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("check");
             }
             (0, Subcommand::Doc { .. }) => {
-                eprintln!("ERROR: cannot document anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("doc");
             }
             (0, Subcommand::Clippy { .. }) => {
-                eprintln!("ERROR: cannot run clippy on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("clippy");
             }
             (0, Subcommand::Dist) => {
-                eprintln!("ERROR: cannot dist anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("dist");
             }
             (0, Subcommand::Install) => {
-                eprintln!("ERROR: cannot install anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("install");
             }
             _ => {}
         }
@@ -1234,7 +1241,7 @@ impl Config {
             llvm_use_libcxx: llvm_use_libcxx.unwrap_or(false),
             llvm_use_linker,
             llvm_version_suffix,
-            local_rebuild: build_local_rebuild.unwrap_or(false),
+            local_rebuild,
             locked_deps: build_locked_deps.unwrap_or(false),
             low_priority: build_low_priority.unwrap_or(false),
             mandir: install_mandir.map(PathBuf::from),
@@ -1663,8 +1670,9 @@ impl Config {
 
     /// Returns the codegen backend that should be configured as the *default* codegen backend
     /// for a rustc compiled by bootstrap.
-    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<&CodegenBackendKind> {
-        self.enabled_codegen_backends(target).first()
+    pub fn default_codegen_backend(&self, target: TargetSelection) -> &CodegenBackendKind {
+        // We're guaranteed to have always at least one codegen backend listed.
+        self.enabled_codegen_backends(target).first().unwrap()
     }
 
     pub fn jemalloc(&self, target: TargetSelection) -> bool {
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index 7f111094c3f..c54df456d52 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -415,6 +415,10 @@ pub(crate) fn parse_codegen_backends(
         };
         found_backends.push(backend);
     }
+    if found_backends.is_empty() {
+        eprintln!("ERROR: `{section}.codegen-backends` should not be set to `[]`");
+        exit!(1);
+    }
     found_backends
 }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 073954e9337..606d88d3db4 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -526,4 +526,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "The `optimized-compiler-builtins` option now accepts a path to an existing compiler-rt builtins library.",
     },
+    ChangeInfo {
+        change_id: 145876,
+        severity: ChangeSeverity::Info,
+        summary: "It is now possible to `check/build/dist` the standard stage 0 library if you use a stage0 rustc built from in-tree sources. This is useful for quickly cross-compiling the standard library. You have to enable build.local-rebuild for this to work.",
+    },
 ];
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
index cdbc1cda025..0bb51af817a 100644
--- a/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
@@ -26,23 +26,10 @@ ENV CC_aarch64_pc_windows_gnullvm=aarch64-w64-mingw32-clang \
 
 ENV HOST=aarch64-pc-windows-gnullvm
 
-# We are bootstrapping this target and cannot use previously built artifacts.
-# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
-# despite no such directory existing:
-# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
-# llvm
-# stage2
-ENV NO_DOWNLOAD_CI_LLVM 1
-
 ENV RUST_CONFIGURE_ARGS \
-    --enable-extended \
+    --enable-full-tools \
     --enable-profiler \
     --enable-sanitizers \
-    --disable-docs \
-    --set llvm.download-ci-llvm=false \
-    --set rust.llvm-tools=false
-# LLVM cross tools are not installed into expected location so copying fails.
-# Probably will solve itself once this target can host itself on Windows.
-# --enable-full-tools \
+    --disable-docs
 
 ENV SCRIPT python3 ../x.py dist --host $HOST --target $HOST
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
index 1ee3951beb5..da0c065c854 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
@@ -28,23 +28,10 @@ ENV CC_i686_pc_windows_gnullvm=i686-w64-mingw32-clang \
 ENV HOST=x86_64-pc-windows-gnullvm
 ENV TARGETS=i686-pc-windows-gnullvm,x86_64-pc-windows-gnullvm
 
-# We are bootstrapping this target and cannot use previously built artifacts.
-# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
-# despite no such directory existing:
-# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
-# llvm
-# stage2
-ENV NO_DOWNLOAD_CI_LLVM 1
-
 ENV RUST_CONFIGURE_ARGS \
-    --enable-extended \
+    --enable-full-tools \
     --enable-profiler \
     --enable-sanitizers \
-    --disable-docs \
-    --set llvm.download-ci-llvm=false \
-    --set rust.llvm-tools=false
-# LLVM cross tools are not installed into expected location so copying fails.
-# Probably will solve itself once these targets can host themselves on Windows.
-# --enable-full-tools \
+    --disable-docs
 
 ENV SCRIPT python3 ../x.py dist --host $HOST --target $TARGETS
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index b97568b0819..5052d86f0ac 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -38,11 +38,15 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-debug \
       --enable-lld \
+      --set rust.debuginfo-level-tests=1 \
       --set llvm.use-linker=lld \
       --set target.x86_64-unknown-linux-gnu.linker=clang \
       --set target.x86_64-unknown-linux-gnu.cc=clang \
       --set target.x86_64-unknown-linux-gnu.cxx=clang++
 
+# This job checks:
+# - That ui tests can be built with `-Cdebuginfo=1`
+
 # This job appears to be checking two separate things:
 # - That we can build the compiler with `--enable-debug`
 #   (without necessarily testing the result).
@@ -51,4 +55,5 @@ ENV RUST_CONFIGURE_ARGS \
 
 ENV SCRIPT \
   python3 ../x.py --stage 2 build && \
+  python3 ../x.py --stage 2 test tests/ui && \
   python3 ../x.py --stage 2 test tests/run-make
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 22d32a29b36..2f815bcd141 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -328,8 +328,8 @@ target | std | host | notes
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
 [`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |   | LoongArch64 OpenHarmony
-[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32D ABI)
-[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32S ABI)
+[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * |   | LoongArch32 Bare-metal (ILP32D ABI)
+[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |   | LoongArch32 Bare-metal (ILP32S ABI)
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 [`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) |  |  | Motorola 680x0
 `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index b16924babd1..d02952eb487 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -190,5 +190,5 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
 /// and a rustc warning would be triggered, see #15301
 fn fn_is_externally_exported(cx: &LateContext<'_>, def_id: DefId) -> bool {
     let attrs = cx.tcx.codegen_fn_attrs(def_id);
-    attrs.contains_extern_indicator(cx.tcx, def_id)
+    attrs.contains_extern_indicator()
 }
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index d9e374c414c..ae1b25f8857 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -279,7 +279,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
                                 return None;
                             }
                             let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
-                            if codegen_fn_attrs.contains_extern_indicator(tcx, local_def_id.into())
+                            if codegen_fn_attrs.contains_extern_indicator()
                                 || codegen_fn_attrs
                                     .flags
                                     .contains(CodegenFnAttrFlags::USED_COMPILER)
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 1b5d9d50996..e0c077e9931 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -134,8 +134,7 @@ pub fn iter_exported_symbols<'tcx>(
     for def_id in crate_items.definitions() {
         let exported = tcx.def_kind(def_id).has_codegen_attrs() && {
             let codegen_attrs = tcx.codegen_fn_attrs(def_id);
-            codegen_attrs.contains_extern_indicator(tcx, def_id.into())
-                || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
+            codegen_attrs.contains_extern_indicator()
                 || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
                 || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
         };
diff --git a/tests/ui/attributes/crate-only-as-outer.rs b/tests/ui/attributes/crate-only-as-outer.rs
new file mode 100644
index 00000000000..5a7d916c90d
--- /dev/null
+++ b/tests/ui/attributes/crate-only-as-outer.rs
@@ -0,0 +1,10 @@
+#![deny(unused)]
+#[crate_name = "owo"]
+//~^ ERROR: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+
+fn main() {}
+
+mod inner {
+    #![crate_name = "iwi"]
+    //~^ ERROR: the `#![crate_name]` attribute can only be used at the crate root
+}
diff --git a/tests/ui/attributes/crate-only-as-outer.stderr b/tests/ui/attributes/crate-only-as-outer.stderr
new file mode 100644
index 00000000000..270f02af987
--- /dev/null
+++ b/tests/ui/attributes/crate-only-as-outer.stderr
@@ -0,0 +1,26 @@
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/crate-only-as-outer.rs:2:1
+   |
+LL | #[crate_name = "owo"]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this function
+  --> $DIR/crate-only-as-outer.rs:5:1
+   |
+LL | fn main() {}
+   | ^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/crate-only-as-outer.rs:1:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
+
+error: the `#![crate_name]` attribute can only be used at the crate root
+  --> $DIR/crate-only-as-outer.rs:8:5
+   |
+LL |     #![crate_name = "iwi"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.rs b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
index e850345fbf1..1c411048385 100644
--- a/tests/ui/diagnostic-flags/colored-session-opt-error.rs
+++ b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
@@ -1,4 +1,8 @@
 //@ check-pass
 //@ ignore-windows
 //@ compile-flags: -Cremark=foo --error-format=human --color=always
+
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 fn main() {}
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 60666481bec..3d814700d98 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
@@ -482,21 +482,26 @@ mod no_implicit_prelude {
 
 #[reexport_test_harness_main = "2900"]
 //~^ WARN crate-level attribute should be
+//~| HELP add a `!`
 mod reexport_test_harness_main {
     mod inner { #![reexport_test_harness_main="2900"] }
     //~^ WARN crate-level attribute should be
 
     #[reexport_test_harness_main = "2900"] fn f() { }
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 
     #[reexport_test_harness_main = "2900"] struct S;
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 
     #[reexport_test_harness_main = "2900"] type T = S;
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 
     #[reexport_test_harness_main = "2900"] impl S { }
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 }
 
 // Cannot feed "2700" to `#[macro_escape]` without signaling an error.
@@ -534,21 +539,26 @@ mod macro_escape {
 
 #[no_std]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod no_std {
     mod inner { #![no_std] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[no_std] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_std] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_std] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_std] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 // At time of authorship, #[proc_macro_derive = "2500"] signals error
@@ -760,21 +770,26 @@ mod must_use {
 
 #[windows_subsystem = "windows"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod windows_subsystem {
     mod inner { #![windows_subsystem="windows"] }
     //~^ WARN crate-level attribute should be in the root module
 
     #[windows_subsystem = "windows"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[windows_subsystem = "windows"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[windows_subsystem = "windows"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[windows_subsystem = "windows"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 // BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
@@ -782,135 +797,170 @@ mod windows_subsystem {
 #[crate_name = "0900"]
 //~^ WARN crate-level attribute should be an inner attribute
 mod crate_name {
+//~^ NOTE This attribute does not have an `!`, which means it is applied to this module
     mod inner { #![crate_name="0900"] }
-//~^ WARN crate-level attribute should be in the root module
+//~^ WARN the `#![crate_name]` attribute can only be used at the crate root
 
     #[crate_name = "0900"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this function
 
     #[crate_name = "0900"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this struct
 
     #[crate_name = "0900"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this type alias
 
     #[crate_name = "0900"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this implementation block
 }
 
 #[crate_type = "0800"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod crate_type {
     mod inner { #![crate_type="0800"] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[crate_type = "0800"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[crate_type = "0800"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[crate_type = "0800"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[crate_type = "0800"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[feature(x0600)]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod feature {
     mod inner { #![feature(x0600)] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[feature(x0600)] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[feature(x0600)] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[feature(x0600)] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[feature(x0600)] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 
 #[no_main]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod no_main_1 {
     mod inner { #![no_main] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[no_main] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_main] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_main] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_main] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[no_builtins]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod no_builtins {
     mod inner { #![no_builtins] }
     //~^ WARN crate-level attribute should be in the root module
 
     #[no_builtins] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_builtins] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_builtins] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_builtins] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[recursion_limit="0200"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod recursion_limit {
     mod inner { #![recursion_limit="0200"] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[recursion_limit="0200"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[recursion_limit="0200"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[recursion_limit="0200"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[recursion_limit="0200"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[type_length_limit="0100"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod type_length_limit {
     mod inner { #![type_length_limit="0100"] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[type_length_limit="0100"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[type_length_limit="0100"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[type_length_limit="0100"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[type_length_limit="0100"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 fn main() {}
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 7488c68b59f..65e3d29e269 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:506:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:511:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ 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:503:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
@@ -198,20 +198,30 @@ note: the lint level is defined here
 LL | #![warn(unused_attributes, unknown_lints)]
    |         ^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+warning: crate-level attribute should be an inner attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:535:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:1
    |
 LL | #[no_std]
    | ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![no_std]
+   |  +
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:1
    |
 LL |   #[link()]
    |   ^^^^^^^^^
@@ -226,53 +236,82 @@ 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: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771: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:782:1
    |
-LL | #[crate_name = "0900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+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:801:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:820:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:845:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:840:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:870:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:859:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:894:1
    |
 LL | #[no_builtins]
    | ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:878:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:918:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:897:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:942:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:72:1
@@ -321,67 +360,107 @@ LL |     #[macro_export] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487: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:489:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:492:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:495:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:498:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:498:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![reexport_test_harness_main = "2900"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544: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:541:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:544:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:547:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:550:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_std] impl S { }
+   |      +
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:17
    |
 LL |     mod inner { #![link()] }
    |     ------------^^^^^^^^^^-- not an `extern` block
@@ -389,7 +468,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:696:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
    |
 LL |     #[link()] fn f() { }
    |     ^^^^^^^^^ ---------- not an `extern` block
@@ -397,7 +476,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:701:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
    |
 LL |     #[link()] struct S;
    |     ^^^^^^^^^ --------- not an `extern` block
@@ -405,7 +484,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:706:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
    |
 LL |     #[link()] type T = S;
    |     ^^^^^^^^^ ----------- not an `extern` block
@@ -413,7 +492,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:711:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
    |
 LL |     #[link()] impl S { }
    |     ^^^^^^^^^ ---------- not an `extern` block
@@ -421,7 +500,7 @@ 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:716:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
    |
 LL |     #[link()] extern "Rust" {}
    |     ^^^^^^^^^
@@ -429,244 +508,354 @@ 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: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775: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:767:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5
    |
 LL |     #[windows_subsystem = "windows"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:770:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782: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:773:5
    |
-LL |     #[windows_subsystem = "windows"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+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:776:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
    |
-LL |     #[windows_subsystem = "windows"] impl S { }
+LL |     #[windows_subsystem = "windows"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785: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:788:5
+help: add a `!`
    |
-LL |     #[crate_name = "0900"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+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:791:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790: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:794:5
+LL |     #[windows_subsystem = "windows"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-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:797:5
+help: add a `!`
    |
-LL |     #[crate_name = "0900"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #![windows_subsystem = "windows"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825: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:807:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:828:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:810:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:832:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:813:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:816:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![crate_type = "0800"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:849: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:826:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:852:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:829:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:856:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:832:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:835:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:864:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![feature(x0600)] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:874: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:846:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:849:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:852:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:885:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:855:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:889:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_main] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:898: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:865:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:901:5
    |
 LL |     #[no_builtins] fn f() { }
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:868:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:905:5
    |
 LL |     #[no_builtins] struct S;
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:871:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:5
    |
 LL |     #[no_builtins] type T = S;
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:874:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:913:5
    |
 LL |     #[no_builtins] impl S { }
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_builtins] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:922: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:884:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:925:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:887:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:929:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:890:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:933:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:893:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:937:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![recursion_limit="0200"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:900:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:946: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:903:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:949:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:906:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:953:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:909:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:957:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+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:912:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:961:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![type_length_limit="0100"] impl S { }
+   |      +
 
 warning: `#[macro_use]` attribute cannot be used on functions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5
@@ -993,7 +1182,7 @@ LL |     #[no_implicit_prelude] impl S { }
    = help: `#[no_implicit_prelude]` can be applied to modules and crates
 
 warning: `#[macro_escape]` attribute cannot be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
@@ -1002,7 +1191,7 @@ LL |     #[macro_escape] fn f() { }
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[macro_escape]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
@@ -1011,7 +1200,7 @@ LL |     #[macro_escape] struct S;
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[macro_escape]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
@@ -1020,7 +1209,7 @@ LL |     #[macro_escape] type T = S;
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
@@ -1029,7 +1218,7 @@ LL |     #[macro_escape] impl S { }
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[cold]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:1
    |
 LL | #[cold]
    | ^^^^^^^
@@ -1038,7 +1227,7 @@ LL | #[cold]
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[cold]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:578:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:588:17
    |
 LL |     mod inner { #![cold] }
    |                 ^^^^^^^^
@@ -1047,7 +1236,7 @@ LL |     mod inner { #![cold] }
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[cold]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:586:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:596:5
    |
 LL |     #[cold] struct S;
    |     ^^^^^^^
@@ -1056,7 +1245,7 @@ LL |     #[cold] struct S;
    = 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:592:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:602:5
    |
 LL |     #[cold] type T = S;
    |     ^^^^^^^
@@ -1065,7 +1254,7 @@ LL |     #[cold] type T = S;
    = 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:598:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:608:5
    |
 LL |     #[cold] impl S { }
    |     ^^^^^^^
@@ -1074,7 +1263,7 @@ LL |     #[cold] impl S { }
    = 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:605:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:1
    |
 LL | #[link_name = "1900"]
    | ^^^^^^^^^^^^^^^^^^^^^
@@ -1083,7 +1272,7 @@ LL | #[link_name = "1900"]
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on foreign modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:621:5
    |
 LL |     #[link_name = "1900"]
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1092,7 +1281,7 @@ LL |     #[link_name = "1900"]
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:618:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:628:17
    |
 LL |     mod inner { #![link_name="1900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^
@@ -1101,7 +1290,7 @@ LL |     mod inner { #![link_name="1900"] }
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:5
    |
 LL |     #[link_name = "1900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1110,7 +1299,7 @@ LL |     #[link_name = "1900"] fn f() { }
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:640:5
    |
 LL |     #[link_name = "1900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1119,7 +1308,7 @@ LL |     #[link_name = "1900"] struct S;
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
    |
 LL |     #[link_name = "1900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1128,7 +1317,7 @@ LL |     #[link_name = "1900"] type T = S;
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
    |
 LL |     #[link_name = "1900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1137,7 +1326,7 @@ LL |     #[link_name = "1900"] impl S { }
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_section]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
    |
 LL | #[link_section = "1800"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1146,7 +1335,7 @@ LL | #[link_section = "1800"]
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:17
    |
 LL |     mod inner { #![link_section="1800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
@@ -1155,7 +1344,7 @@ LL |     mod inner { #![link_section="1800"] }
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
    |
 LL |     #[link_section = "1800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1164,7 +1353,7 @@ LL |     #[link_section = "1800"] struct S;
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
    |
 LL |     #[link_section = "1800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1173,7 +1362,7 @@ LL |     #[link_section = "1800"] type T = S;
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
    |
 LL |     #[link_section = "1800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1182,7 +1371,7 @@ LL |     #[link_section = "1800"] impl S { }
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[must_use]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
@@ -1191,7 +1380,7 @@ LL | #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 warning: `#[must_use]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:17
    |
 LL |     mod inner { #![must_use] }
    |                 ^^^^^^^^^^^^
@@ -1200,7 +1389,7 @@ LL |     mod inner { #![must_use] }
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 warning: `#[must_use]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
    |
 LL |     #[must_use] type T = S;
    |     ^^^^^^^^^^^
@@ -1209,7 +1398,7 @@ LL |     #[must_use] type T = S;
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 warning: `#[must_use]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
    |
 LL |     #[must_use] impl S { }
    |     ^^^^^^^^^^^
@@ -1217,6 +1406,76 @@ LL |     #[must_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: `#[must_use]` can be applied to functions, data types, unions, and traits
 
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:1
+   |
+LL | #[crate_name = "0900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:1
+   |
+LL | / mod crate_name {
+LL | |
+LL | |     mod inner { #![crate_name="0900"] }
+...  |
+LL | | }
+   | |_^
+
+warning: the `#![crate_name]` attribute can only be used at the crate root
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:17
+   |
+LL |     mod inner { #![crate_name="0900"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:5
+   |
+LL |     #[crate_name = "0900"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this function
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:28
+   |
+LL |     #[crate_name = "0900"] fn f() { }
+   |                            ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:5
+   |
+LL |     #[crate_name = "0900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this struct
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:28
+   |
+LL |     #[crate_name = "0900"] struct S;
+   |                            ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:5
+   |
+LL |     #[crate_name = "0900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this type alias
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:28
+   |
+LL |     #[crate_name = "0900"] type T = S;
+   |                            ^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:5
+   |
+LL |     #[crate_name = "0900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this implementation block
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:28
+   |
+LL |     #[crate_name = "0900"] impl S { }
+   |                            ^^^^^^^^^^
+
 warning: `#[should_panic]` attribute cannot be used on crates
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1
    |
diff --git a/tests/ui/issues/issue-29466.rs b/tests/ui/issues/issue-29466.rs
index dbc37506a17..3962940e848 100644
--- a/tests/ui/issues/issue-29466.rs
+++ b/tests/ui/issues/issue-29466.rs
@@ -2,6 +2,9 @@
 //
 //@ run-pass
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 #![allow(unused_variables)]
 
 macro_rules! m(
diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs
index 66c5be20693..6d5b86411f3 100644
--- a/tests/ui/limits/huge-enum.rs
+++ b/tests/ui/limits/huge-enum.rs
@@ -2,6 +2,9 @@
 //@ normalize-stderr: "std::option::Option<\[u32; \d+\]>" -> "TYPE"
 //@ normalize-stderr: "\[u32; \d+\]" -> "TYPE"
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 #[cfg(target_pointer_width = "32")]
 type BIG = Option<[u32; (1<<29)-1]>;
 
diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr
index 18168b3fa5c..5b97a2104a3 100644
--- a/tests/ui/limits/huge-enum.stderr
+++ b/tests/ui/limits/huge-enum.stderr
@@ -1,5 +1,5 @@
 error: values of the type `Option<TYPE>` are too big for the target architecture
-  --> $DIR/huge-enum.rs:12:9
+  --> $DIR/huge-enum.rs:15:9
    |
 LL |     let big: BIG = None;
    |         ^^^
diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr
index c678562ab54..ae5f6b3adec 100644
--- a/tests/ui/lint/linker-warning.stderr
+++ b/tests/ui/lint/linker-warning.stderr
@@ -1,4 +1,4 @@
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+warning: crate-level attribute should be an inner attribute
   --> $DIR/linker-warning.rs:7:1
    |
 LL | #[allow(linker_messages)]
@@ -9,6 +9,10 @@ note: the lint level is defined here
    |
 LL | #![warn(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+LL | #![allow(linker_messages)]
+   |  +
 
 warning: unused attribute
   --> $DIR/linker-warning.rs:4:1
diff --git a/tests/ui/lint/lint-misplaced-attr.stderr b/tests/ui/lint/lint-misplaced-attr.stderr
index abaf4620e6f..bcfda170080 100644
--- a/tests/ui/lint/lint-misplaced-attr.stderr
+++ b/tests/ui/lint/lint-misplaced-attr.stderr
@@ -10,11 +10,16 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute
   --> $DIR/lint-misplaced-attr.rs:10:1
    |
 LL | #[crate_type = "bin"] fn main() {}
    | ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![crate_type = "bin"] fn main() {}
+   |  +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
index 37fbf93ffa1..c507b6590c2 100644
--- a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
+++ b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
@@ -1,7 +1,7 @@
 #![deny(unused)]
 
 #[crate_name = concat !()]
-//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]
+//~^ ERROR crate-level attribute should be an inner attribute
 macro_rules! a {
     //~^ ERROR unused macro definition
     () => {};
diff --git a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
index 4ffb55d493a..b06e65af7bc 100644
--- a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
+++ b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
@@ -11,12 +11,20 @@ LL | #![deny(unused)]
    |         ^^^^^^
    = note: `#[deny(unused_macros)]` implied by `#[deny(unused)]`
 
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
   --> $DIR/concat-in-crate-name-issue-137687.rs:3:1
    |
 LL | #[crate_name = concat !()]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: This attribute does not have an `!`, which means it is applied to this macro def
+  --> $DIR/concat-in-crate-name-issue-137687.rs:5:1
+   |
+LL | / macro_rules! a {
+LL | |
+LL | |     () => {};
+LL | | }
+   | |_^
    = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
index 9d61120463c..af64be8f6e9 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -1,4 +1,4 @@
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute
   --> $DIR/unused-attr-macro-rules.rs:11:1
    |
 LL | #[recursion_limit="1"]
@@ -9,6 +9,10 @@ note: the lint level is defined here
    |
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+LL | #![recursion_limit="1"]
+   |  +
 
 error: `#[macro_use]` attribute cannot be used on macro defs
   --> $DIR/unused-attr-macro-rules.rs:7:1
diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs
index 378ade67bfd..21428d876e2 100644
--- a/tests/ui/panics/issue-47429-short-backtraces.rs
+++ b/tests/ui/panics/issue-47429-short-backtraces.rs
@@ -6,6 +6,9 @@
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=1
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 // This is needed to avoid test output differences across std being built with v0 symbols vs legacy
 // symbols.
 //@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
diff --git a/tests/ui/panics/issue-47429-short-backtraces.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.run.stderr
index 13b59a7c7af..32aa6a3502e 100644
--- a/tests/ui/panics/issue-47429-short-backtraces.run.stderr
+++ b/tests/ui/panics/issue-47429-short-backtraces.run.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:24:5:
+thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:27:5:
 explicit panic
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs
index 7d5b4169340..61c07a97c70 100644
--- a/tests/ui/panics/runtime-switch.rs
+++ b/tests/ui/panics/runtime-switch.rs
@@ -6,6 +6,9 @@
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=0
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 // This is needed to avoid test output differences across std being built with v0 symbols vs legacy
 // symbols.
 //@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
diff --git a/tests/ui/panics/runtime-switch.run.stderr b/tests/ui/panics/runtime-switch.run.stderr
index f3f60445952..48a12b59b69 100644
--- a/tests/ui/panics/runtime-switch.run.stderr
+++ b/tests/ui/panics/runtime-switch.run.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:28:5:
+thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:31:5:
 explicit panic
 stack backtrace:
    0: std::panicking::begin_panic