about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs29
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs5
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl6
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs162
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs11
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs25
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs8
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/query/keys.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs43
-rw-r--r--compiler/rustc_middle/src/traits/query.rs59
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/search_graph.rs11
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs1
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs4
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs4
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs11
-rw-r--r--compiler/rustc_traits/src/type_op.rs14
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs32
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs2
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs3
-rw-r--r--src/librustdoc/json/conversions.rs4
-rw-r--r--src/rustdoc-json-types/lib.rs9
-rw-r--r--tests/codegen/iter-repeat-n-trivial-drop.rs2
-rw-r--r--tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir60
-rw-r--r--tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir4
-rw-r--r--tests/mir-opt/building/issue_101867.main.built.after.mir4
-rw-r--r--tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir8
-rw-r--r--tests/mir-opt/issue_72181_1.main.built.after.mir4
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.32bit.mir4
-rw-r--r--tests/mir-opt/issue_99325.main.built.after.64bit.mir4
-rw-r--r--tests/rustdoc-json/traits/is_dyn_compatible.rs19
-rw-r--r--tests/rustdoc-json/traits/is_object_safe.rs19
-rw-r--r--tests/ui/coherence/coherence-cow.re_a.stderr7
-rw-r--r--tests/ui/coherence/coherence-cow.re_b.stderr7
-rw-r--r--tests/ui/coherence/coherence-cow.re_c.stderr7
-rw-r--r--tests/ui/coherence/coherence-fundamental-trait-objects.stderr7
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr7
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr7
-rw-r--r--tests/ui/coherence/coherence-impls-copy.stderr28
-rw-r--r--tests/ui/coherence/coherence-impls-send.stderr21
-rw-r--r--tests/ui/coherence/coherence-impls-sized.stderr21
-rw-r--r--tests/ui/coherence/coherence-negative-impls-copy-bad.stderr21
-rw-r--r--tests/ui/coherence/coherence-orphan.stderr16
-rw-r--r--tests/ui/coherence/coherence-overlapping-pairs.stderr7
-rw-r--r--tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr9
-rw-r--r--tests/ui/coherence/coherence-pair-covered-uncovered.stderr7
-rw-r--r--tests/ui/coherence/coherence-vec-local-2.stderr7
-rw-r--r--tests/ui/coherence/coherence-vec-local.stderr7
-rw-r--r--tests/ui/coherence/coherence_local_err_struct.stderr7
-rw-r--r--tests/ui/coherence/coherence_local_err_tuple.stderr7
-rw-r--r--tests/ui/coherence/impl-foreign-for-foreign.stderr7
-rw-r--r--tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr27
-rw-r--r--tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr18
-rw-r--r--tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr9
-rw-r--r--tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr33
-rw-r--r--tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr14
-rw-r--r--tests/ui/dropck/drop-on-non-struct.stderr7
-rw-r--r--tests/ui/error-codes/E0117.stderr7
-rw-r--r--tests/ui/error-codes/e0119/complex-impl.stderr7
-rw-r--r--tests/ui/errors/issue-99572-impl-trait-on-pointer.rs20
-rw-r--r--tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr16
-rw-r--r--tests/ui/issues/issue-67535.stderr27
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.classic.stderr7
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.next.stderr7
-rw-r--r--tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr7
-rw-r--r--tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr21
86 files changed, 602 insertions, 565 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 40a6d506ffa..2437a43bd5a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -3,12 +3,16 @@ use std::rc::Rc;
 
 use rustc_errors::Diag;
 use rustc_hir::def_id::LocalDefId;
-use rustc_infer::infer::canonical::Canonical;
+use rustc_infer::infer::canonical::CanonicalQueryInput;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_infer::infer::{
     InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _,
 };
 use rustc_infer::traits::ObligationCause;
+use rustc_infer::traits::query::{
+    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
+    CanonicalTypeOpProvePredicateGoal,
+};
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{
     self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex,
@@ -95,9 +99,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tc
     }
 }
 
-impl<'tcx> ToUniverseInfo<'tcx>
-    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
-{
+impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpProvePredicateGoal<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
         UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
             canonical_query: self,
@@ -107,7 +109,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
 }
 
 impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
-    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
+    for CanonicalTypeOpNormalizeGoal<'tcx, T>
 {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
         UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
@@ -117,9 +119,7 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
     }
 }
 
-impl<'tcx> ToUniverseInfo<'tcx>
-    for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
-{
+impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
         UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(AscribeUserTypeQuery {
             canonical_query: self,
@@ -128,7 +128,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
     }
 }
 
-impl<'tcx, F> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F>> {
+impl<'tcx, F> ToUniverseInfo<'tcx> for CanonicalQueryInput<'tcx, type_op::custom::CustomTypeOp<F>> {
     fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
         // We can't rerun custom type ops.
         UniverseInfo::other()
@@ -211,8 +211,7 @@ trait TypeOpInfo<'tcx> {
 }
 
 struct PredicateQuery<'tcx> {
-    canonical_query:
-        Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>,
+    canonical_query: CanonicalTypeOpProvePredicateGoal<'tcx>,
     base_universe: ty::UniverseIndex,
 }
 
@@ -220,7 +219,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
     fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
         tcx.dcx().create_err(HigherRankedLifetimeError {
             cause: Some(HigherRankedErrorCause::CouldNotProve {
-                predicate: self.canonical_query.value.value.predicate.to_string(),
+                predicate: self.canonical_query.canonical.value.value.predicate.to_string(),
             }),
             span,
         })
@@ -253,7 +252,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
 }
 
 struct NormalizeQuery<'tcx, T> {
-    canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>,
+    canonical_query: CanonicalTypeOpNormalizeGoal<'tcx, T>,
     base_universe: ty::UniverseIndex,
 }
 
@@ -264,7 +263,7 @@ where
     fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
         tcx.dcx().create_err(HigherRankedLifetimeError {
             cause: Some(HigherRankedErrorCause::CouldNotNormalize {
-                value: self.canonical_query.value.value.value.to_string(),
+                value: self.canonical_query.canonical.value.value.value.to_string(),
             }),
             span,
         })
@@ -306,7 +305,7 @@ where
 }
 
 struct AscribeUserTypeQuery<'tcx> {
-    canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>,
+    canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
     base_universe: ty::UniverseIndex,
 }
 
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 0c6f8cd7b5b..fde68615cc0 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -137,7 +137,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             locations,
             category,
-            param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
+            param_env.and(type_op::prove_predicate::ProvePredicate { predicate }),
         );
     }
 
@@ -162,7 +162,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             location.to_locations(),
             category,
-            param_env.and(type_op::normalize::Normalize::new(value)),
+            param_env.and(type_op::normalize::Normalize { value }),
         );
         result.unwrap_or(value)
     }
@@ -223,7 +223,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
-            self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
+            self.param_env.and(type_op::ascribe_user_type::AscribeUserType { mir_ty, user_ty }),
         );
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index cded9935f97..8e1faf025e2 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -280,7 +280,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             }
             let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
                 .param_env
-                .and(type_op::normalize::Normalize::new(ty))
+                .and(type_op::normalize::Normalize { value: ty })
                 .fully_perform(self.infcx, span)
                 .unwrap_or_else(|guar| TypeOpOutput {
                     output: Ty::new_error(self.infcx.tcx, guar),
@@ -318,7 +318,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
                 let result: Result<_, ErrorGuaranteed> = self
                     .param_env
-                    .and(type_op::normalize::Normalize::new(ty))
+                    .and(type_op::normalize::Normalize { value: ty })
                     .fully_perform(self.infcx, span);
                 let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
                     continue;
@@ -373,7 +373,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
     ) -> Option<&'tcx QueryRegionConstraints<'tcx>> {
         let TypeOpOutput { output: bounds, constraints, .. } = self
             .param_env
-            .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
+            .and(type_op::ImpliedOutlivesBounds { ty })
             .fully_perform(self.infcx, span)
             .map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty))
             .ok()?;
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index a5175e653d8..35963228181 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -11,8 +11,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
 use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
 use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
-use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
+use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
 use tracing::debug;
 
 use crate::location::RichLocation;
@@ -632,7 +631,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
 
         match typeck
             .param_env
