about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-03-21 14:56:29 +0100
committerRalf Jung <post@ralfj.de>2025-03-21 14:56:29 +0100
commitf24ea85633f8def515b7df074219090a4ce13dbc (patch)
treea7011752e3e03be2300e7110457a9bfab2b196d4 /compiler
parent29f022ce3c3ae31cc3a7542f17156efb3dbea308 (diff)
parent4ac032f857b46037b55c1fc0fa702450aad37f43 (diff)
downloadrust-f24ea85633f8def515b7df074219090a4ce13dbc.tar.gz
rust-f24ea85633f8def515b7df074219090a4ce13dbc.zip
Merge from rustc
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs14
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs19
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs33
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs45
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
-rw-r--r--compiler/rustc_const_eval/messages.ftl4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs3
-rw-r--r--compiler/rustc_const_eval/src/errors.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs13
-rw-r--r--compiler/rustc_expand/src/config.rs35
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs8
-rw-r--r--compiler/rustc_hir/src/hir.rs13
-rw-r--r--compiler/rustc_hir/src/intravisit.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs10
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp16
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map.rs8
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs16
-rw-r--r--compiler/rustc_next_trait_solver/src/coherence.rs5
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs7
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs8
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs11
-rw-r--r--compiler/rustc_session/src/config.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs9
-rw-r--r--compiler/rustc_type_ir/src/macros.rs13
44 files changed, 336 insertions, 183 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index e24b45c5b19..e08850da4a7 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1513,16 +1513,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }))
     }
 
