about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs13
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/tests.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs199
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs17
-rw-r--r--compiler/rustc_interface/src/interface.rs109
-rw-r--r--compiler/rustc_interface/src/tests.rs98
-rw-r--r--compiler/rustc_interface/src/util.rs16
-rw-r--r--compiler/rustc_log/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs15
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs36
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_session/src/config.rs12
-rw-r--r--compiler/rustc_session/src/session.rs34
-rw-r--r--compiler/rustc_span/src/lib.rs53
-rw-r--r--compiler/rustc_span/src/source_map.rs26
-rw-r--r--compiler/rustc_span/src/symbol.rs1
18 files changed, 358 insertions, 287 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 0cf96797028..519eeeded9a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -36,6 +36,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+use std::cmp;
 use std::fmt;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
@@ -731,6 +732,13 @@ impl BindingAnnotation {
             Self::MUT_REF_MUT => "mut ref mut ",
         }
     }
+
+    pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {
+        if let ByRef::Yes(old_mutbl) = &mut self.0 {
+            *old_mutbl = cmp::min(*old_mutbl, mutbl);
+        }
+        self
+    }
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index e7f692144ff..c4f062405bb 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -907,8 +907,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
     module: CachedModuleCodegen,
     module_config: &ModuleConfig,
 ) -> WorkItemResult<B> {
-    assert!(module_config.emit_obj != EmitObj::None);
-
     let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
 
     let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
@@ -928,12 +926,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
         }
     };
 
-    let object = load_from_incr_comp_dir(
-        cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)),
-        module.source.saved_files.get("o").unwrap_or_else(|| {
-            cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
-        }),
-    );
     let dwarf_object =
         module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
             let dwarf_obj_out = cgcx
@@ -955,9 +947,14 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
         }
     };
 
+    let should_emit_obj = module_config.emit_obj != EmitObj::None;
     let assembly = load_from_incr_cache(module_config.emit_asm, OutputType::Assembly);
     let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly);
     let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode);
