diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 8f5737dd4ad1d..6454a02c11595 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1317,7 +1317,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Find the type of `e`. Supply hints based on the type we are casting to,
         // if appropriate.
         let t_cast = self.to_ty_saving_user_provided_ty(t);
-        let t_cast = self.resolve_vars_if_possible(t_cast);
+        // FIXME(-Ztrait-solver): This structural resolve is only here for diagnostics,
+        // because we use the TyKind to early return from `CastCheck::new`.
+        let t_cast = self.try_structurally_resolve_type(t.span, t_cast);
         let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
         let t_expr = self.resolve_vars_if_possible(t_expr);
 
@@ -3142,7 +3144,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &[Ident],
         expr: &'tcx hir::Expr<'tcx>,
     ) -> Ty<'tcx> {
-        let container = self.to_ty(container).normalized;
+        // We only need to normalize in the old solver
+        let container = self.normalize(expr.span, self.to_ty(container));
 
         let mut field_indices = Vec::with_capacity(fields.len());
         let mut current_container = container;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index ecafb50f42094..b15133faca2ad 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -2,7 +2,7 @@ use crate::callee::{self, DeferredCallResolution};
 use crate::errors::CtorIsPrivate;
 use crate::method::{self, MethodCallee, SelfSource};
 use crate::rvalue_scopes;
-use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, RawTy};
+use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
@@ -324,6 +324,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
     }
 