-            .and(DropckOutlives::new(dropped_ty))
+            .and(DropckOutlives { dropped_ty })
             .fully_perform(typeck.infcx, DUMMY_SP)
         {
             Ok(TypeOpOutput { output, constraints, .. }) => {
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index a9f30ffd6da..507297ce162 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -356,12 +356,14 @@ hir_analysis_only_current_traits_arbitrary = only traits defined in the current
 
 hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait
 
-hir_analysis_only_current_traits_label = impl doesn't use only types from inside the current crate
-
 hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign
 
 hir_analysis_only_current_traits_note = define and implement a trait or new type instead
 
+hir_analysis_only_current_traits_note_more_info = for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
+
+hir_analysis_only_current_traits_note_uncovered = impl doesn't have any local type before any uncovered type parameters
+
 hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
 
 hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index af4445a7fd4..77e81af3ca9 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1434,24 +1434,27 @@ pub(crate) enum OnlyCurrentTraits {
     #[diag(hir_analysis_only_current_traits_outside, code = E0117)]
     Outside {
         #[primary_span]
-        #[label(hir_analysis_only_current_traits_label)]
         span: Span,
+        #[note(hir_analysis_only_current_traits_note_uncovered)]
+        #[note(hir_analysis_only_current_traits_note_more_info)]
         #[note(hir_analysis_only_current_traits_note)]
         note: (),
     },
     #[diag(hir_analysis_only_current_traits_primitive, code = E0117)]
     Primitive {
         #[primary_span]
-        #[label(hir_analysis_only_current_traits_label)]
         span: Span,
+        #[note(hir_analysis_only_current_traits_note_uncovered)]
+        #[note(hir_analysis_only_current_traits_note_more_info)]
         #[note(hir_analysis_only_current_traits_note)]
         note: (),
     },
     #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)]
     Arbitrary {
         #[primary_span]
-        #[label(hir_analysis_only_current_traits_label)]
         span: Span,
+        #[note(hir_analysis_only_current_traits_note_uncovered)]
+        #[note(hir_analysis_only_current_traits_note_more_info)]
         #[note(hir_analysis_only_current_traits_note)]
         note: (),
     },
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 7bdd3c95ad1..f4d7b59e9c8 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1320,84 +1320,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let expected_ty = expected.coercion_target_type(self, expr.span);
         if expected_ty == self.tcx.types.bool {
-            // The expected type is `bool` but this will result in `()` so we can reasonably
-            // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
-            // The likely cause of this is `if foo = bar { .. }`.
-            let actual_ty = self.tcx.types.unit;
-            let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
-            let lhs_ty = self.check_expr(lhs);
-            let rhs_ty = self.check_expr(rhs);
-            let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
-                let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs());
-                let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs());
-                self.may_coerce(rhs, lhs)
-            };
-            let (applicability, eq) = if self.may_coerce(rhs_ty, lhs_ty) {
-                (Applicability::MachineApplicable, true)
-            } else if refs_can_coerce(rhs_ty, lhs_ty) {
-                // The lhs and rhs are likely missing some references in either side. Subsequent
-                // suggestions will show up.
-                (Applicability::MaybeIncorrect, true)
-            } else if let ExprKind::Binary(
-                Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
-                _,
-                rhs_expr,
-            ) = lhs.kind
-            {
-                // if x == 1 && y == 2 { .. }
-                //                 +
-                let actual_lhs_ty = self.check_expr(rhs_expr);
-                (
-                    Applicability::MaybeIncorrect,
-                    self.may_coerce(rhs_ty, actual_lhs_ty)
-                        || refs_can_coerce(rhs_ty, actual_lhs_ty),
-                )
-            } else if let ExprKind::Binary(
-                Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
-                lhs_expr,
-                _,
-            ) = rhs.kind
-            {
-                // if x == 1 && y == 2 { .. }
-                //       +
-                let actual_rhs_ty = self.check_expr(lhs_expr);
-                (
-                    Applicability::MaybeIncorrect,
-                    self.may_coerce(actual_rhs_ty, lhs_ty)
-                        || refs_can_coerce(actual_rhs_ty, lhs_ty),
-                )
-            } else {
-                (Applicability::MaybeIncorrect, false)
-            };
-            if !lhs.is_syntactic_place_expr()
-                && lhs.is_approximately_pattern()
-                && !matches!(lhs.kind, hir::ExprKind::Lit(_))
-            {
-                // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
-                if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
-                    self.tcx.parent_hir_node(expr.hir_id)
-                {
-                    err.span_suggestion_verbose(
-                        expr.span.shrink_to_lo(),
-                        "you might have meant to use pattern matching",
-                        "let ",
-                        applicability,
-                    );
-                };
-            }
-            if eq {
-                err.span_suggestion_verbose(
-                    span.shrink_to_hi(),
-                    "you might have meant to compare for equality",
-                    '=',
-                    applicability,
-                );
-            }
-
-            // If the assignment expression itself is ill-formed, don't
-            // bother emitting another error
-            let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
-            return Ty::new_error(self.tcx, reported);
+            let guar = self.expr_assign_expected_bool_error(expr, lhs, rhs, span);
+            return Ty::new_error(self.tcx, guar);
         }
 
         let lhs_ty = self.check_expr_with_needs(lhs, Needs::MutPlace);
