about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs37
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs11
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs10
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs13
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs6
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs7
-rw-r--r--compiler/rustc_hir/src/hir.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs5
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs4
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs9
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs7
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs10
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs6
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs29
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs1
-rw-r--r--compiler/rustc_lint/src/unused.rs16
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs18
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7k_apple_watchos.rs2
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs69
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs44
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_traits/src/type_op.rs9
-rw-r--r--library/alloc/src/rc.rs84
-rw-r--r--library/alloc/src/sync.rs85
-rw-r--r--library/alloc/tests/arc.rs15
-rw-r--r--library/alloc/tests/rc.rs15
-rw-r--r--library/core/src/future/mod.rs1
-rw-r--r--library/core/src/macros/mod.rs1
-rw-r--r--src/bootstrap/cc_detect.rs40
-rw-r--r--src/bootstrap/config.rs9
-rw-r--r--src/ci/docker/host-x86_64/armhf-gnu/Dockerfile2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css17
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css22
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css23
-rw-r--r--src/librustdoc/html/static/css/themes/light.css24
-rw-r--r--src/librustdoc/html/static/js/settings.js60
-rw-r--r--src/test/run-make-fulldeps/tools.mk23
-rw-r--r--src/test/run-make/issue-36710/Makefile5
-rw-r--r--src/test/rustdoc-gui/codeblock-tooltip.goml80
-rw-r--r--src/test/rustdoc-gui/settings.goml41
-rw-r--r--src/test/rustdoc-gui/theme-change.goml47
-rw-r--r--src/test/ui/async-await/in-trait/early-bound-1.rs17
-rw-r--r--src/test/ui/async-await/in-trait/early-bound-2.rs15
-rw-r--r--src/test/ui/async-await/in-trait/object-safety.rs13
-rw-r--r--src/test/ui/async-await/in-trait/object-safety.stderr27
-rw-r--r--src/test/ui/async-await/track-caller/panic-track-caller.rs76
-rw-r--r--src/test/ui/consts/const-eval/issue-104390.rs10
-rw-r--r--src/test/ui/consts/const-eval/issue-104390.stderr65
-rw-r--r--src/test/ui/dyn-star/return.rs10
-rw-r--r--src/test/ui/dyn-star/return.stderr11
-rw-r--r--src/test/ui/impl-trait/in-trait/object-safety.stderr12
-rw-r--r--src/test/ui/lint/issue-104392.rs11
-rw-r--r--src/test/ui/lint/issue-104392.stderr27
-rw-r--r--src/test/ui/typeck/issue-103899.rs5
-rw-r--r--src/test/ui/typeck/issue-103899.stderr12
-rw-r--r--src/test/ui/typeck/issue-104510-ice.rs16
-rw-r--r--src/test/ui/typeck/issue-104510-ice.stderr9
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_async.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs10
-rw-r--r--src/tools/compiletest/src/runtest.rs4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/shims/time.rs48
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs9
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-misc.rs20
105 files changed, 1148 insertions, 526 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 450cdf246b1..db0d8b08a94 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -11,7 +11,7 @@ use super::LoweringContext;
 
 use rustc_ast::ptr::P;
 use rustc_ast::*;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::definitions::DefPathData;
@@ -71,7 +71,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             .emit();
         }
 
-        let mut clobber_abis = FxHashMap::default();
+        let mut clobber_abis = FxIndexMap::default();
         if let Some(asm_arch) = asm_arch {
             for (abi_name, abi_span) in &asm.clobber_abis {
                 match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index eb64027f369..01716859a9d 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -655,15 +655,40 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             hir::ExprKind::Closure(c)
         };
-        let generator = hir::Expr {
-            hir_id: self.lower_node_id(closure_node_id),
-            kind: generator_kind,
-            span: self.lower_span(span),
+        let parent_has_track_caller = self
+            .attrs
+            .values()
+            .find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some())
+            .is_some();
+        let unstable_span =
+            self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
+
+        let hir_id = if parent_has_track_caller {
+            let generator_hir_id = self.lower_node_id(closure_node_id);
+            self.lower_attrs(
+                generator_hir_id,
+                &[Attribute {
+                    kind: AttrKind::Normal(ptr::P(NormalAttr {
+                        item: AttrItem {
+                            path: Path::from_ident(Ident::new(sym::track_caller, span)),
+                            args: MacArgs::Empty,
+                            tokens: None,
+                        },
+                        tokens: None,
+                    })),
+                    id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(),
+                    style: AttrStyle::Outer,
+                    span: unstable_span,
+                }],
+            );
+            generator_hir_id
+        } else {
+            self.lower_node_id(closure_node_id)
         };
 
+        let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
+
         // `future::from_generator`:
-        let unstable_span =
-            self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
         let gen_future = self.expr_lang_item_path(
             unstable_span,
             hir::LangItem::FromGenerator,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 756f35e901d..77c5ed6036e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -6,7 +6,6 @@ use super::{FnDeclKind, LoweringContext, ParamMode};
 use rustc_ast::ptr::P;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -67,7 +66,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             // HirId handling.
             bodies: Vec::new(),
             attrs: SortedMap::default(),
-            children: FxHashMap::default(),
+            children: Vec::default(),
             current_hir_id_owner: hir::CRATE_OWNER_ID,
             item_local_id_counter: hir::ItemLocalId::new(0),
             node_id_to_local_id: Default::default(),
@@ -86,7 +85,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
             impl_trait_defs: Vec::new(),
             impl_trait_bounds: Vec::new(),
             allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
-            allow_gen_future: Some([sym::gen_future][..].into()),
+            allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()),
             allow_into_future: Some([sym::into_future][..].into()),
             generics_def_id_map: Default::default(),
         };
@@ -534,12 +533,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 for new_node_id in [id1, id2] {
                     let new_id = self.local_def_id(new_node_id);
                     let Some(res) = resolutions.next() else {
+                        debug_assert!(self.children.iter().find(|(id, _)| id == &new_id).is_none());
                         // Associate an HirId to both ids even if there is no resolution.
-                        let _old = self.children.insert(
+                        self.children.push((
                             new_id,
-                            hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id)),
+                            hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id))),
                         );
-                        debug_assert!(_old.is_none());
                         continue;
                     };
                     let ident = *ident;
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5ab75b1294b..ecc2578dd2a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -34,7 +34,6 @@
 #![feature(let_chains)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
@@ -107,7 +106,7 @@ struct LoweringContext<'a, 'hir> {
     /// Attributes inside the owner being lowered.
     attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
     /// Collect items that were created by lowering the current owner.
-    children: FxHashMap<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
+    children: Vec<(LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>)>,
 
     generator_kind: Option<hir::GeneratorKind>,
 
@@ -611,8 +610,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.impl_trait_defs = current_impl_trait_defs;
         self.impl_trait_bounds = current_impl_trait_bounds;
 
-        let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info));
-        debug_assert!(_old.is_none())
+        debug_assert!(self.children.iter().find(|(id, _)| id == &def_id).is_none());
+        self.children.push((def_id, hir::MaybeOwner::Owner(info)));
     }
 
     /// Installs the remapping `remap` in scope while `f` is being executed.
@@ -719,8 +718,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                 assert_ne!(local_id, hir::ItemLocalId::new(0));
                 if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
-                    // Do not override a `MaybeOwner::Owner` that may already here.
-                    self.children.entry(def_id).or_insert(hir::MaybeOwner::NonOwner(hir_id));
+                    self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
                     self.local_id_to_def_id.insert(local_id, def_id);
                 }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index dd222485daf..b2db77944fd 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -7,9 +7,7 @@ use rustc_infer::infer::{DefiningAnchor, InferCtxt};
 use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{
-    self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
-};
+use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -256,8 +254,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         // Require the hidden type to be well-formed with only the generics of the opaque type.
         // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
         // hidden type is well formed even without those bounds.
-        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
-            .to_predicate(infcx.tcx);
+        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
 
         let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
 
@@ -282,6 +279,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         }
 
         ocx.register_obligation(Obligation::misc(
+            infcx.tcx,
             instantiated_ty.span,
             body_id,
             param_env,
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index a581726a15c..d0cf8622a44 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -92,8 +92,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 trait_ref,
                 constness: ty::BoundConstness::NotConst,
                 polarity: ty::ImplPolarity::Positive,
-            }))
-            .to_predicate(self.tcx()),
+            })),
             locations,
             category,
         );
@@ -122,14 +121,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
     pub(super) fn prove_predicates(
         &mut self,
-        predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
+        predicates: impl IntoIterator<
+            Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
+        >,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
         for predicate in predicates {
-            let predicate = predicate.to_predicate(self.tcx());
-            debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
-
             self.prove_predicate(predicate, locations, category);
         }
     }
@@ -137,11 +135,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     pub(super) fn prove_predicate(
         &mut self,
-        predicate: ty::Predicate<'tcx>,
+        predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
         let param_env = self.param_env;
+        let predicate = predicate.to_predicate(self.tcx());
         self.fully_perform_op(
             locations,
             category,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 6ccc29b09c0..7d36a63943c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -33,8 +33,7 @@ use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
-    OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType,
-    UserTypeAnnotationIndex,
+    OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
 };
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::{Span, DUMMY_SP};
@@ -1069,8 +1068,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
 
                     self.prove_predicate(
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into()))
-                            .to_predicate(self.tcx()),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())),
                         Locations::All(span),
                         ConstraintCategory::TypeAnnotation,
                     );
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 5a8b3e30b9f..36956f5dd6d 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -732,7 +732,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         polarity: ty::ImplPolarity::Positive,
                     });
                     let obligation =
-                        Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);
+                        Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred);
 
                     let implsrc = {
                         let infcx = tcx.infer_ctxt().build();
@@ -816,6 +816,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                             if !nonconst_call_permission {
                                 let obligation = Obligation::new(
+                                    tcx,
                                     ObligationCause::dummy_with_span(*fn_span),
                                     param_env,
                                     tcx.mk_predicate(
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 25b420bed17..b90e0962ce6 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -62,7 +62,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
     }
 
     fn is_async(&self) -> bool {
-        self.tcx.asyncness(self.def_id()) == hir::IsAsync::Async
+        self.tcx.asyncness(self.def_id()).is_async()
     }
 }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index b28d7019491..2d4afd0dc35 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -147,6 +147,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 }
                 Adt(..) => {
                     let obligation = Obligation::new(
+                        tcx,
                         ObligationCause::dummy(),
                         param_env,
                         Binder::dummy(TraitPredicate {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index d995d533ca3..6fd12985170 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -156,6 +156,7 @@ impl Qualif for NeedsNonConstDrop {
         let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None);
 
         let obligation = Obligation::new(
+            cx.tcx,
             ObligationCause::dummy(),
             cx.param_env,
             ty::Binder::dummy(ty::TraitPredicate {
@@ -351,7 +352,11 @@ where
     // FIXME(valtrees): check whether const qualifs should behave the same
     // way for type and mir constants.
     let uneval = match constant.literal {
-        ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
+        ConstantKind::Ty(ct)
+            if matches!(ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_)) =>
+        {
+            None
+        }
         ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
         ConstantKind::Unevaluated(uv, _) => Some(uv),
         ConstantKind::Val(..) => None,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7d8b859a6b4..e0a38645065 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2720,6 +2720,12 @@ pub enum IsAsync {
     NotAsync,
 }
 
+impl IsAsync {
+    pub fn is_async(self) -> bool {
+        self == IsAsync::Async
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum Defaultness {
     Default { has_value: bool },
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0ba5e615101..f76b282fa76 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -19,9 +19,7 @@ use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{
-    self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -464,9 +462,8 @@ fn check_opaque_meets_bounds<'tcx>(
     // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
     // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
     // hidden type is well formed even without those bounds.
-    let predicate =
-        ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into())).to_predicate(tcx);
-    ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
+    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into()));
+    ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
 
     // Check that all obligations are satisfied by the implementation's
     // version.
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 7c99896b457..81672213dc7 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -238,7 +238,7 @@ fn compare_predicate_entailment<'tcx>(
                 kind: impl_m.kind,
             },
         );
-        ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
+        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
     // We now need to check that the signature of the impl method is
@@ -521,7 +521,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
                 let num_trait_substs = trait_to_impl_substs.len();
                 let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
                 let ty = tcx.fold_regions(ty, |region, _| {
-                    let (ty::ReFree(_) | ty::ReEarlyBound(_)) = region.kind() else { return region; };
+                    match region.kind() {
+                        // Remap all free regions, which correspond to late-bound regions in the function.
+                        ty::ReFree(_) => {}
+                        // Remap early-bound regions as long as they don't come from the `impl` itself.
+                        ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {}
+                        _ => return region,
+                    }
                     let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
                     else {
                         tcx
@@ -605,6 +611,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
                 );
 
                 self.ocx.register_obligation(traits::Obligation::new(
+                    self.tcx(),
                     ObligationCause::new(
                         self.span,
                         self.body_id,
@@ -681,9 +688,7 @@ fn report_trait_method_mismatch<'tcx>(
                 // Suggestion to change output type. We do not suggest in `async` functions
                 // to avoid complex logic or incorrect output.
                 match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
-                    ImplItemKind::Fn(ref sig, _)
-                        if sig.header.asyncness == hir::IsAsync::NotAsync =>
-                    {
+                    ImplItemKind::Fn(ref sig, _) if !sig.header.asyncness.is_async() => {
                         let msg = "change the output type to match the trait";
                         let ap = Applicability::MachineApplicable;
                         match sig.decl.output {
@@ -1579,7 +1584,7 @@ fn compare_type_predicate_entailment<'tcx>(
             },
         );
         ocx.register_obligations(obligations);
-        ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
+        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
     }
 
     // Check that all obligations are satisfied by the implementation's
@@ -1784,7 +1789,7 @@ pub fn check_type_bounds<'tcx>(
         .subst_iter_copied(tcx, rebased_substs)
         .map(|(concrete_ty_bound, span)| {
             debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
-            traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
+            traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
         })
         .collect();
     debug!("check_type_bounds: item_bounds={:?}", obligations);
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index efb34e4ff65..1d7ceda725a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -14,8 +14,8 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
-    TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    self, AdtKind, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+    TypeVisitable, TypeVisitor,
 };
 use rustc_middle::ty::{GenericArgKind, InternalSubsts};
 use rustc_session::parse::feature_err;
@@ -75,9 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
         // for a type to be WF, we do not need to check if const trait predicates satisfy.
         let param_env = self.param_env.without_const();
         self.ocx.register_obligation(traits::Obligation::new(
+            self.tcx(),
             cause,
             param_env,
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()),
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
         ));
     }
 }
@@ -1111,12 +1112,12 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
                     traits::MiscObligation,
                 );
                 wfcx.register_obligation(traits::Obligation::new(
+                    tcx,
                     cause,
                     wfcx.param_env,
                     ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
                         ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
-                    ))
-                    .to_predicate(tcx),
+                    )),
                 ));
             }
         }
@@ -1453,7 +1454,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
                 wfcx.body_id,
                 traits::ItemObligation(def_id.to_def_id()),
             );