-    fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
+    fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {
         self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {
-            PatKind::Ident(_, ident, _) => self.lower_ident(ident),
-            PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)),
+            PatKind::Ident(_, ident, _) => {
+                if ident.name != kw::Empty {
+                    Some(self.lower_ident(ident))
+                } else {
+                    None
+                }
+            }
+            PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),
             _ => {
                 self.dcx().span_delayed_bug(
                     param.pat.span,
                     "non-ident/wild param pat must trigger an error",
                 );
-                Ident::new(kw::Empty, self.lower_span(param.pat.span))
+                None
             }
         }))
     }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 232d60be4eb..75839e86b8d 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -336,6 +336,7 @@ impl<'a> AstValidator<'a> {
                     sym::allow,
                     sym::cfg,
                     sym::cfg_attr,
+                    sym::cfg_attr_trace,
                     sym::deny,
                     sym::expect,
                     sym::forbid,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index a8eaff7346b..cdb18179449 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -578,11 +578,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         let mut printed = false;
         for attr in attrs {
             if attr.style == kind {
-                self.print_attribute_inline(attr, is_inline);
-                if is_inline {
-                    self.nbsp();
+                if self.print_attribute_inline(attr, is_inline) {
+                    if is_inline {
+                        self.nbsp();
+                    }
+                    printed = true;
                 }
-                printed = true;
             }
         }
         if printed && trailing_hardbreak && !is_inline {
@@ -591,7 +592,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         printed
     }
 
-    fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) {
+    fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool {
+        if attr.has_name(sym::cfg_attr_trace) {
+            // It's not a valid identifier, so avoid printing it
+            // to keep the printed code reasonably parse-able.
+            return false;
+        }
         if !is_inline {
             self.hardbreak_if_not_bol();
         }
@@ -610,6 +616,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                 self.hardbreak()
             }
         }
+        true
     }
 
     fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) {
@@ -2047,7 +2054,7 @@ impl<'a> State<'a> {
     }
 
     fn print_attribute(&mut self, attr: &ast::Attribute) {
-        self.print_attribute_inline(attr, false)
+        self.print_attribute_inline(attr, false);
     }
 
     fn print_meta_list_item(&mut self, item: &ast::MetaItemInner) {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 2694a1eda78..978186f76a1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2514,12 +2514,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let ty::Tuple(params) = tupled_params.kind() else { return };
 
         // Find the first argument with a matching type, get its name
-        let Some((_, this_name)) =
-            params.iter().zip(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| {
+        let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map(
+            |(param_ty, name)| {
                 // FIXME: also support deref for stuff like `Rc` arguments
-                param_ty.peel_refs() == local_ty && name != &Ident::empty()
-            })
-        else {
+                if param_ty.peel_refs() == local_ty { name } else { None }
+            },
+        ) else {
             return;
         };
 
@@ -3787,7 +3787,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 method_args,
                 *fn_span,
                 call_source.from_hir_call(),
-                Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
+                self.infcx.tcx.fn_arg_names(method_did)[0],
             )
         {
             err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 208d510db2e..899e145c2c0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1029,7 +1029,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 method_args,
                 *fn_span,
                 call_source.from_hir_call(),
-                Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
+                self.infcx.tcx.fn_arg_names(method_did)[0],
             );
 
             return FnSelfUse {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
index b617f4d37f5..f6000e72840 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
@@ -146,6 +146,7 @@ pub(crate) struct CoverageSpan {
 #[derive(Clone, Debug, Default)]
 pub(crate) struct Regions {
     pub(crate) code_regions: Vec<CodeRegion>,
+    pub(crate) expansion_regions: Vec<ExpansionRegion>,
     pub(crate) branch_regions: Vec<BranchRegion>,
     pub(crate) mcdc_branch_regions: Vec<MCDCBranchRegion>,
     pub(crate) mcdc_decision_regions: Vec<MCDCDecisionRegion>,
@@ -154,10 +155,16 @@ pub(crate) struct Regions {
 impl Regions {
     /// Returns true if none of this structure's tables contain any regions.
     pub(crate) fn has_no_regions(&self) -> bool {
-        let Self { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
-            self;
+        let Self {
+            code_regions,
+            expansion_regions,
+            branch_regions,
+            mcdc_branch_regions,
+            mcdc_decision_regions,
+        } = self;
 
         code_regions.is_empty()
+            && expansion_regions.is_empty()
             && branch_regions.is_empty()
             && mcdc_branch_regions.is_empty()
             && mcdc_decision_regions.is_empty()
@@ -172,6 +179,14 @@ pub(crate) struct CodeRegion {
     pub(crate) counter: Counter,
 }
 
+/// Must match the layout of `LLVMRustCoverageExpansionRegion`.
+#[derive(Clone, Debug)]
+#[repr(C)]
+pub(crate) struct ExpansionRegion {
+    pub(crate) cov_span: CoverageSpan,
+    pub(crate) expanded_file_id: u32,
+}
+
 /// Must match the layout of `LLVMRustCoverageBranchRegion`.
 #[derive(Clone, Debug)]
 #[repr(C)]
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
index 2cd7fa3225a..907d6d41a1f 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
@@ -63,8 +63,18 @@ pub(crate) fn write_function_mappings_to_buffer(
     expressions: &[ffi::CounterExpression],
     regions: &ffi::Regions,
 ) -> Vec<u8> {
-    let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
-        regions;
+    let ffi::Regions {
+        code_regions,
+        expansion_regions,
+        branch_regions,
+        mcdc_branch_regions,
+        mcdc_decision_regions,
+    } = regions;
+
+    // SAFETY:
+    // - All types are FFI-compatible and have matching representations in Rust/C++.
+    // - For pointer/length pairs, the pointer and length come from the same vector or slice.
+    // - C++ code does not retain any pointers after the call returns.
     llvm::build_byte_buffer(|buffer| unsafe {
         llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer(
             virtual_file_mapping.as_ptr(),
@@ -73,6 +83,8 @@ pub(crate) fn write_function_mappings_to_buffer(
             expressions.len(),
             code_regions.as_ptr(),
             code_regions.len(),
+            expansion_regions.as_ptr(),
+            expansion_regions.len(),
             branch_regions.as_ptr(),
             branch_regions.len(),
             mcdc_branch_regions.as_ptr(),
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index 5b487bc1a8b..048e1988c32 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -120,12 +120,22 @@ fn fill_region_tables<'tcx>(
     // Associate that global file ID with a local file ID for this function.
     let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id);
 
-    let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
-        &mut covfun.regions;
-
-    let make_cov_span =
-        |span: Span| spans::make_coverage_span(local_file_id, source_map, &source_file, span);
+    // In rare cases, _all_ of a function's spans are discarded, and coverage
+    // codegen needs to handle that gracefully to avoid #133606.
+    // It's hard for tests to trigger this organically, so instead we set
+    // `-Zcoverage-options=discard-all-spans-in-codegen` to force it to occur.
     let discard_all = tcx.sess.coverage_discard_all_spans_in_codegen();
+    let make_coords = |span: Span| {
+        if discard_all { None } else { spans::make_coords(source_map, &source_file, span) }
+    };
+
+    let ffi::Regions {
+        code_regions,
+        expansion_regions: _, // FIXME(Zalathar): Fill out support for expansion regions
+        branch_regions,
+        mcdc_branch_regions,
+        mcdc_decision_regions,
+    } = &mut covfun.regions;
 
     // For each counter/region pair in this function+file, convert it to a
     // form suitable for FFI.
@@ -140,17 +150,8 @@ fn fill_region_tables<'tcx>(
             ffi::Counter::from_term(term)
         };
 
-        // Convert the `Span` into coordinates that we can pass to LLVM, or
-        // discard the span if conversion fails. In rare, cases _all_ of a
-        // function's spans are discarded, and the rest of coverage codegen
-        // needs to handle that gracefully to avoid a repeat of #133606.
-        // We don't have a good test case for triggering that organically, so
-        // instead we set `-Zcoverage-options=discard-all-spans-in-codegen`
-        // to force it to occur.
-        let Some(cov_span) = make_cov_span(span) else { continue };
-        if discard_all {
-            continue;
-        }
+        let Some(coords) = make_coords(span) else { continue };
+        let cov_span = coords.make_coverage_span(local_file_id);
 
         match *kind {
             MappingKind::Code { bcb } => {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
index 3193be31ada..39a59560c9d 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
@@ -5,22 +5,40 @@ use tracing::debug;
 use crate::coverageinfo::ffi;
 use crate::coverageinfo::mapgen::LocalFileId;
 
+/// Line and byte-column coordinates of a source code span within some file.
+/// The file itself must be tracked separately.
+#[derive(Clone, Copy, Debug)]
+pub(crate) struct Coords {
+    /// 1-based starting line of the source code span.
+    pub(crate) start_line: u32,
+    /// 1-based starting column (in bytes) of the source code span.
+    pub(crate) start_col: u32,
+    /// 1-based ending line of the source code span.
+    pub(crate) end_line: u32,
+    /// 1-based ending column (in bytes) of the source code span. High bit must be unset.
+    pub(crate) end_col: u32,
+}
+
+impl Coords {
+    /// Attaches a local file ID to these coordinates to produce an `ffi::CoverageSpan`.
+    pub(crate) fn make_coverage_span(&self, local_file_id: LocalFileId) -> ffi::CoverageSpan {
+        let &Self { start_line, start_col, end_line, end_col } = self;
+        let file_id = local_file_id.as_u32();
+        ffi::CoverageSpan { file_id, start_line, start_col, end_line, end_col }
+    }
+}
+
 /// Converts the span into its start line and column, and end line and column.
 ///
 /// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by
 /// the compiler, these column numbers are denoted in **bytes**, because that's what
 /// LLVM's `llvm-cov` tool expects to see in coverage maps.
 ///
-/// Returns `None` if the conversion failed for some reason. This shouldn't happen,
+/// Returns `None` if the conversion failed for some reason. This should be uncommon,
 /// but it's hard to rule out entirely (especially in the presence of complex macros
 /// or other expansions), and if it does happen then skipping a span or function is
 /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid.
-pub(crate) fn make_coverage_span(
-    file_id: LocalFileId,
-    source_map: &SourceMap,
-    file: &SourceFile,
-    span: Span,
-) -> Option<ffi::CoverageSpan> {
+pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> {
     let span = ensure_non_empty_span(source_map, span)?;
 
     let lo = span.lo();
@@ -44,8 +62,7 @@ pub(crate) fn make_coverage_span(
     start_line = source_map.doctest_offset_line(&file.name, start_line);
     end_line = source_map.doctest_offset_line(&file.name, end_line);
 
-    check_coverage_span(ffi::CoverageSpan {
-        file_id: file_id.as_u32(),
+    check_coords(Coords {
         start_line: start_line as u32,
         start_col: start_col as u32,
         end_line: end_line as u32,
@@ -80,8 +97,8 @@ fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
 /// it will immediately exit with a fatal error. To prevent that from happening,
 /// discard regions that are improperly ordered, or might be interpreted in a
 /// way that makes them improperly ordered.
-fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan> {
-    let ffi::CoverageSpan { file_id: _, start_line, start_col, end_line, end_col } = cov_span;
+fn check_coords(coords: Coords) -> Option<Coords> {
+    let Coords { start_line, start_col, end_line, end_col } = coords;
 
     // Line/column coordinates are supposed to be 1-based. If we ever emit
     // coordinates of 0, `llvm-cov` might misinterpret them.
@@ -94,17 +111,17 @@ fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan>
     let is_ordered = (start_line, start_col) <= (end_line, end_col);
 
     if all_nonzero && end_col_has_high_bit_unset && is_ordered {
-        Some(cov_span)
+        Some(coords)
     } else {
         debug!(
-            ?cov_span,
+            ?coords,
             ?all_nonzero,
             ?end_col_has_high_bit_unset,
             ?is_ordered,
             "Skipping source region that would be misinterpreted or rejected by LLVM"
         );
         // If this happens in a debug build, ICE to make it easier to notice.
-        debug_assert!(false, "Improper source region: {cov_span:?}");
+        debug_assert!(false, "Improper source region: {coords:?}");
         None
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 39087a4d6f4..83efb3ea660 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2019,6 +2019,8 @@ unsafe extern "C" {
         NumExpressions: size_t,
         CodeRegions: *const crate::coverageinfo::ffi::CodeRegion,
         NumCodeRegions: size_t,
+        ExpansionRegions: *const crate::coverageinfo::ffi::ExpansionRegion,
+        NumExpansionRegions: size_t,
         BranchRegions: *const crate::coverageinfo::ffi::BranchRegion,
         NumBranchRegions: size_t,
         MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion,
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index ccf9b240d40..dd481e04abb 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -93,7 +93,7 @@ const_eval_expected_inbounds_pointer =
     }
 
 const_eval_extern_static =
-    cannot access extern static ({$did})
+    cannot access extern static `{$did}`
 const_eval_extern_type_field = `extern type` field does not have a known offset
 
 const_eval_fn_ptr_call =
@@ -381,7 +381,7 @@ const_eval_thread_local_access =
     thread-local statics cannot be accessed at compile-time
 
 const_eval_thread_local_static =
-    cannot access thread local static ({$did})
+    cannot access thread local static `{$did}`
 const_eval_too_generic =
     encountered overly generic constant
 const_eval_too_many_caller_args =
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 4db862afd9f..496f6c86f71 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -22,7 +22,7 @@ use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
-    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, RangeSet, Scalar,
+    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar,
     compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom,
     throw_unsup, throw_unsup_format,
 };
@@ -688,6 +688,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
         _tcx: TyCtxtAt<'tcx>,
         _machine: &mut Self,
         _alloc_extra: &mut Self::AllocExtra,
+        _ptr: Pointer<Option<Self::Provenance>>,
         (_alloc_id, immutable): (AllocId, bool),
         range: AllocRange,
     ) -> InterpResult<'tcx> {
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index b020eeccf71..e2675e2f4c9 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -898,6 +898,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
             UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
         }
     }
+
     fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
         use UnsupportedOpInfo::*;
 
@@ -917,9 +918,9 @@ impl ReportErrorExt for UnsupportedOpInfo {
             OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
                 diag.arg("ptr", ptr);
             }
-            ThreadLocalStatic(did) | ExternStatic(did) => {
-                diag.arg("did", format!("{did:?}"));
-            }
+            ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| {
+                diag.arg("did", tcx.def_path_str(did));
+            }),
         }
     }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index a21bf018d01..e5026eff21f 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -400,6 +400,8 @@ pub trait Machine<'tcx>: Sized {
     ) -> InterpResult<'tcx, Self::AllocExtra>;
 
     /// Hook for performing extra checks on a memory read access.
+    /// `ptr` will always be a pointer with the provenance in `prov` pointing to the beginning of
+    /// `range`.
     ///
     /// This will *not* be called during validation!
     ///
@@ -413,6 +415,7 @@ pub trait Machine<'tcx>: Sized {
         _tcx: TyCtxtAt<'tcx>,
         _machine: &Self,
         _alloc_extra: &Self::AllocExtra,
+        _ptr: Pointer<Option<Self::Provenance>>,
         _prov: (AllocId, Self::ProvenanceExtra),
         _range: AllocRange,
     ) -> InterpResult<'tcx> {
@@ -432,11 +435,14 @@ pub trait Machine<'tcx>: Sized {
 
     /// Hook for performing extra checks on a memory write access.
     /// This is not invoked for ZST accesses, as no write actually happens.
+    /// `ptr` will always be a pointer with the provenance in `prov` pointing to the beginning of
+    /// `range`.
     #[inline(always)]
     fn before_memory_write(
         _tcx: TyCtxtAt<'tcx>,
         _machine: &mut Self,
         _alloc_extra: &mut Self::AllocExtra,
+        _ptr: Pointer<Option<Self::Provenance>>,
         _prov: (AllocId, Self::ProvenanceExtra),
         _range: AllocRange,
     ) -> InterpResult<'tcx> {
@@ -444,11 +450,14 @@ pub trait Machine<'tcx>: Sized {
     }
 
     /// Hook for performing extra operations on a memory deallocation.
+    /// `ptr` will always be a pointer with the provenance in `prov` pointing to the beginning of
+    /// the allocation.
     #[inline(always)]
     fn before_memory_deallocation(
         _tcx: TyCtxtAt<'tcx>,
         _machine: &mut Self,
         _alloc_extra: &mut Self::AllocExtra,
+        _ptr: Pointer<Option<Self::Provenance>>,
         _prov: (AllocId, Self::ProvenanceExtra),
         _size: Size,
         _align: Align,
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 75726269a86..8f286971e63 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -385,6 +385,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             self.tcx,
             &mut self.machine,
             &mut alloc.extra,
+            ptr,
             (alloc_id, prov),
             size,
             alloc.align,
@@ -727,6 +728,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     self.tcx,
                     &self.machine,
                     &alloc.extra,
+                    ptr,
                     (alloc_id, prov),
                     range,
                 )?;
@@ -816,7 +818,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         if let Some((alloc_id, offset, prov, alloc, machine)) = ptr_and_alloc {
             let range = alloc_range(offset, size);
             if !validation_in_progress {
-                M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+                M::before_memory_write(
+                    tcx,
+                    machine,
+                    &mut alloc.extra,
+                    ptr,
+                    (alloc_id, prov),
+                    range,
+                )?;
             }
             interp_ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id }))
         } else {
@@ -1373,6 +1382,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             tcx,
             &self.machine,
             &src_alloc.extra,
+            src,
             (src_alloc_id, src_prov),
             src_range,
         )?;
@@ -1403,6 +1413,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             tcx,
             extra,
             &mut dest_alloc.extra,
+            dest,
             (dest_alloc_id, dest_prov),
             dest_range,
         )?;
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 5570c0c38e8..ada49eef7b2 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -1,12 +1,15 @@
 //! Conditional compilation stripping.
 
+use std::iter;
+
 use rustc_ast::ptr::P;
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{
     AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
 };
 use rustc_ast::{
-    self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, NodeId,
+    self as ast, AttrKind, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner,
+    NodeId, NormalAttr,
 };
 use rustc_attr_parsing as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
@@ -275,10 +278,23 @@ impl<'a> StripUnconfigured<'a> {
     pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
         validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr);
 
+        // A trace attribute left in AST in place of the original `cfg_attr` attribute.
+        // It can later be used by lints or other diagnostics.
+        let mut trace_attr = cfg_attr.clone();
+        match &mut trace_attr.kind {
+            AttrKind::Normal(normal) => {
+                let NormalAttr { item, tokens } = &mut **normal;
+                item.path.segments[0].ident.name = sym::cfg_attr_trace;
+                // This makes the trace attributes unobservable to token-based proc macros.
+                *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default()));
+            }
+            AttrKind::DocComment(..) => unreachable!(),
+        }
+
         let Some((cfg_predicate, expanded_attrs)) =
             rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
         else {
-            return vec![];
+            return vec![trace_attr];
         };
 
         // Lint on zero attributes in source.
@@ -292,22 +308,21 @@ impl<'a> StripUnconfigured<'a> {
         }
 
         if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
-            return vec![];
+            return vec![trace_attr];
         }
 
         if recursive {
             // We call `process_cfg_attr` recursively in case there's a
             // `cfg_attr` inside of another `cfg_attr`. E.g.
             //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
-            expanded_attrs
+            let expanded_attrs = expanded_attrs
                 .into_iter()
-                .flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item)))
-                .collect()
+                .flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item)));
+            iter::once(trace_attr).chain(expanded_attrs).collect()
         } else {
-            expanded_attrs
-                .into_iter()
-                .map(|item| self.expand_cfg_attr_item(cfg_attr, item))
-                .collect()
+            let expanded_attrs =
+                expanded_attrs.into_iter().map(|item| self.expand_cfg_attr_item(cfg_attr, item));
+            iter::once(trace_attr).chain(expanded_attrs).collect()
         }
     }
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 40857e0066e..5430bfde785 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -752,6 +752,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(Word, List: r#""...""#), DuplicatesOk,
         EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
     ),