@@ -1450,6 +1374,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// The expected type is `bool` but this will result in `()` so we can reasonably
+    /// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
+    /// The likely cause of this is `if foo = bar { .. }`.
+    fn expr_assign_expected_bool_error(
+        &self,
+        expr: &'tcx hir::Expr<'tcx>,
+        lhs: &'tcx hir::Expr<'tcx>,
+        rhs: &'tcx hir::Expr<'tcx>,
+        span: Span,
+    ) -> ErrorGuaranteed {
+        let actual_ty = self.tcx.types.unit;
+        let expected_ty = self.tcx.types.bool;
+        let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
+        let lhs_ty = self.check_expr(lhs);
+        let rhs_ty = self.check_expr(rhs);
+        let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
+            let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs());
+            let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs());
+            self.may_coerce(rhs, lhs)
+        };
+        let (applicability, eq) = if self.may_coerce(rhs_ty, lhs_ty) {
+            (Applicability::MachineApplicable, true)
+        } else if refs_can_coerce(rhs_ty, lhs_ty) {
+            // The lhs and rhs are likely missing some references in either side. Subsequent
+            // suggestions will show up.
+            (Applicability::MaybeIncorrect, true)
+        } else if let ExprKind::Binary(
+            Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+            _,
+            rhs_expr,
+        ) = lhs.kind
+        {
+            // if x == 1 && y == 2 { .. }
+            //                 +
+            let actual_lhs = self.check_expr(rhs_expr);
+            let may_eq = self.may_coerce(rhs_ty, actual_lhs) || refs_can_coerce(rhs_ty, actual_lhs);
+            (Applicability::MaybeIncorrect, may_eq)
+        } else if let ExprKind::Binary(
+            Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+            lhs_expr,
+            _,
+        ) = rhs.kind
+        {
+            // if x == 1 && y == 2 { .. }
+            //       +
+            let actual_rhs = self.check_expr(lhs_expr);
+            let may_eq = self.may_coerce(actual_rhs, lhs_ty) || refs_can_coerce(actual_rhs, lhs_ty);
+            (Applicability::MaybeIncorrect, may_eq)
+        } else {
+            (Applicability::MaybeIncorrect, false)
+        };
+
+        if !lhs.is_syntactic_place_expr()
+            && lhs.is_approximately_pattern()
+            && !matches!(lhs.kind, hir::ExprKind::Lit(_))
+        {
+            // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
+            if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
+                self.tcx.parent_hir_node(expr.hir_id)
+            {
+                err.span_suggestion_verbose(
+                    expr.span.shrink_to_lo(),
+                    "you might have meant to use pattern matching",
+                    "let ",
+                    applicability,
+                );
+            };
+        }
+        if eq {
+            err.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                "you might have meant to compare for equality",
+                '=',
+                applicability,
+            );
+        }
+
+        // If the assignment expression itself is ill-formed, don't
+        // bother emitting another error
+        err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error())
+    }
+
     pub(super) fn check_expr_let(
         &self,
         let_expr: &'tcx hir::LetExpr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index ba6bfd3a5e9..1be711887d9 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -340,13 +340,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
     {
         let mut orig_values = OriginalQueryValues::default();
-        let param_env_and_self_ty = self.canonicalize_query(
+        let query_input = self.canonicalize_query(
             ParamEnvAnd { param_env: self.param_env, value: self_ty },
             &mut orig_values,
         );
 
         let steps = match mode {
-            Mode::MethodCall => self.tcx.method_autoderef_steps(param_env_and_self_ty),
+            Mode::MethodCall => self.tcx.method_autoderef_steps(query_input),
             Mode::Path => self.probe(|_| {
                 // Mode::Path - the deref steps is "trivial". This turns
                 // our CanonicalQuery into a "trivial" QueryResponse. This
@@ -355,11 +355,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let infcx = &self.infcx;
                 let (ParamEnvAnd { param_env: _, value: self_ty }, canonical_inference_vars) =
-                    infcx.instantiate_canonical(span, &param_env_and_self_ty);
-                debug!(
-                    "probe_op: Mode::Path, param_env_and_self_ty={:?} self_ty={:?}",
-                    param_env_and_self_ty, self_ty
-                );
+                    infcx.instantiate_canonical(span, &query_input.canonical);
+                debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
                 MethodAutoderefStepsResult {
                     steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
                         self_ty: self.make_query_response_ignoring_pending_obligations(
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 35ea4233825..e3519dfb028 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -17,7 +17,8 @@ use tracing::debug;
 
 use crate::infer::InferCtxt;
 use crate::infer::canonical::{
-    Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
+    Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind,
+    OriginalQueryValues,
 };
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -40,12 +41,12 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         value: ty::ParamEnvAnd<'tcx, V>,
         query_state: &mut OriginalQueryValues<'tcx>,
-    ) -> Canonical<'tcx, ty::ParamEnvAnd<'tcx, V>>
+    ) -> CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, V>>
     where
         V: TypeFoldable<TyCtxt<'tcx>>,
     {
         let (param_env, value) = value.into_parts();
-        let mut param_env = self.tcx.canonical_param_env_cache.get_or_insert(
+        let param_env = self.tcx.canonical_param_env_cache.get_or_insert(
             self.tcx,
             param_env,
             query_state,
@@ -62,9 +63,7 @@ impl<'tcx> InferCtxt<'tcx> {
             },
         );
 
-        param_env.defining_opaque_types = self.defining_opaque_types;
-
-        Canonicalizer::canonicalize_with_base(
+        let canonical = Canonicalizer::canonicalize_with_base(
             param_env,
             value,
             Some(self),
@@ -72,7 +71,8 @@ impl<'tcx> InferCtxt<'tcx> {
             &CanonicalizeAllFreeRegions,
             query_state,
         )
-        .unchecked_map(|(param_env, value)| param_env.and(value))
+        .unchecked_map(|(param_env, value)| param_env.and(value));
+        CanonicalQueryInput { canonical, defining_opaque_types: self.defining_opaque_types() }
     }
 
     /// Canonicalizes a query *response* `V`. When we canonicalize a
@@ -544,7 +544,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             max_universe: ty::UniverseIndex::ROOT,
             variables: List::empty(),
             value: (),
-            defining_opaque_types: infcx.map(|i| i.defining_opaque_types).unwrap_or_default(),
         };
         Canonicalizer::canonicalize_with_base(
             base,
@@ -614,15 +613,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
             .max()
             .unwrap_or(ty::UniverseIndex::ROOT);
 
-        assert!(
-            !infcx.is_some_and(|infcx| infcx.defining_opaque_types != base.defining_opaque_types)
-        );
-        Canonical {
-            max_universe,
-            variables: canonical_variables,
-            value: (base.value, out_value),
-            defining_opaque_types: base.defining_opaque_types,
-        }
+        Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) }
     }
 
     /// Creates a canonical variable replacing `kind` from the input,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 7ef714475fc..f1195d0d4c0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -25,7 +25,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::extension;
 pub use rustc_macros::{TypeFoldable, TypeVisitable};
-use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
+use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
 use rustc_middle::infer::unify_key::{
     ConstVariableOrigin, ConstVariableValue, ConstVidKey, EffectVarValue, EffectVidKey,
 };
@@ -606,14 +606,14 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     pub fn build_with_canonical<T>(
         mut self,
         span: Span,
-        canonical: &Canonical<'tcx, T>,
+        input: &CanonicalQueryInput<'tcx, T>,
     ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
-        self.defining_opaque_types = canonical.defining_opaque_types;
+        self.defining_opaque_types = input.defining_opaque_types;
         let infcx = self.build();
-        let (value, args) = infcx.instantiate_canonical(span, canonical);
+        let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
         (infcx, value, args)
     }
 
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index d4314978819..ac55497f8b3 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -34,6 +34,7 @@ use crate::infer::MemberConstraint;
 use crate::mir::ConstraintCategory;
 use crate::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
 
+pub type CanonicalQueryInput<'tcx, V> = ir::CanonicalQueryInput<TyCtxt<'tcx>, V>;
 pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
 pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
 pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
@@ -182,7 +183,6 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
                 max_universe: ty::UniverseIndex::ROOT,
                 variables: List::empty(),
                 value: key,
-                defining_opaque_types: ty::List::empty(),
             };
         }
 
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 80adbe74fe7..ba7b57c891c 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -7,7 +7,7 @@ use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{DUMMY_SP, Span};
 use rustc_target::abi;
 
-use crate::infer::canonical::Canonical;
+use crate::infer::canonical::CanonicalQueryInput;
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::layout::{TyAndLayout, ValidityRequirement};
 use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
@@ -485,7 +485,7 @@ impl Key for Option<Symbol> {
 
 /// Canonical query goals correspond to abstract trait operations that
 /// are not tied to any crate in particular.
-impl<'tcx, T: Clone> Key for Canonical<'tcx, T> {
+impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
     type Cache<V> = DefaultCache<Self, V>;
 
     fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f0be70e00df..33128bdbf1e 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -65,10 +65,11 @@ use crate::query::plumbing::{
     CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at,
 };
 use crate::traits::query::{
-    CanonicalAliasGoal, CanonicalPredicateGoal, CanonicalTyGoal,
-    CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
-    CanonicalTypeOpProvePredicateGoal, DropckConstraint, DropckOutlivesResult,
-    MethodAutoderefStepsResult, NoSolution, NormalizationResult, OutlivesBound,
+    CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal,
+    CanonicalPredicateGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
+    CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, DropckConstraint,
+    DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult,
+    OutlivesBound,
 };
 use crate::traits::{
     CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource,
@@ -2010,7 +2011,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{}`", goal.value.value }
+        desc { "normalizing `{}`", goal.canonical.value.value }
     }
 
     /// <div class="warning">
@@ -2024,7 +2025,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{}`", goal.value.value }
+        desc { "normalizing `{}`", goal.canonical.value.value }
     }
 
     /// <div class="warning">
@@ -2038,7 +2039,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{}`", goal.value.value }
+        desc { "normalizing `{}`", goal.canonical.value.value }
     }
 
     /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
@@ -2049,32 +2050,32 @@ rustc_queries! {
     }
 
     query implied_outlives_bounds_compat(
-        goal: CanonicalTyGoal<'tcx>
+        goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
         NoSolution,
     > {
-        desc { "computing implied outlives bounds for `{}`", goal.value.value }
+        desc { "computing implied outlives bounds for `{}`", goal.canonical.value.value.ty }
     }
 
     query implied_outlives_bounds(
-        goal: CanonicalTyGoal<'tcx>
+        goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
         NoSolution,
     > {
-        desc { "computing implied outlives bounds v2 for `{}`", goal.value.value }
+        desc { "computing implied outlives bounds v2 for `{}`", goal.canonical.value.value.ty }
     }
 
     /// Do not call this query directly:
     /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead.
     query dropck_outlives(
-        goal: CanonicalTyGoal<'tcx>
+        goal: CanonicalDropckOutlivesGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>,
         NoSolution,
     > {
-        desc { "computing dropck types for `{}`", goal.value.value }
+        desc { "computing dropck types for `{}`", goal.canonical.value.value.dropped_ty }
     }
 
     /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
@@ -2082,7 +2083,7 @@ rustc_queries! {
     query evaluate_obligation(
         goal: CanonicalPredicateGoal<'tcx>
     ) -> Result<EvaluationResult, OverflowError> {
-        desc { "evaluating trait selection obligation `{}`", goal.value.value }
+        desc { "evaluating trait selection obligation `{}`", goal.canonical.value.value }
     }
 
     /// Do not call this query directly: part of the `Eq` type-op
@@ -2092,7 +2093,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
         NoSolution,
     > {
-        desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value }
+        desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.canonical.value.value }
     }
 
     /// Do not call this query directly: part of the `ProvePredicate` type-op
@@ -2102,7 +2103,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
         NoSolution,
     > {
-        desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.value.value }
+        desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.canonical.value.value }
     }
 
     /// Do not call this query directly: part of the `Normalize` type-op
@@ -2112,7 +2113,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{}`", goal.value.value.value }
+        desc { "normalizing `{}`", goal.canonical.value.value.value }
     }
 
     /// Do not call this query directly: part of the `Normalize` type-op
@@ -2122,7 +2123,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{:?}`", goal.value.value.value }
+        desc { "normalizing `{:?}`", goal.canonical.value.value.value }
     }
 
     /// Do not call this query directly: part of the `Normalize` type-op
@@ -2132,7 +2133,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{:?}`", goal.value.value.value }
+        desc { "normalizing `{:?}`", goal.canonical.value.value.value }
     }
 
     /// Do not call this query directly: part of the `Normalize` type-op
@@ -2142,7 +2143,7 @@ rustc_queries! {
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>,
         NoSolution,
     > {
-        desc { "normalizing `{:?}`", goal.value.value.value }
+        desc { "normalizing `{:?}`", goal.canonical.value.value.value }
     }
 
     query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool {
@@ -2163,7 +2164,7 @@ rustc_queries! {
     query method_autoderef_steps(
         goal: CanonicalTyGoal<'tcx>
     ) -> MethodAutoderefStepsResult<'tcx> {
-        desc { "computing autoderef types for `{}`", goal.value.value }
+        desc { "computing autoderef types for `{}`", goal.canonical.value.value }
     }
 
     query supported_target_features(_: CrateNum) -> &'tcx UnordMap<String, Option<Symbol>> {
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 81a543e647a..eeed5118592 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -11,16 +11,13 @@ use rustc_span::Span;
 pub use rustc_type_ir::solve::NoSolution;
 
 use crate::error::DropCheckOverflow;
-use crate::infer::canonical::{Canonical, QueryResponse};
+use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse};
 use crate::ty::{self, GenericArg, Ty, TyCtxt};
 
 pub mod type_op {
-    use std::fmt;
-
     use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
 
-    use crate::ty::fold::TypeFoldable;
-    use crate::ty::{Predicate, Ty, TyCtxt, UserType};
+    use crate::ty::{Predicate, Ty, UserType};
 
     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
     pub struct AscribeUserType<'tcx> {
@@ -28,12 +25,6 @@ pub mod type_op {
         pub user_ty: UserType<'tcx>,
     }
 
-    impl<'tcx> AscribeUserType<'tcx> {
-        pub fn new(mir_ty: Ty<'tcx>, user_ty: UserType<'tcx>) -> Self {
-            Self { mir_ty, user_ty }
-        }
-    }
-
     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
     pub struct Eq<'tcx> {
         pub a: Ty<'tcx>,
@@ -51,46 +42,50 @@ pub mod type_op {
         pub predicate: Predicate<'tcx>,
     }
 
-    impl<'tcx> ProvePredicate<'tcx> {
-        pub fn new(predicate: Predicate<'tcx>) -> Self {
-            ProvePredicate { predicate }
-        }
-    }
-
     #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
     pub struct Normalize<T> {
         pub value: T,
     }
 
-    impl<'tcx, T> Normalize<T>
-    where
-        T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>,
-    {
-        pub fn new(value: T) -> Self {
-            Self { value }
-        }
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
+    pub struct ImpliedOutlivesBounds<'tcx> {
+        pub ty: Ty<'tcx>,
+    }
+
+    #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
+    pub struct DropckOutlives<'tcx> {
+        pub dropped_ty: Ty<'tcx>,
     }
 }
 
-pub type CanonicalAliasGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
+pub type CanonicalAliasGoal<'tcx> =
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
 
-pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
+pub type CanonicalTyGoal<'tcx> = CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
 
-pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
+pub type CanonicalPredicateGoal<'tcx> =
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
 
 pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>;
 
-pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
+pub type CanonicalTypeOpEqGoal<'tcx> =
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>;
 
 pub type CanonicalTypeOpSubtypeGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>;
 
 pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>;
 
 pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
-    Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
+
+pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
+
+pub type CanonicalDropckOutlivesGoal<'tcx> =
+    CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DropckOutlives<'tcx>>>;
 
 #[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)]
 pub struct DropckOutlivesResult<'tcx> {
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 0bf9d7b9249..23634d35c07 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -83,8 +83,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
 
         let (max_universe, variables) = canonicalizer.finalize();
 
-        let defining_opaque_types = delegate.defining_opaque_types();
-        Canonical { defining_opaque_types, max_universe, variables, value }
+        Canonical { max_universe, variables, value }
     }
 
     fn get_or_insert_bound_var(
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 6a3d58b5906..76d5f0ea07b 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -17,7 +17,7 @@ pub trait SolverDelegate:
     fn build_with_canonical<V>(
         cx: Self::Interner,
         solver_mode: SolverMode,
-        canonical: &ty::Canonical<Self::Interner, V>,
+        canonical: &ty::CanonicalQueryInput<Self::Interner, V>,
     ) -> (Self, V, ty::CanonicalVarValues<Self::Interner>)
     where
         V: TypeFoldable<Self::Interner>;
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index fdefec33eeb..f49f3a1a3bf 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -60,7 +60,7 @@ where
             (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
 
         let mut orig_values = Default::default();
-        let canonical_goal = Canonicalizer::canonicalize(
+        let canonical = Canonicalizer::canonicalize(
             self.delegate,
             CanonicalizeMode::Input,
             &mut orig_values,
@@ -71,7 +71,11 @@ where
                     .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),
             },
         );
-        (orig_values, canonical_goal)
+        let query_input = ty::CanonicalQueryInput {
+            canonical,
+            defining_opaque_types: self.delegate.defining_opaque_types(),
+        };
+        (orig_values, query_input)
     }
 
     /// To return the constraints of a canonical query to the caller, we canonicalize:
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 0f8b796d602..cbefc826fb7 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -283,11 +283,11 @@ where
 
         let mut ecx = EvalCtxt {
             delegate,
-            variables: canonical_input.variables,
+            variables: canonical_input.canonical.variables,
             var_values,
             is_normalizes_to_goal: false,
             predefined_opaques_in_body: input.predefined_opaques_in_body,
-            max_input_universe: canonical_input.max_universe,
+            max_input_universe: canonical_input.canonical.max_universe,
             search_graph,
             nested_goals: NestedGoals::new(),
             tainted: Ok(()),
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 8fe39bb4ee1..ff91fa13fd0 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -313,6 +313,5 @@ fn response_no_constraints_raw<I: Interner>(
             external_constraints: cx.mk_external_constraints(ExternalConstraintsData::default()),
             certainty,
         },
-        defining_opaque_types: Default::default(),
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
index 0e3f179b0c8..843200ca184 100644
--- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
@@ -96,14 +96,19 @@ where
     }
 
     fn step_is_coinductive(cx: I, input: CanonicalInput<I>) -> bool {
-        input.value.goal.predicate.is_coinductive(cx)
+        input.canonical.value.goal.predicate.is_coinductive(cx)
     }
 }
 
 fn response_no_constraints<I: Interner>(
     cx: I,
-    goal: CanonicalInput<I>,
+    input: CanonicalInput<I>,
     certainty: Certainty,
 ) -> QueryResult<I> {
-    Ok(super::response_no_constraints_raw(cx, goal.max_universe, goal.variables, certainty))
+    Ok(super::response_no_constraints_raw(
+        cx,
+        input.canonical.max_universe,
+        input.canonical.variables,
+        certainty,
+    ))
 }
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 3080a0c9892..e36055e8575 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -184,11 +184,11 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
 
             // If the extern crate isn't in the extern prelude,
             // there is no way it can be written as a `use`.
-            if !self
+            if self
                 .r
                 .extern_prelude
                 .get(&extern_crate.ident)
-                .is_some_and(|entry| !entry.introduced_by_item)
+                .is_none_or(|entry| entry.introduced_by_item)
             {
                 continue;
             }
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
index 70e8bf633a9..398af96127b 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -24,6 +24,7 @@ pub(crate) fn target() -> Target {
                 | SanitizerSet::LEAK
                 | SanitizerSet::MEMORY
                 | SanitizerSet::THREAD,
+            direct_access_external_data: Some(false),
             ..base::linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
index 90bcd9a45cf..73d7f0ce4d0 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
@@ -22,6 +22,7 @@ pub(crate) fn target() -> Target {
                 | SanitizerSet::LEAK
                 | SanitizerSet::MEMORY
                 | SanitizerSet::THREAD,
+            direct_access_external_data: Some(false),
             ..base::linux_ohos::opts()
         },
     }
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index f232a896f96..bacb3b1b1b8 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -5,7 +5,9 @@ use rustc_hir::lang_items::LangItem;
 pub use rustc_infer::infer::*;
 use rustc_macros::extension;
 use rustc_middle::arena::ArenaAllocatable;
-use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
+use rustc_middle::infer::canonical::{
+    Canonical, CanonicalQueryInput, CanonicalQueryResponse, QueryResponse,
+};
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
 use rustc_span::DUMMY_SP;
@@ -132,7 +134,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     /// `K: TypeFoldable<TyCtxt<'tcx>>`.)
     fn enter_canonical_trait_query<K, R>(
         self,
-        canonical_key: &Canonical<'tcx, K>,
+        canonical_key: &CanonicalQueryInput<'tcx, K>,
         operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
     ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
     where
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index df9ac2b80fd..62f56beb34b 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::canonical::{
-    Canonical, CanonicalExt as _, CanonicalVarInfo, CanonicalVarValues,
+    Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
 };
 use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::solve::Goal;
@@ -47,7 +47,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     fn build_with_canonical<V>(
         interner: TyCtxt<'tcx>,
         solver_mode: SolverMode,
-        canonical: &Canonical<'tcx, V>,
+        canonical: &CanonicalQueryInput<'tcx, V>,
     ) -> (Self, V, CanonicalVarValues<'tcx>)
     where
         V: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 339e4bf1f22..88c11e55b7a 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_infer::infer::InferOk;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
+use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
 use rustc_macros::extension;
 use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints};
 use rustc_middle::span_bug;
@@ -54,11 +55,12 @@ fn implied_outlives_bounds<'a, 'tcx>(
     assert!(!ty.has_non_region_infer());
 
     let mut canonical_var_values = OriginalQueryValues::default();
-    let canonical_ty = infcx.canonicalize_query(param_env.and(ty), &mut canonical_var_values);
+    let input = ImpliedOutlivesBounds { ty };
+    let canonical = infcx.canonicalize_query(param_env.and(input), &mut canonical_var_values);
     let implied_bounds_result = if compat {
-        infcx.tcx.implied_outlives_bounds_compat(canonical_ty)
+        infcx.tcx.implied_outlives_bounds_compat(canonical)
     } else {
-        infcx.tcx.implied_outlives_bounds(canonical_ty)
+        infcx.tcx.implied_outlives_bounds(canonical)
     };
     let Ok(canonical_result) = implied_bounds_result else {
         return vec![];
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index c70fe13fc69..4ff0910c9b9 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -1,4 +1,5 @@
 use rustc_data_structures::fx::FxHashSet;
+use rustc_infer::traits::query::type_op::DropckOutlives;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::{DUMMY_SP, Span};
@@ -88,10 +89,10 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
 
 pub fn compute_dropck_outlives_inner<'tcx>(
     ocx: &ObligationCtxt<'_, 'tcx>,
-    goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
+    goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
 ) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
     let tcx = ocx.infcx.tcx;
-    let ParamEnvAnd { param_env, value: for_ty } = goal;
+    let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
 
     let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
 
@@ -99,7 +100,7 @@ pub fn compute_dropck_outlives_inner<'tcx>(
     // something from the stack and invoke
     // `dtorck_constraint_for_ty_inner`. This may produce new types that
     // have to be pushed on the stack. This continues until we have explored
-    // all the reachable types from the type `for_ty`.
+    // all the reachable types from the type `dropped_ty`.
     //
     // Example: Imagine that we have the following code:
     //
@@ -129,7 +130,7 @@ pub fn compute_dropck_outlives_inner<'tcx>(
     // lead to us trying to push `A` a second time -- to prevent
     // infinite recursion, we notice that `A` was already pushed
     // once and stop.
-    let mut ty_stack = vec![(for_ty, 0)];
+    let mut ty_stack = vec![(dropped_ty, 0)];
 
     // Set used to detect infinite recursion.
     let mut ty_set = FxHashSet::default();
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index c84c3147a38..dc3f5544613 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, User
 use rustc_span::{DUMMY_SP, Span};
 use tracing::{debug, instrument};
 
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
 use crate::traits::ObligationCtxt;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
@@ -22,7 +22,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
 
     fn perform_query(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_ascribe_user_type(canonicalized)
     }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index bab038af9ed..dfd0cab6905 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,7 +1,7 @@
-use rustc_infer::infer::canonical::Canonical;
+use rustc_infer::infer::canonical::CanonicalQueryInput;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::traits::query::OutlivesBound;
-use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
+use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
 use rustc_middle::infer::canonical::CanonicalQueryResponse;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt};
@@ -14,11 +14,6 @@ use tracing::debug;
 use crate::traits::query::NoSolution;
 use crate::traits::{ObligationCtxt, wf};
 
-#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
-pub struct ImpliedOutlivesBounds<'tcx> {
-    pub ty: Ty<'tcx>,
-}
-
 impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
     type QueryResponse = Vec<OutlivesBound<'tcx>>;
 
@@ -38,16 +33,8 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
 
     fn perform_query(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
-        // FIXME this `unchecked_map` is only necessary because the
-        // query is defined as taking a `ParamEnvAnd<Ty>`; it should
-        // take an `ImpliedOutlivesBounds` instead
-        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
-            let ImpliedOutlivesBounds { ty } = value;
-            param_env.and(ty)
-        });
-
         if tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
             tcx.implied_outlives_bounds(canonicalized)
         } else {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 5ae8c87ec02..a618d96ce95 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -1,7 +1,6 @@
 use std::fmt;
 
 use rustc_errors::ErrorGuaranteed;
-use rustc_infer::infer::canonical::Certainty;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::fold::TypeFoldable;
@@ -9,7 +8,8 @@ use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_span::Span;
 
 use crate::infer::canonical::{
-    Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
+    CanonicalQueryInput, CanonicalQueryResponse, Certainty, OriginalQueryValues,
+    QueryRegionConstraints,
 };
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::{ObligationCause, ObligationCtxt};
@@ -80,7 +80,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
     /// not captured in the return value.
     fn perform_query(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution>;
 
     /// In the new trait solver, we already do caching in the solver itself,
@@ -102,7 +102,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
     ) -> Result<
         (
             Self::QueryResponse,
-            Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
+            Option<CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>>,
             PredicateObligations<'tcx>,
             Certainty,
         ),
@@ -135,7 +135,7 @@ where
     Q: QueryTypeOp<'tcx>,
 {
     type Output = Q::QueryResponse;
-    type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
+    type ErrorInfo = CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Q>>;
 
     fn fully_perform(
         self,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 62d5655922b..94df222932e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -6,7 +6,7 @@ pub use rustc_middle::traits::query::type_op::Normalize;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
 use crate::traits::ObligationCtxt;
 
 impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
@@ -21,7 +21,7 @@ where
 
     fn perform_query(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
         T::type_op_method(tcx, canonicalized)
     }
@@ -40,14 +40,14 @@ pub trait Normalizable<'tcx>:
 {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution>;
 }
 
 impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_ty(canonicalized)
     }
@@ -56,7 +56,7 @@ impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
 impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_clause(canonicalized)
     }
@@ -65,7 +65,7 @@ impl<'tcx> Normalizable<'tcx> for ty::Clause<'tcx> {
 impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_poly_fn_sig(canonicalized)
     }