-            traits::Obligation::new(cause, wfcx.param_env, pred)
+            traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
         });
 
     let predicates = predicates.0.instantiate_identity(tcx);
@@ -1783,8 +1784,7 @@ fn receiver_is_implemented<'tcx>(
         substs: tcx.mk_substs_trait(receiver_ty, &[]),
     });
 
-    let obligation =
-        traits::Obligation::new(cause, wfcx.param_env, trait_ref.without_const().to_predicate(tcx));
+    let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref.without_const());
 
     if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) {
         true
@@ -1931,6 +1931,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
                 }
 
                 let obligation = traits::Obligation::new(
+                    tcx,
                     traits::ObligationCause::new(span, self.body_id, traits::TrivialBound),
                     empty_env,
                     pred,
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index b0fdfcf38a6..4f9d5826583 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ObligationCause, WellFormedLoc};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
+use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_trait_selection::traits;
 
 pub fn provide(providers: &mut Providers) {
@@ -74,10 +74,10 @@ fn diagnostic_hir_wf_check<'tcx>(
             let errors = traits::fully_solve_obligation(
                 &infcx,
                 traits::Obligation::new(
+                    self.tcx,
                     cause,
                     self.param_env,
-                    ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into()))
-                        .to_predicate(self.tcx),
+                    ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())),
                 ),
             );
             if !errors.is_empty() {
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 6a4a6a5b0a5..139f2e84136 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diagnostic, MultiSpan};
 use rustc_hir::{self as hir, ExprKind};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::Obligation;
-use rustc_middle::ty::{self, ToPredicate, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{
@@ -538,23 +538,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .bound_explicit_item_bounds(rpit_def_id)
                         .subst_iter_copied(self.tcx, substs)
                     {
-                        let pred = match pred.kind().skip_binder() {
+                        let pred = pred.kind().rebind(match pred.kind().skip_binder() {
                             ty::PredicateKind::Trait(mut trait_pred) => {
                                 assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
                                 trait_pred.trait_ref.substs =
                                     self.tcx.mk_substs_trait(ty, &trait_pred.trait_ref.substs[1..]);
-                                pred.kind().rebind(trait_pred).to_predicate(self.tcx)
+                                ty::PredicateKind::Trait(trait_pred)
                             }
                             ty::PredicateKind::Projection(mut proj_pred) => {
                                 assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
                                 proj_pred.projection_ty.substs = self
                                     .tcx
                                     .mk_substs_trait(ty, &proj_pred.projection_ty.substs[1..]);
-                                pred.kind().rebind(proj_pred).to_predicate(self.tcx)
+                                ty::PredicateKind::Projection(proj_pred)
                             }
                             _ => continue,
-                        };
+                        });
                         if !self.predicate_must_hold_modulo_regions(&Obligation::new(
+                            self.tcx,
                             ObligationCause::misc(span, self.body_id),
                             self.param_env,
                             pred,
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index ed2218b8746..302d512c71d 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -380,6 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         predicates.predicates.iter().zip(&predicates.spans)
                     {
                         let obligation = Obligation::new(
+                            self.tcx,
                             ObligationCause::dummy_with_span(callee_expr.span),
                             self.param_env,
                             *predicate,
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 1578cddd490..b9e90e47e50 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -102,7 +102,7 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
 
-    if let ty::Dynamic(..) = declared_ret_ty.kind() {
+    if let ty::Dynamic(_, _, ty::Dyn) = declared_ret_ty.kind() {
         // FIXME: We need to verify that the return type is `Sized` after the return expression has
         // been evaluated so that we have types available for all the nodes being returned, but that
         // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 71949b42118..174b4331382 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -55,7 +55,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut};
+use rustc_middle::ty::{self, Ty, TypeAndMut};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
 use rustc_span::{self, BytePos, DesugaringKind, Span};
@@ -278,13 +278,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             for &source_ty in &[a, b] {
                 if source_ty != target_ty {
                     obligations.push(Obligation::new(
+                        self.tcx(),
                         self.cause.clone(),
                         self.param_env,
                         ty::Binder::dummy(ty::PredicateKind::Coerce(ty::CoercePredicate {
                             a: source_ty,
                             b: target_ty,
-                        }))
-                        .to_predicate(self.tcx()),
+                        })),
                     ));
                 }
             }
@@ -669,7 +669,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     continue;
                 }
             };
-            match selcx.select(&obligation.with(trait_pred)) {
+            match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) {
                 // Uncertain or unimplemented.
                 Ok(None) => {
                     if trait_pred.def_id() == unsize_did {
@@ -783,10 +783,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 // and then require that the resulting predicate (e.g., `usize: Clone`)
                 // holds (it does).
                 let predicate = predicate.with_self_ty(self.tcx, a);
-                Obligation::new(self.cause.clone(), self.param_env, predicate)
+                Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate)
             })
             // Enforce the region bound (e.g., `usize: 'static`, in our example).
             .chain([Obligation::new(
+                self.tcx,
                 self.cause.clone(),
                 self.param_env,
                 self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 97d05b4f95c..c826a886ca6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -22,8 +22,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
-    self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty,
-    UserType,
+    self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, Ty, UserType,
 };
 use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts};
 use rustc_session::lint;
@@ -559,9 +558,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // WF obligations never themselves fail, so no real need to give a detailed cause:
         let cause = traits::ObligationCause::new(span, self.body_id, code);
         self.register_predicate(traits::Obligation::new(
+            self.tcx,
             cause,
             self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx),
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
         ));
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8cf70eb5431..c3833b4872d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -73,7 +73,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
                 let ty = self.resolve_vars_if_possible(ty);
                 if ty.has_non_region_infer() {
-                    assert!(self.is_tainted_by_errors());
                     self.tcx.ty_error()
                 } else {
                     self.tcx.erase_regions(ty)
@@ -2150,6 +2149,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             ),
                         );
                         let obligation = traits::Obligation::new(
+                            self.tcx,
                             traits::ObligationCause::dummy(),
                             self.param_env,
                             ty::Binder::dummy(ty::TraitPredicate {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 06e6e4350fc..316ecb0ed52 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1090,14 +1090,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(into_def_id) = self.tcx.get_diagnostic_item(sym::Into)
             && self.predicate_must_hold_modulo_regions(&traits::Obligation::new(
+                self.tcx,
                 self.misc(expr.span),
                 self.param_env,
                 ty::Binder::dummy(ty::TraitRef {
                     def_id: into_def_id,
                     substs: self.tcx.mk_substs_trait(expr_ty, &[expected_ty.into()]),
                 })
-                .to_poly_trait_predicate()
-                .to_predicate(self.tcx),
+                .to_poly_trait_predicate(),
             ))
         {
             let sugg = if expr.precedence().order() >= PREC_POSTFIX {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 3f390cba3e7..37336edd1fd 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -20,7 +20,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
-use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable};
+use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
@@ -293,10 +293,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let poly_trait_ref = ty::Binder::dummy(trait_ref);
         (
             traits::Obligation::misc(
+                self.tcx,
                 span,
                 self.body_id,
                 self.param_env,
-                poly_trait_ref.without_const().to_predicate(self.tcx),
+                poly_trait_ref.without_const(),
             ),
             substs,
         )
@@ -335,6 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         (
             traits::Obligation::new(
+                self.tcx,
                 traits::ObligationCause::new(
                     span,
                     self.body_id,
@@ -346,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     },
                 ),
                 self.param_env,
-                poly_trait_ref.without_const().to_predicate(self.tcx),
+                poly_trait_ref.without_const(),
             ),
             substs,
         )
@@ -523,9 +525,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             method_ty, obligation
         );
         obligations.push(traits::Obligation::new(
+            tcx,
             cause,
             self.param_env,
-            ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())).to_predicate(tcx),
+            ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())),
         ));
 
         let callee = MethodCallee { def_id, substs, sig: fn_sig };
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 46a76085189..9d75ccad133 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -19,7 +19,8 @@ use rustc_middle::middle::stability;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::AssocItem;
 use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::ToPredicate;
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitable};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
@@ -1429,7 +1430,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
         let predicate = ty::Binder::dummy(trait_ref).to_poly_trait_predicate();
-        let obligation = traits::Obligation::new(cause, self.param_env, predicate);
+        let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate);
         traits::SelectionContext::new(self).select(&obligation)
     }
 
@@ -1560,7 +1561,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     let predicate =
                         ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx);
                     parent_pred = Some(predicate);
-                    let obligation = traits::Obligation::new(cause, self.param_env, predicate);
+                    let obligation =
+                        traits::Obligation::new(self.tcx, cause, self.param_env, predicate);
                     if !self.predicate_may_hold(&obligation) {
                         result = ProbeResult::NoMatch;
                         if self.probe(|_| {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 19f56c73823..e2c5edd0e88 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -23,7 +23,7 @@ use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
@@ -80,10 +80,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
                         let poly_trait_ref = ty::Binder::dummy(trait_ref);
                         let obligation = Obligation::misc(
+                            tcx,
                             span,
                             self.body_id,
                             self.param_env,
-                            poly_trait_ref.without_const().to_predicate(tcx),
+                            poly_trait_ref.without_const(),
                         );
                         self.predicate_may_hold(&obligation)
                     })
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index a299a3e578d..34f54328230 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -581,9 +581,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
             }
         };
-        let predicate = predicate.0.rebind(atom).to_predicate(self.tcx);
+        let predicate = predicate.0.rebind(atom);
 
-        Obligation::new(cause, param_env, predicate)
+        Obligation::new(self.tcx, cause, param_env, predicate)
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index a973bf54b05..37f071a19ac 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -37,7 +37,7 @@ use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitable};
 use rustc_middle::ty::{IntType, UintType};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -347,10 +347,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
 
         if needs_wf {
             self.obligations.push(Obligation::new(
+                self.tcx(),
                 self.trace.cause.clone(),
                 self.param_env,
-                ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into()))
-                    .to_predicate(self.infcx.tcx),
+                ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())),
             ));
         }
 
@@ -444,9 +444,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
             ty::PredicateKind::ConstEquate(b, a)
         };
         self.obligations.push(Obligation::new(
+            self.tcx(),
             self.trace.cause.clone(),
             self.param_env,
-            ty::Binder::dummy(predicate).to_predicate(self.tcx()),
+            ty::Binder::dummy(predicate),
         ));
     }
 }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index a982f11f718..1fa95f8d62a 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -595,7 +595,12 @@ impl<'tcx> InferCtxt<'tcx> {
             }
             // Require that the predicate holds for the concrete type.
             debug!(?predicate);
-            obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate));
+            obligations.push(traits::Obligation::new(
+                self.tcx,
+                cause.clone(),
+                param_env,
+                predicate,
+            ));
         }
         Ok(InferOk { value: (), obligations })
     }
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index 9f12bc972a8..eb6deee291c 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -1,5 +1,5 @@
 use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, ToPredicate, Ty};
+use rustc_middle::ty::{self, Ty};
 
 use crate::traits::{Obligation, PredicateObligation};
 
@@ -28,12 +28,8 @@ impl<'tcx> InferCtxt<'tcx> {
         });
         let projection =
             ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty_var.into() });
-        let obligation = Obligation::with_depth(
-            cause,
-            recursion_depth,
-            param_env,
-            projection.to_predicate(self.tcx),
-        );
+        let obligation =
+            Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
         obligations.push(obligation);
         ty_var
     }
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 97354ba5d1b..8c8445a4d9e 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -6,7 +6,7 @@ use crate::traits::Obligation;
 use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use std::mem;
 
 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@@ -95,14 +95,14 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
                 // can't make progress on `A <: B` if both A and B are
                 // type variables, so record an obligation.
                 self.fields.obligations.push(Obligation::new(
+                    self.tcx(),
                     self.fields.trace.cause.clone(),
                     self.fields.param_env,
                     ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                         a_is_expected: self.a_is_expected,
                         a,
                         b,
-                    }))
-                    .to_predicate(self.tcx()),
+                    })),
                 ));
 
                 Ok(a)
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index c8600ded987..a9e6241bf6b 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -10,7 +10,7 @@ pub mod util;
 
 use rustc_hir as hir;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, Const, Ty, TyCtxt};
+use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
 use rustc_span::Span;
 
 pub use self::FulfillmentErrorCode::*;
@@ -124,38 +124,41 @@ pub enum FulfillmentErrorCode<'tcx> {
 
 impl<'tcx, O> Obligation<'tcx, O> {
     pub fn new(
+        tcx: TyCtxt<'tcx>,
         cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        predicate: O,
+        predicate: impl ToPredicate<'tcx, O>,
     ) -> Obligation<'tcx, O> {
-        Obligation { cause, param_env, recursion_depth: 0, predicate }
+        Self::with_depth(tcx, cause, 0, param_env, predicate)
     }
 
     pub fn with_depth(
+        tcx: TyCtxt<'tcx>,
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
-        predicate: O,
+        predicate: impl ToPredicate<'tcx, O>,
     ) -> Obligation<'tcx, O> {
+        let predicate = predicate.to_predicate(tcx);
         Obligation { cause, param_env, recursion_depth, predicate }
     }
 
     pub fn misc(
+        tcx: TyCtxt<'tcx>,
         span: Span,
         body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
-        trait_ref: O,
+        trait_ref: impl ToPredicate<'tcx, O>,
     ) -> Obligation<'tcx, O> {
-        Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref)
+        Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
     }
 
-    pub fn with<P>(&self, value: P) -> Obligation<'tcx, P> {
-        Obligation {
-            cause: self.cause.clone(),
-            param_env: self.param_env,
-            recursion_depth: self.recursion_depth,
-            predicate: value,
-        }
+    pub fn with<P>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        value: impl ToPredicate<'tcx, P>,
+    ) -> Obligation<'tcx, P> {
+        Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
     }
 }
 
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 619582c0539..7e0a8a0df16 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -108,6 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                 // then we must've taken advantage of the hack in `project_and_unify_types` where
                 // we replace opaques with inference vars. Emit a warning!
                 if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new(
+                    cx.tcx,
                     traits::ObligationCause::dummy(),
                     cx.param_env,
                     assoc_pred,
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index ff0fb9bae92..9ae34013ecb 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -533,16 +533,14 @@ trait UnusedDelimLint {
         right_pos: Option<BytePos>,
     ) {
         let spans = match value.kind {
-            ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
-                let start = block.stmts[0].span;
-                let end = block.stmts[block.stmts.len() - 1].span;
-                if let Some(start) = start.find_ancestor_inside(value.span)
-                    && let Some(end) = end.find_ancestor_inside(value.span)
+            ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
+                if let StmtKind::Expr(expr) = &block.stmts[0].kind
+                    && let ExprKind::Err = expr.kind
                 {
-                    Some((
-                        value.span.with_hi(start.lo()),
-                        value.span.with_lo(end.hi()),
-                    ))
+                    return
+                }
+                if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
+                    Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
                 } else {
                     None
                 }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 05382bd887c..1890c0e24bb 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -924,10 +924,13 @@ impl ObjectSafetyViolation {
             }
             ObjectSafetyViolation::Method(
                 name,
-                MethodViolationCode::ReferencesImplTraitInTrait,
+                MethodViolationCode::ReferencesImplTraitInTrait(_),
                 _,
             ) => format!("method `{}` references an `impl Trait` type in its return type", name)
                 .into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::AsyncFn, _) => {
+                format!("method `{}` is `async`", name).into()
+            }
             ObjectSafetyViolation::Method(
                 name,
                 MethodViolationCode::WhereClauseReferencesSelf,
@@ -1035,7 +1038,10 @@ pub enum MethodViolationCode {
     ReferencesSelfOutput,
 
     /// e.g., `fn foo(&self) -> impl Sized`
-    ReferencesImplTraitInTrait,
+    ReferencesImplTraitInTrait(Span),
+
+    /// e.g., `async fn foo(&self)`
+    AsyncFn,
 
     /// e.g., `fn foo(&self) where Self: Clone`
     WhereClauseReferencesSelf,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 18eb06b83c9..f9a762261e2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1125,42 +1125,42 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
     }
 }
 
-pub trait ToPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
+pub trait ToPredicate<'tcx, Predicate> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate;
 }
 