+    // Trace that is left when a `cfg_attr` attribute is expanded.
+    // The attribute is not gated, to avoid stability errors, but it cannot be used in stable or
+    // unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only
+    // be generated by the compiler.
+    ungated!(
+        cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk,
+        EncodeCrossCrate::No
+    ),
 
     // ==========================================================================
     // Internal attributes, Diagnostics related:
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index b5857e359a2..751c379b21a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2949,7 +2949,7 @@ impl<'hir> TraitItem<'hir> {
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum TraitFn<'hir> {
     /// No default body in the trait, just a signature.
-    Required(&'hir [Ident]),
+    Required(&'hir [Option<Ident>]),
 
     /// Both signature and body are provided in the trait.
     Provided(BodyId),
@@ -3354,7 +3354,9 @@ pub struct BareFnTy<'hir> {
     pub abi: ExternAbi,
     pub generic_params: &'hir [GenericParam<'hir>],
     pub decl: &'hir FnDecl<'hir>,
-    pub param_names: &'hir [Ident],
+    // `Option` because bare fn parameter names are optional. We also end up
+    // with `None` in some error cases, e.g. invalid parameter patterns.
+    pub param_names: &'hir [Option<Ident>],
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
@@ -4335,7 +4337,12 @@ impl ForeignItem<'_> {
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum ForeignItemKind<'hir> {
     /// A foreign function.
-    Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>),
+    ///
+    /// All argument idents are actually always present (i.e. `Some`), but
+    /// `&[Option<Ident>]` is used because of code paths shared with `TraitFn`
+    /// and `BareFnTy`. The sharing is due to all of these cases not allowing
+    /// arbitrary patterns for parameters.
+    Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>),
     /// A foreign static item (`static ext: u8`).
     Static(&'hir Ty<'hir>, Mutability, Safety),
     /// A foreign type.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index b79ae1e7cc2..506358341b5 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -655,7 +655,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
         ForeignItemKind::Fn(ref sig, param_names, ref generics) => {
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_fn_decl(sig.decl));
-            walk_list!(visitor, visit_ident, param_names.iter().copied());
+            for ident in param_names.iter().copied() {
+                visit_opt!(visitor, visit_ident, ident);
+            }
         }
         ForeignItemKind::Static(ref typ, _, _) => {
             try_visit!(visitor.visit_ty_unambig(typ));
@@ -1169,7 +1171,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
         }
         TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
             try_visit!(visitor.visit_fn_decl(sig.decl));
