about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast/src/token.rs73
-rw-r--r--compiler/rustc_const_eval/messages.ftl2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs76
-rw-r--r--compiler/rustc_const_eval/src/errors.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs10
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/errors.rs7
-rw-r--r--compiler/rustc_expand/src/expand.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs25
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs55
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs28
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs2
-rw-r--r--src/bootstrap/src/core/builder.rs28
-rw-r--r--src/bootstrap/src/utils/helpers.rs2
-rwxr-xr-xsrc/etc/pre-push.sh2
-rw-r--r--src/tools/build-manifest/README.md2
-rw-r--r--src/tools/build_helper/src/util.rs28
-rw-r--r--src/tools/compiletest/src/header.rs1
-rw-r--r--src/tools/compiletest/src/header/needs.rs26
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/tests/fail/extern-type-field-offset.stderr4
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs6
-rw-r--r--src/tools/tidy/Cargo.toml1
-rw-r--r--src/tools/tidy/src/deps.rs14
-rw-r--r--src/tools/tidy/src/extdeps.rs15
-rw-r--r--tests/run-make/symlinked-extern/rmake.rs1
-rw-r--r--tests/run-make/symlinked-libraries/rmake.rs1
-rw-r--r--tests/run-make/symlinked-rlib/rmake.rs1
-rw-r--r--tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr2
-rw-r--r--tests/ui/consts/const-eval/validation-ice-extern-type-field.rs15
-rw-r--r--tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr9
-rw-r--r--tests/ui/delegation/glob-traitless-qpath.rs11
-rw-r--r--tests/ui/delegation/glob-traitless-qpath.stderr14
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr6
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr6
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.rs2
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.stderr25
43 files changed, 343 insertions, 211 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9d1481ec768..b4f623e626d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5678,6 +5678,7 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
+ "build_helper",
  "cargo_metadata 0.15.4",
  "fluent-syntax",
  "ignore",
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index cc66cc87652..efe19566152 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -1,6 +1,8 @@
 pub use BinOpToken::*;
 pub use LitKind::*;
 pub use Nonterminal::*;
+pub use NtExprKind::*;
+pub use NtPatKind::*;
 pub use TokenKind::*;
 
 use crate::ast;
@@ -871,6 +873,27 @@ impl PartialEq<TokenKind> for Token {
     }
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)]
+pub enum NtPatKind {
+    // Matches or-patterns. Was written using `pat` in edition 2021 or later.
+    PatWithOr,
+    // Doesn't match or-patterns.
+    // - `inferred`: was written using `pat` in edition 2015 or 2018.
+    // - `!inferred`: was written using `pat_param`.
+    PatParam { inferred: bool },
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)]
+pub enum NtExprKind {
+    // Matches expressions using the post-edition 2024. Was written using
+    // `expr` in edition 2024 or later.
+    Expr,
+    // Matches expressions using the pre-edition 2024 rules.
+    // - `inferred`: was written using `expr` in edition 2021 or earlier.
+    // - `!inferred`: was written using `expr_2021`.
+    Expr2021 { inferred: bool },
+}
+
 #[derive(Clone, Encodable, Decodable)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
@@ -892,19 +915,8 @@ pub enum NonterminalKind {
     Item,
     Block,
     Stmt,
-    PatParam {
-        /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the
-        /// edition of the span. This is used for diagnostics.
-        inferred: bool,
-    },
-    PatWithOr,
-    Expr,
-    /// Matches an expression using the rules from edition 2021 and earlier.
-    Expr2021 {
-        /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the
-        /// edition of the span. This is used for diagnostics AND feature gating.
-        inferred: bool,
-    },
+    Pat(NtPatKind),
+    Expr(NtExprKind),
     Ty,
     Ident,
     Lifetime,
@@ -926,20 +938,22 @@ impl NonterminalKind {
             sym::item => NonterminalKind::Item,
             sym::block => NonterminalKind::Block,
             sym::stmt => NonterminalKind::Stmt,
-            sym::pat => match edition() {
-                Edition::Edition2015 | Edition::Edition2018 => {
-                    NonterminalKind::PatParam { inferred: true }
+            sym::pat => {
+                if edition().at_least_rust_2021() {
+                    NonterminalKind::Pat(PatWithOr)
+                } else {
+                    NonterminalKind::Pat(PatParam { inferred: true })
                 }
-                Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr,
-            },
-            sym::pat_param => NonterminalKind::PatParam { inferred: false },
-            sym::expr => match edition() {
-                Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => {
-                    NonterminalKind::Expr2021 { inferred: true }
+            }
+            sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
+            sym::expr => {
+                if edition().at_least_rust_2024() {
+                    NonterminalKind::Expr(Expr)
+                } else {
+                    NonterminalKind::Expr(Expr2021 { inferred: true })
                 }
-                Edition::Edition2024 => NonterminalKind::Expr,
-            },
-            sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false },
+            }
+            sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
             sym::ty => NonterminalKind::Ty,
             sym::ident => NonterminalKind::Ident,
             sym::lifetime => NonterminalKind::Lifetime,
@@ -951,15 +965,16 @@ impl NonterminalKind {
             _ => return None,
         })
     }
+
     fn symbol(self) -> Symbol {
         match self {
             NonterminalKind::Item => sym::item,
             NonterminalKind::Block => sym::block,
             NonterminalKind::Stmt => sym::stmt,
-            NonterminalKind::PatParam { inferred: false } => sym::pat_param,
-            NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat,
-            NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr,
-            NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021,
+            NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
+            NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
+            NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
+            NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
             NonterminalKind::Ty => sym::ty,
             NonterminalKind::Ident => sym::ident,
             NonterminalKind::Lifetime => sym::lifetime,
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 1476fe285ef..cd269810741 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -89,6 +89,8 @@ const_eval_exact_div_has_remainder =
 
 const_eval_extern_static =
     cannot access extern static ({$did})
+const_eval_extern_type_field = `extern type` field does not have a known offset
+
 const_eval_fn_ptr_call =
     function pointers need an RFC before allowed to be called in {const_eval_const_context}s
 const_eval_for_loop_into_iter_non_const =
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index c60df06bb0e..d8efaa66415 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -386,33 +386,8 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
         CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
     );
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
-    res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| {
-        let (error, backtrace) = error.into_parts();
-        backtrace.print_backtrace();
-
-        let (kind, instance) = if ecx.tcx.is_static(cid.instance.def_id()) {
-            ("static", String::new())
-        } else {
-            // If the current item has generics, we'd like to enrich the message with the
-            // instance and its args: to show the actual compile-time values, in addition to
-            // the expression, leading to the const eval error.
-            let instance = &cid.instance;
-            if !instance.args.is_empty() {
-                let instance = with_no_trimmed_paths!(instance.to_string());
-                ("const_with_path", instance)
-            } else {
-                ("const", String::new())
-            }
-        };
-
-        super::report(
-            *ecx.tcx,
-            error,
-            DUMMY_SP,
-            || super::get_span_and_frames(ecx.tcx, ecx.stack()),
-            |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames },
-        )
-    })
+    res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
+        .map_err(|error| report_eval_error(&ecx, cid, error))
 }
 
 #[inline(always)]