-impl<'tcx> ToPredicate<'tcx> for Predicate<'tcx> {
-    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+impl<'tcx, T> ToPredicate<'tcx, T> for T {
+    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T {
         self
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
+impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tcx>> {
     #[inline(always)]
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         tcx.mk_predicate(self)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(PredicateKind::Trait).to_predicate(tcx)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx)
     }
 }
 
-impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
+impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.map_bound(PredicateKind::Projection).to_predicate(tcx)
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index a56450a3573..02848bcffb2 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -893,6 +893,7 @@ symbols! {
         masked,
         match_beginning_vert,
         match_default_bindings,
+        matches_macro,
         maxnumf32,
         maxnumf64,
         may_dangle,
diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
index 2cf2cbc7510..52ee68e7560 100644
--- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
@@ -12,6 +12,8 @@ pub fn target() -> Target {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             forces_embed_bitcode: true,
+            dynamic_linking: false,
+            position_independent_executables: true,
             // These arguments are not actually invoked - they just have
             // to look right to pass App Store validation.
             bitcode_llvm_cmdline: "-triple\0\
diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
index 45ead8d65ab..6e1d00d1f6c 100644
--- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs
@@ -12,6 +12,8 @@ pub fn target() -> Target {
             features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
             forces_embed_bitcode: true,
+            dynamic_linking: false,
+            position_independent_executables: true,
             // These arguments are not actually invoked - they just have
             // to look right to pass App Store validation.
             bitcode_llvm_cmdline: "-triple\0\
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 54c738d8389..b7240a82897 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -3,8 +3,8 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 use rustc_hir as hir;
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::ty::TypeVisitable;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
-use rustc_middle::ty::{ToPredicate, TypeVisitable};
 use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
@@ -130,9 +130,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
 
         let obligation = traits::Obligation::new(
+            tcx,
             cause.clone(),
             self.param_env,
-            ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
+            ty::Binder::dummy(trait_ref).without_const(),
         );
         if !self.infcx.predicate_may_hold(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 188f8bb7e2a..5869bc76b59 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -96,8 +96,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             PolyTraitRef::to_poly_trait_predicate,
             PolyTraitRef::to_poly_trait_predicate_negative_polarity,
         ] {
-            let result =
-                selcx.select(&Obligation::new(ObligationCause::dummy(), orig_env, f(&trait_pred)));
+            let result = selcx.select(&Obligation::new(
+                tcx,
+                ObligationCause::dummy(),
+                orig_env,
+                f(&trait_pred),
+            ));
             if let Ok(Some(ImplSource::UserDefined(_))) = result {
                 debug!(
                     "find_auto_trait_generics({:?}): \
@@ -280,8 +284,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
 
             // Call `infcx.resolve_vars_if_possible` to see if we can
             // get rid of any inference variables.
-            let obligation =
-                infcx.resolve_vars_if_possible(Obligation::new(dummy_cause.clone(), new_env, pred));
+            let obligation = infcx.resolve_vars_if_possible(Obligation::new(
+                tcx,
+                dummy_cause.clone(),
+                new_env,
+                pred,
+            ));
             let result = select.select(&obligation);
 
             match result {
@@ -706,7 +714,10 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     // and turn them into an explicit negative impl for our type.
                     debug!("Projecting and unifying projection predicate {:?}", predicate);
 
-                    match project::poly_project_and_unify_type(select, &obligation.with(p)) {
+                    match project::poly_project_and_unify_type(
+                        select,
+                        &obligation.with(self.tcx, p),
+                    ) {
                         ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
                             debug!(
                                 "evaluate_nested_obligations: Unable to unify predicate \
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 8a62bf01567..ca4299f7db3 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -40,7 +40,7 @@ pub fn codegen_select_candidate<'tcx>(
 
     let obligation_cause = ObligationCause::dummy();
     let obligation =
-        Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
+        Obligation::new(tcx, obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
 
     let selection = match selcx.select(&obligation) {
         Ok(Some(selection)) => selection,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 58da54afb75..6a5744f5f76 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -32,7 +32,7 @@ pub fn recompute_applicable_impls<'tcx>(
             impl_predicates
                 .predicates
                 .iter()
-                .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)),
+                .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
         );
 
         ocx.select_where_possible().is_empty()
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 786cadaa6ce..f087afa20ba 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -344,14 +344,14 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
                 });
                 let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]);
                 let obligation = Obligation::new(
+                    self.tcx,
                     ObligationCause::dummy(),
                     param_env,
                     ty.rebind(ty::TraitPredicate {
                         trait_ref: ty::TraitRef::new(trait_def_id, substs),
                         constness,
                         polarity,
-                    })
-                    .to_predicate(self.tcx),
+                    }),
                 );
                 let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx);
                 fulfill_cx.register_predicate_obligation(self, obligation);
@@ -984,7 +984,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 );
                                 trait_pred
                             });
-                            let unit_obligation = obligation.with(predicate.to_predicate(tcx));
+                            let unit_obligation = obligation.with(tcx, predicate);
                             if self.predicate_may_hold(&unit_obligation) {
                                 err.note(
                                     "this error might have been caused by changes to \
@@ -2012,7 +2012,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             ..*tr
         });
 
-        Obligation::new(ObligationCause::dummy(), param_env, trait_pred.to_predicate(self.tcx))
+        Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -2100,11 +2100,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     )
                 };
 
-                let obligation = Obligation::new(
-                    obligation.cause.clone(),
-                    obligation.param_env,
-                    trait_ref.to_poly_trait_predicate(),
-                );
+                let obligation = obligation.with(self.tcx, trait_ref.to_poly_trait_predicate());
                 let mut selcx = SelectionContext::with_query_mode(
                     &self,
                     crate::traits::TraitQueryMode::Standard,
@@ -2534,11 +2530,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             )
             .value;
 
-            let obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                cleaned_pred.to_predicate(selcx.tcx()),
-            );
+            let obligation =
+                Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
 
             self.predicate_may_hold(&obligation)
         })
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 84daaf97ecf..b8609077036 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -301,7 +301,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
     ) where
-        T: fmt::Display;
+        T: fmt::Display + ToPredicate<'tcx, T>;
 
     /// Suggest to await before try: future? => future.await?
     fn suggest_await_before_try(
@@ -334,7 +334,7 @@ pub trait TypeErrCtxtExt<'tcx> {
     );
 }
 
-fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
+fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
     (
         generics.tail_span_for_predicate_suggestion(),
         format!("{} {}", generics.add_where_or_trailing_comma(), pred),
@@ -416,7 +416,7 @@ fn suggest_restriction<'tcx>(
             },
             // `fn foo(t: impl Trait)`
             //                       ^ suggest `where <T as Trait>::A: Bound`
-            predicate_constraint(hir_generics, trait_pred.to_predicate(tcx).to_string()),
+            predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)),
         ];
         sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string())));
 
@@ -440,9 +440,7 @@ fn suggest_restriction<'tcx>(
                 .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
             super_traits,
         ) {
-            (_, None) => {
-                predicate_constraint(hir_generics, trait_pred.to_predicate(tcx).to_string())
-            }
+            (_, None) => predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)),
             (None, Some((ident, []))) => (
                 ident.span.shrink_to_hi(),
                 format!(": {}", trait_pred.print_modifiers_and_trait_path()),
@@ -1162,7 +1160,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         for predicate in predicates.iter() {
             if !self.predicate_must_hold_modulo_regions(
-                &obligation.with(predicate.with_self_ty(self.tcx, self_ref_ty)),
+                &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)),
             ) {
                 return;
             }
@@ -1523,7 +1521,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let self_ty_satisfies_dyn_predicates = |self_ty| {
                             predicates.iter().all(|predicate| {
                                 let pred = predicate.with_self_ty(self.tcx, self_ty);
-                                let obl = Obligation::new(cause.clone(), param_env, pred);
+                                let obl = Obligation::new(self.tcx, cause.clone(), param_env, pred);
                                 self.predicate_may_hold(&obl)
                             })
                         };
@@ -2704,7 +2702,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                 obligated_types.push(ty);
 
-                let parent_predicate = parent_trait_ref.to_predicate(tcx);
+                let parent_predicate = parent_trait_ref;
                 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
                     // #74711: avoid a stack overflow
                     ensure_sufficient_stack(|| {
@@ -2766,7 +2764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     _ => err.note(&msg),
                 };
 
-                let mut parent_predicate = parent_trait_pred.to_predicate(tcx);
+                let mut parent_predicate = parent_trait_pred;
                 let mut data = &data.derived;
                 let mut count = 0;
                 seen_requirements.insert(parent_def_id);
@@ -2826,7 +2824,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             }
             ObligationCauseCode::DerivedObligation(ref data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
-                let parent_predicate = parent_trait_ref.to_predicate(tcx);
+                let parent_predicate = parent_trait_ref;
                 // #74711: avoid a stack overflow
                 ensure_sufficient_stack(|| {
                     self.note_obligation_cause_code(
@@ -3070,9 +3068,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         ..*tr
                     });
                     let field_obl = Obligation::new(
+                        self.tcx,
                         obligation.cause.clone(),
                         obligation.param_env,
-                        trait_pred.to_predicate(self.tcx),
+                        trait_pred,
                     );
                     self.predicate_must_hold_modulo_regions(&field_obl)
                 })
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 4905bb69cc5..d84f768cce4 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -9,7 +9,6 @@ use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{self, Binder, Const, Ty, TypeVisitable};
 use std::marker::PhantomData;
 
@@ -296,7 +295,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 &mut obligations,
             );
             if predicate != obligation.predicate {
-                obligations.push(obligation.with(predicate));
+                obligations.push(obligation.with(infcx.tcx, predicate));
                 return ProcessResult::Changed(mk_pending(obligations));
             }
         }