-            walk_list!(visitor, visit_ident, param_names.iter().copied());
+            for ident in param_names.iter().copied() {
+                visit_opt!(visitor, visit_ident, ident);
+            }
         }
         TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
             try_visit!(visitor.visit_fn(
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index ca820deebdf..84d07c711fa 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1034,7 +1034,13 @@ fn report_trait_method_mismatch<'tcx>(
             let span = tcx
                 .hir_body_param_names(body)
                 .zip(sig.decl.inputs.iter())
-                .map(|(param, ty)| param.span.to(ty.span))
+                .map(|(param_name, ty)| {
+                    if let Some(param_name) = param_name {
+                        param_name.span.to(ty.span)
+                    } else {
+                        ty.span
+                    }
+                })
                 .next()
                 .unwrap_or(impl_err_span);
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 0b7fc44460e..74ba4ffe25e 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -3,11 +3,10 @@
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::ErrorGuaranteed;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
 use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
 use rustc_middle::ty::{
-    self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -356,13 +355,20 @@ fn orphan_check<'tcx>(
             })
         }
         OrphanCheckErr::NonLocalInputType(tys) => {
-            let generics = tcx.generics_of(impl_def_id);
-            let tys = tys
-                .into_iter()
-                .map(|(ty, is_target_ty)| {
-                    (ty.fold_with(&mut TyVarReplacer { infcx: &infcx, generics }), is_target_ty)
-                })
-                .collect();
+            let tys = infcx.probe(|_| {
+                // Map the unconstrained args back to their params,
+                // ignoring any type unification errors.
+                for (arg, id_arg) in
+                    std::iter::zip(args, ty::GenericArgs::identity_for_item(tcx, impl_def_id))
+                {
+                    let _ = infcx.at(&cause, ty::ParamEnv::empty()).eq(
+                        DefineOpaqueTypes::No,
+                        arg,
+                        id_arg,
+                    );
+                }
+                infcx.resolve_vars_if_possible(tys)
+            });
             OrphanCheckErr::NonLocalInputType(tys)
         }
     })