@@ -74,7 +74,7 @@ impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
 impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> {
     fn type_op_method(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
         tcx.type_op_normalize_fn_sig(canonicalized)
     }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index d891d4ca06f..fa05f901f66 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -1,23 +1,12 @@
-use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
 use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution};
-use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
 use crate::traits::ObligationCtxt;
 use crate::traits::query::dropck_outlives::{
     compute_dropck_outlives_inner, trivial_dropck_outlives,
 };
-
-#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
-pub struct DropckOutlives<'tcx> {
-    dropped_ty: Ty<'tcx>,
-}
-
-impl<'tcx> DropckOutlives<'tcx> {
-    pub fn new(dropped_ty: Ty<'tcx>) -> Self {
-        DropckOutlives { dropped_ty }
-    }
-}
+use crate::traits::query::type_op::DropckOutlives;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
     type QueryResponse = DropckOutlivesResult<'tcx>;
@@ -31,16 +20,8 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
 
     fn perform_query(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
-        // FIXME convert to the type expected by the `dropck_outlives`
-        // query. This should eventually be fixed by changing the
-        // *underlying query*.
-        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
-            let DropckOutlives { dropped_ty } = value;
-            param_env.and(dropped_ty)
-        });
-
         tcx.dropck_outlives(canonicalized)
     }
 