@@ -307,7 +306,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 // This means we need to pass it the bound version of our
                 // predicate.
                 ty::PredicateKind::Trait(trait_ref) => {
-                    let trait_obligation = obligation.with(binder.rebind(trait_ref));
+                    let trait_obligation = obligation.with(infcx.tcx, binder.rebind(trait_ref));
 
                     self.process_trait_obligation(
                         obligation,
@@ -316,7 +315,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                     )
                 }
                 ty::PredicateKind::Projection(data) => {
-                    let project_obligation = obligation.with(binder.rebind(data));
+                    let project_obligation = obligation.with(infcx.tcx, binder.rebind(data));
 
                     self.process_projection_obligation(
                         obligation,
@@ -335,9 +334,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 | ty::PredicateKind::ConstEquate(..) => {
                     let pred =
                         ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
-                    ProcessResult::Changed(mk_pending(vec![
-                        obligation.with(pred.to_predicate(self.selcx.tcx())),
-                    ]))
+                    ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
                 }
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
                     bug!("TypeWellFormedFromEnv is only used for Chalk")
@@ -345,7 +342,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
             },
             Some(pred) => match pred {
                 ty::PredicateKind::Trait(data) => {
-                    let trait_obligation = obligation.with(Binder::dummy(data));
+                    let trait_obligation = obligation.with(infcx.tcx, Binder::dummy(data));
 
                     self.process_trait_obligation(
                         obligation,
@@ -370,7 +367,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                 }
 
                 ty::PredicateKind::Projection(ref data) => {
-                    let project_obligation = obligation.with(Binder::dummy(*data));
+                    let project_obligation = obligation.with(infcx.tcx, Binder::dummy(*data));
 
                     self.process_projection_obligation(
                         obligation,
@@ -697,7 +694,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
             }
             // Let the caller handle the recursion
             ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![
-                project_obligation.with(project_obligation.predicate.to_predicate(tcx)),
+                project_obligation.with(tcx, project_obligation.predicate),
             ])),
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
                 ProcessResult::Error(CodeProjectionError(e))
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 10e48610e3a..ddc9b768f07 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -440,7 +440,7 @@ pub fn impossible_predicates<'tcx>(
     let ocx = ObligationCtxt::new(&infcx);
     let predicates = ocx.normalize(ObligationCause::dummy(), param_env, predicates);
     for predicate in predicates {
-        let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+        let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
         ocx.register_obligation(obligation);
     }
     let errors = ocx.select_all_or_error();
@@ -530,6 +530,7 @@ fn is_impossible_method<'tcx>(
     let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
         if pred.visit_with(&mut visitor).is_continue() {
             Some(Obligation::new(
+                tcx,
                 ObligationCause::dummy_with_span(*span),
                 param_env,
                 ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 0bb25a74dc8..9745e0137ee 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -375,6 +375,7 @@ fn object_safety_violation_for_method(
         let span = match (&v, node) {
             (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
             (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
+            (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
             (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
                 node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span())
             }
@@ -437,8 +438,8 @@ fn virtual_call_violation_for_method<'tcx>(
     if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
         return Some(MethodViolationCode::ReferencesSelfOutput);
     }
-    if contains_illegal_impl_trait_in_trait(tcx, sig.output()) {
-        return Some(MethodViolationCode::ReferencesImplTraitInTrait);
+    if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
+        return Some(code);
     }
 
     // We can't monomorphize things like `fn foo<A>(...)`.
@@ -723,10 +724,9 @@ fn receiver_is_dispatchable<'tcx>(
             def_id: dispatch_from_dyn_did,
             substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
         })
-        .without_const()
-        .to_predicate(tcx);
+        .without_const();
 
-        Obligation::new(ObligationCause::dummy(), param_env, predicate)
+        Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
     };
 
     let infcx = tcx.infer_ctxt().build();
@@ -865,16 +865,24 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
 
 pub fn contains_illegal_impl_trait_in_trait<'tcx>(
     tcx: TyCtxt<'tcx>,
+    fn_def_id: DefId,
     ty: ty::Binder<'tcx, Ty<'tcx>>,
-) -> bool {
+) -> Option<MethodViolationCode> {
+    // This would be caught below, but rendering the error as a separate
+    // `async-specific` message is better.
+    if tcx.asyncness(fn_def_id).is_async() {
+        return Some(MethodViolationCode::AsyncFn);
+    }
+
     // FIXME(RPITIT): Perhaps we should use a visitor here?
-    ty.skip_binder().walk().any(|arg| {
+    ty.skip_binder().walk().find_map(|arg| {
         if let ty::GenericArgKind::Type(ty) = arg.unpack()
             && let ty::Projection(proj) = ty.kind()
+            && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
         {
-            tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+            Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id)))
         } else {
-            false
+            None
         }
     })
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 572f82117cc..ede6cd607b7 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -200,7 +200,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
             infcx.replace_bound_vars_with_placeholders(obligation.predicate);
         let new_universe = infcx.universe();
 
-        let placeholder_obligation = obligation.with(placeholder_predicate);
+        let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
         match project_and_unify_type(selcx, &placeholder_obligation) {
             ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
             ProjectAndUnifyResult::Holds(obligations)
@@ -517,6 +517,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             let obligation = Obligation::with_depth(
+                                self.tcx(),
                                 self.cause.clone(),
                                 recursion_limit.0,
                                 self.param_env,
@@ -573,6 +574,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                     && !self.tcx().sess.opts.actually_rustdoc
                 {
                     let obligation = Obligation::with_depth(
+                        self.selcx.tcx(),
                         self.cause.clone(),
                         recursion_limit.0,
                         self.param_env,
@@ -1110,7 +1112,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
         }
     }
 
-    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
+    let obligation =
+        Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_ty);
 
     match project(selcx, &obligation) {
         Ok(Projected::Progress(Progress {
@@ -1343,8 +1346,8 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
             ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs })
                 .to_poly_trait_predicate();
 
-        let _ =
-            selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
+        let _ = selcx.infcx().commit_if_ok(|_| {
+            match selcx.select(&obligation.with(tcx, trait_predicate)) {
                 Ok(Some(super::ImplSource::UserDefined(data))) => {
                     candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
                         ImplTraitInTraitCandidate::Impl(data),
@@ -1364,7 +1367,8 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
                     candidate_set.mark_error(e);
                     return Err(());
                 }
-            });
+            }
+        });
     }
 }
 
@@ -1538,7 +1542,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
     let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
-    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
+    let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref.to_poly_trait_predicate());
     let _ = selcx.infcx().commit_if_ok(|_| {
         let impl_source = match selcx.select(&trait_obligation) {
             Ok(Some(impl_source)) => impl_source,
@@ -1705,12 +1709,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
                         if selcx.infcx().predicate_must_hold_modulo_regions(
                             &obligation.with(
+                                selcx.tcx(),
                                 ty::Binder::dummy(ty::TraitRef::new(
                                     selcx.tcx().require_lang_item(LangItem::Sized, None),
                                     selcx.tcx().mk_substs_trait(self_ty, &[]),
                                 ))
-                                .without_const()
-                                .to_predicate(selcx.tcx()),
+                                .without_const(),
                             ),
                         ) =>
                     {
@@ -1966,13 +1970,8 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
             tcx.require_lang_item(LangItem::Sized, None),
             tcx.mk_substs_trait(self_ty, &[]),
         ))
-        .without_const()
-        .to_predicate(tcx);
-        obligations.push(Obligation::new(
-            obligation.cause.clone(),
-            obligation.param_env,
-            sized_predicate,
-        ));
+        .without_const();
+        obligations.push(obligation.with(tcx, sized_predicate));
     }
 
     let substs = tcx.mk_substs([self_ty.into()].iter());
@@ -2289,6 +2288,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map(
         |(pred, span)| {
             Obligation::with_depth(
+                tcx,
                 ObligationCause::new(
                     obligation.cause.span,
                     obligation.cause.body_id,
@@ -2342,6 +2342,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
             nested,
         );
         nested.push(Obligation::with_depth(
+            tcx,
             obligation.cause.clone(),
             obligation.recursion_depth + 1,
             obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index a7932b332c9..f5c98558a25 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -208,6 +208,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
+                                self.tcx(),
                                 self.cause.clone(),
                                 recursion_limit.0,
                                 self.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index 8cf500a466b..dfe19a5a86d 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -1,8 +1,8 @@
 use crate::infer::InferCtxt;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{ObligationCause, PredicateObligation};
+use crate::traits::PredicateObligation;
 use rustc_infer::traits::TraitEngine;
-use rustc_middle::ty::{self, ToPredicate};
+use rustc_middle::ty;
 
 pub(crate) fn update<'tcx, T>(
     engine: &mut T,
@@ -25,9 +25,7 @@ pub(crate) fn update<'tcx, T>(
 
         // Then construct a new obligation with Self = () added
         // to the ParamEnv, and see if it holds.
-        let o = rustc_infer::traits::Obligation::new(
-            ObligationCause::dummy(),
-            obligation.param_env,
+        let o = obligation.with(infcx.tcx,
             obligation
                 .predicate
                 .kind()
@@ -38,8 +36,7 @@ pub(crate) fn update<'tcx, T>(
                         constness: tpred.constness,
                         polarity: tpred.polarity,
                     })
-                )
-                .to_predicate(infcx.tcx),
+                ),
         );
         // Don't report overflow errors. Otherwise equivalent to may_hold.
         if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 3671a0d87df..3995ea58db1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -13,7 +13,7 @@ use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
 use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitable};
 use rustc_target::spec::abi::Abi;
 
 use crate::traits;
@@ -718,9 +718,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
 
         let obligation = traits::Obligation::new(
+            tcx,
             cause.clone(),
             param_env,
-            ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
+            ty::Binder::dummy(trait_ref).without_const(),
         );
         if !self.infcx.predicate_may_hold(&obligation) {
             return None;
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 28b4bae7cbe..9d43f72b85f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -194,6 +194,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     &mut obligations,
                 );
                 obligations.push(Obligation::with_depth(
+                    self.tcx(),
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
@@ -482,11 +483,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 super_trait,
                 &mut nested,
             );
-            nested.push(Obligation::new(
-                obligation.cause.clone(),
-                obligation.param_env,
-                normalized_super_trait,
-            ));
+            nested.push(obligation.with(tcx, normalized_super_trait));
         }
 
         let assoc_types: Vec<_> = tcx
@@ -581,11 +578,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     subst_bound,
                     &mut nested,
                 );
-                nested.push(Obligation::new(
-                    obligation.cause.clone(),
-                    obligation.param_env,
-                    normalized_bound,
-                ));
+                nested.push(obligation.with(tcx, normalized_bound));
             }
         }
 
@@ -644,9 +637,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             self.tcx().mk_substs_trait(output_ty, &[]),
         ));
         nested.push(Obligation::new(
+            self.infcx.tcx,
             cause,
             obligation.param_env,
-            tr.to_poly_trait_predicate().to_predicate(self.tcx()),
+            tr.to_poly_trait_predicate(),
         ));
 
         Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
@@ -727,11 +721,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // FIXME: Chalk
 
         if !self.tcx().sess.opts.unstable_opts.chalk {
-            nested.push(Obligation::new(
-                obligation.cause.clone(),
-                obligation.param_env,
-                ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind))
-                    .to_predicate(self.tcx()),
+            nested.push(obligation.with(
+                self.tcx(),
+                ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
             ));
         }
 
@@ -860,10 +852,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
+                    tcx,
                     cause,
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(outlives).to_predicate(tcx),
+                    obligation.predicate.rebind(outlives),
                 ));
             }
             _ => bug!(),
@@ -957,10 +950,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(
+                    tcx,
                     cause,
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(outlives).to_predicate(tcx),
+                    obligation.predicate.rebind(outlives),
                 ));
             }
 
@@ -979,6 +973,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 let predicate_to_obligation = |predicate| {
                     Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
@@ -1255,20 +1250,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         obligation.param_env,
                         cause.clone(),
                         obligation.recursion_depth + 1,
-                        self_ty
-                            .rebind(ty::TraitPredicate {
-                                trait_ref: ty::TraitRef {
-                                    def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
-                                    substs: self.tcx().mk_substs_trait(nested_ty, &[]),
-                                },
-                                constness: ty::BoundConstness::ConstIfConst,
-                                polarity: ty::ImplPolarity::Positive,
-                            })
-                            .to_predicate(tcx),
+                        self_ty.rebind(ty::TraitPredicate {
+                            trait_ref: ty::TraitRef {
+                                def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
+                                substs: self.tcx().mk_substs_trait(nested_ty, &[]),
+                            },
+                            constness: ty::BoundConstness::ConstIfConst,
+                            polarity: ty::ImplPolarity::Positive,
+                        }),
                         &mut nested,
                     );
 
                     nested.push(Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
@@ -1280,18 +1274,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // since it's either not `const Drop` (and we raise an error during selection),
                 // or it's an ADT (and we need to check for a custom impl during selection)
                 _ => {
-                    let predicate = self_ty
-                        .rebind(ty::TraitPredicate {
-                            trait_ref: ty::TraitRef {
-                                def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
-                                substs: self.tcx().mk_substs_trait(nested_ty, &[]),
-                            },
-                            constness: ty::BoundConstness::ConstIfConst,
-                            polarity: ty::ImplPolarity::Positive,
-                        })
-                        .to_predicate(tcx);
+                    let predicate = self_ty.rebind(ty::TraitPredicate {
+                        trait_ref: ty::TraitRef {
+                            def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
+                            substs: self.tcx().mk_substs_trait(nested_ty, &[]),
+                        },
+                        constness: ty::BoundConstness::ConstIfConst,
+                        polarity: ty::ImplPolarity::Positive,
+                    });
 
                     nested.push(Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3a899c03b4c..c369c5de52b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -445,7 +445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::PredicateKind::Trait(t) => {
                     let t = bound_predicate.rebind(t);
                     debug_assert!(!t.has_escaping_bound_vars());
-                    let obligation = obligation.with(t);
+                    let obligation = obligation.with(self.tcx(), t);
                     self.evaluate_trait_predicate_recursively(previous_stack, obligation)
                 }
 
@@ -596,7 +596,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 ty::PredicateKind::Projection(data) => {
                     let data = bound_predicate.rebind(data);
-                    let project_obligation = obligation.with(data);
+                    let project_obligation = obligation.with(self.tcx(), data);
                     match project::poly_project_and_unify_type(self, &project_obligation) {
                         ProjectAndUnifyResult::Holds(mut subobligations) => {
                             'compute_res: {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index fc0a9f69003..d05e893de43 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -4,7 +4,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
 use rustc_span::Span;
 
 use std::iter;
@@ -324,7 +324,7 @@ impl<'tcx> WfPredicates<'tcx> {
             extend_cause_with_original_assoc_item_obligation(
                 tcx, trait_ref, item, &mut cause, predicate,
             );
-            traits::Obligation::with_depth(cause, depth, param_env, predicate)
+            traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate)
         };
 
         if let Elaborate::All = elaborate {
@@ -356,10 +356,11 @@ impl<'tcx> WfPredicates<'tcx> {
                         }
                     }
                     traits::Obligation::with_depth(
+                        tcx,
                         cause,
                         depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
                     )
                 }),
         );
@@ -407,10 +408,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 .filter(|arg| !arg.has_escaping_bound_vars())
                 .map(|arg| {
                     traits::Obligation::with_depth(
+                        tcx,
                         cause.clone(),
                         depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
                     )
                 }),
         );
@@ -424,10 +426,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 substs: self.tcx.mk_substs_trait(subty, &[]),
             };
             self.out.push(traits::Obligation::with_depth(
+                self.tcx,
                 cause,
                 self.recursion_depth,
                 self.param_env,
-                ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx),
+                ty::Binder::dummy(trait_ref).without_const(),
             ));
         }
     }
@@ -454,10 +457,10 @@ impl<'tcx> WfPredicates<'tcx> {
                             self.out.extend(obligations);
 
                             let predicate =
-                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
-                                    .to_predicate(self.tcx());
+                                ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
                             let cause = self.cause(traits::WellFormed(None));
                             self.out.push(traits::Obligation::with_depth(
+                                self.tcx(),
                                 cause,
                                 self.recursion_depth,
                                 self.param_env,
@@ -468,11 +471,11 @@ impl<'tcx> WfPredicates<'tcx> {
                             let cause = self.cause(traits::WellFormed(None));
 
                             self.out.push(traits::Obligation::with_depth(
+                                self.tcx(),
                                 cause,
                                 self.recursion_depth,
                                 self.param_env,
-                                ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
-                                    .to_predicate(self.tcx()),
+                                ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())),
                             ));
                         }
                         ty::ConstKind::Error(_)
@@ -556,13 +559,13 @@ impl<'tcx> WfPredicates<'tcx> {
                     if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                         self.out.push(traits::Obligation::with_depth(
+                            self.tcx(),
                             cause,
                             depth,
                             param_env,
                             ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
                                 ty::OutlivesPredicate(rty, r),
-                            ))
-                            .to_predicate(self.tcx()),
+                            )),
                         ));
                     }
                 }
@@ -656,11 +659,11 @@ impl<'tcx> WfPredicates<'tcx> {
                         let tcx = self.tcx();
                         self.out.extend(component_traits.map(|did| {
                             traits::Obligation::with_depth(
+                                tcx,
                                 cause.clone(),
                                 depth,
                                 param_env,
-                                ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did))
-                                    .to_predicate(tcx),
+                                ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)),
                             )
                         }));
                     }
@@ -681,11 +684,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 ty::Infer(_) => {
                     let cause = self.cause(traits::WellFormed(None));
                     self.out.push(traits::Obligation::with_depth(
+                        self.tcx(),
                         cause,
                         self.recursion_depth,
                         param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))
-                            .to_predicate(self.tcx()),
+                        ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())),
                     ));
                 }
             }
@@ -724,7 +727,13 @@ impl<'tcx> WfPredicates<'tcx> {
                 if remap_constness {
                     pred = pred.without_const(self.tcx);
                 }
-                traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
+                traits::Obligation::with_depth(
+                    self.tcx,
+                    cause,
+                    self.recursion_depth,
+                    self.param_env,
+                    pred,
+                )
             })
             .filter(|pred| !pred.has_escaping_bound_vars())
             .collect()
@@ -794,10 +803,11 @@ impl<'tcx> WfPredicates<'tcx> {
                 let outlives =
                     ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
                 self.out.push(traits::Obligation::with_depth(
+                    self.tcx,
                     cause,
                     self.recursion_depth,
                     self.param_env,
-                    outlives.to_predicate(self.tcx),
+                    outlives,
                 ));
             }
         }
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 493d5de0807..e94c8efe69a 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -26,7 +26,7 @@ fn evaluate_obligation<'tcx>(
     let ParamEnvAnd { param_env, value: predicate } = goal;
 
     let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
