diff --git a/Cargo.lock b/Cargo.lock
index 7f328b97b53ac..f85d523fc1bcc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3879,6 +3879,7 @@ dependencies = [
 name = "rustc_hir_analysis"
 version = "0.0.0"
 dependencies = [
+ "itertools",
  "rustc_arena",
  "rustc_ast",
  "rustc_attr",
@@ -3917,6 +3918,7 @@ dependencies = [
 name = "rustc_hir_typeck"
 version = "0.0.0"
 dependencies = [
+ "itertools",
  "rustc_ast",
  "rustc_attr",
  "rustc_data_structures",
@@ -4200,6 +4202,7 @@ name = "rustc_mir_build"
 version = "0.0.0"
 dependencies = [
  "either",
+ "itertools",
  "rustc_apfloat",
  "rustc_arena",
  "rustc_ast",
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index bb802c4eb461c..f48c9359908af 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1215,7 +1215,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     Applicability::MaybeIncorrect,
                                 );
                                 for error in errors {
-                                    if let FulfillmentErrorCode::CodeSelectionError(
+                                    if let FulfillmentErrorCode::SelectionError(
                                         SelectionError::Unimplemented,
                                     ) = error.code
                                         && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 60164e84d5469..0a6b758efa564 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1291,7 +1291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                 }
                                 // The type doesn't implement Clone because of unmet obligations.
                                 for error in errors {
-                                    if let traits::FulfillmentErrorCode::CodeSelectionError(
+                                    if let traits::FulfillmentErrorCode::SelectionError(
                                         traits::SelectionError::Unimplemented,
                                     ) = error.code
                                         && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 61b6bef3b87b9..59518f68ab149 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,6 +7,7 @@
 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
 //! contain revealed `impl Trait` values).
 
+use itertools::Itertools;
 use rustc_infer::infer::BoundRegionConversionTime;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty};
@@ -39,9 +40,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             user_provided_sig,
         );
 
-        for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip(
-            // In MIR, closure args begin with an implicit `self`. Skip it!
-            body.args_iter().skip(1).map(|local| &body.local_decls[local]),
+        let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id())
+            && user_provided_sig.inputs().is_empty();
+
+        for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq(
+            // In MIR, closure args begin with an implicit `self`.
+            // Also, coroutines have a resume type which may be implicitly `()`.
+            body.args_iter()
+                .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 })
+                .map(|local| &body.local_decls[local]),
         ) {
             self.ascribe_user_type_skip_wf(
                 arg_decl.ty,
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 2e4baf26176c3..11dcf4108d4ec 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -35,7 +35,7 @@ use rustc_lint::unerased_lint_store;
 use rustc_metadata::creader::MetadataLoader;
 use rustc_metadata::locator;
 use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
-use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType, TrimmedDefPaths};
+use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
 use rustc_session::{config, EarlyDiagCtxt, Session};
@@ -204,7 +204,7 @@ impl Callbacks for TimePassesCallbacks {
         //
         self.time_passes = (config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes)
             .then(|| config.opts.unstable_opts.time_passes_format);
-        config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
+        config.opts.trimmed_def_paths = true;
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index b5ebc1fab765d..648b569a217f0 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -9,6 +9,7 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.11"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 410706110c96e..7d145ea1f23a8 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -3,6 +3,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html
 
+use itertools::Itertools;
 use rustc_arena::DroplessArena;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -91,7 +92,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow<!> {
             if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
                 let child_variances = self.tcx.variances_of(def_id);
-                for (a, v) in args.iter().zip(child_variances) {
+                for (a, v) in args.iter().zip_eq(child_variances) {
                     if *v != ty::Bivariant {
                         a.visit_with(self)?;
                     }
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index b0c60304424ad..975f93756427e 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.11"
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 7873257c4e3d1..2bb7caea3c432 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -2,6 +2,7 @@
 use super::method::MethodCallee;
 use super::{FnCtxt, PlaceOp};
 
+use itertools::Itertools;
 use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
 use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
@@ -32,8 +33,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         autoderef: &Autoderef<'a, 'tcx>,
     ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
-        let mut obligations = vec![];
         let steps = autoderef.steps();
+        if steps.is_empty() {
+            return InferOk { obligations: vec![], value: vec![] };
+        }
+
+        let mut obligations = vec![];
         let targets =
             steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
         let steps: Vec<_> = steps
@@ -54,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     None
                 }
             })
-            .zip(targets)
+            .zip_eq(targets)
             .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
             .collect();
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 76360239c454d..1ad79cb78c4b1 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Finally, for ambiguity-related errors, we actually want to look
         // for a parameter that is the source of the inference type left
         // over in this predicate.
-        if let traits::FulfillmentErrorCode::CodeAmbiguity { .. } = error.code {
+        if let traits::FulfillmentErrorCode::Ambiguity { .. } = error.code {
             fallback_param_to_point_at = None;
             self_param_to_point_at = None;
             param_to_point_at =
@@ -361,10 +361,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: &traits::FulfillmentError<'tcx>,
         span: Span,
     ) -> bool {
-        if let traits::FulfillmentErrorCode::CodeSelectionError(
-            traits::SelectionError::OutputTypeParameterMismatch(
-                box traits::SelectionOutputTypeParameterMismatch { expected_trait_ref, .. },
-            ),
+        if let traits::FulfillmentErrorCode::SelectionError(
+            traits::SelectionError::SignatureMismatch(box traits::SignatureMismatchData {
+                expected_trait_ref,
+                ..
+            }),
         ) = error.code
             && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) =
                 expected_trait_ref.skip_binder().self_ty().kind()
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8cd5ed3494b18..4704d52abfc2f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -9,6 +9,7 @@ use crate::{
     struct_span_code_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy,
     TupleArgumentsFlag,
 };
+use itertools::Itertools;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::{
@@ -421,7 +422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 formal_input_tys
                     .iter()
                     .copied()
-                    .zip(expected_input_tys.iter().copied())
+                    .zip_eq(expected_input_tys.iter().copied())
                     .map(|vars| self.resolve_vars_if_possible(vars)),
             );
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 6944b5eb176b9..81b7de7f63497 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1648,7 +1648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     for error in errors {
-                        if let traits::FulfillmentErrorCode::CodeSelectionError(
+                        if let traits::FulfillmentErrorCode::SelectionError(
                             traits::SelectionError::Unimplemented,
                         ) = error.code
                             && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs
index 4f973c1f0101d..72567b43a5f84 100644
--- a/compiler/rustc_index_macros/src/lib.rs
+++ b/compiler/rustc_index_macros/src/lib.rs
@@ -39,6 +39,9 @@ mod newtype;
     feature = "nightly",
     allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq)
 )]
+// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped,
+// and the corresponding one on SpecOptionPartialEq
+#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))]
 pub fn newtype_index(input: TokenStream) -> TokenStream {
     newtype::newtype(input)
 }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 11b5b437eff92..db46b39ce25fc 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -631,13 +631,6 @@ impl<'tcx> InferCtxt<'tcx> {
                 ct_op: |ct| ct,
             });
 
-            if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() {
-                if projection.term.references_error() {
-                    // No point on adding any obligations since there's a type error involved.
-                    obligations.clear();
-                    return;
-                }
-            }
             // Require that the predicate holds for the concrete type.
             debug!(?predicate);
             obligations.push(traits::Obligation::new(
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index b9be178916cf5..fdae093aac8b4 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -17,7 +17,6 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
 use rustc_span::Span;
 
-pub use self::FulfillmentErrorCode::*;
 pub use self::ImplSource::*;
 pub use self::SelectionError::*;
 
@@ -129,12 +128,12 @@ pub struct FulfillmentError<'tcx> {
 #[derive(Clone)]
 pub enum FulfillmentErrorCode<'tcx> {
     /// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented.
-    CodeCycle(Vec<PredicateObligation<'tcx>>),
-    CodeSelectionError(SelectionError<'tcx>),
-    CodeProjectionError(MismatchedProjectionTypes<'tcx>),
-    CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
-    CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
-    CodeAmbiguity {
+    Cycle(Vec<PredicateObligation<'tcx>>),
+    SelectionError(SelectionError<'tcx>),
+    ProjectionError(MismatchedProjectionTypes<'tcx>),
+    SubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
+    ConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
+    Ambiguity {
         /// Overflow reported from the new solver `-Znext-solver`, which will
         /// be reported as an regular error as opposed to a fatal error.
         overflow: bool,
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 51c06c8970b16..3b4050fcd27ef 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -37,18 +37,19 @@ impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
 
 impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use traits::FulfillmentErrorCode::*;
         match *self {
-            super::CodeSelectionError(ref e) => write!(f, "{e:?}"),
-            super::CodeProjectionError(ref e) => write!(f, "{e:?}"),
-            super::CodeSubtypeError(ref a, ref b) => {
+            SelectionError(ref e) => write!(f, "{e:?}"),
+            ProjectionError(ref e) => write!(f, "{e:?}"),
+            SubtypeError(ref a, ref b) => {
                 write!(f, "CodeSubtypeError({a:?}, {b:?})")
             }
-            super::CodeConstEquateError(ref a, ref b) => {
+            ConstEquateError(ref a, ref b) => {
                 write!(f, "CodeConstEquateError({a:?}, {b:?})")
             }
-            super::CodeAmbiguity { overflow: false } => write!(f, "Ambiguity"),
-            super::CodeAmbiguity { overflow: true } => write!(f, "Overflow"),
-            super::CodeCycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
+            Ambiguity { overflow: false } => write!(f, "Ambiguity"),
+            Ambiguity { overflow: true } => write!(f, "Overflow"),
+            Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index bebee8df10e86..135680b934936 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -604,7 +604,7 @@ pub enum SelectionError<'tcx> {
     /// After a closure impl has selected, its "outputs" were evaluated
     /// (which for closures includes the "input" type params) and they
     /// didn't resolve. See `confirm_poly_trait_refs` for more.
-    OutputTypeParameterMismatch(Box<SelectionOutputTypeParameterMismatch<'tcx>>),
+    SignatureMismatch(Box<SignatureMismatchData<'tcx>>),
     /// The trait pointed by `DefId` is not object safe.
     TraitNotObjectSafe(DefId),
     /// A given constant couldn't be evaluated.
@@ -618,7 +618,7 @@ pub enum SelectionError<'tcx> {
 }
 
 #[derive(Clone, Debug, TypeVisitable)]
-pub struct SelectionOutputTypeParameterMismatch<'tcx> {
+pub struct SignatureMismatchData<'tcx> {
     pub found_trait_ref: ty::PolyTraitRef<'tcx>,
     pub expected_trait_ref: ty::PolyTraitRef<'tcx>,
     pub terr: ty::error::TypeError<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a10bdc6012c07..6c9000c45f61b 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -15,7 +15,6 @@ use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
 use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPathDataName};
 use rustc_hir::LangItem;
-use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -365,26 +364,19 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
     /// Try to see if this path can be trimmed to a unique symbol name.
     fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
-        if with_forced_trimmed_paths() {
-            let trimmed = self.force_print_trimmed_def_path(def_id)?;
-            if trimmed {
-                return Ok(true);
-            }
+        if with_forced_trimmed_paths() && self.force_print_trimmed_def_path(def_id)? {
+            return Ok(true);
         }
-        if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
-            || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
-            || with_no_trimmed_paths()
-            || with_crate_prefix()
+        if self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
+            && self.tcx().sess.opts.trimmed_def_paths
+            && !with_no_trimmed_paths()
+            && !with_crate_prefix()
+            && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
         {
-            return Ok(false);
-        }
-
-        match self.tcx().trimmed_def_paths(()).get(&def_id) {
-            None => Ok(false),
-            Some(symbol) => {
-                write!(self, "{}", Ident::with_dummy_span(*symbol))?;
-                Ok(true)
-            }
+            write!(self, "{}", Ident::with_dummy_span(*symbol))?;
+            Ok(true)
+        } else {
+            Ok(false)
         }
     }
 
@@ -3080,18 +3072,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
 // this is pub to be able to intra-doc-link it
 pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
-    let mut map: DefIdMap<Symbol> = Default::default();
-
-    if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
-        // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting.
-        //
-        // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
-        // wrapper can be used to suppress this query, in exchange for full paths being formatted.
-        tcx.sess.good_path_delayed_bug(
-            "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
-        );
-    }
-
+    assert!(tcx.sess.opts.trimmed_def_paths);
+
+    // Trimming paths is expensive and not optimized, since we expect it to only be used for error
+    // reporting.
+    //
+    // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
+    // wrapper can be used to suppress this query, in exchange for full paths being formatted.
+    tcx.sess.good_path_delayed_bug(
+        "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
+    );
+
+    // Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while
+    // non-unique pairs will have a `None` entry.
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
         &mut FxHashMap::default();
 
@@ -3121,6 +3114,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
         }
     });
 
+    // Put the symbol from all the unique namespace+symbol pairs into `map`.
+    let mut map: DefIdMap<Symbol> = Default::default();
     for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() {
         use std::collections::hash_map::Entry::{Occupied, Vacant};
 
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 6d681dc295efb..d71f712132205 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 either = "1"
+itertools = "0.11"
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b8d08319422d4..714c5f2686eb5 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,5 +1,6 @@
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
+use itertools::Itertools;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_ast::attr;
@@ -654,7 +655,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
                         ty::ClosureKind::FnOnce => closure_ty,
                     };
                     (
-                        [self_ty].into_iter().chain(sig.inputs().to_vec()).collect(),
+                        [self_ty].into_iter().chain(sig.inputs()[0].tuple_fields()).collect(),
                         sig.output(),
                         None,
                     )
@@ -835,7 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.upvars = tcx
             .closure_captures(self.def_id)
             .iter()
-            .zip(capture_tys)
+            .zip_eq(capture_tys)
             .enumerate()
             .map(|(i, (captured_place, ty))| {
                 let name = captured_place.to_symbol();
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 78d72b3028416..22094c112fc18 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -2,6 +2,7 @@ use crate::errors;
 use crate::thir::cx::region::Scope;
 use crate::thir::cx::Cx;
 use crate::thir::util::UserAnnotatedTyHelpers;
+use itertools::Itertools;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -565,7 +566,7 @@ impl<'tcx> Cx<'tcx> {
                     .tcx
                     .closure_captures(def_id)
                     .iter()
-                    .zip(args.upvar_tys())
+                    .zip_eq(args.upvar_tys())
                     .map(|(captured_place, ty)| {
                         let upvars = self.capture_upvar(expr, captured_place, ty);
                         self.thir.exprs.push(upvars)
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index fe1166457baea..ac15c3b407b27 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -533,21 +533,6 @@ impl Default for ErrorOutputType {
     }
 }
 
-/// Parameter to control path trimming.
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
-pub enum TrimmedDefPaths {
-    /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive
-    /// query.
-    #[default]
-    Never,
-    /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call
-    /// `good_path_delayed_bug`.
-    Always,
-    /// `try_print_trimmed_def_path` calls the expensive query, the query calls
-    /// `good_path_delayed_bug`.
-    GoodPath,
-}
-
 #[derive(Clone, Hash, Debug)]
 pub enum ResolveDocLinks {
     /// Do not resolve doc links.
@@ -1089,7 +1074,7 @@ impl Default for Options {
             debug_assertions: true,
             actually_rustdoc: false,
             resolve_doc_links: ResolveDocLinks::None,
-            trimmed_def_paths: TrimmedDefPaths::default(),
+            trimmed_def_paths: false,
             cli_forced_codegen_units: None,
             cli_forced_local_thinlto_off: false,
             remap_path_prefix: Vec::new(),
@@ -2926,7 +2911,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         debug_assertions,
         actually_rustdoc: false,
         resolve_doc_links: ResolveDocLinks::ExportedMetadata,
-        trimmed_def_paths: TrimmedDefPaths::default(),
+        trimmed_def_paths: false,
         cli_forced_codegen_units: codegen_units,
         cli_forced_local_thinlto_off: disable_local_thinlto,
         remap_path_prefix,
@@ -3210,7 +3195,7 @@ pub(crate) mod dep_tracking {
         LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy, OptLevel,
         OutFileName, OutputType, OutputTypes, Polonius, RemapPathScopeComponents, ResolveDocLinks,
         SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
-        TrimmedDefPaths, WasiExecModel,
+        WasiExecModel,
     };
     use crate::lint;
     use crate::utils::NativeLib;
@@ -3305,7 +3290,6 @@ pub(crate) mod dep_tracking {
         SymbolManglingVersion,
         RemapPathScopeComponents,
         SourceFileHashAlgorithm,
-        TrimmedDefPaths,
         OutFileName,
         OutputType,
         RealFileName,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 2d91a3fbd9116..f4bf79f93f287 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -183,7 +183,7 @@ top_level_options!(
         resolve_doc_links: ResolveDocLinks [TRACKED],
 
         /// Control path trimming.
-        trimmed_def_paths: TrimmedDefPaths [TRACKED],
+        trimmed_def_paths: bool [TRACKED],
 
         /// Specifications of codegen units / ThinLTO which are forced as a
         /// result of parsing command line options. These are not necessarily
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 09f4f3e9702ff..c847425ebf46a 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -66,10 +66,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                         .0
                     {
                         Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
-                            FulfillmentErrorCode::CodeAmbiguity { overflow: false }
+                            FulfillmentErrorCode::Ambiguity { overflow: false }
                         }
                         Ok((_, Certainty::Maybe(MaybeCause::Overflow), _)) => {
-                            FulfillmentErrorCode::CodeAmbiguity { overflow: true }
+                            FulfillmentErrorCode::Ambiguity { overflow: true }
                         }
                         Ok((_, Certainty::Yes, _)) => {
                             bug!("did not expect successful goal when collecting ambiguity errors")
@@ -108,18 +108,18 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                                 obligation: obligation.clone(),
                                 code: match goal.predicate.kind().skip_binder() {
                                     ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
-                                        FulfillmentErrorCode::CodeProjectionError(
+                                        FulfillmentErrorCode::ProjectionError(
                                             // FIXME: This could be a `Sorts` if the term is a type
                                             MismatchedProjectionTypes { err: TypeError::Mismatch },
                                         )
                                     }
                                     ty::PredicateKind::NormalizesTo(..) => {
-                                        FulfillmentErrorCode::CodeProjectionError(
+                                        FulfillmentErrorCode::ProjectionError(
                                             MismatchedProjectionTypes { err: TypeError::Mismatch },
                                         )
                                     }
                                     ty::PredicateKind::AliasRelate(_, _, _) => {
-                                        FulfillmentErrorCode::CodeProjectionError(
+                                        FulfillmentErrorCode::ProjectionError(
                                             MismatchedProjectionTypes { err: TypeError::Mismatch },
                                         )
                                     }
@@ -128,7 +128,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                                             goal.predicate.kind().rebind((pred.a, pred.b)),
                                         );
                                         let expected_found = ExpectedFound::new(true, a, b);
-                                        FulfillmentErrorCode::CodeSubtypeError(
+                                        FulfillmentErrorCode::SubtypeError(
                                             expected_found,
                                             TypeError::Sorts(expected_found),
                                         )
@@ -138,7 +138,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                                             goal.predicate.kind().rebind((pred.a, pred.b)),
                                         );
                                         let expected_found = ExpectedFound::new(false, a, b);
-                                        FulfillmentErrorCode::CodeSubtypeError(
+                                        FulfillmentErrorCode::SubtypeError(
                                             expected_found,
                                             TypeError::Sorts(expected_found),
                                         )
@@ -146,7 +146,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                                     ty::PredicateKind::Clause(_)
                                     | ty::PredicateKind::ObjectSafe(_)
                                     | ty::PredicateKind::Ambiguous => {
-                                        FulfillmentErrorCode::CodeSelectionError(
+                                        FulfillmentErrorCode::SelectionError(
                                             SelectionError::Unimplemented,
                                         )
                                     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index b970ec7f726ea..149dcffe333de 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -14,8 +14,8 @@ use crate::traits::specialize::to_pretty_impl_header;
 use crate::traits::NormalizeExt;
 use crate::traits::{
     elaborate, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
-    ObligationCause, ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
-    PredicateObligation, SelectionError, TraitNotObjectSafe,
+    ObligationCause, ObligationCauseCode, ObligationCtxt, Overflow, PredicateObligation,
+    SelectionError, SignatureMismatch, TraitNotObjectSafe,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{
@@ -30,7 +30,7 @@ use rustc_hir::{GenericParam, Item, Node};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
-use rustc_middle::traits::{DefiningAnchor, SelectionOutputTypeParameterMismatch};
+use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData};
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
@@ -785,14 +785,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                     ty::PredicateKind::Subtype(predicate) => {
                         // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // `FulfillmentErrorCode::SubtypeError`,
                         // not selection error.
                         span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
                     }
 
                     ty::PredicateKind::Coerce(predicate) => {
                         // Errors for Coerce predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // `FulfillmentErrorCode::SubtypeError`,
                         // not selection error.
                         span_bug!(span, "coerce requirement gave wrong error: `{:?}`", predicate)
                     }
@@ -891,22 +891,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
 
-            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
+            SignatureMismatch(box SignatureMismatchData {
                 found_trait_ref,
                 expected_trait_ref,
                 terr: terr @ TypeError::CyclicTy(_),
-            }) => self.report_type_parameter_mismatch_cyclic_type_error(
+            }) => self.report_cyclic_signature_error(
                 &obligation,
                 found_trait_ref,
                 expected_trait_ref,
                 terr,
             ),
-            OutputTypeParameterMismatch(box SelectionOutputTypeParameterMismatch {
+            SignatureMismatch(box SignatureMismatchData {
                 found_trait_ref,
                 expected_trait_ref,
                 terr: _,
             }) => {
-                match self.report_type_parameter_mismatch_error(
+                match self.report_signature_mismatch_error(
                     &obligation,
                     span,
                     found_trait_ref,
@@ -1492,7 +1492,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         kind: ty::ClosureKind,
     ) -> DiagnosticBuilder<'tcx>;
 
-    fn report_type_parameter_mismatch_cyclic_type_error(
+    fn report_cyclic_signature_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
@@ -1506,7 +1506,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
         def_id: DefId,
     ) -> DiagnosticBuilder<'tcx>;
 
-    fn report_type_parameter_mismatch_error(
+    fn report_signature_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
@@ -1572,23 +1572,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
 
         match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+            FulfillmentErrorCode::SelectionError(ref selection_error) => {
                 self.report_selection_error(
                     error.obligation.clone(),
                     &error.root_obligation,
                     selection_error,
                 );
             }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+            FulfillmentErrorCode::ProjectionError(ref e) => {
                 self.report_projection_error(&error.obligation, e);
             }
-            FulfillmentErrorCode::CodeAmbiguity { overflow: false } => {
+            FulfillmentErrorCode::Ambiguity { overflow: false } => {
                 self.maybe_report_ambiguity(&error.obligation);
             }
-            FulfillmentErrorCode::CodeAmbiguity { overflow: true } => {
+            FulfillmentErrorCode::Ambiguity { overflow: true } => {
                 self.report_overflow_no_abort(error.obligation.clone());
             }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+            FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => {
                 self.report_mismatched_types(
                     &error.obligation.cause,
                     expected_found.expected,
@@ -1597,7 +1597,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 )
                 .emit();
             }
-            FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => {
+            FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => {
                 let mut diag = self.report_mismatched_consts(
                     &error.obligation.cause,
                     expected_found.expected,
@@ -1622,7 +1622,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
                 diag.emit();
             }
-            FulfillmentErrorCode::CodeCycle(ref cycle) => {
+            FulfillmentErrorCode::Cycle(ref cycle) => {
                 self.report_overflow_obligation_cycle(cycle);
             }
         }
@@ -3366,7 +3366,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         self.dcx().create_err(err)
     }
 
-    fn report_type_parameter_mismatch_cyclic_type_error(
+    fn report_cyclic_signature_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
@@ -3427,7 +3427,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err
     }
 
-    fn report_type_parameter_mismatch_error(
+    fn report_signature_mismatch_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
@@ -3446,10 +3446,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         };
 
         let found_did = match *found_trait_ty.kind() {
-            ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => {
-                Some(did)
-            }
-            ty::Adt(def, _) => Some(def.did()),
+            ty::Closure(did, _) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => Some(did),
             _ => None,
         };
 
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 472342f98980d..0337672b3027e 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -18,9 +18,6 @@ use super::const_evaluatable;
 use super::project::{self, ProjectAndUnifyResult};
 use super::select::SelectionContext;
 use super::wf;
-use super::CodeAmbiguity;
-use super::CodeProjectionError;
-use super::CodeSelectionError;
 use super::EvaluationResult;
 use super::PredicateObligation;
 use super::Unimplemented;
@@ -140,7 +137,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         _infcx: &InferCtxt<'tcx>,
     ) -> Vec<FulfillmentError<'tcx>> {
         self.predicates
-            .to_errors(CodeAmbiguity { overflow: false })
+            .to_errors(FulfillmentErrorCode::Ambiguity { overflow: false })
             .into_iter()
             .map(to_fulfillment_error)
             .collect()
@@ -414,7 +411,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
                 ty::PredicateKind::ObjectSafe(trait_def_id) => {
                     if !self.selcx.tcx().check_is_object_safe(trait_def_id) {
-                        ProcessResult::Error(CodeSelectionError(Unimplemented))
+                        ProcessResult::Error(FulfillmentErrorCode::SelectionError(Unimplemented))
                     } else {
                         ProcessResult::Changed(vec![])
                     }
@@ -485,7 +482,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Ok(Err(err)) => {
                             let expected_found =
                                 ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b);
-                            ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
+                            ProcessResult::Error(FulfillmentErrorCode::SubtypeError(
                                 expected_found,
                                 err,
                             ))
@@ -508,7 +505,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
                         Ok(Err(err)) => {
                             let expected_found = ExpectedFound::new(false, coerce.a, coerce.b);
-                            ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
+                            ProcessResult::Error(FulfillmentErrorCode::SubtypeError(
                                 expected_found,
                                 err,
                             ))
@@ -534,7 +531,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         Err(
                             e @ NotConstEvaluatable::MentionsParam
                             | e @ NotConstEvaluatable::Error(_),
-                        ) => ProcessResult::Error(CodeSelectionError(
+                        ) => ProcessResult::Error(FulfillmentErrorCode::SelectionError(
                             SelectionError::NotConstEvaluatable(e),
                         )),
                     }
@@ -623,20 +620,22 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                 Ok(inf_ok) => {
                                     ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
                                 }
-                                Err(err) => ProcessResult::Error(
-                                    FulfillmentErrorCode::CodeConstEquateError(
+                                Err(err) => {
+                                    ProcessResult::Error(FulfillmentErrorCode::ConstEquateError(
                                         ExpectedFound::new(true, c1, c2),
                                         err,
-                                    ),
-                                ),
+                                    ))
+                                }
                             }
                         }
                         (Err(ErrorHandled::Reported(reported, _)), _)
-                        | (_, Err(ErrorHandled::Reported(reported, _))) => ProcessResult::Error(
-                            CodeSelectionError(SelectionError::NotConstEvaluatable(
-                                NotConstEvaluatable::Error(reported.into()),
-                            )),
-                        ),
+                        | (_, Err(ErrorHandled::Reported(reported, _))) => {
+                            ProcessResult::Error(FulfillmentErrorCode::SelectionError(
+                                SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(
+                                    reported.into(),
+                                )),
+                            ))
+                        }
                         (Err(ErrorHandled::TooGeneric(_)), _)
                         | (_, Err(ErrorHandled::TooGeneric(_))) => {
                             if c1.has_non_region_infer() || c2.has_non_region_infer() {
@@ -644,7 +643,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                             } else {
                                 // Two different constants using generic parameters ~> error.
                                 let expected_found = ExpectedFound::new(true, c1, c2);
-                                ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError(
+                                ProcessResult::Error(FulfillmentErrorCode::ConstEquateError(
                                     expected_found,
                                     TypeError::ConstMismatch(expected_found),
                                 ))
@@ -659,7 +658,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         ty,
                     ) {
                         Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
-                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
+                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::SelectionError(
                             SelectionError::Unimplemented,
                         )),
                     }
@@ -682,7 +681,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
             Ok(())
         } else {
             let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
-            Err(FulfillmentErrorCode::CodeCycle(cycle))
+            Err(FulfillmentErrorCode::Cycle(cycle))
         }
     }
 }
@@ -737,7 +736,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             Err(selection_err) => {
                 debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth);
 
-                ProcessResult::Error(CodeSelectionError(selection_err))
+                ProcessResult::Error(FulfillmentErrorCode::SelectionError(selection_err))
             }
         }
     }
@@ -789,7 +788,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
                 project_obligation.with(tcx, project_obligation.predicate),
             ])),
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
-                ProcessResult::Error(CodeProjectionError(e))
+                ProcessResult::Error(FulfillmentErrorCode::ProjectionError(e))
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index e20bb06d7770a..74f388e53a3c9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
-use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
+use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
 use rustc_middle::ty::{
     self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
     TraitPredicate, Ty, TyCtxt, TypeVisitableExt,
@@ -26,9 +26,9 @@ use crate::traits::vtable::{
 };
 use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
-    ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
-    OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, Unimplemented,
+    ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, PolyTraitObligation,
+    PredicateObligation, Selection, SelectionError, SignatureMismatch, TraitNotObjectSafe,
+    Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -922,7 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 obligations
             })
             .map_err(|terr| {
-                OutputTypeParameterMismatch(Box::new(SelectionOutputTypeParameterMismatch {
+                SignatureMismatch(Box::new(SignatureMismatchData {
                     expected_trait_ref: obligation_trait_ref,
                     found_trait_ref: expected_trait_ref,
                     terr,
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 200d022c80c69..b37d9714ddd8c 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP};
 
 use super::util;
 use super::SelectionContext;
@@ -142,10 +142,30 @@ pub fn translate_args_with_cause<'tcx>(
 pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
+    // If specialization is enabled for this crate then no extra checks are needed.
+    // If it's not, and either of the `impl`s is local to this crate, then this definitely
+    // isn't specializing - unless specialization is enabled for the `impl` span,
+    // e.g. if it comes from an `allow_internal_unstable` macro
     let features = tcx.features();
     let specialization_enabled = features.specialization || features.min_specialization;
-    if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
-        return false;
+    if !specialization_enabled {
+        if impl1_def_id.is_local() {
+            let span = tcx.def_span(impl1_def_id);
+            if !span.allows_unstable(sym::specialization)
+                && !span.allows_unstable(sym::min_specialization)
+            {
+                return false;
+            }
+        }
+
+        if impl2_def_id.is_local() {
+            let span = tcx.def_span(impl2_def_id);
+            if !span.allows_unstable(sym::specialization)
+                && !span.allows_unstable(sym::min_specialization)
+            {
+                return false;
+            }
+        }
     }
 
     // We determine whether there's a subset relationship by:
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 2cd1c3b502ae7..f3fae63ecc7b2 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -63,7 +63,7 @@ pub fn codegen_select_candidate<'tcx>(
         // Cycle errors are the only post-monomorphization errors possible; emit them now so
         // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
         for err in errors {
-            if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
+            if let FulfillmentErrorCode::Cycle(cycle) = err.code {
                 infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
             }
         }
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index b8c71bc96f88f..21a016e29d699 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -54,7 +54,7 @@ fn normalize_projection_ty<'tcx>(
                     // that impl vars are constrained by the signature, for example).
                     if !tcx.sess.opts.actually_rustdoc {
                         for error in &errors {
-                            if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code {
+                            if let FulfillmentErrorCode::Cycle(cycle) = &error.code {
                                 ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
                             }
                         }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index b8351463c55c7..2fc4bfd4aa31c 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1052,6 +1052,8 @@ fn variant_info_for_coroutine<'tcx>(
     def_id: DefId,
     args: ty::GenericArgsRef<'tcx>,
 ) -> (Vec<VariantInfo>, Option<Size>) {
+    use itertools::Itertools;
+
     let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
         return (vec![], None);
     };
@@ -1064,7 +1066,7 @@ fn variant_info_for_coroutine<'tcx>(
         .as_coroutine()
         .upvar_tys()
         .iter()
-        .zip(upvar_names)
+        .zip_eq(upvar_names)
         .enumerate()
         .map(|(field_idx, (_, name))| {
             let field_layout = layout.field(cx, field_idx);
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 3598598cfa02a..27b59cfc8c24d 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -20,6 +20,9 @@ union Data<T, F> {
 /// A value which is initialized on the first access.
 ///
 /// This type is a thread-safe [`LazyCell`], and can be used in statics.
+/// Since initialization may be called from multiple threads, any
+/// dereferencing call will block the calling thread if another
+/// initialization routine is currently running.
 ///
 /// [`LazyCell`]: crate::cell::LazyCell
 ///
@@ -81,8 +84,7 @@ pub struct LazyLock<T, F = fn() -> T> {
 }
 
 impl<T, F: FnOnce() -> T> LazyLock<T, F> {
-    /// Creates a new lazy value with the given initializing
-    /// function.
+    /// Creates a new lazy value with the given initializing function.
     #[inline]
     #[unstable(feature = "lazy_cell", issue = "109736")]
     pub const fn new(f: F) -> LazyLock<T, F> {
@@ -134,9 +136,11 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
         }
     }
 
-    /// Forces the evaluation of this lazy value and
-    /// returns a reference to result. This is equivalent
-    /// to the `Deref` impl, but is explicit.
+    /// Forces the evaluation of this lazy value and returns a reference to
+    /// result. This is equivalent to the `Deref` impl, but is explicit.
+    ///
+    /// This method will block the calling thread if another initialization
+    /// routine is currently running.
     ///
     /// # Examples
     ///
@@ -204,6 +208,11 @@ impl<T, F> Drop for LazyLock<T, F> {
 impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     type Target = T;
 
+    /// Dereferences the value.
+    ///
+    /// This method will block the calling thread if another initialization
+    /// routine is currently running.
+    ///
     #[inline]
     fn deref(&self) -> &T {
         LazyLock::force(self)
@@ -232,7 +241,7 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
 }
 
 // We never create a `&F` from a `&LazyLock<T, F>` so it is fine
-// to not impl `Sync` for `F`
+// to not impl `Sync` for `F`.
 #[unstable(feature = "lazy_cell", issue = "109736")]
 unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
 // auto-derived `Send` impl is OK.
diff --git a/tests/ui/async-await/issues/issue-65159.rs b/tests/ui/async-await/issues/issue-65159.rs
index aed111e214422..7197a4fb91a0b 100644
--- a/tests/ui/async-await/issues/issue-65159.rs
+++ b/tests/ui/async-await/issues/issue-65159.rs
@@ -5,7 +5,7 @@
 async fn copy() -> Result<()>
 //~^ ERROR enum takes 2 generic arguments
 {
-    Ok(()) //~ ERROR: type annotations needed
+    Ok(())
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr
index 77a0ea5027c18..19512116a66cd 100644
--- a/tests/ui/async-await/issues/issue-65159.stderr
+++ b/tests/ui/async-await/issues/issue-65159.stderr
@@ -11,18 +11,6 @@ help: add missing generic argument
 LL | async fn copy() -> Result<(), E>
    |                             +++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-65159.rs:8:5
-   |
-LL |     Ok(())
-   |     ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
-   |
-help: consider specifying the generic arguments
-   |
-LL |     Ok::<(), E>(())
-   |       +++++++++
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0107, E0282.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
index c10246eec6491..b52939ffc119c 100644
--- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
+++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
@@ -17,7 +17,6 @@ async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
     //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied
     //~^^ ERROR struct takes 1 generic argument but 0 generic arguments were supplied
     LockedMarket(coroutine.lock().unwrap().buy())
-    //~^ ERROR: cannot return value referencing temporary value
 }
 
 struct LockedMarket<T>(T);
diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
index 2b10cf67d15b3..516c1d065e670 100644
--- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
+++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
@@ -7,7 +7,7 @@ LL | async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
    |                                                           expected 0 lifetime arguments
    |
 note: struct defined here, with 0 lifetime parameters
-  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
    |
 LL | struct LockedMarket<T>(T);
    |        ^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
    |                                                           ^^^^^^^^^^^^ expected 1 generic argument
    |
 note: struct defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
    |
 LL | struct LockedMarket<T>(T);
    |        ^^^^^^^^^^^^ -
@@ -28,16 +28,6 @@ help: add missing generic argument
 LL | async fn buy_lock(coroutine: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
    |                                                                          +++
 
-error[E0515]: cannot return value referencing temporary value
-  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5
-   |
-LL |     LockedMarket(coroutine.lock().unwrap().buy())
-   |     ^^^^^^^^^^^^^-------------------------^^^^^^^
-   |     |            |
-   |     |            temporary value created here
-   |     returns a value referencing data owned by the current function
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0515.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/impl-trait/issue-72911.rs b/tests/ui/impl-trait/issue-72911.rs
index 63f4898f4306b..7ba8579e24fb1 100644
--- a/tests/ui/impl-trait/issue-72911.rs
+++ b/tests/ui/impl-trait/issue-72911.rs
@@ -15,6 +15,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint>
 
 fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
     //~^ ERROR: failed to resolve
+    //~| ERROR: `()` is not an iterator
     unimplemented!()
 }
 
diff --git a/tests/ui/impl-trait/issue-72911.stderr b/tests/ui/impl-trait/issue-72911.stderr
index 0e86561aa2779..44c20a7be53df 100644
--- a/tests/ui/impl-trait/issue-72911.stderr
+++ b/tests/ui/impl-trait/issue-72911.stderr
@@ -1,3 +1,11 @@
+error[E0277]: `()` is not an iterator
+  --> $DIR/issue-72911.rs:16:20
+   |
+LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+
 error[E0433]: failed to resolve: use of undeclared crate or module `foo`
   --> $DIR/issue-72911.rs:11:33
    |
@@ -10,6 +18,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo`
 LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
    |                                         ^^^ use of undeclared crate or module `foo`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0433`.
+Some errors have detailed explanations: E0277, E0433.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/issues/issue-92305.rs b/tests/ui/impl-trait/issues/issue-92305.rs
index e16199caaaa21..4a89238d07e60 100644
--- a/tests/ui/impl-trait/issues/issue-92305.rs
+++ b/tests/ui/impl-trait/issues/issue-92305.rs
@@ -5,7 +5,6 @@ use std::iter;
 fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
     //~^ ERROR: missing generics for struct `Vec` [E0107]
     iter::empty()
-    //~^ ERROR: type annotations needed
 }
 
 fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> {
diff --git a/tests/ui/impl-trait/issues/issue-92305.stderr b/tests/ui/impl-trait/issues/issue-92305.stderr
index 55e966bd7bfd8..88fb1fb27070e 100644
--- a/tests/ui/impl-trait/issues/issue-92305.stderr
+++ b/tests/ui/impl-trait/issues/issue-92305.stderr
@@ -9,18 +9,6 @@ help: add missing generic argument
 LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
    |                                                +++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-92305.rs:7:5
-   |
-LL |     iter::empty()
-   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
-   |
-help: consider specifying the generic argument
-   |
-LL |     iter::empty::<T>()
-   |                +++++
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0107, E0282.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/specialization/allow_internal_unstable.rs b/tests/ui/specialization/allow_internal_unstable.rs
new file mode 100644
index 0000000000000..317782b7b7285
--- /dev/null
+++ b/tests/ui/specialization/allow_internal_unstable.rs
@@ -0,0 +1,18 @@
+// check-pass
+// test for #119950
+// compile-flags: --crate-type lib
+
+#![allow(internal_features)]
+#![feature(allow_internal_unstable)]
+
+#[allow_internal_unstable(min_specialization)]
+macro_rules! test {
+    () => {
+        struct T<U>(U);
+        trait Tr {}
+        impl<U> Tr for T<U> {}
+        impl Tr for T<u8> {}
+    }
+}
+
+test! {}