@@ -536,40 +542,3 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> {
         }
     }
 }
-
-struct TyVarReplacer<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'tcx>,
-    generics: &'tcx ty::Generics,
-}
-
-impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
-            return ty;
-        }
-        let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
-            return ty.super_fold_with(self);
-        };
-        let origin = self.infcx.type_var_origin(vid);
-        if let Some(def_id) = origin.param_def_id {
-            // The generics of an `impl` don't have a parent, we can index directly.
-            let index = self.generics.param_def_id_to_index[&def_id];
-            let name = self.generics.own_params[index as usize].name;
-
-            Ty::new_param(self.infcx.tcx, index, name)
-        } else {
-            ty
-        }
-    }
-
-    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        if !ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
-            return ct;
-        }
-        ct.super_fold_with(self)
-    }
-}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 5fed2e35287..170500c7a16 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -49,10 +49,12 @@ pub(crate) fn validate_cmse_abi<'tcx>(
                 Ok(Err(index)) => {
                     // fn(x: u32, u32, u32, u16, y: u16) -> u32,
                     //                           ^^^^^^
-                    let span = bare_fn_ty.param_names[index]
-                        .span
-                        .to(bare_fn_ty.decl.inputs[index].span)
-                        .to(bare_fn_ty.decl.inputs.last().unwrap().span);
+                    let span = if let Some(ident) = bare_fn_ty.param_names[index] {
+                        ident.span.to(bare_fn_ty.decl.inputs[index].span)
+                    } else {
+                        bare_fn_ty.decl.inputs[index].span
+                    }
+                    .to(bare_fn_ty.decl.inputs.last().unwrap().span);
                     let plural = bare_fn_ty.param_names.len() - index != 1;
                     dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi });
                 }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 98b81dd3def..ddaca89ccf8 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2,6 +2,7 @@
 //! the definitions in this file have equivalents in `rustc_ast_pretty`.
 
 // tidy-alphabetical-start
+#![feature(let_chains)]
 #![recursion_limit = "256"]
 // tidy-alphabetical-end
 