+    let object = load_from_incr_cache(should_emit_obj, OutputType::Object);
+    if should_emit_obj && object.is_none() {
+        cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name })
+    }
 
     WorkItemResult::Finished(CompiledModule {
         name: module.name,
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 71a1113a649..9641d336c3f 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -575,6 +575,8 @@ declare_features! (
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
     (unstable, raw_ref_op, "1.41.0", Some(64490)),
+    /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
+    (incomplete, ref_pat_eat_one_layer_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references.
     (incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows using the `#[register_tool]` attribute.
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 74b8e88a977..571923b5462 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -14,7 +14,7 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    create_session_globals_then(Edition::Edition2024, || {
+    create_session_globals_then(Edition::Edition2024, None, || {
         let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
         let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index cdc6c4d809d..fd74899ae48 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -80,6 +80,7 @@ struct TopInfo<'tcx> {
 #[derive(Copy, Clone)]
 struct PatInfo<'tcx, 'a> {
     binding_mode: BindingAnnotation,
+    max_ref_mutbl: Mutability,
     top_info: TopInfo<'tcx>,
     decl_origin: Option<DeclOrigin<'a>>,
 
@@ -161,8 +162,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         decl_origin: Option<DeclOrigin<'tcx>>,
     ) {
         let info = TopInfo { expected, origin_expr, span };
-        let pat_info =
-            PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin, current_depth: 0 };
+        let pat_info = PatInfo {
+            binding_mode: INITIAL_BM,
+            max_ref_mutbl: Mutability::Mut,
+            top_info: info,
+            decl_origin,
+            current_depth: 0,
+        };
         self.check_pat(pat, expected, pat_info);
     }
 
@@ -173,7 +179,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Conversely, inside this module, `check_pat_top` should never be used.
     #[instrument(level = "debug", skip(self, pat_info))]
     fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
-        let PatInfo { binding_mode: def_bm, top_info: ti, current_depth, .. } = pat_info;
+        let PatInfo { binding_mode: def_bm, max_ref_mutbl, top_info: ti, current_depth, .. } =
+            pat_info;
 
         let path_res = match &pat.kind {
             PatKind::Path(qpath) => Some(
@@ -182,10 +189,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => None,
         };
         let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res));
-        let (expected, def_bm, ref_pattern_already_consumed) =
-            self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode);
+        let (expected, def_bm, max_ref_mutbl, ref_pattern_already_consumed) =
+            self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode, max_ref_mutbl);
         let pat_info = PatInfo {
             binding_mode: def_bm,
+            max_ref_mutbl,
             top_info: ti,
             decl_origin: pat_info.decl_origin,
             current_depth: current_depth + 1,
@@ -290,16 +298,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         def_bm: BindingAnnotation,
         adjust_mode: AdjustMode,
-    ) -> (Ty<'tcx>, BindingAnnotation, bool) {
+        max_ref_mutbl: Mutability,
+    ) -> (Ty<'tcx>, BindingAnnotation, Mutability, bool) {
+        if let ByRef::Yes(mutbl) = def_bm.0 {
+            debug_assert!(mutbl <= max_ref_mutbl);
+        }
         match adjust_mode {
-            AdjustMode::Pass => (expected, def_bm, false),
-            AdjustMode::Reset => (expected, INITIAL_BM, false),
-            AdjustMode::ResetAndConsumeRef(mutbl) => {
-                (expected, INITIAL_BM, def_bm.0 == ByRef::Yes(mutbl))
+            AdjustMode::Pass => (expected, def_bm, max_ref_mutbl, false),
+            AdjustMode::Reset => (expected, INITIAL_BM, Mutability::Mut, false),
+            AdjustMode::ResetAndConsumeRef(ref_pat_mutbl) => {
+                let mutbls_match = def_bm.0 == ByRef::Yes(ref_pat_mutbl);
+                if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+                    if mutbls_match {
+                        debug!("consuming inherited reference");
+                        (expected, INITIAL_BM, cmp::min(max_ref_mutbl, ref_pat_mutbl), true)
+                    } else {
+                        let (new_ty, new_bm, max_ref_mutbl) = if ref_pat_mutbl == Mutability::Mut {
+                            self.peel_off_references(
+                                pat,
+                                expected,
+                                def_bm,
+                                Mutability::Not,
+                                max_ref_mutbl,
+                            )
+                        } else {
+                            (expected, def_bm.cap_ref_mutability(Mutability::Not), Mutability::Not)
+                        };
+                        (new_ty, new_bm, max_ref_mutbl, false)
+                    }
+                } else {
+                    (expected, INITIAL_BM, max_ref_mutbl, mutbls_match)
+                }
             }
             AdjustMode::Peel => {
-                let peeled = self.peel_off_references(pat, expected, def_bm);
-                (peeled.0, peeled.1, false)
+                let peeled =
+                    self.peel_off_references(pat, expected, def_bm, Mutability::Mut, max_ref_mutbl);
+                (peeled.0, peeled.1, peeled.2, false)
             }
         }
     }
@@ -380,7 +414,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
         mut def_bm: BindingAnnotation,
-    ) -> (Ty<'tcx>, BindingAnnotation) {
+        max_peelable_mutability: Mutability,
+        mut max_ref_mutability: Mutability,
+    ) -> (Ty<'tcx>, BindingAnnotation, Mutability) {
         let mut expected = self.try_structurally_resolve_type(pat.span, expected);
         // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
         // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
@@ -391,7 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // See the examples in `ui/match-defbm*.rs`.
         let mut pat_adjustments = vec![];
-        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
+        while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
+            && inner_mutability <= max_peelable_mutability
+        {
             debug!("inspecting {:?}", expected);
 
             debug!("current discriminant is Ref, inserting implicit deref");
@@ -411,6 +449,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
         }
 
+        if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+            def_bm = def_bm.cap_ref_mutability(max_ref_mutability);
+            if def_bm.0 == ByRef::Yes(Mutability::Not) {
+                max_ref_mutability = Mutability::Not;
+            }
+        }
+
         if !pat_adjustments.is_empty() {
             debug!("default binding mode is now {:?}", def_bm);
             self.typeck_results
@@ -419,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .insert(pat.hir_id, pat_adjustments);
         }
 
-        (expected, def_bm)
+        (expected, def_bm, max_ref_mutability)
     }
 
     fn check_pat_lit(
@@ -1109,15 +1154,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth } = pat_info;
         let tcx = self.tcx;
         let on_error = |e| {
             for pat in subpats {
-                self.check_pat(
-                    pat,
-                    Ty::new_error(tcx, e),
-                    PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
-                );
+                self.check_pat(pat, Ty::new_error(tcx, e), pat_info);
             }
         };
         let report_unexpected_res = |res: Res| {
@@ -1162,7 +1202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
 
         // Type-check the tuple struct pattern against the expected type.
-        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti);
+        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
         let had_err = if let Some(err) = diag {
             err.emit();
             true
@@ -1180,11 +1220,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
                 let field = &variant.fields[FieldIdx::from_usize(i)];
                 let field_ty = self.field_ty(subpat.span, field, args);
-                self.check_pat(
-                    subpat,
-                    field_ty,
-                    PatInfo { binding_mode: def_bm, top_info: ti, decl_origin, current_depth },
-                );
+                self.check_pat(subpat, field_ty, pat_info);
 
                 self.tcx.check_stability(
                     variant.fields[FieldIdx::from_usize(i)].did,
@@ -2071,61 +2107,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_info: PatInfo<'tcx, '_>,
         consumed_inherited_ref: bool,
     ) -> Ty<'tcx> {
-        let tcx = self.tcx;
-        let expected = self.shallow_resolve(expected);
-        let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
-            Ok(()) => {
-                // `demand::subtype` would be good enough, but using `eqtype` turns
-                // out to be equally general. See (note_1) for details.
-
-                // Take region, inner-type from expected type if we can,
-                // to avoid creating needless variables. This also helps with
-                // the bad interactions of the given hack detailed in (note_1).
-                debug!("check_pat_ref: expected={:?}", expected);
-                match *expected.kind() {
-                    ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
-                    _ => {
-                        if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
-                            // We already matched against a match-ergonmics inserted reference,
-                            // so we don't need to match against a reference from the original type.
-                            // Save this infor for use in lowering later
-                            self.typeck_results
-                                .borrow_mut()
-                                .skipped_ref_pats_mut()
-                                .insert(pat.hir_id);
-                            (expected, expected)
-                        } else {
-                            let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                                param_def_id: None,
-                                span: inner.span,
-                            });
-                            let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
-                            debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
-                            let err = self.demand_eqtype_pat_diag(
-                                pat.span,
-                                expected,
-                                ref_ty,
-                                pat_info.top_info,
-                            );
+        if consumed_inherited_ref
+            && pat.span.at_least_rust_2024()
+            && self.tcx.features().ref_pat_eat_one_layer_2024
+        {
+            self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+            self.check_pat(inner, expected, pat_info);
+            expected
+        } else {
+            let tcx = self.tcx;
+            let expected = self.shallow_resolve(expected);
+            let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
+                Ok(()) => {
+                    // `demand::subtype` would be good enough, but using `eqtype` turns
+                    // out to be equally general. See (note_1) for details.
+
+                    // Take region, inner-type from expected type if we can,
+                    // to avoid creating needless variables. This also helps with
+                    // the bad interactions of the given hack detailed in (note_1).
+                    debug!("check_pat_ref: expected={:?}", expected);
+                    match *expected.kind() {
+                        ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
+                        _ => {
+                            if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere {
+                                // We already matched against a match-ergonmics inserted reference,
+                                // so we don't need to match against a reference from the original type.
+                                // Save this infor for use in lowering later
+                                self.typeck_results
+                                    .borrow_mut()
+                                    .skipped_ref_pats_mut()
+                                    .insert(pat.hir_id);
+                                (expected, expected)
+                            } else {
+                                let inner_ty = self.next_ty_var(TypeVariableOrigin {
+                                    param_def_id: None,
+                                    span: inner.span,
+                                });
+                                let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
+                                debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
+                                let err = self.demand_eqtype_pat_diag(
+                                    pat.span,
+                                    expected,
+                                    ref_ty,
+                                    pat_info.top_info,
+                                );
 
-                            // Look for a case like `fn foo(&foo: u32)` and suggest
-                            // `fn foo(foo: &u32)`
-                            if let Some(mut err) = err {
-                                self.borrow_pat_suggestion(&mut err, pat);
-                                err.emit();
+                                // Look for a case like `fn foo(&foo: u32)` and suggest
+                                // `fn foo(foo: &u32)`
+                                if let Some(mut err) = err {
+                                    self.borrow_pat_suggestion(&mut err, pat);
+                                    err.emit();
+                                }
+                                (ref_ty, inner_ty)
                             }
-                            (ref_ty, inner_ty)
                         }
                     }
                 }
-            }
-            Err(guar) => {
-                let err = Ty::new_error(tcx, guar);
-                (err, err)
-            }
-        };
-        self.check_pat(inner, inner_ty, pat_info);
-        ref_ty
+                Err(guar) => {
+                    let err = Ty::new_error(tcx, guar);
+                    (err, err)
+                }
+            };
+            self.check_pat(inner, inner_ty, pat_info);
+            ref_ty
+        }
     }
 
     /// Create a reference type with a fresh region variable.
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index f3f214f2123..2963557bb3c 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -945,14 +945,27 @@ impl<'tcx> InferCtxt<'tcx> {
             (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
                 return Err((a_vid, b_vid));
             }
+            // We don't silently want to constrain hidden types here, so we assert that either one side is
+            // an infer var, so it'll get constrained to whatever the other side is, or there are no opaque
+            // types involved.
+            // We don't expect this to actually get hit, but if it does, we now at least know how to write
+            // a test for it.
+            (_, ty::Infer(ty::TyVar(_))) => {}
+            (ty::Infer(ty::TyVar(_)), _) => {}
+            _ if (r_a, r_b).has_opaque_types() => {
+                span_bug!(
+                    cause.span(),
+                    "opaque types got hidden types registered from within subtype predicate: {r_a:?} vs {r_b:?}"
+                )
+            }
             _ => {}
         }
 
         self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
             if a_is_expected {
-                Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b))
+                Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
             } else {
-                Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a))
+                Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
             }
         })
     }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index da2fb490a36..c5b81dbd679 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItemKind};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::defer;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::jobserver;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
