diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 001b24c31de..a43330e2d4e 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -374,9 +374,18 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
         }
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
-            ty::Infer(ty::TyVar(vid)) => {
+            ty::Infer(ty::TyVar(mut vid)) => {
+                // We need to canonicalize the *root* of our ty var.
+                // This is so that our canonical response correctly reflects
+                // any equated inference vars correctly!
+                let root_vid = self.infcx.root_var(vid);
+                if root_vid != vid {
+                    t = self.infcx.tcx.mk_ty_var(root_vid);
+                    vid = root_vid;
+                }
+
                 debug!("canonical: type var found with vid {:?}", vid);
                 match self.infcx.probe_ty_var(vid) {
                     // `t` could be a float / int variable; canonicalize that instead.
@@ -467,9 +476,18 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
         }
     }
 
-    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+    fn fold_const(&mut self, mut ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
         match ct.kind() {
-            ty::ConstKind::Infer(InferConst::Var(vid)) => {
+            ty::ConstKind::Infer(InferConst::Var(mut vid)) => {
+                // We need to canonicalize the *root* of our const var.
+                // This is so that our canonical response correctly reflects
+                // any equated inference vars correctly!
+                let root_vid = self.infcx.root_const_var(vid);
+                if root_vid != vid {
+                    ct = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), ct.ty());
+                    vid = root_vid;
+                }
+
                 debug!("canonical: const var found with vid {:?}", vid);
                 match self.infcx.probe_const_var(vid) {
                     Ok(c) => {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index fb067e7ac21..4a2a5557313 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1359,6 +1359,10 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner.borrow_mut().type_variables().root_var(var)
     }
 
+    pub fn root_const_var(&self, var: ty::ConstVid<'tcx>) -> ty::ConstVid<'tcx> {
+        self.inner.borrow_mut().const_unification_table().find(var)
+    }
+
     /// Where possible, replaces type/const variables in
     /// `value` with their final value. Note that region variables
     /// are unaffected. If a type/const variable has not been unified, it
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
index c048d4a2aad..981a8f45e45 100644
--- a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
@@ -261,12 +261,23 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
         self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+    fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> {
         let kind = match *t.kind() {
-            ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
-                Ok(t) => return self.fold_ty(t),
-                Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
-            },
+            ty::Infer(ty::TyVar(mut vid)) => {
+                // We need to canonicalize the *root* of our ty var.
+                // This is so that our canonical response correctly reflects
+                // any equated inference vars correctly!
+                let root_vid = self.infcx.root_var(vid);
+                if root_vid != vid {
+                    t = self.infcx.tcx.mk_ty_var(root_vid);
+                    vid = root_vid;
+                }
+
+                match self.infcx.probe_ty_var(vid) {
+                    Ok(t) => return self.fold_ty(t),
+                    Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
+                }
+            }
             ty::Infer(ty::IntVar(_)) => {
                 let nt = self.infcx.shallow_resolve(t);
                 if nt != t {
@@ -338,13 +349,23 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
         self.interner().mk_bound(self.binder_index, bt)
     }
 
-    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+    fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> {
         let kind = match c.kind() {
-            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid)
-            {
-                Ok(c) => return self.fold_const(c),
-                Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
-            },
+            ty::ConstKind::Infer(ty::InferConst::Var(mut vid)) => {
+                // We need to canonicalize the *root* of our const var.
+                // This is so that our canonical response correctly reflects
+                // any equated inference vars correctly!
+                let root_vid = self.infcx.root_const_var(vid);
+                if root_vid != vid {
+                    c = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), c.ty());
+                    vid = root_vid;
+                }
+
+                match self.infcx.probe_const_var(vid) {
+                    Ok(c) => return self.fold_const(c),
+                    Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
+                }
+            }
             ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
                 bug!("fresh var during canonicalization: {c:?}")
             }
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 57b6a452737..43fd415e871 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -238,6 +238,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             && has_changed
             && !self.in_projection_eq_hack
             && !self.search_graph.in_cycle()
+            && false
         {
             let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
             let canonical_response =
diff --git a/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs
new file mode 100644
index 00000000000..d1c6b1077e8
--- /dev/null
+++ b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs
@@ -0,0 +1,39 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+trait Mirror {
+    type Item;
+}
+
+struct Wrapper<T>(T);
+impl<T> Mirror for Wrapper<T> {
+    type Item = T;
+}
+
+fn mirror<T>()
+where
+    Wrapper<T>: Mirror<Item = i32>,
+{
+}
+
+fn main() {
+    mirror::<_ /* ?0 */>();
+
+    // Solving `<Wrapper<?0> as Mirror>::Item = i32`
+
+    // First, we replace the term with a fresh infer var:
+    // `<Wrapper<?0> as Mirror>::Item = ?1`
+
+    // We select the impl candidate on line #6, which leads us to learn that
+    // `?0 == ?1`.
+
+    // That should be reflected in our canonical response, which should have
+    // `^0 = ^0, ^1 = ^0`
+    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    // !! We used to return a totally unconstrained response here :< !!
+    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+    // Then, during the "equate term" part of the projection solving, we
+    // instantiate the response from the unconstrained projection predicate,
+    // and equate `?0 == i32`.
+}
diff --git a/tests/ui/traits/new-solver/deduce-ty-from-object.rs b/tests/ui/traits/new-solver/deduce-ty-from-object.rs
new file mode 100644
index 00000000000..7398bce7b61
--- /dev/null
+++ b/tests/ui/traits/new-solver/deduce-ty-from-object.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+fn main() {
+    let x: Box<dyn Iterator<Item = ()>> = Box::new(std::iter::empty());
+}