@@ -898,7 +899,7 @@ impl<'a> State<'a> {
         ident: Ident,
         m: &hir::FnSig<'_>,
         generics: &hir::Generics<'_>,
-        arg_names: &[Ident],
+        arg_names: &[Option<Ident>],
         body_id: Option<hir::BodyId>,
     ) {
         self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
@@ -2121,7 +2122,7 @@ impl<'a> State<'a> {
         header: hir::FnHeader,
         name: Option<Symbol>,
         generics: &hir::Generics<'_>,
-        arg_names: &[Ident],
+        arg_names: &[Option<Ident>],
         body_id: Option<hir::BodyId>,
     ) {
         self.print_fn_header_info(header);
@@ -2141,7 +2142,7 @@ impl<'a> State<'a> {
                 s.print_implicit_self(&decl.implicit_self);
             } else {
                 if let Some(arg_name) = arg_names.get(i) {
-                    if arg_name.name != kw::Empty {
+                    if let Some(arg_name) = arg_name {
                         s.word(arg_name.to_string());
                         s.word(":");
                         s.space();
@@ -2451,7 +2452,7 @@ impl<'a> State<'a> {
         decl: &hir::FnDecl<'_>,
         name: Option<Symbol>,
         generic_params: &[hir::GenericParam<'_>],
-        arg_names: &[Ident],
+        arg_names: &[Option<Ident>],
     ) {
         self.ibox(INDENT_UNIT);
         self.print_formal_generic_params(generic_params);
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index fc1f9a7f2e0..a4776338f6c 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -164,11 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
 
                 let interior = self.next_ty_var(expr_span);
-                self.deferred_coroutine_interiors.borrow_mut().push((
-                    expr_def_id,
-                    body.id(),
-                    interior,
-                ));
+                self.deferred_coroutine_interiors.borrow_mut().push((expr_def_id, interior));
 
                 // Coroutines that come from coroutine closures have not yet determined
                 // their kind ty, so make a fresh infer var which will be constrained
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 64886957ff3..d75c2853ba0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -633,18 +633,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let coroutines = std::mem::take(&mut *self.deferred_coroutine_interiors.borrow_mut());
         debug!(?coroutines);
 
-        for &(expr_def_id, body_id, interior) in coroutines.iter() {
-            debug!(?expr_def_id);
+        let mut obligations = vec![];
+
+        for &(coroutine_def_id, interior) in coroutines.iter() {
+            debug!(?coroutine_def_id);
 
             // Create the `CoroutineWitness` type that we will unify with `interior`.
             let args = ty::GenericArgs::identity_for_item(
                 self.tcx,
-                self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
+                self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()),
             );
-            let witness = Ty::new_coroutine_witness(self.tcx, expr_def_id.to_def_id(), args);
+            let witness = Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args);
 
             // Unify `interior` with `witness` and collect all the resulting obligations.
-            let span = self.tcx.hir_body(body_id).value.span;
+            let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span;
             let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else {
                 span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind())
             };
@@ -653,15 +655,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Will never define opaque types, as all we do is instantiate a type variable.
                 .eq(DefineOpaqueTypes::Yes, interior, witness)
                 .expect("Failed to unify coroutine interior type");
-            let mut obligations = ok.obligations;
 
-            // Also collect the obligations that were unstalled by this unification.
+            obligations.extend(ok.obligations);
+        }
+
+        // FIXME: Use a real visitor for unstalled obligations in the new solver.
+        if !coroutines.is_empty() {
             obligations
                 .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx));
-
-            let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause));
-            self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(obligations);
         }
+
+        self.typeck_results
+            .borrow_mut()
+            .coroutine_stalled_predicates
+            .extend(obligations.into_iter().map(|o| (o.predicate, o.cause)));
     }
 
     #[instrument(skip(self), level = "debug")]
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 90bdb3c4b37..f4bd7ec701f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1135,7 +1135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && self.tcx.def_kind(fn_def_id).is_fn_like()
                 && let self_implicit =
                     matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
-                && let Some(arg) =
+                && let Some(Some(arg)) =
                     self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
                 && arg.name != kw::SelfLower
             {
@@ -2678,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
                 debug_assert_eq!(params.len(), fn_inputs.len());
                 Some((
-                    fn_inputs.zip(params.iter().map(|&param| FnParam::Name(param))).collect(),
+                    fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(),
                     generics,
                 ))
             }
@@ -2709,14 +2709,20 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
 #[derive(Clone, Copy)]
 enum FnParam<'hir> {
     Param(&'hir hir::Param<'hir>),
-    Name(Ident),
+    Name(Option<Ident>),
 }
 
 impl FnParam<'_> {
     fn span(&self) -> Span {
         match self {
             Self::Param(param) => param.span,
-            Self::Name(ident) => ident.span,
+            Self::Name(ident) => {
+                if let Some(ident) = ident {
+                    ident.span
+                } else {
+                    DUMMY_SP
+                }
+            }
         }
     }
 
@@ -2733,7 +2739,8 @@ impl FnParam<'_> {
                         Some(ident.name)
                     }
                     FnParam::Name(ident)