+    // FIXME(-Ztrait-solver=next): This could be replaced with `try_structurally_resolve`
+    // calls after the new trait solver is stable.
+    /// TODO: I don't know what to call this.
+    pub(super) fn structurally_normalize_after_astconv(
+        &self,
+        span: Span,
+        value: Ty<'tcx>,
+    ) -> Ty<'tcx> {
+        match self
+            .at(&self.misc(span), self.param_env)
+            .structurally_normalize(value, &mut **self.inh.fulfillment_cx.borrow_mut())
+        {
+            Ok(ty) => ty,
+            Err(errors) => {
+                let guar = self.err_ctxt().report_fulfillment_errors(&errors);
+                Ty::new_error(self.tcx, guar)
+            }
+        }
+    }
+
     pub fn require_type_meets(
         &self,
         ty: Ty<'tcx>,
@@ -374,37 +394,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn handle_raw_ty(&self, span: Span, ty: Ty<'tcx>) -> RawTy<'tcx> {
-        RawTy { raw: ty, normalized: self.normalize(span, ty) }
-    }
-
-    pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> RawTy<'tcx> {
+    pub fn to_ty(&self, ast_t: &hir::Ty<'_>) -> Ty<'tcx> {
         let t = self.astconv().ast_ty_to_ty(ast_t);
         self.register_wf_obligation(t.into(), ast_t.span, traits::WellFormed(None));
-        self.handle_raw_ty(ast_t.span, t)
+        t
     }
 
     pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
         let ty = self.to_ty(ast_ty);
         debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
 
-        if Self::can_contain_user_lifetime_bounds(ty.raw) {
-            let c_ty = self.canonicalize_response(UserType::Ty(ty.raw));
+        if Self::can_contain_user_lifetime_bounds(ty) {
+            let c_ty = self.canonicalize_response(UserType::Ty(ty));
             debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
             self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
         }
 
-        ty.normalized
+        self.normalize(ast_ty.span, ty)
     }
 
-    pub(super) fn user_args_for_adt(ty: RawTy<'tcx>) -> UserArgs<'tcx> {
-        match (ty.raw.kind(), ty.normalized.kind()) {
+    pub(super) fn user_args_for_adt(raw: Ty<'tcx>, normalized: Ty<'tcx>) -> UserArgs<'tcx> {
+        match (raw.kind(), normalized.kind()) {
             (ty::Adt(_, args), _) => UserArgs { args, user_self_ty: None },
             (_, ty::Adt(adt, args)) => UserArgs {
                 args,
-                user_self_ty: Some(UserSelfTy { impl_def_id: adt.did(), self_ty: ty.raw }),
+                user_self_ty: Some(UserSelfTy { impl_def_id: adt.did(), self_ty: raw }),
             },
-            _ => bug!("non-adt type {:?}", ty),
+            _ => bug!("non-adt type {:?}", raw),
         }
     }
 
@@ -817,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &'tcx QPath<'tcx>,
         hir_id: hir::HirId,
         span: Span,
-    ) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
+    ) -> (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
         debug!(
             "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
             qpath, hir_id, span
@@ -841,15 +857,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // We manually call `register_wf_obligation` in the success path
                 // below.
                 let ty = self.astconv().ast_ty_to_ty_in_path(qself);
-                (self.handle_raw_ty(span, ty), qself, segment)
+                (ty, qself, segment)
             }
             QPath::LangItem(..) => {
                 bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
             }
         };
+
+        // FIXME(-Ztrait-solver=next): Can use `try_structurally_resolve` after migration.
+        let normalized =
+            if !ty.is_ty_var() { self.structurally_normalize_after_astconv(span, ty) } else { ty };
+
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
-            self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
+            self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
             // Return directly on cache hit. This is useful to avoid doubly reporting
             // errors with default match binding modes. See #44614.
             let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@@ -857,7 +878,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let item_name = item_segment.ident;
         let result = self
-            .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
+            .resolve_fully_qualified_call(span, item_name, normalized, qself.span, hir_id)
             .and_then(|r| {
                 // lint bare trait if the method is found in the trait
                 if span.edition().at_least_rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
@@ -876,14 +897,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
 
                 let trait_missing_method =
-                    matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
+                    matches!(error, method::MethodError::NoMatch(_)) && normalized.is_trait();
                 // If we have a path like `MyTrait::missing_method`, then don't register
                 // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
                 // register a WF obligation so that we can detect any additional
                 // errors in the self type.
                 if !trait_missing_method {
                     self.register_wf_obligation(
-                        ty.raw.into(),
+                        ty.into(),
                         qself.span,
                         traits::WellFormed(None),
                     );
@@ -902,7 +923,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if item_name.name != kw::Empty {
                     if let Some(mut e) = self.report_method_error(
                         span,
-                        ty.normalized,
+                        normalized,
                         item_name,
                         SelfSource::QPath(qself),
                         error,
@@ -918,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             });
 
         if result.is_ok() {
-            self.register_wf_obligation(ty.raw.into(), qself.span, traits::WellFormed(None));
+            self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
         }
 
         // Write back the new resolution.
@@ -1082,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn instantiate_value_path(
         &self,
         segments: &[hir::PathSegment<'_>],
-        self_ty: Option<RawTy<'tcx>>,
+        self_ty: Option<Ty<'tcx>>,
         res: Res,
         span: Span,
         hir_id: hir::HirId,
@@ -1093,7 +1114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Res::Local(_) | Res::SelfCtor(_) => vec![],
             Res::Def(kind, def_id) => self.astconv().def_ids_for_value_path_segments(
                 segments,
-                self_ty.map(|ty| ty.raw),
+                self_ty.map(|ty| ty),
                 kind,
                 def_id,
                 span,
@@ -1107,8 +1128,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
                 if let Some(self_ty) = self_ty =>
             {
-                let adt_def = self_ty.normalized.ty_adt_def().unwrap();
-                user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty: self_ty.raw });
+                let adt_def = self.structurally_normalize_after_astconv(span, self_ty).ty_adt_def().unwrap();
+                user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did(), self_ty });
                 is_alias_variant_ctor = true;
             }
             Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
@@ -1127,7 +1148,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // inherent impl, we need to record the
                             // `T` for posterity (see `UserSelfTy` for
                             // details).
-                            let self_ty = self_ty.expect("UFCS sugared assoc missing Self").raw;
+                            let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
                             user_self_ty = Some(UserSelfTy { impl_def_id: container_id, self_ty });
                         }
                     }
@@ -1206,9 +1227,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             path_segs.last().is_some_and(|PathSeg(def_id, _)| tcx.generics_of(*def_id).has_self);
 
         let (res, self_ctor_args) = if let Res::SelfCtor(impl_def_id) = res {
-            let ty =
-                self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).instantiate_identity());
-            match ty.normalized.ty_adt_def() {
+            let ty = tcx.at(span).type_of(impl_def_id).instantiate_identity();
+            let normalized = self.structurally_normalize_after_astconv(span, ty);
+            match normalized.ty_adt_def() {
                 Some(adt_def) if adt_def.has_ctor() => {
                     let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
                     // Check the visibility of the ctor.
@@ -1218,7 +1239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
                     }
                     let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
-                    let user_args = Self::user_args_for_adt(ty);
+                    let user_args = Self::user_args_for_adt(ty, normalized);
                     user_self_ty = user_args.user_self_ty;
                     (new_res, Some(user_args.args))
                 }
@@ -1227,7 +1248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         span,
                         "the `Self` constructor can only be used with tuple or unit structs",
                     );
-                    if let Some(adt_def) = ty.normalized.ty_adt_def() {
+                    if let Some(adt_def) = normalized.ty_adt_def() {
                         match adt_def.adt_kind() {
                             AdtKind::Enum => {
                                 err.help("did you mean to use one of the enum's variants?");
@@ -1299,7 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
-                        self.fcx.to_ty(ty).raw.into()
+                        self.fcx.to_ty(ty).into()
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
                         self.fcx.const_arg_to_const(&ct.value, param.def_id).into()
@@ -1367,7 +1388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 def_id,
                 &[],
                 has_self,
-                self_ty.map(|s| s.raw),
+                self_ty.map(|s| s),
                 &arg_count,
                 &mut CreateCtorSubstsContext {
                     fcx: self,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index e102c51c7eeca..a22621fbf4955 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -6,7 +6,7 @@ use crate::method::MethodCallee;
 use crate::TupleArgumentsFlag::*;
 use crate::{errors, Expectation::*};
 use crate::{
-    struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, RawTy, TupleArgumentsFlag,
+    struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, Needs, TupleArgumentsFlag,
 };
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
@@ -1346,6 +1346,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
         let path_span = qpath.span();
         let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
+        let normalized = self.structurally_normalize_after_astconv(path_span, ty);
+
         let variant = match def {
             Res::Err => {
                 let guar =
@@ -1353,18 +1355,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.set_tainted_by_errors(guar);
                 return Err(guar);
             }
-            Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
-                Some(adt) => {
-                    Some((adt.variant_of_res(def), adt.did(), Self::user_args_for_adt(ty)))
-                }
-                _ => bug!("unexpected type: {:?}", ty.normalized),
+            Res::Def(DefKind::Variant, _) => match normalized.ty_adt_def() {
+                Some(adt) => Some((
+                    adt.variant_of_res(def),
+                    adt.did(),
+                    Self::user_args_for_adt(ty, normalized),
+                )),
+                _ => bug!("unexpected type: {:?}", normalized),
             },
             Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
             | Res::SelfTyParam { .. }
-            | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
-                Some(adt) if !adt.is_enum() => {
-                    Some((adt.non_enum_variant(), adt.did(), Self::user_args_for_adt(ty)))
-                }
+            | Res::SelfTyAlias { .. } => match normalized.ty_adt_def() {
+                Some(adt) if !adt.is_enum() => Some((
+                    adt.non_enum_variant(),
+                    adt.did(),
+                    Self::user_args_for_adt(ty, normalized),
+                )),
                 _ => None,
             },
             _ => bug!("unexpected definition: {:?}", def),
@@ -1379,9 +1385,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Check bounds on type arguments used in the path.
             self.add_required_obligations_for_hir(path_span, did, args, hir_id);
 
-            Ok((variant, ty.normalized))
+            Ok((variant, normalized))
         } else {
-            Err(match *ty.normalized.kind() {
+            Err(match *normalized.kind() {
                 ty::Error(guar) => {
                     // E0071 might be caused by a spelling error, which will have
                     // already caused an error message and probably a suggestion
@@ -1394,7 +1400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     path_span,
                     E0071,
                     "expected struct, variant or union type, found {}",
-                    ty.normalized.sort_string(self.tcx)
+                    normalized.sort_string(self.tcx)
                 )
                 .span_label(path_span, "not a struct")
                 .emit(),
@@ -1802,23 +1808,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         qpath: &QPath<'_>,
         path_span: Span,
         hir_id: hir::HirId,
-    ) -> (Res, RawTy<'tcx>) {
+    ) -> (Res, Ty<'tcx>) {
         match *qpath {
             QPath::Resolved(ref maybe_qself, ref path) => {
-                let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
+                let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
                 let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
-                (path.res, self.handle_raw_ty(path_span, ty))
+                (path.res, ty)
             }
             QPath::TypeRelative(ref qself, ref segment) => {
                 let ty = self.to_ty(qself);
 
                 let result = self
                     .astconv()
-                    .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
+                    .associated_path_to_ty(hir_id, path_span, ty, qself, segment, true);
                 let ty = result
                     .map(|(ty, _, _)| ty)
                     .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar));
-                let ty = self.handle_raw_ty(path_span, ty);
                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
 
                 // Write back the new resolution.
@@ -1827,8 +1832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
             }
             QPath::LangItem(lang_item, span, id) => {
-                let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id);
-                (res, self.handle_raw_ty(path_span, ty))
+                self.resolve_lang_item_path(lang_item, span, hir_id, id)
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 6a82b00211e45..0b391547e6d9f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -325,15 +325,3 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
         Some(&self.infcx)
     }
 }
-
-/// Represents a user-provided type in the raw form (never normalized).
-///
-/// This is a bridge between the interface of `AstConv`, which outputs a raw `Ty`,
-/// and the API in this module, which expect `Ty` to be fully normalized.
-#[derive(Clone, Copy, Debug)]
-pub struct RawTy<'tcx> {
-    pub raw: Ty<'tcx>,
-
-    /// The normalized form of `raw`, stored here for efficiency.
-    pub normalized: Ty<'tcx>,
-}
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 4f45a24b216ea..d9b63fc6bb269 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -74,9 +74,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
         let local_ty = match decl.ty {
             Some(ref ty) => {
                 let o_ty = self.fcx.to_ty(&ty);
-
-                let c_ty =
-                    self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw));
+                let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty));
                 debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
                 self.fcx
                     .typeck_results
@@ -84,7 +82,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
                     .user_provided_types_mut()
                     .insert(ty.hir_id, c_ty);
 
-                Some(o_ty.normalized)
+                // We only need to normalize here in the old solver
+                let normalized = self.fcx.normalize(ty.span, o_ty);
+                Some(normalized)
             }
             None => None,
         };
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index c4d3cbc9faab0..ddb916864d752 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -51,7 +51,6 @@ use crate::check::check_fn;
 use crate::coercion::DynamicCoerceMany;
 use crate::diverges::Diverges;
 use crate::expectation::Expectation;
-use crate::fn_ctxt::RawTy;
 use crate::gather_locals::GatherLocalsVisitor;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 7c73f6a89cdb2..92ac36bb5aa77 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -395,7 +395,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
                         self.cfcx.fcx.astconv().ast_region_to_region(lt, Some(param)).into()
                     }
                     (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
-                        self.cfcx.to_ty(ty).raw.into()
+                        self.cfcx.to_ty(ty).into()
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
                         self.cfcx.const_arg_to_const(&ct.value, param.def_id).into()
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index d8eb8c71b5ea3..df45d5146d9e4 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1,4 +1,4 @@
-use crate::{errors, FnCtxt, RawTy};
+use crate::{errors, FnCtxt};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{
@@ -874,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat: &Pat<'tcx>,
         qpath: &hir::QPath<'_>,
-        path_resolution: (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
+        path_resolution: (Res, Option<Ty<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
         expected: Ty<'tcx>,
         ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
diff --git a/tests/ui/traits/new-solver/normalize-path-for-method.rs b/tests/ui/traits/new-solver/normalize-path-for-method.rs
new file mode 100644
index 0000000000000..b54e027d72a1c
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-path-for-method.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Ztrait-solver=next
+// run-pass
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+struct Foo;
+impl Foo {
+    fn new() -> Self { Foo }
+}
+
+fn main() {
+    <Foo as Mirror>::Assoc::new();
+}