@@ -21,7 +22,7 @@ use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileN
 use rustc_session::filesearch::{self, sysroot_candidates};
 use rustc_session::parse::ParseSess;
 use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session};
-use rustc_span::source_map::FileLoader;
+use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
 use rustc_span::symbol::sym;
 use rustc_span::FileName;
 use std::path::PathBuf;
@@ -323,6 +324,18 @@ pub struct Config {
     pub expanded_args: Vec<String>,
 }
 
+/// Initialize jobserver before getting `jobserver::client` and `build_session`.
+pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) {
+    jobserver::initialize_checked(|err| {
+        #[allow(rustc::untranslatable_diagnostic)]
+        #[allow(rustc::diagnostic_outside_of_impl)]
+        early_dcx
+            .early_struct_warn(err)
+            .with_note("the build environment is likely misconfigured")
+            .emit()
+    });
+}
+
 // JUSTIFICATION: before session exists, only config
 #[allow(rustc::bad_opt_access)]
 #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
@@ -334,20 +347,25 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
 
     // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
     let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
-    early_dcx.initialize_checked_jobserver();
+    initialize_checked_jobserver(&early_dcx);
+
+    crate::callbacks::setup_callbacks();
+
+    let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
+    let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
+    let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
+    let path_mapping = config.opts.file_path_mapping();
+    let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
 
     util::run_in_thread_pool_with_globals(
         config.opts.edition,
         config.opts.unstable_opts.threads,
+        SourceMapInputs { file_loader, path_mapping, hash_kind },
         |current_gcx| {
-            crate::callbacks::setup_callbacks();
-
+            // The previous `early_dcx` can't be reused here because it doesn't
+            // impl `Send`. Creating a new one is fine.
             let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
 
-            let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
-
-            let target = config::build_target_config(&early_dcx, &config.opts, &sysroot);
-
             let codegen_backend = match config.make_codegen_backend {
                 None => util::get_codegen_backend(
                     &early_dcx,
@@ -372,9 +390,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.opts.unstable_opts.translate_directionality_markers,
             ) {
                 Ok(bundle) => bundle,
-                Err(e) => {
-                    early_dcx.early_fatal(format!("failed to load fluent bundle: {e}"));
-                }
+                Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
             };
 
             let mut locale_resources = Vec::from(config.locale_resources);
@@ -393,7 +409,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.registry.clone(),
                 locale_resources,
                 config.lint_caps,
-                config.file_loader,
                 target,
                 sysroot,
                 util::rustc_version_str().unwrap_or("unknown"),
@@ -440,45 +455,43 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 current_gcx,
             };
 
-            rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || {
-                // There are two paths out of `f`.
-                // - Normal exit.
-                // - Panic, e.g. triggered by `abort_if_errors`.
-                //
-                // We must run `finish_diagnostics` in both cases.
-                let res = {
-                    // If `f` panics, `finish_diagnostics` will run during
-                    // unwinding because of the `defer`.
-                    let mut guar = None;
-                    let sess_abort_guard = defer(|| {
-                        guar = compiler.sess.finish_diagnostics(&config.registry);
-                    });
-
-                    let res = f(&compiler);
-
-                    // If `f` doesn't panic, `finish_diagnostics` will run
-                    // normally when `sess_abort_guard` is dropped.
-                    drop(sess_abort_guard);
-
-                    // If `finish_diagnostics` emits errors (e.g. stashed
-                    // errors) we can't return an error directly, because the
-                    // return type of this function is `R`, not `Result<R, E>`.
-                    // But we need to communicate the errors' existence to the
-                    // caller, otherwise the caller might mistakenly think that
-                    // no errors occurred and return a zero exit code. So we
-                    // abort (panic) instead, similar to if `f` had panicked.
-                    if guar.is_some() {
-                        compiler.sess.dcx().abort_if_errors();
-                    }
+            // There are two paths out of `f`.
+            // - Normal exit.
+            // - Panic, e.g. triggered by `abort_if_errors`.
+            //
+            // We must run `finish_diagnostics` in both cases.
+            let res = {
+                // If `f` panics, `finish_diagnostics` will run during
+                // unwinding because of the `defer`.
+                let mut guar = None;
+                let sess_abort_guard = defer(|| {
+                    guar = compiler.sess.finish_diagnostics(&config.registry);
+                });
+
+                let res = f(&compiler);
+
+                // If `f` doesn't panic, `finish_diagnostics` will run
+                // normally when `sess_abort_guard` is dropped.
+                drop(sess_abort_guard);
+
+                // If `finish_diagnostics` emits errors (e.g. stashed
+                // errors) we can't return an error directly, because the
+                // return type of this function is `R`, not `Result<R, E>`.
+                // But we need to communicate the errors' existence to the
+                // caller, otherwise the caller might mistakenly think that
+                // no errors occurred and return a zero exit code. So we
+                // abort (panic) instead, similar to if `f` had panicked.
+                if guar.is_some() {
+                    compiler.sess.dcx().abort_if_errors();
+                }
 
-                    res
-                };
+                res
+            };
 
-                let prof = compiler.sess.prof.clone();
-                prof.generic_activity("drop_compiler").run(move || drop(compiler));
+            let prof = compiler.sess.prof.clone();
+            prof.generic_activity("drop_compiler").run(move || drop(compiler));
 
-                res
-            })
+            res
         },
     )
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 923581d1cb6..e563728c893 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -1,5 +1,5 @@
 #![allow(rustc::bad_opt_access)]