-                        if ident.name != kw::Empty && ident.name != kw::Underscore =>
+                        if let Some(ident) = ident
+                            && ident.name != kw::Underscore =>
                     {
                         Some(ident.name)
                     }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index cdfae51583b..908c3ee2eb8 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3766,7 +3766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 {
                                     let self_first_arg = match method {
                                         hir::TraitFn::Required([ident, ..]) => {
-                                            ident.name == kw::SelfLower
+                                            matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
                                         }
                                         hir::TraitFn::Provided(body_id) => {
                                             self.tcx.hir_body(*body_id).params.first().is_some_and(
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 88f4f7caa95..5b4fc51cec8 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -59,7 +59,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
 
     pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>,
 
-    pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>)>>,
+    pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, Ty<'tcx>)>>,
 
     pub(super) deferred_repeat_expr_checks:
         RefCell<Vec<(&'tcx hir::Expr<'tcx>, Ty<'tcx>, ty::Const<'tcx>)>>,
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 715e3506ab8..752636ccaf0 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -424,7 +424,9 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
         if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind {
             self.check_snake_case(cx, "trait method", &item.ident);
             for param_name in pnames {
-                self.check_snake_case(cx, "variable", param_name);
+                if let Some(param_name) = param_name {
+                    self.check_snake_case(cx, "variable", param_name);
+                }
             }
         }
     }
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index 0471baa1f9c..b8884486c33 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -78,6 +78,13 @@ struct LLVMRustCoverageCodeRegion {
 };
 
 // Must match the layout of
+// `rustc_codegen_llvm::coverageinfo::ffi::ExpansionRegion`.
+struct LLVMRustCoverageExpansionRegion {
+  LLVMRustCoverageSpan Span;
+  uint32_t ExpandedFileID;
+};
+
+// Must match the layout of
 // `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`.
 struct LLVMRustCoverageBranchRegion {
   LLVMRustCoverageSpan Span;
@@ -151,6 +158,8 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer(
     const unsigned *VirtualFileMappingIDs, size_t NumVirtualFileMappingIDs,
     const LLVMRustCounterExpression *RustExpressions, size_t NumExpressions,
     const LLVMRustCoverageCodeRegion *CodeRegions, size_t NumCodeRegions,
+    const LLVMRustCoverageExpansionRegion *ExpansionRegions,
+    size_t NumExpansionRegions,
     const LLVMRustCoverageBranchRegion *BranchRegions, size_t NumBranchRegions,
     const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions,
     size_t NumMCDCBranchRegions,
@@ -179,6 +188,13 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer(
         Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd));
   }
 
+  // Expansion regions:
+  for (const auto &Region : ArrayRef(ExpansionRegions, NumExpansionRegions)) {
+    MappingRegions.push_back(coverage::CounterMappingRegion::makeExpansion(
+        Region.Span.FileID, Region.ExpandedFileID, Region.Span.LineStart,
+        Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd));
+  }
+
   // Branch regions:
   for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) {
     MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion(
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index f6cf218db9d..4610a571da0 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1318,7 +1318,7 @@ impl<'a> CrateMetadataRef<'a> {
             .expect("argument names not encoded for a function")
             .decode((self, sess))
             .nth(0)
-            .is_some_and(|ident| ident.name == kw::SelfLower)
+            .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. })))
     }
 
     fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 5536c93f84a..dc453b1e747 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -443,7 +443,7 @@ define_tables! {
     rendered_const: Table<DefIndex, LazyValue<String>>,
     rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>,
     asyncness: Table<DefIndex, ty::Asyncness>,
-    fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
+    fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
     coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
     coroutine_for_closure: Table<DefIndex, RawDefId>,
     coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 2e589150d3e..f17efab81ec 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -280,11 +280,11 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> {
+    pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> {
         self.hir_body(id).params.iter().map(|param| match param.pat.kind {
-            PatKind::Binding(_, _, ident, _) => ident,
-            PatKind::Wild => Ident::new(kw::Underscore, param.pat.span),
-            _ => Ident::empty(),
+            PatKind::Binding(_, _, ident, _) => Some(ident),
+            PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)),
+            _ => None,
         })
     }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 94a5a3769a3..527c18addbe 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1410,7 +1410,7 @@ rustc_queries! {
         desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
     }
 