-    let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+    let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
 
     selcx.evaluate_root_obligation(&obligation)
 }
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 98cb3f21555..9eceae8b44f 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -91,7 +91,12 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
     }
 
     fn prove_predicate(&self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
-        self.ocx.register_obligation(Obligation::new(cause, self.param_env, predicate));
+        self.ocx.register_obligation(Obligation::new(
+            self.ocx.infcx.tcx,
+            cause,
+            self.param_env,
+            predicate,
+        ));
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -256,5 +261,5 @@ pub fn type_op_prove_predicate_with_cause<'tcx>(
     cause: ObligationCause<'tcx>,
 ) {
     let (param_env, ProvePredicate { predicate }) = key.into_parts();
-    ocx.register_obligation(Obligation::new(cause, param_env, predicate));
+    ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
 }
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 006d813e5f9..f3cbfe27b3e 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -293,6 +293,15 @@ struct RcBox<T: ?Sized> {
     value: T,
 }
 
+/// Calculate layout for `RcBox<T>` using the inner value's layout
+fn rcbox_layout_for_value_layout(layout: Layout) -> Layout {
+    // Calculate layout using the given value layout.
+    // Previously, layout was calculated on the expression
+    // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
+    // reference (see #54908).
+    Layout::new::<RcBox<()>>().extend(layout).unwrap().0.pad_to_align()
+}
+
 /// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference
 /// Counted'.
 ///
@@ -1334,11 +1343,7 @@ impl<T: ?Sized> Rc<T> {
         allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
         mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
     ) -> *mut RcBox<T> {
-        // Calculate layout using the given value layout.
-        // Previously, layout was calculated on the expression
-        // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
-        // reference (see #54908).
-        let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
+        let layout = rcbox_layout_for_value_layout(value_layout);
         unsafe {
             Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox)
                 .unwrap_or_else(|_| handle_alloc_error(layout))
@@ -1357,11 +1362,7 @@ impl<T: ?Sized> Rc<T> {
         allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
         mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
     ) -> Result<*mut RcBox<T>, AllocError> {
-        // Calculate layout using the given value layout.
-        // Previously, layout was calculated on the expression
-        // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
-        // reference (see #54908).
-        let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
+        let layout = rcbox_layout_for_value_layout(value_layout);
 
         // Allocate for the layout.
         let ptr = allocate(layout)?;
@@ -1428,7 +1429,7 @@ impl<T> Rc<[T]> {
         }
     }
 
-    /// Copy elements from slice into newly allocated Rc<\[T\]>
+    /// Copy elements from slice into newly allocated `Rc<[T]>`
     ///
     /// Unsafe because the caller must either take ownership or bind `T: Copy`
     #[cfg(not(no_global_oom_handling))]
@@ -1440,6 +1441,48 @@ impl<T> Rc<[T]> {
         }
     }
 
+    /// Create an `Rc<[T]>` by reusing the underlying memory
+    /// of a `Vec<T>`. This will return the vector if the existing allocation
+    /// is not large enough.
+    #[cfg(not(no_global_oom_handling))]
+    fn try_from_vec_in_place(mut v: Vec<T>) -> Result<Rc<[T]>, Vec<T>> {
+        let layout_elements = Layout::array::<T>(v.len()).unwrap();
+        let layout_allocation = Layout::array::<T>(v.capacity()).unwrap();
+        let layout_rcbox = rcbox_layout_for_value_layout(layout_elements);
+        let mut ptr = NonNull::new(v.as_mut_ptr()).expect("`Vec<T>` stores `NonNull<T>`");
+        if layout_rcbox.size() > layout_allocation.size()
+            || layout_rcbox.align() > layout_allocation.align()
+        {
+            // Can't fit - calling `grow` would involve `realloc`
+            // (which copies the elements), followed by copying again.
+            return Err(v);
+        }
+        if layout_rcbox.size() < layout_allocation.size()
+            || layout_rcbox.align() < layout_allocation.align()
+        {
+            // We need to shrink the allocation so that it fits
+            // https://doc.rust-lang.org/nightly/std/alloc/trait.Allocator.html#memory-fitting
+            // SAFETY:
+            // - Vec allocates by requesting `Layout::array::<T>(capacity)`, so this capacity matches
+            // - `layout_rcbox` is smaller
+            // If this fails, the ownership has not been transferred
+            if let Ok(p) = unsafe { Global.shrink(ptr.cast(), layout_allocation, layout_rcbox) } {
+                ptr = p.cast();
+            } else {
+                return Err(v);
+            }
+        }
+        // Make sure the vec's memory isn't deallocated now
+        let v = mem::ManuallyDrop::new(v);
+        let ptr: *mut RcBox<[T]> = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), v.len()) as _;
+        unsafe {
+            ptr::copy(ptr.cast::<T>(), &mut (*ptr).value as *mut [T] as *mut T, v.len());
+            ptr::write(&mut (*ptr).strong, Cell::new(1));
+            ptr::write(&mut (*ptr).weak, Cell::new(1));
+            Ok(Self::from_ptr(ptr))
+        }
+    }
+
     /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size.
     ///
     /// Behavior is undefined should the size be wrong.
@@ -1965,14 +2008,17 @@ impl<T> From<Vec<T>> for Rc<[T]> {
     /// assert_eq!(vec![1, 2, 3], *shared);
     /// ```
     #[inline]
-    fn from(mut v: Vec<T>) -> Rc<[T]> {
-        unsafe {
-            let rc = Rc::copy_from_slice(&v);
-
-            // Allow the Vec to free its memory, but not destroy its contents
-            v.set_len(0);
-
-            rc
+    fn from(v: Vec<T>) -> Rc<[T]> {
+        match Rc::try_from_vec_in_place(v) {
+            Ok(rc) => rc,
+            Err(mut v) => {
+                unsafe {
+                    let rc = Rc::copy_from_slice(&v);
+                    // Allow the Vec to free its memory, but not destroy its contents
+                    v.set_len(0);
+                    rc
+                }
+            }
         }
     }
 }
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 81cd7707488..37e07eb5998 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -333,6 +333,15 @@ struct ArcInner<T: ?Sized> {
     data: T,
 }
 
+/// Calculate layout for `ArcInner<T>` using the inner value's layout
+fn arcinner_layout_for_value_layout(layout: Layout) -> Layout {
+    // Calculate layout using the given value layout.
+    // Previously, layout was calculated on the expression
+    // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
+    // reference (see #54908).
+    Layout::new::<ArcInner<()>>().extend(layout).unwrap().0.pad_to_align()
+}
+
 unsafe impl<T: ?Sized + Sync + Send> Send for ArcInner<T> {}
 unsafe impl<T: ?Sized + Sync + Send> Sync for ArcInner<T> {}
 
@@ -1154,11 +1163,7 @@ impl<T: ?Sized> Arc<T> {
         allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
         mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
     ) -> *mut ArcInner<T> {
-        // Calculate layout using the given value layout.
-        // Previously, layout was calculated on the expression
-        // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
-        // reference (see #54908).
-        let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
+        let layout = arcinner_layout_for_value_layout(value_layout);
         unsafe {
             Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner)
                 .unwrap_or_else(|_| handle_alloc_error(layout))
@@ -1176,11 +1181,7 @@ impl<T: ?Sized> Arc<T> {
         allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
         mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
     ) -> Result<*mut ArcInner<T>, AllocError> {
-        // Calculate layout using the given value layout.
-        // Previously, layout was calculated on the expression
-        // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
-        // reference (see #54908).
-        let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
+        let layout = arcinner_layout_for_value_layout(value_layout);
 
         let ptr = allocate(layout)?;
 
@@ -1246,7 +1247,7 @@ impl<T> Arc<[T]> {
         }
     }
 
-    /// Copy elements from slice into newly allocated Arc<\[T\]>
+    /// Copy elements from slice into newly allocated `Arc<[T]>`
     ///
     /// Unsafe because the caller must either take ownership or bind `T: Copy`.
     #[cfg(not(no_global_oom_handling))]
@@ -1260,6 +1261,49 @@ impl<T> Arc<[T]> {
         }
     }
 
+    /// Create an `Arc<[T]>` by reusing the underlying memory
+    /// of a `Vec<T>`. This will return the vector if the existing allocation
+    /// is not large enough.
+    #[cfg(not(no_global_oom_handling))]
+    fn try_from_vec_in_place(mut v: Vec<T>) -> Result<Arc<[T]>, Vec<T>> {
+        let layout_elements = Layout::array::<T>(v.len()).unwrap();
+        let layout_allocation = Layout::array::<T>(v.capacity()).unwrap();
+        let layout_arcinner = arcinner_layout_for_value_layout(layout_elements);
+        let mut ptr = NonNull::new(v.as_mut_ptr()).expect("`Vec<T>` stores `NonNull<T>`");
+        if layout_arcinner.size() > layout_allocation.size()
+            || layout_arcinner.align() > layout_allocation.align()
+        {
+            // Can't fit - calling `grow` would involve `realloc`
+            // (which copies the elements), followed by copying again.
+            return Err(v);
+        }
+        if layout_arcinner.size() < layout_allocation.size()
+            || layout_arcinner.align() < layout_allocation.align()
+        {
+            // We need to shrink the allocation so that it fits
+            // https://doc.rust-lang.org/nightly/std/alloc/trait.Allocator.html#memory-fitting
+            // SAFETY:
+            // - Vec allocates by requesting `Layout::array::<T>(capacity)`, so this capacity matches
+            // - `layout_arcinner` is smaller
+            // If this fails, the ownership has not been transferred
+            if let Ok(p) = unsafe { Global.shrink(ptr.cast(), layout_allocation, layout_arcinner) }
+            {
+                ptr = p.cast();
+            } else {
+                return Err(v);
+            }
+        }
+        // Make sure the vec's memory isn't deallocated now
+        let v = mem::ManuallyDrop::new(v);
+        let ptr: *mut ArcInner<[T]> = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), v.len()) as _;
+        unsafe {
+            ptr::copy(ptr.cast::<T>(), &mut (*ptr).data as *mut [T] as *mut T, v.len());
+            ptr::write(&mut (*ptr).strong, atomic::AtomicUsize::new(1));
+            ptr::write(&mut (*ptr).weak, atomic::AtomicUsize::new(1));
+            Ok(Self::from_ptr(ptr))
+        }
+    }
+
     /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size.
     ///
     /// Behavior is undefined should the size be wrong.
