the .eq() in instantiate_normalizes_to_term may fail
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs
index 3427044..9dc65d1 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs
@@ -82,7 +82,7 @@ pub(super) fn compute_normalizes_to_goal(
             },
             |ecx| {
                 ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
-                    this.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    this.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias)?;
                     this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                 })
             },
@@ -111,13 +111,9 @@ pub fn push_const_arg_has_type_goal(
         Ok(())
     }
 
-    /// When normalizing an associated item, constrain the expected term to `term`.
+    /// When normalizing an associated item, constrain the expected term to `value`.
     ///
-    /// We know `term` to always be a fully unconstrained inference variable, so
-    /// `eq` should never fail here. However, in case `term` contains aliases, we
-    /// emit nested `AliasRelate` goals to structurally normalize the alias.
-    ///
-    /// Additionally, when `term` is a const, this registers a `ConstArgHasType`
+    /// Additionally, when `value` is a const, this registers a `ConstArgHasType`
     /// goal to ensure that the const value's type matches the declared type of
     /// the alias it was normalized from.
     ///
@@ -140,11 +136,13 @@ pub fn push_const_arg_has_type_goal(
     fn instantiate_normalizes_to_term(
         &mut self,
         goal: Goal<I, NormalizesTo<I>>,
-        term: I::Term,
+        value: I::Term,
     ) -> Result<(), NoSolutionOrRerunNonErased> {
-        self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, term)?;
-        self.eq(goal.param_env, goal.predicate.term, term)
-            .expect("expected goal term to be fully unconstrained");
+        self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.alias, value)?;
+        // While `goal.predicate.term` should always be a fully unconstrained inference variable,
+        // `eq` can still fail if `value` is not fully normalized, due to `eq` eagerly normalizing,
+        // and that normalization can fail.
+        self.eq(goal.param_env, goal.predicate.term, value)?;
         Ok(())
     }
 
@@ -154,14 +152,13 @@ fn structurally_instantiate_normalizes_to_term(
         &mut self,
         goal: Goal<I, NormalizesTo<I>>,
         term: ty::AliasTerm<I>,
-    ) {
+    ) -> Result<(), NoSolutionOrRerunNonErased> {
         self.relate(
             goal.param_env,
             term.to_term(self.cx(), ty::IsRigid::Yes),
             ty::Invariant,
             goal.predicate.term,
         )
-        .expect("expected goal term to be fully unconstrained");
     }
 }
 
@@ -359,7 +356,7 @@ fn consider_impl_candidate(
                                 ecx.structurally_instantiate_normalizes_to_term(
                                     goal,
                                     goal.predicate.alias,
-                                );
+                                )?;
                                 return ecx.evaluate_added_goals_and_make_canonical_response(
                                     Certainty::Yes,
                                 );
@@ -394,7 +391,10 @@ fn consider_impl_candidate(
                         ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous))?;
                         return then(ecx, Certainty::Yes);
                     } else {
-                        ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                        ecx.structurally_instantiate_normalizes_to_term(
+                            goal,
+                            goal.predicate.alias,
+                        )?;
                         return then(ecx, Certainty::Yes);
                     }
                 } else {
@@ -770,7 +770,7 @@ fn consider_builtin_pointee_candidate(
                         this.structurally_instantiate_normalizes_to_term(
                             goal,
                             goal.predicate.alias,
-                        );
+                        )?;
                         this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                     })
                 });
@@ -1026,7 +1026,7 @@ fn consider_builtin_discriminant_kind_candidate(
             // this impl candidate anyways. It's still a bit scuffed.
             ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => {
                 return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
-                    ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
+                    ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias)?;
                     ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                 });
             }
diff --git a/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs
new file mode 100644
index 0000000..b469165
--- /dev/null
+++ b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.rs
@@ -0,0 +1,15 @@
+//@ compile-flags: -Znext-solver
+
+//! This test is extremely similar to `nested-rerun-not-erased-in-normalizes-to.rs`, however,
+//! instead of the eager normalization failing due to an anon const when in ErasedNotCoherence, this
+//! just straight up fails normalization because u32 is not Iterator
+
+#![feature(ptr_metadata)]
+
+struct ThisStructAintValid(<u32 as Iterator>::Item);
+//~^ ERROR `u32` is not an iterator
+
+fn main() {
+    let y: <ThisStructAintValid as std::ptr::Pointee>::Metadata;
+    //~^ ERROR type mismatch resolving `<ThisStructAintValid as Pointee>::Metadata == _`
+}
diff --git a/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr
new file mode 100644
index 0000000..60fd1b3
--- /dev/null
+++ b/tests/ui/traits/next-solver/consider_builtin_pointee_candidate-instantiate-result-fail.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `u32` is not an iterator
+  --> $DIR/consider_builtin_pointee_candidate-instantiate-result-fail.rs:9:28
+   |
+LL | struct ThisStructAintValid(<u32 as Iterator>::Item);
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `u32`
+
+error[E0271]: type mismatch resolving `<ThisStructAintValid as Pointee>::Metadata == _`
+  --> $DIR/consider_builtin_pointee_candidate-instantiate-result-fail.rs:13:12
+   |
+LL |     let y: <ThisStructAintValid as std::ptr::Pointee>::Metadata;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs b/tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs
new file mode 100644
index 0000000..b75598d
--- /dev/null
+++ b/tests/ui/traits/next-solver/nested-rerun-not-erased-in-normalizes-to.rs
@@ -0,0 +1,28 @@
+//@ build-pass
+//@ compile-flags: -Znext-solver
+
+//! Consider:
+//!
+//! goal is <StructTailHasAnonConst as Pointee>::Metadata == ?0, in a typing context of
+//! ErasedNotCoherence
+//!
+//! `consider_builtin_pointee_candidate` looks at StructTailHasAnonConst, realizes it's an ADT,
+//! fetches the struct tail (which is `S<{ 2 + 2 }>`), and calls `instantiate_normalizes_to_term`
+//! with the result of `<Struct<{ 2 + 2 }> as Pointee>::Metadata`
+//!
+//! `instantiate_normalizes_to_term` `.eq()`s `<Struct<{ 2 + 2 }> as Pointee>::Metadata` and `?0`
+//!
+//! this eagerly normalizes, which normalizes the anon const, which fails due to ErasedNotCoherence
+//!
+//! this causes the `.eq()` in `instantiate_normalizes_to_term` to fail, which used to have an
+//! unwrap, which ICEd
+
+#![feature(ptr_metadata)]
+
+struct S<const N: usize>;
+
+struct StructTailHasAnonConst(S<{ 2 + 2 }>);
+
+fn main() {
+    let y: <StructTailHasAnonConst as std::ptr::Pointee>::Metadata;
+}