@@ -438,24 +413,61 @@ fn const_validate_mplace<'tcx>(
         ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
             // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
             // error about the validation failure.
-            .map_err(|error| report_validation_error(&ecx, error, alloc_id))?;
+            .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
         inner = true;
     }
 
     Ok(())
 }
 
-#[inline(always)]
+#[inline(never)]
+fn report_eval_error<'tcx>(
+    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+    cid: GlobalId<'tcx>,
+    error: InterpErrorInfo<'tcx>,
+) -> ErrorHandled {
+    let (error, backtrace) = error.into_parts();
+    backtrace.print_backtrace();
+
+    let (kind, instance) = if ecx.tcx.is_static(cid.instance.def_id()) {
+        ("static", String::new())
+    } else {
+        // If the current item has generics, we'd like to enrich the message with the
+        // instance and its args: to show the actual compile-time values, in addition to
+        // the expression, leading to the const eval error.
+        let instance = &cid.instance;
+        if !instance.args.is_empty() {
+            let instance = with_no_trimmed_paths!(instance.to_string());
+            ("const_with_path", instance)
+        } else {
+            ("const", String::new())
+        }
+    };
+
+    super::report(
+        *ecx.tcx,
+        error,
+        DUMMY_SP,
+        || super::get_span_and_frames(ecx.tcx, ecx.stack()),
+        |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames },
+    )
+}
+
+#[inline(never)]
 fn report_validation_error<'tcx>(
     ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+    cid: GlobalId<'tcx>,
     error: InterpErrorInfo<'tcx>,
     alloc_id: AllocId,
 ) -> ErrorHandled {
+    if !matches!(error.kind(), InterpError::UndefinedBehavior(_)) {
+        // Some other error happened during validation, e.g. an unsupported operation.
+        return report_eval_error(ecx, cid, error);
+    }
+
     let (error, backtrace) = error.into_parts();
     backtrace.print_backtrace();
 
-    let ub_note = matches!(error, InterpError::UndefinedBehavior(_)).then(|| {});
-
     let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
     let (size, align, _) = ecx.get_alloc_info(alloc_id);
     let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes };
@@ -465,6 +477,6 @@ fn report_validation_error<'tcx>(
         error,
         DUMMY_SP,
         || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