@@ -48,6 +29,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
         ocx: &ObligationCtxt<'_, 'tcx>,
         key: ParamEnvAnd<'tcx, Self>,
     ) -> Result<Self::QueryResponse, NoSolution> {
-        compute_dropck_outlives_inner(ocx, key.param_env.and(key.value.dropped_ty))
+        compute_dropck_outlives_inner(ocx, key.param_env.and(key.value))
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 7cdb9ee691e..b2dab379262 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -5,7 +5,7 @@ use rustc_middle::traits::query::NoSolution;
 pub use rustc_middle::traits::query::type_op::ProvePredicate;
 use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
 
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
 use crate::traits::ObligationCtxt;
 
 impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
@@ -49,7 +49,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
 
     fn perform_query(
         tcx: TyCtxt<'tcx>,
-        canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
     ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
         tcx.type_op_prove_predicate(canonicalized)
     }
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 0d052ecf0df..4e5309eea28 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -10,7 +10,7 @@ use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::dropck_outlives::{
     compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
 };
-use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
+use rustc_trait_selection::traits::query::{CanonicalDropckOutlivesGoal, NoSolution};
 use tracing::debug;
 
 pub(crate) fn provide(p: &mut Providers) {
@@ -19,7 +19,7 @@ pub(crate) fn provide(p: &mut Providers) {
 
 fn dropck_outlives<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonical_goal: CanonicalTyGoal<'tcx>,
+    canonical_goal: CanonicalDropckOutlivesGoal<'tcx>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> {
     debug!("dropck_outlives(goal={:#?})", canonical_goal);
 
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index f9e1db567c2..a51eefd908c 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -5,13 +5,14 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::infer::canonical::{self, Canonical};
 use rustc_infer::traits::query::OutlivesBound;
+use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::{
     compute_implied_outlives_bounds_compat_inner, compute_implied_outlives_bounds_inner,
 };
-use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
+use rustc_trait_selection::traits::query::{CanonicalImpliedOutlivesBoundsGoal, NoSolution};
 
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers { implied_outlives_bounds_compat, ..*p };
@@ -20,26 +21,26 @@ pub(crate) fn provide(p: &mut Providers) {
 
 fn implied_outlives_bounds_compat<'tcx>(
     tcx: TyCtxt<'tcx>,
-    goal: CanonicalTyGoal<'tcx>,
+    goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>,
 ) -> Result<
     &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
     NoSolution,
 > {
     tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
-        let (param_env, ty) = key.into_parts();
+        let (param_env, ImpliedOutlivesBounds { ty }) = key.into_parts();
         compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty)
     })
 }
 
 fn implied_outlives_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
-    goal: CanonicalTyGoal<'tcx>,
+    goal: CanonicalImpliedOutlivesBoundsGoal<'tcx>,
 ) -> Result<
     &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
     NoSolution,
 > {
     tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
-        let (param_env, ty) = key.into_parts();
+        let (param_env, ImpliedOutlivesBounds { ty }) = key.into_parts();
         compute_implied_outlives_bounds_inner(ocx, param_env, ty)
     })
 }
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index c982cd66bca..71088a598bb 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -1,7 +1,7 @@
 use std::fmt;
 
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::infer::canonical::{Canonical, QueryResponse};
+use rustc_infer::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse};
 use rustc_middle::query::Providers;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{Clause, FnSig, ParamEnvAnd, PolyFnSig, Ty, TyCtxt, TypeFoldable};
@@ -28,7 +28,7 @@ pub(crate) fn provide(p: &mut Providers) {
 
 fn type_op_ascribe_user_type<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
+    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
         type_op_ascribe_user_type_with_span(ocx, key, None)
@@ -51,35 +51,35 @@ where
 
 fn type_op_normalize_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>,
+    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
 }
 
 fn type_op_normalize_clause<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Clause<'tcx>>>>,
+    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Clause<'tcx>>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Clause<'tcx>>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
 }
 
 fn type_op_normalize_fn_sig<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>,
+    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
 }
 
 fn type_op_normalize_poly_fn_sig<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>,
+    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
 }
 
 fn type_op_prove_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
-    canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
+    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
         type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy());
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index d609e5add14..07cb8b037ec 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -10,6 +10,18 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
 use crate::inherent::*;
 use crate::{self as ty, Interner, UniverseIndex};
 
+#[derive_where(Clone; I: Interner, V: Clone)]
+#[derive_where(Hash; I: Interner, V: Hash)]
+#[derive_where(PartialEq; I: Interner, V: PartialEq)]
+#[derive_where(Eq; I: Interner, V: Eq)]
+#[derive_where(Debug; I: Interner, V: fmt::Debug)]
+#[derive_where(Copy; I: Interner, V: Copy)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
+pub struct CanonicalQueryInput<I: Interner, V> {
+    pub canonical: Canonical<I, V>,
+    pub defining_opaque_types: I::DefiningOpaqueTypes,
+}
+
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
@@ -24,8 +36,6 @@ use crate::{self as ty, Interner, UniverseIndex};
 pub struct Canonical<I: Interner, V> {
     pub value: V,
     pub max_universe: UniverseIndex,
-    // FIXME(lcnr, oli-obk): try moving this into the query inputs instead
-    pub defining_opaque_types: I::DefiningOpaqueTypes,
     pub variables: I::CanonicalVars,
 }
 
@@ -54,27 +64,17 @@ impl<I: Interner, V> Canonical<I, V> {
     /// let b: Canonical<I, (T, Ty<I>)> = a.unchecked_map(|v| (v, ty));
     /// ```
     pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<I, W> {
-        let Canonical { defining_opaque_types, max_universe, variables, value } = self;
-        Canonical { defining_opaque_types, max_universe, variables, value: map_op(value) }
-    }
-
-    /// Allows you to map the `value` of a canonical while keeping the same set of
-    /// bound variables.
-    ///
-    /// **WARNING:** This function is very easy to mis-use, hence the name! See
-    /// the comment of [Canonical::unchecked_map] for more details.
-    pub fn unchecked_rebind<W>(self, value: W) -> Canonical<I, W> {
-        let Canonical { defining_opaque_types, max_universe, variables, value: _ } = self;
-        Canonical { defining_opaque_types, max_universe, variables, value }
+        let Canonical { max_universe, variables, value } = self;
+        Canonical { max_universe, variables, value: map_op(value) }
     }
 }
 
 impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self { value, max_universe, variables, defining_opaque_types } = self;