@@ -2571,14 +2615,17 @@ impl<T> From<Vec<T>> for Arc<[T]> {
     /// assert_eq!(&[1, 2, 3], &shared[..]);
     /// ```
     #[inline]
-    fn from(mut v: Vec<T>) -> Arc<[T]> {
-        unsafe {
-            let arc = Arc::copy_from_slice(&v);
-
-            // Allow the Vec to free its memory, but not destroy its contents
-            v.set_len(0);
-
-            arc
+    fn from(v: Vec<T>) -> Arc<[T]> {
+        match Arc::try_from_vec_in_place(v) {
+            Ok(rc) => rc,
+            Err(mut v) => {
+                unsafe {
+                    let rc = Arc::copy_from_slice(&v);
+                    // Allow the Vec to free its memory, but not destroy its contents
+                    v.set_len(0);
+                    rc
+                }
+            }
         }
     }
 }
diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs
index ce40b5c9b0a..eb379e4d6a1 100644
--- a/library/alloc/tests/arc.rs
+++ b/library/alloc/tests/arc.rs
@@ -210,3 +210,18 @@ fn weak_may_dangle() {
     // `val` dropped here while still borrowed
     // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::sync::Weak`
 }
+
+#[test]
+fn arc_from_vec_opt() {
+    let mut v = Vec::with_capacity(64);
+    v.push(0usize);
+    let addr = v.as_ptr().cast::<u8>();
+    let arc: Arc<[_]> = v.into();
+    unsafe {
+        assert_eq!(
+            arc.as_ptr().cast::<u8>().offset_from(addr),
+            (std::mem::size_of::<usize>() * 2) as isize,
+            "Vector allocation not reused"
+        );
+    }
+}
diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs
index efb39a60966..1d5f3c52006 100644
--- a/library/alloc/tests/rc.rs
+++ b/library/alloc/tests/rc.rs
@@ -206,3 +206,18 @@ fn weak_may_dangle() {
     // `val` dropped here while still borrowed
     // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
 }
+
+#[test]
+fn rc_from_vec_opt() {
+    let mut v = Vec::with_capacity(64);
+    v.push(0usize);
+    let addr = v.as_ptr().cast::<u8>();
+    let rc: Rc<[_]> = v.into();
+    unsafe {
+        assert_eq!(
+            rc.as_ptr().cast::<u8>().offset_from(addr),
+            (std::mem::size_of::<usize>() * 2) as isize,
+            "Vector allocation not reused"
+        );
+    }
+}
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 6487aa08859..107cf92c1c0 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -82,6 +82,7 @@ where
 
     impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
         type Output = T::Return;
+        #[track_caller]
         fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
             // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
             let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 34247c05845..c20ca69a1c6 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -338,6 +338,7 @@ pub macro debug_assert_matches($($arg:tt)*) {
 /// ```
 #[macro_export]
 #[stable(feature = "matches_macro", since = "1.42.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")]
 macro_rules! matches {
     ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
         match $expression {
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index 7795bebaed5..65c882fb801 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -168,23 +168,7 @@ fn set_compiler(
         // compiler already takes into account the triple in question.
         t if t.contains("android") => {
             if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
-                let mut triple_iter = target.triple.split("-");
-                let triple_translated = if let Some(arch) = triple_iter.next() {
-                    let arch_new = match arch {
-                        "arm" | "armv7" | "armv7neon" | "thumbv7" | "thumbv7neon" => "armv7a",
-                        other => other,
-                    };
-                    std::iter::once(arch_new).chain(triple_iter).collect::<Vec<&str>>().join("-")
-                } else {
-                    target.triple.to_string()
-                };
-
-                // API 19 is the earliest API level supported by NDK r25b but AArch64 and x86_64 support
-                // begins at API level 21.
-                let api_level =
-                    if t.contains("aarch64") || t.contains("x86_64") { "21" } else { "19" };
-                let compiler = format!("{}{}-{}", triple_translated, api_level, compiler.clang());
-                cfg.compiler(ndk.join("bin").join(compiler));
+                cfg.compiler(ndk_compiler(compiler, &*target.triple, ndk));
             }
         }
 
@@ -236,8 +220,28 @@ fn set_compiler(
     }
 }
 
+pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> PathBuf {
+    let mut triple_iter = triple.split("-");
+    let triple_translated = if let Some(arch) = triple_iter.next() {
+        let arch_new = match arch {
+            "arm" | "armv7" | "armv7neon" | "thumbv7" | "thumbv7neon" => "armv7a",
+            other => other,
+        };
+        std::iter::once(arch_new).chain(triple_iter).collect::<Vec<&str>>().join("-")
+    } else {
+        triple.to_string()
+    };
+
+    // API 19 is the earliest API level supported by NDK r25b but AArch64 and x86_64 support
+    // begins at API level 21.
+    let api_level =
+        if triple.contains("aarch64") || triple.contains("x86_64") { "21" } else { "19" };
+    let compiler = format!("{}{}-{}", triple_translated, api_level, compiler.clang());
+    ndk.join("bin").join(compiler)
+}
+
 /// The target programming language for a native compiler.
-enum Language {
+pub(crate) enum Language {
     /// The compiler is targeting C.
     C,
     /// The compiler is targeting C++.
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index af004aa5098..c61025b556a 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -15,6 +15,7 @@ use std::str::FromStr;
 
 use crate::builder::TaskPath;
 use crate::cache::{Interned, INTERNER};
+use crate::cc_detect::{ndk_compiler, Language};
 use crate::channel::{self, GitInfo};
 pub use crate::flags::Subcommand;
 use crate::flags::{Color, Flags};
@@ -1237,8 +1238,12 @@ impl Config {
                 if let Some(s) = cfg.no_std {
                     target.no_std = s;
                 }
-                target.cc = cfg.cc.map(PathBuf::from);
-                target.cxx = cfg.cxx.map(PathBuf::from);
+                target.cc = cfg.cc.map(PathBuf::from).or_else(|| {
+                    target.ndk.as_ref().map(|ndk| ndk_compiler(Language::C, &triple, ndk))
+                });
+                target.cxx = cfg.cxx.map(PathBuf::from).or_else(|| {
+                    target.ndk.as_ref().map(|ndk| ndk_compiler(Language::CPlusPlus, &triple, ndk))
+                });
                 target.ar = cfg.ar.map(PathBuf::from);
                 target.ranlib = cfg.ranlib.map(PathBuf::from);
                 target.linker = cfg.linker.map(PathBuf::from);
diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
index 69f88e49520..57e63cd39d2 100644
--- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
@@ -9,7 +9,7 @@ RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-
       curl \
       file \
       g++ \
-      gcc-arm-linux-gnueabihf \
+      g++-arm-linux-gnueabihf \
       git \
       libc6-dev \
       libc6-dev-armhf-cross \
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index d8063705582..cb0b8d4a9bc 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -76,6 +76,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                 for predicate in predicates {
                     debug!("testing predicate {:?}", predicate);
                     let obligation = traits::Obligation::new(
+                        infcx.tcx,
                         traits::ObligationCause::dummy(),
                         param_env,
                         predicate,
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 8738986c7da..5ec2fe47e01 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -217,10 +217,7 @@ h1 a,
 .search-results a,
 .module-item .stab,
 .import-item .stab,
-.result-name .primitive > i, .result-name .keyword > i,
-.method .where,
-.fn .where,
-.where.fmt-newline {
+.result-name .primitive > i, .result-name .keyword > i {
 	color: var(--main-color);
 }
 
@@ -1162,6 +1159,8 @@ pre.rust .doccomment {
 	width: max-content;
 	top: -2px;
 	z-index: 1;
+	background-color: var(--tooltip-background-color);
+	color: var(--tooltip-color);
 }
 
 .example-wrap .tooltip::before {
@@ -1170,10 +1169,10 @@ pre.rust .doccomment {
 	top: 50%;
 	left: 16px;
 	margin-top: -5px;
-	border-width: 5px;
-	border-style: solid;
 	display: none;
 	z-index: 1;
+	border: 5px solid transparent;
+	border-right-color: var(--tooltip-background-color);
 }
 
 .example-wrap.ignore .tooltip::after {
@@ -1393,12 +1392,6 @@ h3.variant {
 	background-color: var(--button-background-color);
 	border: 1px solid var(--border-color);
 	border-radius: 2px;
-	color: var(--settings-button-color);
-}
-
-#settings-menu > a:hover, #settings-menu > a:focus,
-#help-button > a:hover, #help-button > a:focus {
-	border-color: var(--settings-button-border-focus);
 }
 
 #copy-path {
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 8052bd3fcb3..0e4dacb28f7 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -7,8 +7,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--main-background-color: #0f1419;
 	--main-color: #c5c5c5;
 	--settings-input-color: #ffb454;
-	--settings-button-color: #fff;
-	--settings-button-border-focus: #e0e0e0;
 	--sidebar-background-color: #14191f;
 	--sidebar-background-color-hover: rgba(70, 70, 70, 0.33);
 	--code-block-background-color: #191f26;
@@ -67,6 +65,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--test-arrow-hover-background-color: rgba(57, 175, 215, 0.368);
 	--target-background-color: rgba(255, 236, 164, 0.06);
 	--target-border-color: rgba(255, 180, 76, 0.85);
+	--tooltip-background-color: #314559;
+	--tooltip-color: #c5c5c5;
 	--rust-logo-filter: drop-shadow(1px 0 0px #fff)
 		drop-shadow(0 1px 0 #fff)
 		drop-shadow(-1px 0 0 #fff)
@@ -162,15 +162,6 @@ details.rustdoc-toggle > summary::before {
 	color: #788797;
 }
 
-.tooltip::after {
-	background-color: #314559;
-	color: #c5c5c5;
-}
-
-.tooltip::before {
-	border-color: transparent #314559 transparent transparent;
-}
-
 #titles > button.selected {
 	background-color: #141920 !important;
 	border-bottom: 1px solid #ffb44c !important;
@@ -208,10 +199,19 @@ kbd {
 	box-shadow: inset 0 -1px 0 #5c6773;
 }
 
+#settings-menu > a, #help-button > a {
+	color: #fff;
+}
+
 #settings-menu > a img {
 	filter: invert(100);
 }
 
+#settings-menu > a:hover, #settings-menu > a:focus,
+#help-button > a:hover, #help-button > a:focus {
+	border-color: #e0e0e0;
+}
+
 .search-results .result-name span.alias {
 	color: #c5c5c5;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 8680403f766..8e00591179f 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -2,8 +2,6 @@
 	--main-background-color: #353535;
 	--main-color: #ddd;
 	--settings-input-color: #2196f3;
-	--settings-button-color: #000;
-	--settings-button-border-focus: #ffb900;
 	--sidebar-background-color: #505050;
 	--sidebar-background-color-hover: #676767;
 	--code-block-background-color: #2A2A2A;
@@ -62,6 +60,8 @@
 	--test-arrow-hover-background-color: #4e8bca;
 	--target-background-color: #494a3d;
 	--target-border-color: #bb7410;
+	--tooltip-background-color: #000;
+	--tooltip-color: #fff;
 	--rust-logo-filter: drop-shadow(1px 0 0px #fff)
 		drop-shadow(0 1px 0 #fff)
 		drop-shadow(-1px 0 0 #fff)
@@ -84,16 +84,6 @@ details.rustdoc-toggle > summary::before {
 	filter: invert(100%);
 }
 
-.tooltip::after {
-	background-color: #000;
-	color: #fff;
-	border-color: #000;
-}
-
-.tooltip::before {
-	border-color: transparent black transparent transparent;
-}
-
 #titles > button:not(.selected) {
 	background-color: #252525;
 	border-top-color: #252525;
@@ -114,6 +104,15 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
+#settings-menu > a, #help-button > a {
+	color: #000;
+}
+
+#settings-menu > a:hover, #settings-menu > a:focus,
+#help-button > a:hover, #help-button > a:focus {
+	border-color: #ffb900;
+}
+
 .search-results .result-name span.alias {
 	color: #fff;
 }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 37d5e8d1600..e23e3682b16 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -2,8 +2,6 @@
 	--main-background-color: white;
 	--main-color: black;
 	--settings-input-color: #2196f3;
-	--settings-button-color: #000;
-	--settings-button-border-focus: #717171;
 	--sidebar-background-color: #F5F5F5;
 	--sidebar-background-color-hover: #E0E0E0;
 	--code-block-background-color: #F5F5F5;
@@ -60,8 +58,10 @@
 	--test-arrow-background-color: rgba(78, 139, 202, 0.2);
 	--test-arrow-hover-color: #f5f5f5;
 	--test-arrow-hover-background-color: #4e8bca;
-	--target-background-color: #fdFfd3;
+	--target-background-color: #fdffd3;
 	--target-border-color: #ad7c37;
+	--tooltip-background-color: #fdffd3;
+	--tooltip-color: #fff;
 	--rust-logo-filter: initial;
 	/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
 	--crate-search-div-filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg)
@@ -77,15 +77,6 @@ body.source .example-wrap pre.rust a {
 	background: #eee;
 }
 
-.tooltip::after {
-	background-color: #000;
-	color: #fff;
-}
-
-.tooltip::before {
-	border-color: transparent black transparent transparent;
-}
-
 #titles > button:not(.selected) {
 	background-color: #e6e6e6;
 	border-top-color: #e6e6e6;
@@ -106,6 +97,15 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
+#settings-menu > a, #help-button > a {
+	color: #000;
+}
+
+#settings-menu > a:hover, #settings-menu > a:focus,
+#help-button > a:hover, #help-button > a:focus {
+	border-color: #717171;
+}
+
 .search-results .result-name span.alias {
 	color: #000;
 }
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 95cc265f1bd..5256ae916a7 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -9,13 +9,16 @@
     const isSettingsPage = window.location.pathname.endsWith("/settings.html");
 
     function changeSetting(settingName, value) {
+        if (settingName === "theme") {
+            const useSystem = value === "system preference" ? "true" : "false";
+            updateLocalStorage("use-system-theme", useSystem);
+        }
         updateLocalStorage(settingName, value);
 
         switch (settingName) {
             case "theme":
             case "preferred-dark-theme":
             case "preferred-light-theme":
-            case "use-system-theme":
                 updateSystemTheme();
                 updateLightAndDark();
                 break;
@@ -45,7 +48,6 @@
     }
 
     function showLightAndDark() {
-        addClass(document.getElementById("theme").parentElement, "hidden");
         removeClass(document.getElementById("preferred-light-theme").parentElement, "hidden");
         removeClass(document.getElementById("preferred-dark-theme").parentElement, "hidden");
     }
@@ -53,11 +55,11 @@
     function hideLightAndDark() {
         addClass(document.getElementById("preferred-light-theme").parentElement, "hidden");
         addClass(document.getElementById("preferred-dark-theme").parentElement, "hidden");
-        removeClass(document.getElementById("theme").parentElement, "hidden");
     }
 
     function updateLightAndDark() {
-        if (getSettingValue("use-system-theme") !== "false") {
+        const useSystem = getSettingValue("use-system-theme");
+        if (useSystem === "true" || (useSystem === null && getSettingValue("theme") === null)) {
             showLightAndDark();
         } else {
             hideLightAndDark();
@@ -91,7 +93,18 @@
         });
         onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => {
             const settingId = elem.name;
-            const settingValue = getSettingValue(settingId);
+            let settingValue = getSettingValue(settingId);
+            if (settingId === "theme") {
+                const useSystem = getSettingValue("use-system-theme");
+                if (useSystem === "true" || settingValue === null) {
+                    if (useSystem !== "false") {
+                        settingValue = "system preference";
+                    } else {
+                        // This is the default theme.
+                        settingValue = "light";
+                    }
+                }
+            }
             if (settingValue !== null && settingValue !== "null") {
                 elem.checked = settingValue === elem.value;
             }
@@ -120,26 +133,30 @@
 
             if (setting["options"] !== undefined) {
                 // This is a select setting.
-                output += `<div class="radio-line" id="${js_data_name}">\
-                        <span class="setting-name">${setting_name}</span>\
-                        <div class="choices">`;
+                output += `\
+<div class="radio-line" id="${js_data_name}">
+    <span class="setting-name">${setting_name}</span>
+<div class="choices">`;
                 onEach(setting["options"], option => {
                     const checked = option === setting["default"] ? " checked" : "";
+                    const full = `${js_data_name}-${option.replace(/ /g,"-")}`;
 
-                    output += `<label for="${js_data_name}-${option}" class="choice">\
-                           <input type="radio" name="${js_data_name}" \
-                                id="${js_data_name}-${option}" value="${option}"${checked}>\
-                           <span>${option}</span>\
-                         </label>`;
+                    output += `\
+<label for="${full}" class="choice">
+    <input type="radio" name="${js_data_name}"
+        id="${full}" value="${option}"${checked}>
+    <span>${option}</span>
+</label>`;
                 });
                 output += "</div></div>";
             } else {
                 // This is a toggle.
                 const checked = setting["default"] === true ? " checked" : "";
-                output += `<label class="toggle">\
-                        <input type="checkbox" id="${js_data_name}"${checked}>\
-                        <span class="label">${setting_name}</span>\
-                    </label>`;
+                output += `\
+<label class="toggle">\
+    <input type="checkbox" id="${js_data_name}"${checked}>\
+    <span class="label">${setting_name}</span>\
+</label>`;
             }
             output += "</div>";
         }
@@ -157,15 +174,10 @@
 
         const settings = [
             {
-                "name": "Use system theme",
-                "js_name": "use-system-theme",
-                "default": true,
-            },
-            {
                 "name": "Theme",
                 "js_name": "theme",
-                "default": "light",
-                "options": theme_names,
+                "default": "system preference",
+                "options": theme_names.concat("system preference"),
             },
             {
                 "name": "Preferred light theme",
diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk
index 33bf95ac165..0f5425daa16 100644
--- a/src/test/run-make-fulldeps/tools.mk
+++ b/src/test/run-make-fulldeps/tools.mk
@@ -40,6 +40,17 @@ endif
 # e.g. for `$(CC) -o $(RUN_BINFILE)`.
 RUN_BINFILE = $(TMPDIR)/$(1)
 
+# Invoke the generated binary on the remote machine if compiletest was
+# configured to use a remote test device, otherwise run it on the current host.
+ifdef REMOTE_TEST_CLIENT
+# FIXME: if a test requires additional files, this will need to be changed to
+# also push them (by changing the 0 to the number of additional files, and
+# providing the path of the additional files as the last arguments).
+EXECUTE = $(REMOTE_TEST_CLIENT) run 0 $(RUN_BINFILE)
+else
+EXECUTE = $(RUN_BINFILE)
+endif
+
 # RUN and FAIL are basic way we will invoke the generated binary.  On
 # non-windows platforms, they set the LD_LIBRARY_PATH environment
 # variable before running the binary.
@@ -50,16 +61,16 @@ BIN = $(1)
 UNAME = $(shell uname)
 
 ifeq ($(UNAME),Darwin)
-RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE)
-FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0
+RUN = $(TARGET_RPATH_ENV) $(EXECUTE)
+FAIL = $(TARGET_RPATH_ENV) $(EXECUTE) && exit 1 || exit 0
 DYLIB_GLOB = lib$(1)*.dylib
 DYLIB = $(TMPDIR)/lib$(1).dylib
 STATICLIB = $(TMPDIR)/lib$(1).a
 STATICLIB_GLOB = lib$(1)*.a
 else
 ifdef IS_WINDOWS
-RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE)
-FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) && exit 1 || exit 0
+RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(EXECUTE)
+FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(EXECUTE) && exit 1 || exit 0
 DYLIB_GLOB = $(1)*.dll
 DYLIB = $(TMPDIR)/$(1).dll
 ifdef IS_MSVC
@@ -73,8 +84,8 @@ endif
 BIN = $(1).exe
 LLVM_FILECHECK := $(shell cygpath -u "$(LLVM_FILECHECK)")
 else
-RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE)
-FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0
+RUN = $(TARGET_RPATH_ENV) $(EXECUTE)
+FAIL = $(TARGET_RPATH_ENV) $(EXECUTE) && exit 1 || exit 0
 DYLIB_GLOB = lib$(1)*.so
 DYLIB = $(TMPDIR)/lib$(1).so
 STATICLIB = $(TMPDIR)/lib$(1).a
diff --git a/src/test/run-make/issue-36710/Makefile b/src/test/run-make/issue-36710/Makefile
index 986a3f4e64b..d6145c07126 100644
--- a/src/test/run-make/issue-36710/Makefile
+++ b/src/test/run-make/issue-36710/Makefile
@@ -1,6 +1,7 @@
-# ignore-cross-compile $(call RUN,foo) expects to run the target executable natively
-#                              so it won't work with remote-test-server
 # ignore-none no-std is not supported
+# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM
+# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
 # ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain
 #                    (see dist-i586-gnu-i586-i686-musl Dockerfile)
 
diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml
index 8e681a2a0c3..caa1ab8f31e 100644
--- a/src/test/rustdoc-gui/codeblock-tooltip.goml
+++ b/src/test/rustdoc-gui/codeblock-tooltip.goml
@@ -4,7 +4,7 @@ show-text: true
 
 define-function: (
     "check-colors",
-    (theme),
+    (theme, background, color, border),
     [
         // Setting the theme.
         ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
@@ -30,6 +30,25 @@ define-function: (
             ".docblock .example-wrap.compile_fail",
             {"border-left": "2px solid rgb(255, 0, 0)"},
         )),
+        ("assert-css", (
+            ".docblock .example-wrap.compile_fail .tooltip::after",
+            {
+                "content": '"This example deliberately fails to compile"',
+                "text-align": "center",
+                "padding": "5px 3px 3px",
+                "background-color": |background|,
+                "color": |color|,
+                "border": "1px solid " + |border|,
+            },
+        )),
+        ("assert-css", (
+            ".docblock .example-wrap.compile_fail .tooltip::before",
+            {
+                "border-width": "5px",
+                "border-style": "solid",
+                "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
+            },
+        )),
 
         // should_panic block
         ("assert-css", (
@@ -51,6 +70,25 @@ define-function: (
             ".docblock .example-wrap.should_panic",
             {"border-left": "2px solid rgb(255, 0, 0)"},
         )),
+        ("assert-css", (
+            ".docblock .example-wrap.should_panic .tooltip::after",
+            {
+                "content": '"This example panics"',
+                "text-align": "center",
+                "padding": "5px 3px 3px",
+                "background-color": |background|,
+                "color": |color|,
+                "border": "1px solid " + |border|,
+            },
+        )),
+        ("assert-css", (
+            ".docblock .example-wrap.should_panic .tooltip::before",
+            {
+                "border-width": "5px",
+                "border-style": "solid",
+                "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
+            },
+        )),
 
         // ignore block
         ("assert-css", (
@@ -72,9 +110,43 @@ define-function: (
             ".docblock .example-wrap.ignore",
             {"border-left": "2px solid rgb(255, 142, 0)"},
         )),
+        ("assert-css", (
+            ".docblock .example-wrap.ignore .tooltip::after",
+            {
+                "content": '"This example is not tested"',
+                "text-align": "center",
+                "padding": "5px 3px 3px",
+                "background-color": |background|,
+                "color": |color|,
+                "border": "1px solid " + |border|,
+            },
+        )),
+        ("assert-css", (
+            ".docblock .example-wrap.ignore .tooltip::before",
+            {
+                "border-width": "5px",
+                "border-style": "solid",
+                "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
+            },
+        )),
     ],
 )
 
-call-function: ("check-colors", ("ayu"))
-call-function: ("check-colors", ("dark"))
-call-function: ("check-colors", ("light"))
+call-function: ("check-colors", {
+    "theme": "ayu",
+    "background": "rgb(49, 69, 89)",
+    "color": "rgb(197, 197, 197)",
+    "border": "rgb(92, 103, 115)",
+})
+call-function: ("check-colors", {
+    "theme": "dark",
+    "background": "rgb(0, 0, 0)",
+    "color": "rgb(255, 255, 255)",
+    "border": "rgb(224, 224, 224)",
+})
+call-function: ("check-colors", {
+    "theme": "light",
+    "background": "rgb(253, 255, 211)",
+    "color": "rgb(255, 255, 255)",
+    "border": "rgb(224, 224, 224)",
+})
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index 7e7971d47fb..fc3beaa53fa 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -37,8 +37,7 @@ click: "#settings-menu"
 wait-for: "#settings"
 
 // We check that the "Use system theme" is disabled.
-assert-property: ("#use-system-theme", {"checked": "false"})
-assert: "//*[@class='setting-line']//span[text()='Use system theme']"
+assert-property: ("#theme-system-preference", {"checked": "false"})
 // Meaning that only the "theme" menu is showing up.
 assert: ".setting-line:not(.hidden) #theme"
 assert: ".setting-line.hidden #preferred-dark-theme"
@@ -115,13 +114,6 @@ assert-css: (
         "border-color": "rgb(221, 221, 221)",
     },
 )
-assert-css: (
-    "#use-system-theme",
-    {
-        "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(221, 221, 221)",
-    }
-)
 // Let's start with the hover for toggles.
 move-cursor-to: "#auto-hide-large-items"
 assert-css: (
@@ -131,14 +123,6 @@ assert-css: (
         "border-color": "rgb(33, 150, 243)",
     },
 )
-move-cursor-to: "#use-system-theme"
-assert-css: (
-    "#use-system-theme",
-    {
-        "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(33, 150, 243)",
-    }
-)
 move-cursor-to: "#settings-menu > a"
 // Let's now check with the focus for toggles.
 focus: "#auto-hide-large-items"
@@ -150,15 +134,6 @@ assert-css: (
         "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
     },
 )
-focus: "#use-system-theme"
-assert-css: (
-    "#use-system-theme",
-    {
-        "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(221, 221, 221)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
-    },
-)
 // Now we check we both focus and hover for toggles.
 move-cursor-to: "#auto-hide-large-items"
 focus: "#auto-hide-large-items"
@@ -170,24 +145,12 @@ assert-css: (
         "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
     },
 )
-move-cursor-to: "#use-system-theme"
-focus: "#use-system-theme"
-assert-css: (
-    "#use-system-theme",
-    {
-        "background-color": "rgba(0, 0, 0, 0)",
-        "border-color": "rgb(33, 150, 243)",
-        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
-    },
-)
 
 // We now switch the display.
-click: "#use-system-theme"
+click: "#theme-system-preference"
 // Wait for the hidden element to show up.
 wait-for: ".setting-line:not(.hidden) #preferred-dark-theme"
 assert: ".setting-line:not(.hidden) #preferred-light-theme"
-// Check that the theme picking is hidden.
-assert: ".setting-line.hidden #theme"
 
 // We check their text as well.
 assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme")
diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml
index b1de3c36614..cc47f1f450c 100644
--- a/src/test/rustdoc-gui/theme-change.goml
+++ b/src/test/rustdoc-gui/theme-change.goml
@@ -2,31 +2,66 @@
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
 reload:
+
+store-value: (background_light, "rgb(255, 255, 255)")
+store-value: (background_dark, "rgb(53, 53, 53)")
+store-value: (background_ayu, "rgb(15, 20, 25)")
+
 click: "#settings-menu"
 wait-for: "#theme-ayu"
 click: "#theme-ayu"
 // should be the ayu theme so let's check the color.
-wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" })
+wait-for-css: ("body", { "background-color": |background_ayu| })
 assert-local-storage: { "rustdoc-theme": "ayu" }
 click: "#theme-light"
 // should be the light theme so let's check the color.
-wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+wait-for-css: ("body", { "background-color": |background_light| })
 assert-local-storage: { "rustdoc-theme": "light" }
 click: "#theme-dark"
 // Should be the dark theme so let's check the color.
-wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" })
+wait-for-css: ("body", { "background-color": |background_dark| })
 assert-local-storage: { "rustdoc-theme": "dark" }
 
+local-storage: {
+    "rustdoc-preferred-light-theme": "light",
+    "rustdoc-preferred-dark-theme": "light",
+}
 goto: "file://" + |DOC_PATH| + "/settings.html"
+
 wait-for: "#settings"
 click: "#theme-light"
-wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+wait-for-css: ("body", { "background-color": |background_light| })
 assert-local-storage: { "rustdoc-theme": "light" }
 
 click: "#theme-dark"
-wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" })
+wait-for-css: ("body", { "background-color": |background_dark| })
 assert-local-storage: { "rustdoc-theme": "dark" }
 
 click: "#theme-ayu"
-wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" })
+wait-for-css: ("body", { "background-color": |background_ayu| })
 assert-local-storage: { "rustdoc-theme": "ayu" }
+
+assert-local-storage-false: { "rustdoc-use-system-theme": "true" }
+click: "#theme-system-preference"
+wait-for: ".setting-line:not(.hidden) #preferred-light-theme"
+assert-local-storage: { "rustdoc-use-system-theme": "true" }
+// We click on both preferred light and dark themes to be sure that there is a change.
+click: "#preferred-light-theme-dark"
+click: "#preferred-dark-theme-dark"
+wait-for-css: ("body", { "background-color": |background_dark| })
+
+reload:
+// Ensure that the "preferred themes" are still displayed.
+wait-for: ".setting-line:not(.hidden) #preferred-light-theme"
+click: "#theme-light"
+wait-for-css: ("body", { "background-color": |background_light| })
+assert-local-storage: { "rustdoc-theme": "light" }
+// Ensure it's now hidden again
+wait-for: ".setting-line.hidden #preferred-light-theme"
+// And ensure the theme was rightly set.
+wait-for-css: ("body", { "background-color": |background_light| })
+assert-local-storage: { "rustdoc-theme": "light" }
+
+reload:
+wait-for: "#settings"
+assert: ".setting-line.hidden #preferred-light-theme"
diff --git a/src/test/ui/async-await/in-trait/early-bound-1.rs b/src/test/ui/async-await/in-trait/early-bound-1.rs
new file mode 100644
index 00000000000..6b3b142014b
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/early-bound-1.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+    async fn foo(&mut self);
+}
+
+struct MyFoo<'a>(&'a mut ());
+
+impl<'a> Foo for MyFoo<'a> {
+    async fn foo(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/early-bound-2.rs b/src/test/ui/async-await/in-trait/early-bound-2.rs
new file mode 100644
index 00000000000..270443229b0
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/early-bound-2.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+    async fn foo(&mut self);
+}
+
+impl<T: Foo> Foo for &mut T {
+    async fn foo(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/object-safety.rs b/src/test/ui/async-await/in-trait/object-safety.rs
new file mode 100644
index 00000000000..a8bc35f7e0c
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/object-safety.rs
@@ -0,0 +1,13 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+
+trait Foo {
+    async fn foo(&self);
+}
+
+fn main() {
+    let x: &dyn Foo = todo!();
+    //~^ ERROR the trait `Foo` cannot be made into an object
+}
diff --git a/src/test/ui/async-await/in-trait/object-safety.stderr b/src/test/ui/async-await/in-trait/object-safety.stderr
new file mode 100644
index 00000000000..0b318f71f39
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/object-safety.stderr
@@ -0,0 +1,27 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/object-safety.rs:3:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety.rs:11:12
+   |
+LL |     let x: &dyn Foo = todo!();
+   |            ^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety.rs:7:14
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     async fn foo(&self);
+   |              ^^^ ...because method `foo` is `async`
+   = help: consider moving `foo` to another trait
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs
new file mode 100644
index 00000000000..b113c56412f
--- /dev/null
+++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs
@@ -0,0 +1,76 @@
+// run-pass
+// edition:2021
+// needs-unwind
+#![feature(closure_track_caller)]
+
+use std::future::Future;
+use std::panic;
+use std::sync::{Arc, Mutex};
+use std::task::{Context, Poll, Wake};
+use std::thread::{self, Thread};
+
+/// A waker that wakes up the current thread when called.
+struct ThreadWaker(Thread);
+
+impl Wake for ThreadWaker {
+    fn wake(self: Arc<Self>) {
+        self.0.unpark();
+    }
+}
+
+/// Run a future to completion on the current thread.
+fn block_on<T>(fut: impl Future<Output = T>) -> T {
+    // Pin the future so it can be polled.
+    let mut fut = Box::pin(fut);
+
+    // Create a new context to be passed to the future.
+    let t = thread::current();
+    let waker = Arc::new(ThreadWaker(t)).into();
+    let mut cx = Context::from_waker(&waker);
+
+    // Run the future to completion.
+    loop {
+        match fut.as_mut().poll(&mut cx) {
+            Poll::Ready(res) => return res,
+            Poll::Pending => thread::park(),
+        }
+    }
+}
+
+async fn bar() {
+    panic!()
+}
+
+async fn foo() {
+    bar().await
+}
+
+#[track_caller]
+async fn bar_track_caller() {
+    panic!()
+}
+
+async fn foo_track_caller() {
+    bar_track_caller().await
+}
+
+fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
+    let loc = Arc::new(Mutex::new(None));
+
+    let hook = panic::take_hook();
+    {
+        let loc = loc.clone();
+        panic::set_hook(Box::new(move |info| {
+            *loc.lock().unwrap() = info.location().map(|loc| loc.line())
+        }));
+    }
+    panic::catch_unwind(f).unwrap_err();
+    panic::set_hook(hook);
+    let x = loc.lock().unwrap().unwrap();
+    x
+}
+
+fn main() {
+    assert_eq!(panicked_at(|| block_on(foo())), 41);
+    assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
+}
diff --git a/src/test/ui/consts/const-eval/issue-104390.rs b/src/test/ui/consts/const-eval/issue-104390.rs
new file mode 100644
index 00000000000..602d818245a
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-104390.rs
@@ -0,0 +1,10 @@
+fn f1() -> impl Sized { & 2E } //~ ERROR expected at least one digit in exponent
+fn f2() -> impl Sized { && 2E } //~ ERROR expected at least one digit in exponent
+fn f3() -> impl Sized { &'a 2E } //~ ERROR expected at least one digit in exponent
+//~^ ERROR borrow expressions cannot be annotated with lifetimes
+fn f4() -> impl Sized { &'static 2E } //~ ERROR expected at least one digit in exponent
+//~^ ERROR borrow expressions cannot be annotated with lifetimes
+fn f5() -> impl Sized { *& 2E } //~ ERROR expected at least one digit in exponent
+fn f6() -> impl Sized { &'_ 2E } //~ ERROR expected at least one digit in exponent
+//~^ ERROR borrow expressions cannot be annotated with lifetimes
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/issue-104390.stderr b/src/test/ui/consts/const-eval/issue-104390.stderr
new file mode 100644
index 00000000000..865b9996ea3
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-104390.stderr
@@ -0,0 +1,65 @@
+error: expected at least one digit in exponent
+  --> $DIR/issue-104390.rs:1:27
+   |
+LL | fn f1() -> impl Sized { & 2E }
+   |                           ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/issue-104390.rs:2:28
+   |
+LL | fn f2() -> impl Sized { && 2E }
+   |                            ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/issue-104390.rs:3:29
+   |
+LL | fn f3() -> impl Sized { &'a 2E }
+   |                             ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/issue-104390.rs:5:34
+   |
+LL | fn f4() -> impl Sized { &'static 2E }
+   |                                  ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/issue-104390.rs:7:28
+   |
+LL | fn f5() -> impl Sized { *& 2E }
+   |                            ^^
+
+error: expected at least one digit in exponent
+  --> $DIR/issue-104390.rs:8:29
+   |
+LL | fn f6() -> impl Sized { &'_ 2E }
+   |                             ^^
+
+error: borrow expressions cannot be annotated with lifetimes
+  --> $DIR/issue-104390.rs:3:25
+   |
+LL | fn f3() -> impl Sized { &'a 2E }
+   |                         ^--^^^
+   |                          |
+   |                          annotated with lifetime here
+   |                          help: remove the lifetime annotation
+
+error: borrow expressions cannot be annotated with lifetimes
+  --> $DIR/issue-104390.rs:5:25
+   |
+LL | fn f4() -> impl Sized { &'static 2E }
+   |                         ^-------^^^
+   |                          |
+   |                          annotated with lifetime here
+   |                          help: remove the lifetime annotation
+
+error: borrow expressions cannot be annotated with lifetimes
+  --> $DIR/issue-104390.rs:8:25
+   |
+LL | fn f6() -> impl Sized { &'_ 2E }
+   |                         ^--^^^
+   |                          |
+   |                          annotated with lifetime here
+   |                          help: remove the lifetime annotation
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/dyn-star/return.rs b/src/test/ui/dyn-star/return.rs
new file mode 100644
index 00000000000..fa3d8d7d506
--- /dev/null
+++ b/src/test/ui/dyn-star/return.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![feature(dyn_star)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+fn _foo() -> dyn* Unpin {
+    4usize
+}
+
+fn main() {}
diff --git a/src/test/ui/dyn-star/return.stderr b/src/test/ui/dyn-star/return.stderr
new file mode 100644
index 00000000000..e000351a68f
--- /dev/null
+++ b/src/test/ui/dyn-star/return.stderr
@@ -0,0 +1,11 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/return.rs:3:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/in-trait/object-safety.stderr b/src/test/ui/impl-trait/in-trait/object-safety.stderr
index 9a1554b5e1c..ca0e760ff6d 100644
--- a/src/test/ui/impl-trait/in-trait/object-safety.stderr
+++ b/src/test/ui/impl-trait/in-trait/object-safety.stderr
@@ -5,12 +5,12 @@ LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
    |                                 ^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/object-safety.rs:7:8
+  --> $DIR/object-safety.rs:7:22
    |
 LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> impl Debug;
-   |        ^^^ ...because method `baz` references an `impl Trait` type in its return type
+   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
 
 error[E0038]: the trait `Foo` cannot be made into an object
@@ -20,12 +20,12 @@ LL |     let s = i.baz();
    |             ^^^^^^^ `Foo` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/object-safety.rs:7:8
+  --> $DIR/object-safety.rs:7:22
    |
 LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> impl Debug;
-   |        ^^^ ...because method `baz` references an `impl Trait` type in its return type
+   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
 
 error[E0038]: the trait `Foo` cannot be made into an object
@@ -35,12 +35,12 @@ LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
    |             ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/object-safety.rs:7:8
+  --> $DIR/object-safety.rs:7:22
    |
 LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> impl Debug;
-   |        ^^^ ...because method `baz` references an `impl Trait` type in its return type
+   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
    = help: consider moving `baz` to another trait
    = note: required for `Box<u32>` to implement `CoerceUnsized<Box<dyn Foo>>`
    = note: required by cast to type `Box<dyn Foo>`
diff --git a/src/test/ui/lint/issue-104392.rs b/src/test/ui/lint/issue-104392.rs
new file mode 100644
index 00000000000..d5608edb46f
--- /dev/null
+++ b/src/test/ui/lint/issue-104392.rs
@@ -0,0 +1,11 @@
+fn main() {
+    { unsafe 92 } //~ ERROR expected `{`, found `92`
+}
+
+fn foo() {
+    { mod 92 } //~ ERROR expected identifier, found `92`
+}
+
+fn bar() {
+    { trait 92 } //~ ERROR expected identifier, found `92`
+}
diff --git a/src/test/ui/lint/issue-104392.stderr b/src/test/ui/lint/issue-104392.stderr
new file mode 100644
index 00000000000..8e466439ae6
--- /dev/null
+++ b/src/test/ui/lint/issue-104392.stderr
@@ -0,0 +1,27 @@
+error: expected `{`, found `92`
+  --> $DIR/issue-104392.rs:2:14
+   |
+LL |     { unsafe 92 }
+   |       ------ ^^ expected `{`
+   |       |
+   |       while parsing this `unsafe` expression
+   |
+help: try placing this code inside a block
+   |
+LL |     { unsafe { 92 } }
+   |              +    +
+
+error: expected identifier, found `92`
+  --> $DIR/issue-104392.rs:6:11
+   |
+LL |     { mod 92 }
+   |           ^^ expected identifier
+
+error: expected identifier, found `92`
+  --> $DIR/issue-104392.rs:10:13
+   |
+LL |     { trait 92 }
+   |             ^^ expected identifier
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/typeck/issue-103899.rs b/src/test/ui/typeck/issue-103899.rs
index 9d5341dab42..ac9e4c71696 100644
--- a/src/test/ui/typeck/issue-103899.rs
+++ b/src/test/ui/typeck/issue-103899.rs
@@ -1,9 +1,6 @@
 // check-fail
 // failure-status: 101
-// normalize-stderr-test "note: .*" -> ""
-// normalize-stderr-test "thread 'rustc' .*" -> ""
-// normalize-stderr-test " .*\n" -> ""
-// normalize-stderr-test "  .*\n" -> ""
+// dont-check-compiler-stderr
 // known-bug: #103899
 
 trait BaseWithAssoc {
diff --git a/src/test/ui/typeck/issue-103899.stderr b/src/test/ui/typeck/issue-103899.stderr
deleted file mode 100644
index 836c6ee486f..00000000000
--- a/src/test/ui/typeck/issue-103899.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-
-stack
-error:
-
-
-
-
-
-
-
-
-query#0#1end
\ No newline at end of file
diff --git a/src/test/ui/typeck/issue-104510-ice.rs b/src/test/ui/typeck/issue-104510-ice.rs
new file mode 100644
index 00000000000..157bdf07e38
--- /dev/null
+++ b/src/test/ui/typeck/issue-104510-ice.rs
@@ -0,0 +1,16 @@
+// needs-asm-support
+// only-x86_64
+
+struct W<T: ?Sized>(Oops);
+//~^ ERROR cannot find type `Oops` in this scope
+
+unsafe fn test() {
+    let j = W(());
+    let pointer = &j as *const _;
+    core::arch::asm!(
+        "nop",
+        in("eax") pointer,
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-104510-ice.stderr b/src/test/ui/typeck/issue-104510-ice.stderr
new file mode 100644
index 00000000000..ddb510ef047
--- /dev/null
+++ b/src/test/ui/typeck/issue-104510-ice.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Oops` in this scope
+  --> $DIR/issue-104510-ice.rs:4:21
+   |
+LL | struct W<T: ?Sized>(Oops);
+   |                     ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index a37ee82d4c8..218dbeaddca 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1156,7 +1156,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
             }
 
             let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty);
-            let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate);
+            let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
             let infcx = cx.tcx.infer_ctxt().build();
             infcx.predicate_must_hold_modulo_regions(&obligation)
         })
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 090f9f8ff73..5c6a342b3d0 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
-    HirId, IsAsync, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
+    HirId, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
     ) {
         if_chain! {
             if let Some(header) = kind.header();
-            if header.asyncness == IsAsync::NotAsync;
+            if !header.asyncness.is_async();
             // Check that this function returns `impl Future`
             if let FnRetTy::Return(ret_ty) = decl.output;
             if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty);
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 642a64ae77b..c7775313ecd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -419,7 +419,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
 
                         if trait_predicates.any(|predicate| {
                             let predicate = EarlyBinder(predicate).subst(cx.tcx, new_subst);
-                            let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate);
+                            let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
                             !cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
                         }) {
                             return false;
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 0d74c90a834..c8c6f32c6c9 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -695,6 +695,7 @@ fn matches_preds<'tcx>(
             .type_implements_trait(p.def_id, ty, p.substs, cx.param_env)
             .must_apply_modulo_regions(),
         ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new(
+            cx.tcx,
             ObligationCause::dummy(),
             cx.param_env,
             cx.tcx.mk_predicate(Binder::bind_with_vars(
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index bf487c7ca20..3538bef6e06 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, IsAsync, YieldSource};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, YieldSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
         span: Span,
         hir_id: HirId,
     ) {
-        if !span.from_expansion() && fn_kind.asyncness() == IsAsync::Async {
+        if !span.from_expansion() && fn_kind.asyncness().is_async() {
             let mut visitor = AsyncFnVisitor { cx, found_await: false };
             walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), hir_id);
             if !visitor.found_await {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index d32cf1a7936..bb91317d67f 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -87,10 +87,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
 use rustc_hir::{
-    def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, Destination, Expr,
-    ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource,
-    Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind,
-    TraitRef, TyKind, UnOp,
+    def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness,
+    Destination, Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind,
+    LangItem, Local, MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy,
+    QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -1861,7 +1861,7 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
 
 /// Checks if the given function kind is an async function.
 pub fn is_async_fn(kind: FnKind<'_>) -> bool {
-    matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness == IsAsync::Async)
+    matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness.is_async())
 }
 
 /// Peels away all the compiler generated code surrounding the body of an async function,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 8d8ca101cd0..ebce0283fba 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2987,6 +2987,10 @@ impl<'test> TestCx<'test> {
             cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
         }
 
+        if let Some(ref remote_test_client) = self.config.remote_test_client {
+            cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
+        }
+
         // We don't want RUSTFLAGS set from the outside to interfere with
         // compiler flags set in the test cases:
         cmd.env_remove("RUSTFLAGS");
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index b8398377585..d3e139e4651 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-9340e5c1b9dee53fd32a18f7bfb54faabfe00b7b
+2f8d8040166a730d0da7bba0f2864f0ef7ff6364
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 617f90dfaa5..bc0b71fbc20 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -22,21 +22,44 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let this = self.eval_context_mut();
 
-        this.assert_target_os("linux", "clock_gettime");
+        this.assert_target_os_is_unix("clock_gettime");
 
         let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
 
-        // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
-        // Unix epoch, including effects which may cause time to move backwards such as NTP.
-        // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
-        // is just specified to be "faster and less precise", so we implement both the same way.
-        let absolute_clocks =
-            [this.eval_libc_i32("CLOCK_REALTIME")?, this.eval_libc_i32("CLOCK_REALTIME_COARSE")?];
-        // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
-        // never allowed to go backwards. We don't need to do any additonal monotonicity
-        // enforcement because std::time::Instant already guarantees that it is monotonic.
-        let relative_clocks =
-            [this.eval_libc_i32("CLOCK_MONOTONIC")?, this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?];
+        let absolute_clocks;
+        let mut relative_clocks;
+
+        match this.tcx.sess.target.os.as_ref() {
+            "linux" => {
+                // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
+                // Unix epoch, including effects which may cause time to move backwards such as NTP.
+                // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
+                // is just specified to be "faster and less precise", so we implement both the same way.
+                absolute_clocks = vec![
+                    this.eval_libc_i32("CLOCK_REALTIME")?,
+                    this.eval_libc_i32("CLOCK_REALTIME_COARSE")?,
+                ];
+                // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
+                // never allowed to go backwards. We don't need to do any additonal monotonicity
+                // enforcement because std::time::Instant already guarantees that it is monotonic.
+                relative_clocks = vec![
+                    this.eval_libc_i32("CLOCK_MONOTONIC")?,
+                    this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?,
+                ];
+            }
+            "macos" => {
+                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?];
+                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?];
+                // Some clocks only seem to exist in the aarch64 version of the target.
+                if this.tcx.sess.target.arch == "aarch64" {
+                    // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
+                    // that's not really something a program running inside Miri can tell, anyway.
+                    // We need to support it because std uses it.
+                    relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?);
+                }
+            }
+            target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
+        }
 
         let duration = if absolute_clocks.contains(&clk_id) {
             this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?;
@@ -44,6 +67,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         } else if relative_clocks.contains(&clk_id) {
             this.machine.clock.now().duration_since(this.machine.clock.anchor())
         } else {
+            // Unsupported clock.
             let einval = this.eval_libc("EINVAL")?;
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 44a433df1e9..d746f9df90a 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -180,6 +180,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let result = this.gettimeofday(tv, tz)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
+            "clock_gettime" => {
+                let [clk_id, tp] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.clock_gettime(clk_id, tp)?;
+                this.write_scalar(result, dest)?;
+            }
 
             // Allocation
             "posix_memalign" => {
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 2b53152688b..34076e842d5 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -43,15 +43,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(result, dest)?;
             }
 
-            // Time related shims
-            "clock_gettime" => {
-                // This is a POSIX function but it has only been tested on linux.
-                let [clk_id, tp] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.clock_gettime(clk_id, tp)?;
-                this.write_scalar(result, dest)?;
-            }
-
             // Threading
             "pthread_condattr_setclock" => {
                 let [attr, clock_id] =
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
index 904ae2fb17f..2a4300fcd04 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
@@ -181,17 +181,25 @@ fn test_thread_local_errno() {
 }
 
 /// Tests whether clock support exists at all
-#[cfg(target_os = "linux")]
 fn test_clocks() {
     let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
     let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
     assert_eq!(is_error, 0);
-    let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
-    assert_eq!(is_error, 0);
     let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) };
     assert_eq!(is_error, 0);
-    let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
-    assert_eq!(is_error, 0);
+    #[cfg(target_os = "linux")]
+    {
+        let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
+        assert_eq!(is_error, 0);
+        let is_error =
+            unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
+        assert_eq!(is_error, 0);
+    }
+    #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
+    {
+        let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) };
+        assert_eq!(is_error, 0);
+    }
 }
 
 fn test_posix_gettimeofday() {
@@ -293,11 +301,11 @@ fn main() {
     test_thread_local_errno();
 
     test_isatty();
+    test_clocks();
 
     #[cfg(target_os = "linux")]
     {
         test_posix_fadvise();
         test_sync_file_range();
-        test_clocks();
     }
 }