-        move |span, frames| errors::ValidationFailure { span, ub_note, frames, raw_bytes },
+        move |span, frames| errors::ValidationFailure { span, ub_note: (), frames, raw_bytes },
     )
 }
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 5fa48a59794..292d6ba9d08 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -425,7 +425,7 @@ pub struct ValidationFailure {
     #[primary_span]
     pub span: Span,
     #[note(const_eval_validation_failure_note)]
-    pub ub_note: Option<()>,
+    pub ub_note: (),
     #[subdiagnostic]
     pub frames: Vec<FrameNote>,
     #[subdiagnostic]
@@ -825,6 +825,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
         use crate::fluent_generated::*;
         match self {
             UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
+            UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field,
             UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local,
             UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite,
             UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
@@ -845,7 +846,10 @@ impl ReportErrorExt for UnsupportedOpInfo {
             // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to
             // be further processed by validity checking which then turns it into something nice to
             // print. So it's not worth the effort of having diagnostics that can print the `info`.
-            UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {}
+            UnsizedLocal
+            | UnsupportedOpInfo::ExternTypeField
+            | Unsupported(_)
+            | ReadPointerAsInt(_) => {}
             OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
                 diag.arg("ptr", ptr);
             }
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index efa01b54342..cfa814c810a 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -21,7 +21,7 @@ use rustc_target::abi::{self, VariantIdx};
 use tracing::{debug, instrument};
 
 use super::{
-    throw_ub, throw_unsup_format, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
+    throw_ub, throw_unsup, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
     Provenance, Scalar,
 };
 
@@ -186,8 +186,8 @@ where
                     (base_meta, offset)
                 }
                 None => {
-                    // We don't know the alignment of this field, so we cannot adjust.
-                    throw_unsup_format!("`extern type` does not have a known offset")
+                    // We cannot know the alignment of this field, so we cannot adjust.
+                    throw_unsup!(ExternTypeField)
                 }
             }
         } else {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index ca8b9884933..add48e1b186 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -5,6 +5,7 @@
 //! to be const-safe.
 
 use std::fmt::Write;
+use std::hash::Hash;
 use std::num::NonZero;
 
 use either::{Left, Right};
@@ -17,7 +18,8 @@ use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{
     ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
-    ValidationErrorInfo, ValidationErrorKind, ValidationErrorKind::*,
+    UnsupportedOpInfo, ValidationErrorInfo,
+    ValidationErrorKind::{self, *},
 };
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
@@ -26,8 +28,6 @@ use rustc_target::abi::{
     Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
 };
 
-use std::hash::Hash;
-
 use super::{
     err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
     GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
@@ -1028,7 +1028,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             Err(err)
                 if matches!(
                     err.kind(),
-                    err_ub!(ValidationError { .. }) | InterpError::InvalidProgram(_)
+                    err_ub!(ValidationError { .. })
+                        | InterpError::InvalidProgram(_)
+                        | InterpError::Unsupported(UnsupportedOpInfo::ExternTypeField)
                 ) =>
             {
                 Err(err)
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 6113580491e..cc0b110d2bc 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -61,6 +61,9 @@ expand_feature_removed =
 expand_glob_delegation_outside_impls =
     glob delegation is only supported in impls
 
+expand_glob_delegation_traitless_qpath =
+    qualified path without a trait in glob delegation
+
 expand_helper_attribute_name_invalid =
     `{$name}` cannot be a name of derive helper attribute
 
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index c883121fb40..0be7403f25b 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -449,6 +449,13 @@ pub(crate) struct GlobDelegationOutsideImpls {
     pub span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(expand_glob_delegation_traitless_qpath)]
+pub(crate) struct GlobDelegationTraitlessQpath {
+    #[primary_span]
+    pub span: Span,
+}
+
 // This used to be the `proc_macro_back_compat` lint (#83125). It was later
 // turned into a hard error.
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 716bfc8c26b..a331d83aab0 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1,8 +1,9 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
 use crate::errors::{
-    EmptyDelegationMac, GlobDelegationOutsideImpls, IncompleteParse, RecursionLimitReached,
-    RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind,
+    EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
+    RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
+    WrongFragmentKind,
 };
 use crate::mbe::diagnostics::annotate_err_with_kind;
 use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
@@ -1989,6 +1990,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 }
                 None if let Some((deleg, item)) = node.delegation() => {
                     let Some(suffixes) = &deleg.suffixes else {
+                        let traitless_qself =
+                            matches!(&deleg.qself, Some(qself) if qself.position == 0);
                         let item = match node.to_annotatable() {
                             Annotatable::ImplItem(item) => item,
                             ann @ (Annotatable::Item(_)
@@ -2000,6 +2003,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                             }
                             _ => unreachable!(),
                         };
+                        if traitless_qself {
+                            let span = item.span;
+                            self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span });
+                            return Default::default();
+                        }
                         return self.collect_glob_delegation(item, Node::KIND).make_ast::<Node>();
                     };
 
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 0050ff10539..e43ba7c3a5a 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -10,7 +10,9 @@ use crate::mbe::transcribe::transcribe;
 
 use ast::token::IdentIsRaw;
 use rustc_ast as ast;
-use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*};
+use rustc_ast::token::{
+    self, Delimiter, NonterminalKind, NtPatKind::*, Token, TokenKind, TokenKind::*,
+};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
@@ -1145,14 +1147,17 @@ fn check_matcher_core<'tt>(
                     // Macros defined in the current crate have a real node id,
                     // whereas macros from an external crate have a dummy id.
                     if def.id != DUMMY_NODE_ID
-                        && matches!(kind, NonterminalKind::PatParam { inferred: true })
-                        && matches!(next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or))
+                        && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
+                        && matches!(
+                            next_token,
+                            TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or)
+                        )
                     {
                         // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
                         let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
                             span,
                             name,
-                            Some(NonterminalKind::PatParam { inferred: false }),
+                            Some(NonterminalKind::Pat(PatParam { inferred: false })),
                         ));
                         sess.psess.buffer_lint(
                             RUST_2021_INCOMPATIBLE_OR_PATTERNS,
@@ -1185,14 +1190,14 @@ fn check_matcher_core<'tt>(
                             );
                             err.span_label(sp, format!("not allowed after `{kind}` fragments"));
 