+        let Self { value, max_universe, variables } = self;
         write!(
             f,
-            "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?}, defining_opaque_types: {defining_opaque_types:?} }}",
+            "Canonical {{ value: {value}, max_universe: {max_universe:?}, variables: {variables:?} }}",
         )
     }
 }
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index f4fb03562de..3fd2bb61ba5 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -714,7 +714,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
                 // current goal is already part of the same cycle. This check could be
                 // improved but seems to be good enough for now.
                 let last = self.stack.raw.last().unwrap();
-                if !last.heads.opt_lowest_cycle_head().is_some_and(|lowest| lowest <= head) {
+                if last.heads.opt_lowest_cycle_head().is_none_or(|lowest| lowest > head) {
                     continue;
                 }
             }
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index f02c7a32071..b3f8390bbf0 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -71,7 +71,8 @@ pub enum SolverMode {
     Coherence,
 }
 
-pub type CanonicalInput<I, T = <I as Interner>::Predicate> = Canonical<I, QueryInput<I, T>>;
+pub type CanonicalInput<I, T = <I as Interner>::Predicate> =
+    ty::CanonicalQueryInput<I, QueryInput<I, T>>;
 pub type CanonicalResponse<I> = Canonical<I, Response<I>>;
 /// The result of evaluating a canonical query.
 ///
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 77e7d83090b..0130f2ce517 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -672,12 +672,12 @@ impl FromClean<clean::Trait> for Trait {
         let tcx = renderer.tcx;
         let is_auto = trait_.is_auto(tcx);
         let is_unsafe = trait_.safety(tcx) == rustc_hir::Safety::Unsafe;
-        let is_object_safe = trait_.is_dyn_compatible(tcx);
+        let is_dyn_compatible = trait_.is_dyn_compatible(tcx);
         let clean::Trait { items, generics, bounds, .. } = trait_;
         Trait {
             is_auto,
             is_unsafe,
-            is_object_safe,
+            is_dyn_compatible,
             items: renderer.ids(items),
             generics: generics.into_json(renderer),
             bounds: bounds.into_json(renderer),
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index fc64bc98bb9..b0bedab495f 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
 /// This integer is incremented with every breaking change to the API,
 /// and is returned along with the JSON blob as [`Crate::format_version`].
 /// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 35;
+pub const FORMAT_VERSION: u32 = 36;
 
 /// The root of the emitted JSON blob.
 ///
@@ -1082,8 +1082,11 @@ pub struct Trait {
     pub is_auto: bool,
     /// Whether the trait is marked as `unsafe`.
     pub is_unsafe: bool,
-    /// Whether the trait is [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety).
-    pub is_object_safe: bool,
+    // FIXME(dyn_compat_renaming): Update the URL once the Reference is updated and hits stable.
+    /// Whether the trait is [dyn compatible](https://doc.rust-lang.org/reference/items/traits.html#object-safety)[^1].
+    ///
+    /// [^1]: Formerly known as "object safe".
+    pub is_dyn_compatible: bool,
     /// Associated [`Item`]s that can/must be implemented by the `impl` blocks.
     pub items: Vec<Id>,
     /// Information about the type parameters and `where` clauses of the trait.
diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs
index 7de224b92d8..4dab499a8a5 100644
--- a/tests/codegen/iter-repeat-n-trivial-drop.rs
+++ b/tests/codegen/iter-repeat-n-trivial-drop.rs
@@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
 #[no_mangle]
 // CHECK-LABEL: @vec_extend_via_iter_repeat_n
 pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
-    // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef 1234, i64 noundef 1)
+    // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1)
     // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,
 
     let n = 1234_usize;
diff --git a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
index ae445ad9b91..5fc77f95eaf 100644
--- a/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/address_of.address_of_reborrow.SimplifyCfg-initial.after.mir
@@ -1,36 +1,36 @@
 // MIR for `address_of_reborrow` after SimplifyCfg-initial
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
-| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
-| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
-| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
-| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
-| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
-| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
-| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
-| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
-| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
-| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
-| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
-| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
-| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
-| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
-| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
-| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
-| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
-| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
-| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
-| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
-| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
-| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
-| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
-| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
-| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
-| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
-| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
-| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
-| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
+| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
+| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
+| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
+| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
+| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
+| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
+| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
+| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
+| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
+| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
+| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
+| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
+| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
+| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
+| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
+| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
+| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
+| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
+| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
+| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
+| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
+| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
+| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
+| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
+| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
+| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
+| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
+| 27: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
+| 28: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
+| 29: user_ty: Canonical { value: Ty(*mut [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:37:12: 37:22, inferred_ty: *mut [i32]
 |
 fn address_of_reborrow() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index d4f0363e443..b9d26c67538 100644
--- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after SimplifyCfg-initial
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
-| 1: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
+| 0: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
+| 1: user_ty: Canonical { value: Ty(std::option::Option<std::boxed::Box<u32>>), max_universe: U0, variables: [] }, span: $DIR/basic_assignment.rs:38:17: 38:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir
index 34e5bedf4ce..dd1d093c4db 100644
--- a/tests/mir-opt/building/issue_101867.main.built.after.mir
+++ b/tests/mir-opt/building/issue_101867.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
-| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
+| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
+| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
index be972b62cbd..6e349a2a24f 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
+++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
@@ -1,10 +1,10 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
-| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], defining_opaque_types: [] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
+| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
+| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_72181_1.main.built.after.mir b/tests/mir-opt/issue_72181_1.main.built.after.mir
index 293aa37944d..79eaf966833 100644
--- a/tests/mir-opt/issue_72181_1.main.built.after.mir
+++ b/tests/mir-opt/issue_72181_1.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
-| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
+| 0: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
+| 1: user_ty: Canonical { value: Ty(Void), max_universe: U0, variables: [] }, span: $DIR/issue_72181_1.rs:17:12: 17:16, inferred_ty: Void
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
index 161c73529f5..48a399eb39c 100644
--- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
index 161c73529f5..48a399eb39c 100644
--- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir
+++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/rustdoc-json/traits/is_dyn_compatible.rs b/tests/rustdoc-json/traits/is_dyn_compatible.rs
new file mode 100644
index 00000000000..bccf94d17d6
--- /dev/null
+++ b/tests/rustdoc-json/traits/is_dyn_compatible.rs
@@ -0,0 +1,19 @@
+#![no_std]
+
+//@ has "$.index[*][?(@.name=='FooDynIncompatible')]"
+//@ is "$.index[*][?(@.name=='FooDynIncompatible')].inner.trait.is_dyn_compatible" false
+pub trait FooDynIncompatible {
+    fn foo() -> Self;
+}
+
+//@ has "$.index[*][?(@.name=='BarDynIncompatible')]"
+//@ is "$.index[*][?(@.name=='BarDynIncompatible')].inner.trait.is_dyn_compatible" false
+pub trait BarDynIncompatible<T> {
+    fn foo(i: T);
+}
+
+//@ has "$.index[*][?(@.name=='FooDynCompatible')]"
+//@ is "$.index[*][?(@.name=='FooDynCompatible')].inner.trait.is_dyn_compatible" true
+pub trait FooDynCompatible {
+    fn foo(&self);
+}
diff --git a/tests/rustdoc-json/traits/is_object_safe.rs b/tests/rustdoc-json/traits/is_object_safe.rs
deleted file mode 100644
index 35c4e4eb847..00000000000
--- a/tests/rustdoc-json/traits/is_object_safe.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-#![no_std]
-
-//@ has "$.index[*][?(@.name=='FooUnsafe')]"
-//@ is "$.index[*][?(@.name=='FooUnsafe')].inner.trait.is_object_safe" false
-pub trait FooUnsafe {
-    fn foo() -> Self;
-}
-
-//@ has "$.index[*][?(@.name=='BarUnsafe')]"
-//@ is "$.index[*][?(@.name=='BarUnsafe')].inner.trait.is_object_safe" false
-pub trait BarUnsafe<T> {
-    fn foo(i: T);
-}
-
-//@ has "$.index[*][?(@.name=='FooSafe')]"
-//@ is "$.index[*][?(@.name=='FooSafe')].inner.trait.is_object_safe" true
-pub trait FooSafe {
-    fn foo(&self);
-}
diff --git a/tests/ui/coherence/coherence-cow.re_a.stderr b/tests/ui/coherence/coherence-cow.re_a.stderr
index 0bc017817b6..67de3629491 100644
--- a/tests/ui/coherence/coherence-cow.re_a.stderr
+++ b/tests/ui/coherence/coherence-cow.re_a.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T> Remote for Pair<T,Cover<T>> { }
    | ^^^^^^^^^^^^^^^^^^^----------------
-   | |                  |
-   | |                  `Pair` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                    |
+   |                    `Pair` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-cow.re_b.stderr b/tests/ui/coherence/coherence-cow.re_b.stderr
index 9bdb49dcc04..360900cc7ff 100644
--- a/tests/ui/coherence/coherence-cow.re_b.stderr
+++ b/tests/ui/coherence/coherence-cow.re_b.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T> Remote for Pair<Cover<T>,T> { }
    | ^^^^^^^^^^^^^^^^^^^----------------
-   | |                  |
-   | |                  `Pair` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                    |
+   |                    `Pair` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-cow.re_c.stderr b/tests/ui/coherence/coherence-cow.re_c.stderr
index dfff2667ebb..73f2aa196fd 100644
--- a/tests/ui/coherence/coherence-cow.re_c.stderr
+++ b/tests/ui/coherence/coherence-cow.re_c.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T,U> Remote for Pair<Cover<T>,U> { }
    | ^^^^^^^^^^^^^^^^^^^^^----------------
-   | |                    |
-   | |                    `Pair` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      `Pair` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr
index db6a9474804..ca43d70e0b1 100644
--- a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr
+++ b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Misc for dyn Fundamental<Local> {}
    | ^^^^^^^^^^^^^^----------------------
-   | |             |
-   | |             `dyn Fundamental<Local>` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |               |
+   |               `dyn Fundamental<Local>` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
index ea38afc40ce..77d1bdee5ac 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -39,10 +39,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl !Send for dyn Marker2 {}
    | ^^^^^^^^^^^^^^^-----------
-   | |              |
-   | |              `dyn Marker2` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                `dyn Marker2` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
index 2a8713bc327..f38aeaed0aa 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
@@ -39,10 +39,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | unsafe impl Send for dyn Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^-----------
-   | |                    |
-   | |                    `dyn Marker2` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      `dyn Marker2` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)`
diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr
index f529a056b0f..79fe044c4cf 100644
--- a/tests/ui/coherence/coherence-impls-copy.stderr
+++ b/tests/ui/coherence/coherence-impls-copy.stderr
@@ -13,10 +13,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Copy for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^------------------
-   | |             |
-   | |             this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
+   |               |
+   |               this is not defined in the current crate because slices are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for primitive types
@@ -24,10 +25,11 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Copy for i32 {}
    | ^^^^^^^^^^^^^^---
-   | |             |
-   | |             `i32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |               |
+   |               `i32` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0206]: the trait `Copy` cannot be implemented for this type
@@ -41,10 +43,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Copy for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^----------------
-   | |             |
-   | |             this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |               |
+   |               this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0206]: the trait `Copy` cannot be implemented for this type
@@ -58,10 +61,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Copy for [MyType] {}
    | ^^^^^^^^^^^^^^--------
-   | |             |
-   | |             this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
+   |               |
+   |               this is not defined in the current crate because slices are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0206]: the trait `Copy` cannot be implemented for this type
diff --git a/tests/ui/coherence/coherence-impls-send.stderr b/tests/ui/coherence/coherence-impls-send.stderr
index e1071846e14..78e89eb5540 100644
--- a/tests/ui/coherence/coherence-impls-send.stderr
+++ b/tests/ui/coherence/coherence-impls-send.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | unsafe impl Send for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^^^^^^^------------------
-   | |                    |
-   | |                    this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      this is not defined in the current crate because slices are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
@@ -14,10 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | unsafe impl Send for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^^^^^^^^----------------
-   | |                    |
-   | |                    this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `&'static NotSync`
@@ -31,10 +33,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | unsafe impl Send for [MyType] {}
    | ^^^^^^^^^^^^^^^^^^^^^--------
-   | |                    |
-   | |                    this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      this is not defined in the current crate because slices are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/coherence/coherence-impls-sized.stderr b/tests/ui/coherence/coherence-impls-sized.stderr
index 17a7544521d..3201f1b25de 100644
--- a/tests/ui/coherence/coherence-impls-sized.stderr
+++ b/tests/ui/coherence/coherence-impls-sized.stderr
@@ -21,10 +21,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Sized for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^^----------------
-   | |              |
-   | |              this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0322]: explicit impls for the `Sized` trait are not permitted
@@ -44,10 +45,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Sized for [MyType] {}
    | ^^^^^^^^^^^^^^^--------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                this is not defined in the current crate because slices are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0322]: explicit impls for the `Sized` trait are not permitted