-    query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::Ident] {
+    query fn_arg_names(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] {
         desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 855e5043e84..32988965a35 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -43,6 +43,7 @@
 //! This code should only compile in modules where the uninhabitedness of `Foo`
 //! is visible.
 
+use rustc_span::sym;
 use rustc_type_ir::TyKind::*;
 use tracing::instrument;
 
@@ -84,6 +85,21 @@ impl<'tcx> VariantDef {
         InhabitedPredicate::all(
             tcx,
             self.fields.iter().map(|field| {
+                // Unstable fields are always considered to be inhabited. In the future,
+                // this could be extended to be conditional on the field being unstable
+                // only within the module that's querying the inhabitedness, like:
+                //     `let pred = pred.or(InhabitedPredicate::IsUnstable(field.did));`
+                // but this is unnecessary for now, since it would only affect nightly-only
+                // code or code within the standard library itself.
+                // HACK: We filter out `rustc_private` fields since with the flag
+                // `-Zforce-unstable-if-unmarked` we consider all unmarked fields to be
+                // unstable when building the compiler.
+                if tcx
+                    .lookup_stability(field.did)
+                    .is_some_and(|stab| stab.is_unstable() && stab.feature != sym::rustc_private)
+                {
+                    return InhabitedPredicate::True;
+                }
                 let pred = tcx.type_of(field.did).instantiate_identity().inhabited_predicate(tcx);
                 if adt.is_enum() {
                     return pred;
diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs
index 53290203600..f8215a228f5 100644
--- a/compiler/rustc_next_trait_solver/src/coherence.rs
+++ b/compiler/rustc_next_trait_solver/src/coherence.rs
@@ -4,7 +4,8 @@ use std::ops::ControlFlow;
 use derive_where::derive_where;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::{
-    self as ty, InferCtxtLike, Interner, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    self as ty, InferCtxtLike, Interner, TrivialTypeTraversalImpls, TypeVisitable,
+    TypeVisitableExt, TypeVisitor,
 };
 use tracing::instrument;
 
@@ -95,6 +96,8 @@ pub fn trait_ref_is_local_or_fundamental<I: Interner>(tcx: I, trait_ref: ty::Tra
     trait_ref.def_id.is_local() || tcx.trait_is_fundamental(trait_ref.def_id)
 }
 
+TrivialTypeTraversalImpls! { IsFirstInputType, }
+
 #[derive(Debug, Copy, Clone)]
 pub enum IsFirstInputType {
     No,
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 86f673c100c..9ecde2a9eb5 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -16,7 +16,7 @@ use rustc_span::{Span, Symbol, sym};
 use crate::{errors, parse_in};
 
 pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
-    if attr.is_doc_comment() {
+    if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) {
         return;
     }
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index d1917f39c07..e0739c342df 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -272,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             | sym::forbid
                             | sym::cfg
                             | sym::cfg_attr
+                            | sym::cfg_attr_trace
                             // need to be fixed
                             | sym::cfi_encoding // FIXME(cfi_encoding)
                             | sym::pointee // FIXME(derive_coerce_pointee)
@@ -575,6 +576,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // conditional compilation
             sym::cfg,
             sym::cfg_attr,
+            sym::cfg_attr_trace,
             // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`)
             sym::test,
             sym::ignore,
@@ -952,8 +954,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location });
             return;
         }
-        let item_name = self.tcx.hir_name(hir_id);
-        if item_name == doc_alias {
+        if self.tcx.hir_opt_name(hir_id) == Some(doc_alias) {
             tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str });
             return;
         }
@@ -2641,7 +2642,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
         // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
         // in where clauses. After that, only `self.check_attributes` should be enough.
-        const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr];
+        const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace];
         let spans = self
             .tcx
             .hir_attrs(where_predicate.hir_id)
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index fec525c9e8c..a25a80cd45f 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
-use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
 
 use crate::constructor::Constructor::*;
 use crate::constructor::{
@@ -230,7 +230,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                             let is_visible =
                                 adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
                             let is_uninhabited = cx.is_uninhabited(*ty);
-                            let skip = is_uninhabited && !is_visible;
+                            let is_unstable =
+                                cx.tcx.lookup_stability(field.did).is_some_and(|stab| {
+                                    stab.is_unstable() && stab.feature != sym::rustc_private
+                                });
+                            let skip = is_uninhabited && (!is_visible || is_unstable);
                             (ty, PrivateUninhabitedField(skip))
                         });
                         cx.dropless_arena.alloc_from_iter(tys)
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index bcfcc8000c7..3d666055a94 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2217,12 +2217,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                                     .delegation_fn_sigs
                                     .get(&def_id)
                                     .is_some_and(|sig| sig.has_self),
-                                None => self
-                                    .r
-                                    .tcx
-                                    .fn_arg_names(def_id)
-                                    .first()
-                                    .is_some_and(|ident| ident.name == kw::SelfLower),
+                                None => {
+                                    self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| {
+                                        matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
+                                    })
+                                }
                             };
                             if has_self {
                                 return Some(AssocSuggestion::MethodWithSelf { called });
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 701d06e4fd4..43b78423c72 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2082,6 +2082,12 @@ fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! {
     let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
     #[allow(rustc::diagnostic_outside_of_impl)]
     diag.help(format!("valid print requests are: {prints}"));
+
+    if req == "lints" {
+        diag.help(format!("use `-Whelp` to print a list of lints"));
+    }
+
+    diag.help(format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"));
     diag.emit()
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8a8bec35d81..d83863b1f7a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -591,6 +591,7 @@ symbols! {
         cfg_accessible,
         cfg_attr,
         cfg_attr_multi,
+        cfg_attr_trace: "<cfg_attr>", // must not be a valid identifier
         cfg_boolean_literals,
         cfg_contract_checks,
         cfg_doctest,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 393d175ea4c..dc8022b95c3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -1992,13 +1992,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 .iter()
                 .enumerate()
                 .map(|(i, ident)| {
-                    if ident.name.is_empty()
-                        || ident.name == kw::Underscore
-                        || ident.name == kw::SelfLower
+                    if let Some(ident) = ident
+                        && !matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. })
                     {
-                        format!("arg{i}")
-                    } else {
                         format!("{ident}")
+                    } else {
+                        format!("arg{i}")
                     }
                 })
                 .collect();
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index fab1a11304d..c8c293121ca 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -1,10 +1,11 @@
 /// Used for types that are `Copy` and which **do not care arena
 /// allocated data** (i.e., don't need to be folded).
+#[macro_export]
 macro_rules! TrivialTypeTraversalImpls {
     ($($ty:ty,)+) => {
         $(
-            impl<I: $crate::Interner> $crate::fold::TypeFoldable<I> for $ty {
-                fn try_fold_with<F: $crate::fold::FallibleTypeFolder<I>>(
+            impl<I: $crate::Interner> $crate::TypeFoldable<I> for $ty {
+                fn try_fold_with<F: $crate::FallibleTypeFolder<I>>(
                     self,
                     _: &mut F,
                 ) -> ::std::result::Result<Self, F::Error> {
@@ -12,7 +13,7 @@ macro_rules! TrivialTypeTraversalImpls {
                 }
 
                 #[inline]
-                fn fold_with<F: $crate::fold::TypeFolder<I>>(
+                fn fold_with<F: $crate::TypeFolder<I>>(
                     self,
                     _: &mut F,
                 ) -> Self {
@@ -20,14 +21,14 @@ macro_rules! TrivialTypeTraversalImpls {
                 }
             }
 
-            impl<I: $crate::Interner> $crate::visit::TypeVisitable<I> for $ty {
+            impl<I: $crate::Interner> $crate::TypeVisitable<I> for $ty {
                 #[inline]
-                fn visit_with<F: $crate::visit::TypeVisitor<I>>(
+                fn visit_with<F: $crate::TypeVisitor<I>>(
                     &self,
                     _: &mut F)
                     -> F::Result
                 {
-                    <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
+                    <F::Result as $crate::VisitorResult>::output()
                 }
             }
         )+