-                            if kind == NonterminalKind::PatWithOr
+                            if kind == NonterminalKind::Pat(PatWithOr)
                                 && sess.psess.edition.at_least_rust_2021()
                                 && next_token.is_token(&BinOp(token::BinOpToken::Or))
                             {
                                 let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
                                     span,
                                     name,
-                                    Some(NonterminalKind::PatParam { inferred: false }),
+                                    Some(NonterminalKind::Pat(PatParam { inferred: false })),
                                 ));
                                 err.span_suggestion(
                                     span,
@@ -1292,9 +1297,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                 // maintain
                 IsInFollow::Yes
             }
-            NonterminalKind::Stmt
-            | NonterminalKind::Expr
-            | NonterminalKind::Expr2021 { inferred: _ } => {
+            NonterminalKind::Stmt | NonterminalKind::Expr(_) => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1304,7 +1307,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatParam { .. } => {
+            NonterminalKind::Pat(PatParam { .. }) => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1317,7 +1320,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatWithOr => {
+            NonterminalKind::Pat(PatWithOr) => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index fdf187438d3..9c480f17b42 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -2,7 +2,7 @@ use crate::errors;
 use crate::mbe::macro_parser::count_metavar_decls;
 use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
 
-use rustc_ast::token::{self, Delimiter, IdentIsRaw, Token};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, NtExprKind::*, Token};
 use rustc_ast::{tokenstream, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_feature::Features;
@@ -85,36 +85,31 @@ pub(super) fn parse(
                                             span.edition()
                                         }
                                     };
-                                    let kind =
-                                        token::NonterminalKind::from_symbol(fragment.name, edition)
-                                            .unwrap_or_else(|| {
-                                                let help = match fragment.name {
-                                                    sym::expr_2021 => {
-                                                        format!(
-                                                            "fragment specifier `expr_2021` \
-                                                             requires Rust 2021 or later\n\
-                                                             {VALID_FRAGMENT_NAMES_MSG}"
-                                                        )
-                                                    }
-                                                    _ if edition().at_least_rust_2021()
-                                                        && features
-                                                            .expr_fragment_specifier_2024 =>
-                                                    {
-                                                        VALID_FRAGMENT_NAMES_MSG_2021.into()
-                                                    }
-                                                    _ => VALID_FRAGMENT_NAMES_MSG.into(),
-                                                };
-                                                sess.dcx().emit_err(
-                                                    errors::InvalidFragmentSpecifier {
-                                                        span,
-                                                        fragment,
-                                                        help,
-                                                    },
-                                                );
-                                                token::NonterminalKind::Ident
+                                    let kind = NonterminalKind::from_symbol(fragment.name, edition)
+                                        .unwrap_or_else(|| {
+                                            let help = match fragment.name {
+                                                sym::expr_2021 => {
+                                                    format!(
+                                                        "fragment specifier `expr_2021` \
+                                                         requires Rust 2021 or later\n\
+                                                         {VALID_FRAGMENT_NAMES_MSG}"
+                                                    )
+                                                }
+                                                _ if edition().at_least_rust_2021()
+                                                    && features.expr_fragment_specifier_2024 =>
+                                                {
+                                                    VALID_FRAGMENT_NAMES_MSG_2021.into()
+                                                }
+                                                _ => VALID_FRAGMENT_NAMES_MSG.into(),
+                                            };
+                                            sess.dcx().emit_err(errors::InvalidFragmentSpecifier {
+                                                span,
+                                                fragment,
+                                                help,
                                             });
-                                    if kind
-                                        == (token::NonterminalKind::Expr2021 { inferred: false })
+                                            NonterminalKind::Ident
+                                        });
+                                    if kind == NonterminalKind::Expr(Expr2021 { inferred: false })
                                         && !features.expr_fragment_specifier_2024
                                     {
                                         rustc_session::parse::feature_err(
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index fbd67657e3b..f66c9604cbe 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -629,7 +629,7 @@ declare_features! (
     /// Allows unsafe on extern declarations and safety qualifiers over internal items.
     (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
     /// Allows unsized fn parameters.
-    (unstable, unsized_fn_params, "1.49.0", Some(48055)),
+    (internal, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
     (incomplete, unsized_locals, "1.30.0", Some(48055)),
     /// Allows unsized tuple coercion.
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 23680f14397..6a8498abaf9 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -520,6 +520,8 @@ pub enum UnsupportedOpInfo {
     Unsupported(String),
     /// Unsized local variables.
     UnsizedLocal,
+    /// Extern type field with an indeterminate offset.
+    ExternTypeField,
     //
     // The variants below are only reachable from CTFE/const prop, miri will never emit them.
     //
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 59f6eff07b3..4a78b427832 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,5 +1,7 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
+use rustc_ast::token::{
+    self, Delimiter, Nonterminal::*, NonterminalKind, NtExprKind::*, NtPatKind::*, Token,
+};
 use rustc_ast::HasTokens;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
@@ -36,14 +38,14 @@ impl<'a> Parser<'a> {
         }
 
         match kind {
-            NonterminalKind::Expr2021 { inferred: _ } => {
+            NonterminalKind::Expr(Expr2021 { .. }) => {
                 token.can_begin_expr()
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Let)
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Const)
             }
-            NonterminalKind::Expr => {
+            NonterminalKind::Expr(Expr) => {
                 token.can_begin_expr()
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Let)
@@ -74,7 +76,7 @@ impl<'a> Parser<'a> {
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind {
+            NonterminalKind::Pat(pat_kind) => match &token.kind {
                 // box, ref, mut, and other identifiers (can stricten)
                 token::Ident(..) | token::NtIdent(..) |
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
@@ -89,7 +91,7 @@ impl<'a> Parser<'a> {
                 token::Lt |                                 // path (UFCS constant)
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
-                token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
+                token::BinOp(token::Or) => matches!(pat_kind, PatWithOr),
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
@@ -135,31 +137,25 @@ impl<'a> Parser<'a> {
                         .create_err(UnexpectedNonterminal::Statement(self.token.span)));
                 }
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
-                NtPat(self.collect_tokens_no_attrs(|this| match kind {
-                    NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
-                    NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt(
+            NonterminalKind::Pat(pat_kind) => {
+                NtPat(self.collect_tokens_no_attrs(|this| match pat_kind {
+                    PatParam { .. } => this.parse_pat_no_top_alt(None, None),
+                    PatWithOr => this.parse_pat_allow_top_alt(
                         None,
                         RecoverComma::No,
                         RecoverColon::No,
                         CommaRecoveryMode::EitherTupleOrPipe,
                     ),
-                    _ => unreachable!(),
                 })?)
             }
-
-            NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => {
-                NtExpr(self.parse_expr_force_collect()?)
-            }
+            NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?),
             NonterminalKind::Literal => {
                 // The `:literal` matcher does not support attributes
                 NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?)
             }
-
             NonterminalKind::Ty => {
                 NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?)
             }
-
             // this could be handled like a token, since it is one
             NonterminalKind::Ident => {
                 return if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index cc5b0073213..5b18cb3f7e1 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1290,15 +1290,21 @@ fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
 pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
 
 fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
-    if path.path.to_str().unwrap().contains(CODEGEN_BACKEND_PREFIX) {
+    let path = path.path.to_str().unwrap();
+
+    let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
+    let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
+
+    if path.contains(CODEGEN_BACKEND_PREFIX) {
         let mut needs_codegen_backend_config = true;
         for backend in run.builder.config.codegen_backends(run.target) {
-            if path.path.to_str().unwrap().ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend))
-            {
+            if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
                 needs_codegen_backend_config = false;
             }
         }
-        if needs_codegen_backend_config {
+        if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
+            && needs_codegen_backend_config
+        {
             run.builder.info(
                 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
                 HELP: add backend to codegen-backends in config.toml.",
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4fb64595504..2dc7cd7de6a 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1018,7 +1018,7 @@ impl Step for PlainSourceTarball {
             // perhaps it should be removed in favor of making `dist` perform the `vendor` step?
 
             // Ensure we have all submodules from src and other directories checked out.
-            for submodule in builder.get_all_submodules() {
+            for submodule in build_helper::util::parse_gitmodules(&builder.src) {
                 builder.update_submodule(Path::new(submodule));
             }
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 8a2bc3b9d48..efc09c41bf4 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1048,8 +1048,6 @@ impl Step for Tidy {
     /// Once tidy passes, this step also runs `fmt --check` if tests are being run
     /// for the `dev` or `nightly` channels.
     fn run(self, builder: &Builder<'_>) {
-        builder.build.update_submodule(Path::new("src/tools/rustc-perf"));
-
         let mut cmd = builder.tool_cmd(Tool::Tidy);
         cmd.arg(&builder.src);
         cmd.arg(&builder.initial_cargo);
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 2e9c04624c7..14ccbfe0267 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -4,13 +4,11 @@ use std::collections::BTreeSet;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fmt::{Debug, Write};
-use std::fs::{self, File};
+use std::fs;
 use std::hash::Hash;
-use std::io::{BufRead, BufReader};
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::process::Command;
-use std::sync::OnceLock;
 use std::time::{Duration, Instant};
 
 use crate::core::build_steps::tool::{self, SourceType};
@@ -594,7 +592,7 @@ impl<'a> ShouldRun<'a> {
     ///
     /// [`path`]: ShouldRun::path
     pub fn paths(mut self, paths: &[&str]) -> Self {
-        let submodules_paths = self.builder.get_all_submodules();
+        let submodules_paths = build_helper::util::parse_gitmodules(&self.builder.src);
 
         self.paths.insert(PathSet::Set(
             paths
@@ -2243,28 +2241,6 @@ impl<'a> Builder<'a> {
         out
     }
 
-    /// Return paths of all submodules.
-    pub fn get_all_submodules(&self) -> &[String] {
-        static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new();
-
-        let init_submodules_paths = |src: &PathBuf| {
-            let file = File::open(src.join(".gitmodules")).unwrap();
-
-            let mut submodules_paths = vec![];
-            for line in BufReader::new(file).lines().map_while(Result::ok) {
-                let line = line.trim();
-                if line.starts_with("path") {
-                    let actual_path = line.split(' ').last().expect("Couldn't get value of path");
-                    submodules_paths.push(actual_path.to_owned());
-                }
-            }
-
-            submodules_paths
-        };
-
-        SUBMODULES_PATHS.get_or_init(|| init_submodules_paths(&self.src))
-    }
-
     /// Ensure that a given step is built *only if it's supposed to be built by default*, returning
     /// its output. This will cache the step, so it's safe (and good!) to call this as often as
     /// needed to ensure that all dependencies are build.
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 4b6dc45b436..59b29eedb79 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -135,7 +135,7 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
     if config.dry_run() {
         return Ok(());
     }
-    let _ = fs::remove_dir(link);
+    let _ = fs::remove_dir_all(link);
     return symlink_dir_inner(original, link);
 
     #[cfg(not(windows))]
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index c9e1a2733fd..6f86c7ab8a4 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -7,8 +7,6 @@
 
 set -Euo pipefail
 
-# https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570
-unset GIT_DIR
 ROOT_DIR="$(git rev-parse --show-toplevel)"
 
 echo "Running pre-push script $ROOT_DIR/x test tidy"
diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md
index 9d30c554186..2ea1bffb35f 100644
--- a/src/tools/build-manifest/README.md
+++ b/src/tools/build-manifest/README.md
@@ -4,7 +4,7 @@ This tool generates the manifests uploaded to static.rust-lang.org and used by r
 You can see a full list of all manifests at <https://static.rust-lang.org/manifests.txt>.
 This listing is updated by <https://github.com/rust-lang/generate-manifest-list> every 7 days.
 
-This gets called by `promote-release` <https://github.com/rust-lang/promote-release> via `x.py dist hash-and-sign`.
+This gets called by `promote-release` <https://github.com/rust-lang/promote-release>. `promote-release` downloads a pre-built binary of `build-manifest` which is generated in the dist-x86_64-linux builder and uploaded to s3.
 
 ## Adding a new component
 
diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs
index 5801a8648f2..72c05c4c48a 100644
--- a/src/tools/build_helper/src/util.rs
+++ b/src/tools/build_helper/src/util.rs
@@ -1,4 +1,8 @@
+use std::fs::File;
+use std::io::{BufRead, BufReader};
+use std::path::Path;
 use std::process::Command;
+use std::sync::OnceLock;
 
 /// Invokes `build_helper::util::detail_exit` with `cfg!(test)`
 ///
@@ -45,3 +49,27 @@ pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> {
         Ok(())
     }
 }
+
+/// Returns the submodule paths from the `.gitmodules` file in the given directory.
+pub fn parse_gitmodules(target_dir: &Path) -> &[String] {
+    static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new();
+    let gitmodules = target_dir.join(".gitmodules");
+    assert!(gitmodules.exists(), "'{}' file is missing.", gitmodules.display());
+
+    let init_submodules_paths = || {
+        let file = File::open(gitmodules).unwrap();
+
+        let mut submodules_paths = vec![];
+        for line in BufReader::new(file).lines().map_while(Result::ok) {
+            let line = line.trim();
+            if line.starts_with("path") {
+                let actual_path = line.split(' ').last().expect("Couldn't get value of path");
+                submodules_paths.push(actual_path.to_owned());
+            }
+        }
+
+        submodules_paths
+    };
+
+    SUBMODULES_PATHS.get_or_init(|| init_submodules_paths())
+}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 82d80fcc19c..31ae0deb7ec 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -877,6 +877,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-shadow-call-stack",
     "needs-sanitizer-support",
     "needs-sanitizer-thread",
+    "needs-symlink",
     "needs-threads",
     "needs-unwind",
     "needs-wasmtime",
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index b96832db67b..5b2665f7d0b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -144,6 +144,11 @@ pub(super) fn handle_needs(
             condition: config.runner.as_ref().is_some_and(|r| r.contains("wasmtime")),
             ignore_reason: "ignored when wasmtime runner is not available",
         },
+        Need {
+            name: "needs-symlink",
+            condition: cache.symlinks,
+            ignore_reason: "ignored if symlinks are unavailable",
+        },
     ];
 
     let (name, comment) = match ln.split_once([':', ' ']) {
@@ -209,6 +214,7 @@ pub(super) struct CachedNeedsConditions {
     xray: bool,
     rust_lld: bool,
     dlltool: bool,
+    symlinks: bool,
 }
 
 impl CachedNeedsConditions {
@@ -253,6 +259,7 @@ impl CachedNeedsConditions {
                 .exists(),
 
             dlltool: find_dlltool(&config),
+            symlinks: has_symlinks(),
         }
     }
 }
@@ -279,3 +286,22 @@ fn find_dlltool(config: &Config) -> bool {
     };
     dlltool_found
 }
+
+#[cfg(windows)]
+fn has_symlinks() -> bool {
+    if std::env::var_os("CI").is_some() {
+        return true;
+    }
+    let link = std::env::temp_dir().join("RUST_COMPILETEST_SYMLINK_CHECK");
+    if std::os::windows::fs::symlink_file("DOES NOT EXIST", &link).is_ok() {
+        std::fs::remove_file(&link).unwrap();
+        true
+    } else {
+        false
+    }
+}
+
+#[cfg(not(windows))]
+fn has_symlinks() -> bool {
+    true
+}
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 12fb76f3972..1b70a1a1cf0 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -311,7 +311,9 @@ pub fn report_error<'tcx>(
             ResourceExhaustion(_) => "resource exhaustion",
             Unsupported(
                 // We list only the ones that can actually happen.
-                UnsupportedOpInfo::Unsupported(_) | UnsupportedOpInfo::UnsizedLocal,
+                UnsupportedOpInfo::Unsupported(_)
+                | UnsupportedOpInfo::UnsizedLocal
+                | UnsupportedOpInfo::ExternTypeField,
             ) => "unsupported operation",
             InvalidProgram(
                 // We list only the ones that can actually happen.
diff --git a/src/tools/miri/tests/fail/extern-type-field-offset.stderr b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
index e0d6e9ebf1d..3ed5732b4eb 100644
--- a/src/tools/miri/tests/fail/extern-type-field-offset.stderr
+++ b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
@@ -1,8 +1,8 @@
-error: unsupported operation: `extern type` does not have a known offset
+error: unsupported operation: `extern type` field does not have a known offset
   --> $DIR/extern-type-field-offset.rs:LL:CC
    |
 LL |     let _field = &x.a;
-   |                  ^^^^ `extern type` does not have a known offset
+   |                  ^^^^ `extern type` field does not have a known offset
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index 89169e10715..60c827fd03b 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -1,4 +1,4 @@
-use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind};
+use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{ast, ptr};
 use rustc_parse::parser::{ForceCollect, Parser, Recovery};
@@ -48,7 +48,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
 
     parse_macro_arg!(
         Expr,
-        NonterminalKind::Expr,
+        NonterminalKind::Expr(Expr),
         |parser: &mut Parser<'b>| parser.parse_expr(),
         |x: ptr::P<ast::Expr>| Some(x)
     );
@@ -60,7 +60,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
     );
     parse_macro_arg!(
         Pat,
-        NonterminalKind::PatParam { inferred: false },
+        NonterminalKind::Pat(PatParam { inferred: false }),
         |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None),
         |x: ptr::P<ast::Pat>| Some(x)
     );
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index f39438bd9ac..0b05d5add52 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 autobins = false
 
 [dependencies]
+build_helper = { path = "../build_helper" }
 cargo_metadata = "0.15"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 7337c9843c7..aa119819aaa 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,7 +1,9 @@
 //! Checks the licenses of third-party dependencies.
 
+use build_helper::ci::CiEnv;
 use cargo_metadata::{Metadata, Package, PackageId};
 use std::collections::HashSet;
+use std::fs::read_dir;
 use std::path::Path;
 
 /// These are licenses that are allowed for all crates, including the runtime,
@@ -514,7 +516,19 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
 pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
     let mut checked_runtime_licenses = false;
 
+    let submodules = build_helper::util::parse_gitmodules(root);
     for &(workspace, exceptions, permitted_deps) in WORKSPACES {
+        // Skip if it's a submodule, not in a CI environment, and not initialized.
+        //
+        // This prevents enforcing developers to fetch submodules for tidy.
+        if submodules.contains(&workspace.into())
+            && !CiEnv::is_ci()
+            // If the directory is empty, we can consider it as an uninitialized submodule.
+            && read_dir(root.join(workspace)).unwrap().next().is_none()
+        {
+            continue;
+        }
+
         if !root.join(workspace).join("Cargo.lock").exists() {
             tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
             continue;
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index 2118de5f204..8bb80f11711 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -1,6 +1,7 @@
 //! Check for external package sources. Allow only vendorable packages.
 
-use std::fs;
+use build_helper::ci::CiEnv;
+use std::fs::{self, read_dir};
 use std::path::Path;
 
 /// List of allowed sources for packages.
@@ -13,7 +14,19 @@ const ALLOWED_SOURCES: &[&str] = &[
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
 pub fn check(root: &Path, bad: &mut bool) {
+    let submodules = build_helper::util::parse_gitmodules(root);
     for &(workspace, _, _) in crate::deps::WORKSPACES {
+        // Skip if it's a submodule, not in a CI environment, and not initialized.
+        //
+        // This prevents enforcing developers to fetch submodules for tidy.
+        if submodules.contains(&workspace.into())
+            && !CiEnv::is_ci()
+            // If the directory is empty, we can consider it as an uninitialized submodule.
+            && read_dir(root.join(workspace)).unwrap().next().is_none()
+        {
+            continue;
+        }
+
         // FIXME check other workspaces too
         // `Cargo.lock` of rust.
         let path = root.join(workspace).join("Cargo.lock");
diff --git a/tests/run-make/symlinked-extern/rmake.rs b/tests/run-make/symlinked-extern/rmake.rs
index 98f69aefbe6..9ed5b76edcb 100644
--- a/tests/run-make/symlinked-extern/rmake.rs
+++ b/tests/run-make/symlinked-extern/rmake.rs
@@ -9,6 +9,7 @@
 // can result in successful compilation.
 
 //@ ignore-cross-compile
+//@ needs-symlink
 
 use run_make_support::{create_symlink, cwd, fs_wrapper, rustc};
 
diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs
index 3f02f19ccd5..1d1dce5b5cf 100644
--- a/tests/run-make/symlinked-libraries/rmake.rs
+++ b/tests/run-make/symlinked-libraries/rmake.rs
@@ -6,6 +6,7 @@
 // See https://github.com/rust-lang/rust/issues/12459
 
 //@ ignore-cross-compile
+//@ needs-symlink
 
 use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc};
 
diff --git a/tests/run-make/symlinked-rlib/rmake.rs b/tests/run-make/symlinked-rlib/rmake.rs
index 3759ca25928..65ebb191428 100644
--- a/tests/run-make/symlinked-rlib/rmake.rs
+++ b/tests/run-make/symlinked-rlib/rmake.rs
@@ -6,6 +6,7 @@
 // See https://github.com/rust-lang/rust/pull/32828
 
 //@ ignore-cross-compile
+//@ needs-symlink
 
 use run_make_support::{create_symlink, cwd, rustc};
 
diff --git a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr
index 99f37fedd3d..54d45ee8ffb 100644
--- a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr
+++ b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/issue-91827-extern-types-field-offset.rs:38:17
    |
 LL |     let field = &x.a;
-   |                 ^^^^ `extern type` does not have a known offset
+   |                 ^^^^ `extern type` field does not have a known offset
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs b/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs
new file mode 100644
index 00000000000..3502409d576
--- /dev/null
+++ b/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs
@@ -0,0 +1,15 @@
+#![feature(extern_types)]
+
+extern {
+    type Opaque;
+}
+
+struct ThinDst {
+    x: u8,
+    tail: Opaque,
+}
+
+const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) };
+//~^ERROR: evaluation of constant value failed
+
+fn main() {}
diff --git a/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr b/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr
new file mode 100644
index 00000000000..1ec36abc2ec
--- /dev/null
+++ b/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/validation-ice-extern-type-field.rs:12:1
+   |
+LL | const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) };
+   | ^^^^^^^^^^^^^^^^^^ `extern type` field does not have a known offset
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/delegation/glob-traitless-qpath.rs b/tests/ui/delegation/glob-traitless-qpath.rs
new file mode 100644
index 00000000000..abf4b3180ed
--- /dev/null
+++ b/tests/ui/delegation/glob-traitless-qpath.rs
@@ -0,0 +1,11 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl S {
+    reuse <u8>::*; //~ ERROR qualified path without a trait in glob delegation
+    reuse <()>::*; //~ ERROR qualified path without a trait in glob delegation
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/glob-traitless-qpath.stderr b/tests/ui/delegation/glob-traitless-qpath.stderr
new file mode 100644
index 00000000000..e3257de347a
--- /dev/null
+++ b/tests/ui/delegation/glob-traitless-qpath.stderr
@@ -0,0 +1,14 @@
+error: qualified path without a trait in glob delegation
+  --> $DIR/glob-traitless-qpath.rs:7:5
+   |
+LL |     reuse <u8>::*;
+   |     ^^^^^^^^^^^^^^
+
+error: qualified path without a trait in glob delegation
+  --> $DIR/glob-traitless-qpath.rs:8:5
+   |
+LL |     reuse <()>::*;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
index 3f8011d961a..6bbd81ae3e1 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
@@ -9,15 +9,11 @@ LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0080]: it is undefined behavior to use this value
+error[E0080]: evaluation of constant value failed
   --> $DIR/stack-overflow-trait-infer-98842.rs:15:1
    |
 LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
-   |
-   = note: the raw bytes of the constant (size: 4, align: 4) {
-               00 00 00 00                                     │ ....
-           }
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
index 04e2c4483bf..6bbd81ae3e1 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
@@ -9,15 +9,11 @@ LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0080]: it is undefined behavior to use this value
+error[E0080]: evaluation of constant value failed
   --> $DIR/stack-overflow-trait-infer-98842.rs:15:1
    |
 LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
-   |
-   = note: the raw bytes of the constant (size: 8, align: 8) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs
index 54d50346cc8..be4807b2e4a 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.rs
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs
@@ -13,6 +13,6 @@ struct Foo(<&'static Foo as ::core::ops::Deref>::Target);
 // and it will infinitely recurse somewhere trying to figure out the
 // size of this pointer (is my guess):
 const _: *const Foo = 0 as _;
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
 
 pub fn main() {}
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr
deleted file mode 100644
index 8ddddeb5bf2..00000000000
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0391]: cycle detected when computing layout of `Foo`
-   |
-   = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`...
-   = note: ...which again requires computing layout of `Foo`, completing the cycle
-note: cycle used when const-evaluating + checking `_`
-  --> $DIR/stack-overflow-trait-infer-98842.rs:13:1
-   |
-LL | const _: *const Foo = 0 as _;
-   | ^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/stack-overflow-trait-infer-98842.rs:13:1
-   |
-LL | const _: *const Foo = 0 as _;
-   | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
-   |
-   = note: the raw bytes of the constant (size: 8, align: 8) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0080, E0391.
-For more information about an error, try `rustc --explain E0080`.