@@ -61,10 +63,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Sized for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^------------------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                this is not defined in the current crate because slices are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 9 previous errors
diff --git a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr
index 2295d6315d1..074cd87ba92 100644
--- a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr
+++ b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl !Copy for str {}
    | ^^^^^^^^^^^^^^^---
-   | |              |
-   | |              `str` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                `str` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
@@ -14,10 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl !Copy for fn() {}
    | ^^^^^^^^^^^^^^^----
-   | |              |
-   | |              `fn()` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                `fn()` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
@@ -25,10 +27,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl !Copy for () {}
    | ^^^^^^^^^^^^^^^--
-   | |              |
-   | |              this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr
index f6ffae34290..dcf423e24ee 100644
--- a/tests/ui/coherence/coherence-orphan.stderr
+++ b/tests/ui/coherence/coherence-orphan.stderr
@@ -3,11 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl TheTrait<usize> for isize {}
    | ^^^^^---------------^^^^^-----
-   | |    |                   |
-   | |    |                   `isize` is not defined in the current crate
-   | |    `usize` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |                   |
+   |      |                   `isize` is not defined in the current crate
+   |      `usize` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
@@ -15,10 +16,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl !Send for Vec<isize> {}
    | ^^^^^^^^^^^^^^^----------
-   | |              |
-   | |              `Vec` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                |
+   |                `Vec` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/coherence/coherence-overlapping-pairs.stderr b/tests/ui/coherence/coherence-overlapping-pairs.stderr
index 4d0a9c6ee14..6e7a90ac369 100644
--- a/tests/ui/coherence/coherence-overlapping-pairs.stderr
+++ b/tests/ui/coherence/coherence-overlapping-pairs.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T> Remote for lib::Pair<T,Foo> { }
    | ^^^^^^^^^^^^^^^^^^^----------------
-   | |                  |
-   | |                  `Pair` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                    |
+   |                    `Pair` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr
index 15cd66e9d09..d7890d156ca 100644
--- a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr
+++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr
@@ -3,11 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
    | ^^^^^^^^^^^--------------------------^^^^^---
-   | |          |                              |
-   | |          |                              `i32` is not defined in the current crate
-   | |          `Pair` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |            |                              |
+   |            |                              `i32` is not defined in the current crate
+   |            `Pair` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr
index 359dbe8509d..fa3d170f81d 100644
--- a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr
+++ b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T,U> Remote for Pair<T,Local<U>> { }
    | ^^^^^^^^^^^^^^^^^^^^^----------------
-   | |                    |
-   | |                    `Pair` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      `Pair` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-vec-local-2.stderr b/tests/ui/coherence/coherence-vec-local-2.stderr
index e4249710d00..cb12275cf01 100644
--- a/tests/ui/coherence/coherence-vec-local-2.stderr
+++ b/tests/ui/coherence/coherence-vec-local-2.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T> Remote for Vec<Local<T>> { }
    | ^^^^^^^^^^^^^^^^^^^-------------
-   | |                  |
-   | |                  `Vec` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                    |
+   |                    `Vec` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-vec-local.stderr b/tests/ui/coherence/coherence-vec-local.stderr
index c465fb1966e..9278b9458d5 100644
--- a/tests/ui/coherence/coherence-vec-local.stderr
+++ b/tests/ui/coherence/coherence-vec-local.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl Remote for Vec<Local> { }
    | ^^^^^^^^^^^^^^^^----------
-   | |               |
-   | |               `Vec` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                 |
+   |                 `Vec` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence_local_err_struct.stderr b/tests/ui/coherence/coherence_local_err_struct.stderr
index 96572b5a716..280dd57bd42 100644
--- a/tests/ui/coherence/coherence_local_err_struct.stderr
+++ b/tests/ui/coherence/coherence_local_err_struct.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
    | ^^^^^^^^^^^^^^^^^^^^^---------------------
-   | |                    |
-   | |                    `MyStruct` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      `MyStruct` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence_local_err_tuple.stderr b/tests/ui/coherence/coherence_local_err_tuple.stderr
index 85a063bb34a..d07adab0014 100644
--- a/tests/ui/coherence/coherence_local_err_tuple.stderr
+++ b/tests/ui/coherence/coherence_local_err_tuple.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl lib::MyCopy for (MyType,) { }
    | ^^^^^^^^^^^^^^^^^^^^^---------