-use crate::interface::parse_cfg;
+use crate::interface::{initialize_checked_jobserver, parse_cfg};
 use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
 use rustc_session::config::{
@@ -16,6 +16,7 @@ use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
 use rustc_session::{build_session, filesearch, getopts, CompilerIO, EarlyDiagCtxt, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
+use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
 use rustc_span::symbol::sym;
 use rustc_span::{FileName, SourceFileHashAlgorithm};
 use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
@@ -25,42 +26,52 @@ use std::num::NonZero;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
+fn sess_and_cfg<F>(args: &[&'static str], f: F)
+where
+    F: FnOnce(Session, Cfg),
+{
     let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
-    early_dcx.initialize_checked_jobserver();
+    initialize_checked_jobserver(&early_dcx);
 
-    let registry = registry::Registry::new(&[]);
+    let matches = optgroups().parse(args).unwrap();
     let sessopts = build_session_options(&mut early_dcx, &matches);
-    let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
-    let io = CompilerIO {
-        input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
-        output_dir: None,
-        output_file: None,
-        temps_dir,
-    };
-
     let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
-
     let target = rustc_session::config::build_target_config(&early_dcx, &sessopts, &sysroot);
+    let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
+    let sm_inputs = Some(SourceMapInputs {
+        file_loader: Box::new(RealFileLoader) as _,
+        path_mapping: sessopts.file_path_mapping(),
+        hash_kind,
+    });
 
-    let sess = build_session(
-        early_dcx,
-        sessopts,
-        io,
-        None,
-        registry,
-        vec![],
-        Default::default(),
-        None,
-        target,
-        sysroot,
-        "",
-        None,
-        Arc::default(),
-        Default::default(),
-    );
-    let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg"));
-    (sess, cfg)
+    rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || {
+        let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
+        let io = CompilerIO {
+            input: Input::Str { name: FileName::Custom(String::new()), input: String::new() },
+            output_dir: None,
+            output_file: None,
+            temps_dir,
+        };
+
+        let sess = build_session(
+            early_dcx,
+            sessopts,
+            io,
+            None,
+            registry::Registry::new(&[]),
+            vec![],
+            Default::default(),
+            target,
+            sysroot,
+            "",
+            None,
+            Arc::default(),
+            Default::default(),
+        );
+        let cfg = parse_cfg(&sess.dcx(), matches.opt_strs("cfg"));
+        let cfg = build_configuration(&sess, cfg);
+        f(sess, cfg)
+    });
 }
 
 fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
@@ -125,21 +136,15 @@ fn assert_non_crate_hash_different(x: &Options, y: &Options) {
 // When the user supplies --test we should implicitly supply --cfg test
 #[test]
 fn test_switch_implies_cfg_test() {
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["--test".to_string()]).unwrap();
-        let (sess, cfg) = mk_session(matches);
-        let cfg = build_configuration(&sess, cfg);
+    sess_and_cfg(&["--test"], |_sess, cfg| {
         assert!(cfg.contains(&(sym::test, None)));
-    });
+    })
 }
 
 // When the user supplies --test and --cfg test, don't implicitly add another --cfg test
 #[test]
 fn test_switch_implies_cfg_test_unless_cfg_test() {
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
-        let (sess, cfg) = mk_session(matches);
-        let cfg = build_configuration(&sess, cfg);
+    sess_and_cfg(&["--test", "--cfg=test"], |_sess, cfg| {
         let mut test_items = cfg.iter().filter(|&&(name, _)| name == sym::test);
         assert!(test_items.next().is_some());
         assert!(test_items.next().is_none());
@@ -148,22 +153,15 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
 
 #[test]
 fn test_can_print_warnings() {
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
-        let (sess, _) = mk_session(matches);
+    sess_and_cfg(&["-Awarnings"], |sess, _cfg| {
         assert!(!sess.dcx().can_emit_warnings());
     });
 
-    rustc_span::create_default_session_globals_then(|| {
-        let matches =
-            optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap();
-        let (sess, _) = mk_session(matches);
+    sess_and_cfg(&["-Awarnings", "-Dwarnings"], |sess, _cfg| {
         assert!(sess.dcx().can_emit_warnings());
     });
 
-    rustc_span::create_default_session_globals_then(|| {
-        let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
-        let (sess, _) = mk_session(matches);
+    sess_and_cfg(&["-Adead_code"], |sess, _cfg| {
         assert!(sess.dcx().can_emit_warnings());
     });
 }
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index d0f04fccc48..02dcfe9c8df 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -14,6 +14,7 @@ use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
 use rustc_session::{filesearch, Session};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
+use rustc_span::source_map::SourceMapInputs;
 use rustc_span::symbol::sym;
 use rustc_target::spec::Target;
 use session::output::{categorize_crate_type, CRATE_TYPES};
@@ -65,8 +66,9 @@ fn init_stack_size() -> usize {
     })
 }
 
-pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
+fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
+    sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
     // The "thread pool" is a single spawned thread in the non-parallel
@@ -84,7 +86,9 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
         // name contains null bytes.
         let r = builder
             .spawn_scoped(s, move || {
-                rustc_span::create_session_globals_then(edition, || f(CurrentGcx::new()))
+                rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
+                    f(CurrentGcx::new())
+                })
             })
             .unwrap()
             .join();
@@ -100,15 +104,17 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: S
 pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     _threads: usize,
+    sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
-    run_in_thread_with_globals(edition, f)
+    run_in_thread_with_globals(edition, sm_inputs, f)
 }
 
 #[cfg(parallel_compiler)]
 pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send, R: Send>(
     edition: Edition,
     threads: usize,
+    sm_inputs: SourceMapInputs,
     f: F,
 ) -> R {
     use rustc_data_structures::{defer, jobserver, sync::FromDyn};
@@ -120,7 +126,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap());
 
     if !sync::is_dyn_thread_safe() {
-        return run_in_thread_with_globals(edition, |current_gcx| {
+        return run_in_thread_with_globals(edition, sm_inputs, |current_gcx| {
             // Register the thread for use with the `WorkerLocal` type.
             registry.register();
 
@@ -169,7 +175,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
     // pool. Upon creation, each worker thread created gets a copy of the
     // session globals in TLS. This is possible because `SessionGlobals` impls
     // `Send` in the parallel compiler.
-    rustc_span::create_session_globals_then(edition, || {
+    rustc_span::create_session_globals_then(edition, Some(sm_inputs), || {
         rustc_span::with_session_globals(|session_globals| {
             let session_globals = FromDyn::from(session_globals);
             builder
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index e4b67cde244..81257f9be88 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -17,7 +17,7 @@
 //!     rustc_log::init_logger(rustc_log::LoggerConfig::from_env("LOG")).unwrap();
 //!
 //!     let edition = rustc_span::edition::Edition::Edition2021;
-//!     rustc_span::create_session_globals_then(edition, || {
+//!     rustc_span::create_session_globals_then(edition, None, || {
 //!         /* ... */
 //!     });
 //! }
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index 1872f568907..d35b9fc46e4 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -47,12 +47,7 @@ macro_rules! declare_hooks {
         impl Default for Providers {
             fn default() -> Self {
                 Providers {
-                    $($name: |_, $($arg,)*| bug!(
-                        "`tcx.{}{:?}` cannot be called as `{}` was never assigned to a provider function.\n",
-                        stringify!($name),
-                        ($($arg,)*),
-                        stringify!($name),
-                    ),)*
+                    $($name: |_, $($arg,)*| default_hook(stringify!($name), &($($arg,)*))),*
                 }
             }
         }
@@ -84,7 +79,6 @@ declare_hooks! {
     /// via `mir_built`
     hook build_mir(key: LocalDefId) -> mir::Body<'tcx>;
 
-
     /// Imports all `SourceFile`s from the given crate into the current session.
     /// This normally happens automatically when we decode a `Span` from
     /// that crate's metadata - however, the incr comp cache needs
@@ -109,3 +103,10 @@ declare_hooks! {
     /// Create a list-like THIR representation for debugging.
     hook thir_flat(key: LocalDefId) -> String;
 }
+
+#[cold]
+fn default_hook(name: &str, args: &dyn std::fmt::Debug) -> ! {
+    bug!(
+        "`tcx.{name}{args:?}` cannot be called as `{name}` was never assigned to a provider function"
+    )
+}
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 4ce6f7747a5..643861972c4 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -266,13 +266,7 @@ macro_rules! separate_provide_extern_default {
         ()
     };
     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
-        |_, key| bug!(
-            "`tcx.{}({:?})` unsupported by its crate; \
-             perhaps the `{}` query was never assigned a provider function",
-            stringify!($name),
-            key,
-            stringify!($name),
-        )
+        |_, key| $crate::query::plumbing::default_extern_query(stringify!($name), &key)
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         separate_provide_extern_default!([$($modifiers)*][$($args)*])
@@ -462,15 +456,7 @@ macro_rules! define_callbacks {
         impl Default for Providers {
             fn default() -> Self {
                 Providers {
-                    $($name: |_, key| bug!(
-                        "`tcx.{}({:?})` is not supported for this key;\n\
-                        hint: Queries can be either made to the local crate, or the external crate. \
-                        This error means you tried to use it for one that's not supported.\n\
-                        If that's not the case, {} was likely never assigned to a provider function.\n",
-                        stringify!($name),
-                        key,
-                        stringify!($name),
-                    ),)*
+                    $($name: |_, key| $crate::query::plumbing::default_query(stringify!($name), &key)),*
                 }
             }
         }
@@ -661,3 +647,21 @@ use super::erase::EraseType;
 
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct CyclePlaceholder(pub ErrorGuaranteed);
+
+#[cold]
+pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
+    bug!(
+        "`tcx.{name}({key:?})` is not supported for this key;\n\
+        hint: Queries can be either made to the local crate, or the external crate. \
+        This error means you tried to use it for one that's not supported.\n\
+        If that's not the case, {name} was likely never assigned to a provider function.\n",
+    )
+}
+
+#[cold]
+pub(crate) fn default_extern_query(name: &str, key: &dyn std::fmt::Debug) -> ! {
+    bug!(
+        "`tcx.{name}({key:?})` unsupported by its crate; \
+         perhaps the `{name}` query was never assigned a provider function",
+    )
+}
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 133cf8e3349..bcb43a00547 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             hir::PatKind::Ref(inner, _)
                 if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) =>
             {
-                self.lower_pattern_unadjusted(inner)
+                self.lower_pattern(inner)
             }
             _ => self.lower_pattern_unadjusted(pat),
         };
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index d9fc43625ef..2a7b5650fc2 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1125,7 +1125,7 @@ impl Options {
             || self.unstable_opts.query_dep_graph
     }
 
-    pub(crate) fn file_path_mapping(&self) -> FilePathMapping {
+    pub fn file_path_mapping(&self) -> FilePathMapping {
         file_path_mapping(self.remap_path_prefix.clone(), &self.unstable_opts)
     }
 
@@ -1162,6 +1162,16 @@ impl UnstableOptions {
             track_diagnostics: self.track_diagnostics,
         }
     }
+
+    pub fn src_hash_algorithm(&self, target: &Target) -> SourceFileHashAlgorithm {
+        self.src_hash_algorithm.unwrap_or_else(|| {
+            if target.is_like_msvc {
+                SourceFileHashAlgorithm::Sha256
+            } else {
+                SourceFileHashAlgorithm::Md5
+            }
+        })
+    }
 }
 
 // The type of entry function, so users can have their own entry functions
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 38642efadbd..b63c119eee0 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -28,9 +28,9 @@ use rustc_errors::{
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
 use rustc_span::edition::Edition;
-use rustc_span::source_map::{FileLoader, FilePathMapping, RealFileLoader, SourceMap};
+use rustc_span::source_map::{FilePathMapping, SourceMap};
 use rustc_span::{FileNameDisplayPreference, RealFileName};
-use rustc_span::{SourceFileHashAlgorithm, Span, Symbol};
+use rustc_span::{Span, Symbol};
 use rustc_target::asm::InlineAsmArch;
 use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
 use rustc_target::spec::{
@@ -988,7 +988,6 @@ pub fn build_session(
     registry: rustc_errors::registry::Registry,
     fluent_resources: Vec<&'static str>,
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
-    file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     target: Target,
     sysroot: PathBuf,
     cfg_version: &'static str,
@@ -1015,24 +1014,11 @@ pub fn build_session(
         early_dcx.early_warn(warning)
     }
 
-    let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
-    let hash_kind = sopts.unstable_opts.src_hash_algorithm.unwrap_or_else(|| {
-        if target.is_like_msvc {
-            SourceFileHashAlgorithm::Sha256
-        } else {
-            SourceFileHashAlgorithm::Md5
-        }
-    });
-    let source_map = Lrc::new(SourceMap::with_file_loader_and_hash_kind(
-        loader,
-        sopts.file_path_mapping(),
-        hash_kind,
-    ));
-
     let fallback_bundle = fallback_fluent_bundle(
         fluent_resources,
         sopts.unstable_opts.translate_directionality_markers,
     );
+    let source_map = rustc_span::source_map::get_source_map().unwrap();
     let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
 
     let mut dcx =
@@ -1411,16 +1397,10 @@ impl EarlyDiagCtxt {
         self.dcx.warn(msg)
     }
 
-    pub fn initialize_checked_jobserver(&self) {
-        // initialize jobserver before getting `jobserver::client` and `build_session`.
-        jobserver::initialize_checked(|err| {
-            #[allow(rustc::untranslatable_diagnostic)]
-            #[allow(rustc::diagnostic_outside_of_impl)]
-            self.dcx
-                .struct_warn(err)
-                .with_note("the build environment is likely misconfigured")
-                .emit()
-        });
+    #[allow(rustc::untranslatable_diagnostic)]
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    pub fn early_struct_warn(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
+        self.dcx.struct_warn(msg)
     }
 }
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index c1e1175b4bd..f749d4eb833 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -49,7 +49,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 mod caching_source_map_view;
 pub mod source_map;
 pub use self::caching_source_map_view::CachingSourceMapView;
-use source_map::SourceMap;
+use source_map::{SourceMap, SourceMapInputs};
 
 pub mod edition;
 use edition::Edition;
@@ -104,35 +104,35 @@ pub struct SessionGlobals {
     metavar_spans: Lock<FxHashMap<Span, Span>>,
     hygiene_data: Lock<hygiene::HygieneData>,
 
-    /// A reference to the source map in the `Session`. It's an `Option`
-    /// because it can't be initialized until `Session` is created, which
-    /// happens after `SessionGlobals`. `set_source_map` does the
-    /// initialization.
-    ///
-    /// This field should only be used in places where the `Session` is truly
-    /// not available, such as `<Span as Debug>::fmt`.
-    source_map: Lock<Option<Lrc<SourceMap>>>,
+    /// The session's source map, if there is one. This field should only be
+    /// used in places where the `Session` is truly not available, such as
+    /// `<Span as Debug>::fmt`.
+    source_map: Option<Lrc<SourceMap>>,
 }
 
 impl SessionGlobals {
-    pub fn new(edition: Edition) -> SessionGlobals {
+    pub fn new(edition: Edition, sm_inputs: Option<SourceMapInputs>) -> SessionGlobals {
         SessionGlobals {
             symbol_interner: symbol::Interner::fresh(),
             span_interner: Lock::new(span_encoding::SpanInterner::default()),
             metavar_spans: Default::default(),
             hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
-            source_map: Lock::new(None),
+            source_map: sm_inputs.map(|inputs| Lrc::new(SourceMap::with_inputs(inputs))),
         }
     }
 }
 
-pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
+pub fn create_session_globals_then<R>(
+    edition: Edition,
+    sm_inputs: Option<SourceMapInputs>,
+    f: impl FnOnce() -> R,
+) -> R {
     assert!(
         !SESSION_GLOBALS.is_set(),
         "SESSION_GLOBALS should never be overwritten! \
          Use another thread if you need another SessionGlobals"
     );
-    let session_globals = SessionGlobals::new(edition);
+    let session_globals = SessionGlobals::new(edition, sm_inputs);
     SESSION_GLOBALS.set(&session_globals, f)
 }
 
@@ -145,12 +145,13 @@ pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnO
     SESSION_GLOBALS.set(session_globals, f)
 }
 
+/// No source map.
 pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
 where
     F: FnOnce(&SessionGlobals) -> R,
 {
     if !SESSION_GLOBALS.is_set() {
-        let session_globals = SessionGlobals::new(edition);
+        let session_globals = SessionGlobals::new(edition, None);
         SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
     } else {
         SESSION_GLOBALS.with(f)
@@ -164,8 +165,9 @@ where
     SESSION_GLOBALS.with(f)
 }
 
+/// Default edition, no source map.
 pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
-    create_session_globals_then(edition::DEFAULT_EDITION, f)
+    create_session_globals_then(edition::DEFAULT_EDITION, None, f)
 }
 
 // If this ever becomes non thread-local, `decode_syntax_context`
@@ -1318,25 +1320,6 @@ impl<D: SpanDecoder> Decodable<D> for AttrId {
     }
 }
 
-/// Insert `source_map` into the session globals for the duration of the
-/// closure's execution.
-pub fn set_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
-    with_session_globals(|session_globals| {
-        *session_globals.source_map.borrow_mut() = Some(source_map);
-    });
-    struct ClearSourceMap;
-    impl Drop for ClearSourceMap {
-        fn drop(&mut self) {
-            with_session_globals(|session_globals| {
-                session_globals.source_map.borrow_mut().take();
-            });
-        }
-    }
-
-    let _guard = ClearSourceMap;
-    f()
-}
-
 impl fmt::Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Use the global `SourceMap` to print the span. If that's not
@@ -1352,7 +1335,7 @@ impl fmt::Debug for Span {
 
         if SESSION_GLOBALS.is_set() {
             with_session_globals(|session_globals| {
-                if let Some(source_map) = &*session_globals.source_map.borrow() {
+                if let Some(source_map) = &session_globals.source_map {
                     write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
                 } else {
                     fallback(*self, f)
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 93d5f06a167..e3e76caebaf 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -167,9 +167,17 @@ struct SourceMapFiles {
     stable_id_to_source_file: UnhashMap<StableSourceFileId, Lrc<SourceFile>>,
 }
 
+/// Used to construct a `SourceMap` with `SourceMap::with_inputs`.
+pub struct SourceMapInputs {
+    pub file_loader: Box<dyn FileLoader + Send + Sync>,
+    pub path_mapping: FilePathMapping,
+    pub hash_kind: SourceFileHashAlgorithm,
+}
+
 pub struct SourceMap {
     files: RwLock<SourceMapFiles>,
     file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
+
     // This is used to apply the file path remapping as specified via
     // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
     path_mapping: FilePathMapping,
@@ -180,17 +188,15 @@ pub struct SourceMap {
 
 impl SourceMap {
     pub fn new(path_mapping: FilePathMapping) -> SourceMap {
-        Self::with_file_loader_and_hash_kind(
-            Box::new(RealFileLoader),
+        Self::with_inputs(SourceMapInputs {
+            file_loader: Box::new(RealFileLoader),
             path_mapping,
-            SourceFileHashAlgorithm::Md5,
-        )
+            hash_kind: SourceFileHashAlgorithm::Md5,
+        })
     }
 
-    pub fn with_file_loader_and_hash_kind(
-        file_loader: Box<dyn FileLoader + Sync + Send>,
-        path_mapping: FilePathMapping,
-        hash_kind: SourceFileHashAlgorithm,
+    pub fn with_inputs(
+        SourceMapInputs { file_loader, path_mapping, hash_kind }: SourceMapInputs,
     ) -> SourceMap {
         SourceMap {
             files: Default::default(),
@@ -1054,6 +1060,10 @@ impl SourceMap {
     }
 }
 
+pub fn get_source_map() -> Option<Lrc<SourceMap>> {
+    with_session_globals(|session_globals| session_globals.source_map.clone())
+}
+
 #[derive(Clone)]
 pub struct FilePathMapping {
     mapping: Vec<(PathBuf, PathBuf)>,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index be5b0b663c1..46bae1c1e98 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1462,6 +1462,7 @@ symbols! {
         receiver,
         recursion_limit,
         reexport_test_harness_main,
+        ref_pat_eat_one_layer_2024,
         ref_pat_everywhere,
         ref_unwind_safe_trait,
         reference,