-   | |                    |
-   | |                    this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/impl-foreign-for-foreign.stderr b/tests/ui/coherence/impl-foreign-for-foreign.stderr
index 6c74b47a1c4..4ff965290c8 100644
--- a/tests/ui/coherence/impl-foreign-for-foreign.stderr
+++ b/tests/ui/coherence/impl-foreign-for-foreign.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Remote for i32 {
    | ^^^^^^^^^^^^^^^^---
-   | |               |
-   | |               `i32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                 |
+   |                 `i32` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr
index e24537bce22..ce5376f98cb 100644
--- a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr
+++ b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr
@@ -3,11 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Remote1<Rc<i32>> for i32 {
    | ^^^^^----------------^^^^^---
-   | |    |                    |
-   | |    |                    `i32` is not defined in the current crate
-   | |    `Rc` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |                    |
+   |      |                    `i32` is not defined in the current crate
+   |      `Rc` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for primitive types
@@ -15,11 +16,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Remote1<Rc<Local>> for f64 {
    | ^^^^^------------------^^^^^---
-   | |    |                      |
-   | |    |                      `f64` is not defined in the current crate
-   | |    `Rc` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |                      |
+   |      |                      `f64` is not defined in the current crate
+   |      `Rc` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for primitive types
@@ -27,11 +29,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl<T> Remote1<Rc<T>> for f32 {
    | ^^^^^^^^--------------^^^^^---
-   | |       |                  |
-   | |       |                  `f32` is not defined in the current crate
-   | |       `Rc` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |         |                  |
+   |         |                  `f32` is not defined in the current crate
+   |         `Rc` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
index 55ea4409e6f..596f8436567 100644
--- a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
+++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr
@@ -3,11 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl Remote for Box<i32> {
    | ^^^^^------^^^^^--------
-   | |    |          |
-   | |    |          `i32` is not defined in the current crate
-   | |    `std::alloc::Global` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |          |
+   |      |          `i32` is not defined in the current crate
+   |      `std::alloc::Global` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
@@ -15,11 +16,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T> Remote for Box<Rc<T>> {
    | ^^^^^^^^------^^^^^----------
-   | |       |          |
-   | |       |          `Rc` is not defined in the current crate
-   | |       `std::alloc::Global` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |         |          |
+   |         |          `Rc` is not defined in the current crate
+   |         `std::alloc::Global` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr
index fe8a34b78cf..d9dd2b8a8c6 100644
--- a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr
+++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr
@@ -3,11 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Remote1<u32> for f64 {
    | ^^^^^------------^^^^^---
-   | |    |                |
-   | |    |                `f64` is not defined in the current crate
-   | |    `u32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |                |
+   |      |                `f64` is not defined in the current crate
+   |      `u32` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
index 8e77c13e111..91f1886142c 100644
--- a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
+++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr
@@ -3,12 +3,13 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Remote1<Box<String>> for i32 {
    | ^^^^^--------------------^^^^^---
-   | |    |                        |
-   | |    |                        `i32` is not defined in the current crate
-   | |    `String` is not defined in the current crate
-   | |    `std::alloc::Global` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |                        |
+   |      |                        `i32` is not defined in the current crate
+   |      `String` is not defined in the current crate
+   |      `std::alloc::Global` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for primitive types
@@ -16,12 +17,13 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Remote1<Box<Rc<i32>>> for f64 {
    | ^^^^^---------------------^^^^^---
-   | |    |                         |
-   | |    |                         `f64` is not defined in the current crate
-   | |    `Rc` is not defined in the current crate
-   | |    `std::alloc::Global` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |      |                         |
+   |      |                         `f64` is not defined in the current crate
+   |      `Rc` is not defined in the current crate
+   |      `std::alloc::Global` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for primitive types
@@ -29,12 +31,13 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl<T> Remote1<Box<Rc<T>>> for f32 {
    | ^^^^^^^^-------------------^^^^^---
-   | |       |                       |
-   | |       |                       `f32` is not defined in the current crate
-   | |       `Rc` is not defined in the current crate
-   | |       `std::alloc::Global` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |         |                       |
+   |         |                       `f32` is not defined in the current crate
+   |         `Rc` is not defined in the current crate
+   |         `std::alloc::Global` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
index 92346c29198..306a5d1610d 100644
--- a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
+++ b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl Remote for Rc<Local> {
    | ^^^^^^^^^^^^^^^^---------
-   | |               |
-   | |               `Rc` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                 |
+   |                 `Rc` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
@@ -14,10 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl<T> Remote for Arc<T> {
    | ^^^^^^^^^^^^^^^^^^^------
-   | |                  |
-   | |                  `Arc` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                    |
+   |                    `Arc` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/dropck/drop-on-non-struct.stderr b/tests/ui/dropck/drop-on-non-struct.stderr
index e8fbe5e9726..9495642e45e 100644
--- a/tests/ui/dropck/drop-on-non-struct.stderr
+++ b/tests/ui/dropck/drop-on-non-struct.stderr
@@ -9,10 +9,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl<'a> Drop for &'a mut isize {
    | ^^^^^^^^^^^^^^^^^^-------------
-   | |                 |
-   | |                 `isize` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                   |
+   |                   `isize` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr
index f144aa9f72c..f6e80e59304 100644
--- a/tests/ui/error-codes/E0117.stderr
+++ b/tests/ui/error-codes/E0117.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl Drop for u32 {}
    | ^^^^^^^^^^^^^^---
-   | |             |
-   | |             `u32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |               |
+   |               `u32` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
diff --git a/tests/ui/error-codes/e0119/complex-impl.stderr b/tests/ui/error-codes/e0119/complex-impl.stderr
index c0519c60e42..b7e434c4afe 100644
--- a/tests/ui/error-codes/e0119/complex-impl.stderr
+++ b/tests/ui/error-codes/e0119/complex-impl.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl<R> External for (Q, R) {}
    | ^^^^^^^^^^^^^^^^^^^^^------
-   | |                    |
-   | |                    this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                      |
+   |                      this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs
index 272c6bd3fb7..61f11a88c61 100644
--- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs
+++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs
@@ -5,21 +5,23 @@ use std::{fmt, marker};
 struct LocalType;
 
 impl fmt::Display for *mut LocalType {
-//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
-//~| NOTE impl doesn't use only types from inside the current crate
-//~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign
-//~| NOTE define and implement a trait or new type instead
-//~| HELP consider introducing a new wrapper type
+    //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
+    //~| NOTE impl doesn't have any local type before any uncovered type parameters
+    //~| NOTE for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
+    //~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign
+    //~| NOTE define and implement a trait or new type instead
+    //~| HELP consider introducing a new wrapper type
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "This not compile")
     }
 }
 
 impl<T> marker::Copy for *mut T {
-//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
-//~| NOTE impl doesn't use only types from inside the current crate
-//~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign
-//~| NOTE define and implement a trait or new type instead
+    //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
+    //~| NOTE impl doesn't have any local type before any uncovered type parameters
+    //~| NOTE for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
+    //~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign
+    //~| NOTE define and implement a trait or new type instead
 }
 
 fn main() {}
diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr
index 78d7a47deaa..bd40b059e58 100644
--- a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr
+++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl fmt::Display for *mut LocalType {
    | ^^^^^^^^^^^^^^^^^^^^^^--------------
-   | |                     |
-   | |                     `*mut LocalType` is not defined in the current crate because raw pointers are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                       |
+   |                       `*mut LocalType` is not defined in the current crate because raw pointers are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 help: consider introducing a new wrapper type
    |
@@ -16,14 +17,15 @@ LL ~ impl fmt::Display for WrapperType {
    |
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/issue-99572-impl-trait-on-pointer.rs:18:1
+  --> $DIR/issue-99572-impl-trait-on-pointer.rs:19:1
    |
 LL | impl<T> marker::Copy for *mut T {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^------
-   | |                        |
-   | |                        `*mut T` is not defined in the current crate because raw pointers are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                          |
+   |                          `*mut T` is not defined in the current crate because raw pointers are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr
index 4d7a02a5096..2afa2199a6a 100644
--- a/tests/ui/issues/issue-67535.stderr
+++ b/tests/ui/issues/issue-67535.stderr
@@ -3,11 +3,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl std::ops::AddAssign for () {
    | ^^^^^-------------------^^^^^--
-   | |    |                       |
-   | |    |                       this is not defined in the current crate because tuples are always foreign
-   | |    this is not defined in the current crate because this is a foreign trait
-   | impl doesn't use only types from inside the current crate
+   |      |                       |
+   |      |                       this is not defined in the current crate because tuples are always foreign
+   |      this is not defined in the current crate because this is a foreign trait
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
@@ -15,11 +16,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl std::ops::AddAssign for [(); 1] {
    | ^^^^^-------------------^^^^^-------
-   | |    |                       |
-   | |    |                       this is not defined in the current crate because arrays are always foreign
-   | |    this is not defined in the current crate because this is a foreign trait
-   | impl doesn't use only types from inside the current crate
+   |      |                       |
+   |      |                       this is not defined in the current crate because arrays are always foreign
+   |      this is not defined in the current crate because this is a foreign trait
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
@@ -27,11 +29,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl std::ops::AddAssign for &[u8] {
    | ^^^^^-------------------^^^^^-----
-   | |    |                       |
-   | |    |                       this is not defined in the current crate because slices are always foreign
-   | |    this is not defined in the current crate because this is a foreign trait
-   | impl doesn't use only types from inside the current crate
+   |      |                       |
+   |      |                       this is not defined in the current crate because slices are always foreign
+   |      this is not defined in the current crate because this is a foreign trait
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
index 9c1c8df8da4..cf7af41cd4e 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
@@ -30,11 +30,12 @@ error[E0117]: only traits defined in the current crate can be implemented for pr
    |
 LL | impl const std::ops::Add for i32 {
    | ^^^^^^^^^^^-------------^^^^^---
-   | |          |                 |
-   | |          |                 `i32` is not defined in the current crate
-   | |          `i32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |            |                 |
+   |            |                 `i32` is not defined in the current crate
+   |            `i32` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/type-alias-impl-trait/coherence.classic.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr
index ff059bc5806..98badeef382 100644
--- a/tests/ui/type-alias-impl-trait/coherence.classic.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
-   | |                                    |
-   | |                                    type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
-   | impl doesn't use only types from inside the current crate
+   |                                      |
+   |                                      type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr
index dab2786c1f0..8d718383110 100644
--- a/tests/ui/type-alias-impl-trait/coherence.next.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
-   | |                                    |
-   | |                                    `AliasOfForeignType<()>` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                                      |
+   |                                      `AliasOfForeignType<()>` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr
index 41f42455bde..df56db031ed 100644
--- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr
+++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl Eq for Y {}
    | ^^^^^^^^^^^^-
-   | |           |
-   | |           `(u32) is 1..=` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |             |
+   |             `(u32) is 1..=` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
index 32e6e88fc48..c7d714dcb1a 100644
--- a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
+++ b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
@@ -3,10 +3,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl DefaultedTrait for (A,) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^----
-   | |                       |
-   | |                       this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                         |
+   |                         this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
@@ -14,10 +15,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    |
 LL | impl !DefaultedTrait for (B,) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^----
-   | |                        |
-   | |                        this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
+   |                          |
+   |                          this is not defined in the current crate because tuples are always foreign
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error[E0321]: cross-crate traits with a default impl, like `DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate
@@ -31,10 +33,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ty
    |
 LL | impl DefaultedTrait for lib::Something<C> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^-----------------
-   | |                       |
-   | |                       `Something` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   |                         |
+   |                         `Something` is not defined in the current crate
    |
+   = note: impl doesn't have any local type before any uncovered type parameters
+   = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules
    = note: define and implement a trait or new type instead
 
 error: aborting due to 4 previous errors