about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs50
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs244
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs9
15 files changed, 235 insertions, 198 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 265d1f8541c..3d91a2558f0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -54,6 +54,8 @@ use rustc_hash::{FxHashMap, FxHashSet};
 use stdx::{always, never};
 use triomphe::Arc;
 
+use crate::next_solver::DbInterner;
+use crate::next_solver::mapping::NextSolverToChalk;
 use crate::{
     AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx,
     IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode,
@@ -922,13 +924,15 @@ impl<'db> InferenceContext<'db> {
         });
         diagnostics.shrink_to_fit();
         for (_, subst) in method_resolutions.values_mut() {
-            *subst = table.resolve_completely(subst.clone());
+            *subst =
+                table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst.clone());
             *has_errors =
                 *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
         }
         method_resolutions.shrink_to_fit();
         for (_, subst) in assoc_resolutions.values_mut() {
-            *subst = table.resolve_completely(subst.clone());
+            *subst =
+                table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst.clone());
             *has_errors =
                 *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
         }
@@ -946,7 +950,12 @@ impl<'db> InferenceContext<'db> {
         result.tuple_field_access_types = tuple_field_accesses_rev
             .into_iter()
             .enumerate()
-            .map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst)))
+            .map(|(idx, subst)| {
+                (
+                    TupleId(idx as u32),
+                    table.resolve_completely::<_, crate::next_solver::GenericArgs<'db>>(subst),
+                )
+            })
             .inspect(|(_, subst)| {
                 *has_errors =
                     *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
@@ -1015,14 +1024,12 @@ impl<'db> InferenceContext<'db> {
         if let Some(self_param) = self.body.self_param
             && let Some(ty) = param_tys.next()
         {
-            let ty = self.insert_type_vars(ty);
-            let ty = self.normalize_associated_types_in(ty);
+            let ty = self.process_user_written_ty(ty);
             self.write_binding_ty(self_param, ty);
         }
         let mut tait_candidates = FxHashSet::default();
         for (ty, pat) in param_tys.zip(&*self.body.params) {
-            let ty = self.insert_type_vars(ty);
-            let ty = self.normalize_associated_types_in(ty);
+            let ty = self.process_user_written_ty(ty);
 
             self.infer_top_pat(*pat, &ty, None);
             if ty
@@ -1073,7 +1080,7 @@ impl<'db> InferenceContext<'db> {
             None => self.result.standard_types.unit.clone(),
         };
 
-        self.return_ty = self.normalize_associated_types_in(return_ty);
+        self.return_ty = self.process_user_written_ty(return_ty);
         self.return_coercion = Some(CoerceMany::new(self.return_ty.clone()));
 
         // Functions might be defining usage sites of TAITs.
@@ -1415,8 +1422,7 @@ impl<'db> InferenceContext<'db> {
     ) -> Ty {
         let ty = self
             .with_ty_lowering(store, type_source, lifetime_elision, |ctx| ctx.lower_ty(type_ref));
-        let ty = self.insert_type_vars(ty);
-        self.normalize_associated_types_in(ty)
+        self.process_user_written_ty(ty)
     }
 
     fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty {
@@ -1562,15 +1568,35 @@ impl<'db> InferenceContext<'db> {
         ty
     }
 
+    /// Whenever you lower a user-written type, you should call this.
+    fn process_user_written_ty<T, U>(&mut self, ty: T) -> T
+    where
+        T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
+        U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+    {
+        self.table.process_user_written_ty(ty)
+    }
+
+    /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
+    /// while `process_user_written_ty()` should (but doesn't currently).
+    fn process_remote_user_written_ty<T, U>(&mut self, ty: T) -> T
+    where
+        T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
+        U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
+    {
+        self.table.process_remote_user_written_ty(ty)
+    }
+
     /// Recurses through the given type, normalizing associated types mentioned
     /// in it by replacing them by type variables and registering obligations to
     /// resolve later. This should be done once for every type we get from some
     /// type annotation (e.g. from a let type annotation, field type or function
     /// call). `make_ty` handles this already, but e.g. for field types we need
     /// to do it as well.
-    fn normalize_associated_types_in<T>(&mut self, ty: T) -> T
+    fn normalize_associated_types_in<T, U>(&mut self, ty: T) -> T
     where
-        T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+        T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'db, U>,
+        U: NextSolverToChalk<'db, T> + rustc_type_ir::TypeFoldable<DbInterner<'db>>,
     {
         self.table.normalize_associated_types_in(ty)
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 5a69ad68b58..fd7e5a6a0e1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -53,7 +53,7 @@ pub(super) struct ClosureSignature {
     pub(super) expected_sig: FnPointer,
 }
 
-impl InferenceContext<'_> {
+impl<'db> InferenceContext<'db> {
     pub(super) fn infer_closure(
         &mut self,
         body: &ExprId,
@@ -71,9 +71,13 @@ impl InferenceContext<'_> {
             None => (None, None),
         };
 
-        let ClosureSignature { expected_sig: bound_sig, ret_ty: body_ret_ty } =
+        let ClosureSignature { expected_sig: mut bound_sig, ret_ty: body_ret_ty } =
             self.sig_of_closure(body, ret_type, arg_types, closure_kind, expected_sig);
-        let bound_sig = self.normalize_associated_types_in(bound_sig);
+        bound_sig.substitution.0 = self
+            .normalize_associated_types_in::<_, crate::next_solver::GenericArgs<'db>>(
+                bound_sig.substitution.0,
+            );
+        let bound_sig = bound_sig;
         let sig_ty = TyKind::Function(bound_sig.clone()).intern(Interner);
 
         let (id, ty, resume_yield_tys) = match closure_kind {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index bfeb5bae851..0a58ea11bb8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -1419,7 +1419,7 @@ impl InferenceContext<'_> {
             None => self.err_ty(),
         };
 
-        let ret_ty = self.normalize_associated_types_in(ret_ty);
+        let ret_ty = self.process_remote_user_written_ty(ret_ty);
 
         if self.is_builtin_binop(&lhs_ty, &rhs_ty, op) {
             // use knowledge of built-in binary ops, which can sometimes help inference
@@ -1630,8 +1630,7 @@ impl InferenceContext<'_> {
         Some(match res {
             Some((field_id, ty)) => {
                 let adjustments = auto_deref_adjust_steps(&autoderef);
-                let ty = self.insert_type_vars(ty);
-                let ty = self.normalize_associated_types_in(ty);
+                let ty = self.process_remote_user_written_ty(ty);
 
                 (ty, field_id, adjustments, true)
             }
@@ -1641,8 +1640,7 @@ impl InferenceContext<'_> {
                 let ty = self.db.field_types(field_id.parent)[field_id.local_id]
                     .clone()
                     .substitute(Interner, &subst);
-                let ty = self.insert_type_vars(ty);
-                let ty = self.normalize_associated_types_in(ty);
+                let ty = self.process_remote_user_written_ty(ty);
 
                 (ty, Either::Left(field_id), adjustments, false)
             }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
index 16489e3068f..6781bc84d1c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
@@ -88,7 +88,7 @@ impl InferenceContext<'_> {
                                     Some(substs) => f.substitute(Interner, substs),
                                     None => f.substitute(Interner, &Substitution::empty(Interner)),
                                 };
-                                self.normalize_associated_types_in(expected_ty)
+                                self.process_remote_user_written_ty(expected_ty)
                             }
                             None => self.err_ty(),
                         }
@@ -152,7 +152,7 @@ impl InferenceContext<'_> {
                                     Some(substs) => f.substitute(Interner, substs),
                                     None => f.substitute(Interner, &Substitution::empty(Interner)),
                                 };
-                                self.normalize_associated_types_in(expected_ty)
+                                self.process_remote_user_written_ty(expected_ty)
                             }
                             None => {
                                 self.push_diagnostic(InferenceDiagnostic::NoSuchField {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 1f62f9c4aa1..80f7324e58b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -23,7 +23,7 @@ use crate::{
 
 use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource};
 
-impl InferenceContext<'_> {
+impl<'db> InferenceContext<'db> {
     pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty> {
         let (value_def, generic_def, substs) = match self.resolve_value_path(path, id)? {
             ValuePathResolution::GenericDef(value_def, generic_def, substs) => {
@@ -31,13 +31,13 @@ impl InferenceContext<'_> {
             }
             ValuePathResolution::NonGeneric(ty) => return Some(ty),
         };
-        let substs = self.insert_type_vars(substs);
-        let substs = self.normalize_associated_types_in(substs);
+        let substs =
+            self.process_remote_user_written_ty::<_, crate::next_solver::GenericArgs<'db>>(substs);
 
         self.add_required_obligations_for_value_path(generic_def, &substs);
 
         let ty = self.db.value_ty(value_def)?.substitute(Interner, &substs);
-        let ty = self.normalize_associated_types_in(ty);
+        let ty = self.process_remote_user_written_ty(ty);
         Some(ty)
     }
 
@@ -173,14 +173,12 @@ impl InferenceContext<'_> {
             let last = path.segments().last()?;
 
             let (ty, orig_ns) = path_ctx.ty_ctx().lower_ty_ext(type_ref);
-            let ty = self.table.insert_type_vars(ty);
-            let ty = self.table.normalize_associated_types_in(ty);
+            let ty = self.table.process_user_written_ty(ty);
 
             path_ctx.ignore_last_segment();
             let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true);
             drop_ctx(ctx, no_diagnostics);
-            let ty = self.table.insert_type_vars(ty);
-            let ty = self.table.normalize_associated_types_in(ty);
+            let ty = self.table.process_user_written_ty(ty);
             self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
         } else {
             let hygiene = self.body.expr_or_pat_path_hygiene(id);
@@ -223,8 +221,7 @@ impl InferenceContext<'_> {
                                 return None;
                             }
 
-                            let ty = self.insert_type_vars(ty);
-                            let ty = self.normalize_associated_types_in(ty);
+                            let ty = self.process_user_written_ty(ty);
 
                             self.resolve_ty_assoc_item(ty, last_segment.name, id)
                         }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index ec4b7ee85dc..19b83d3c212 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -12,12 +12,14 @@ use hir_expand::name::Name;
 use intern::sym;
 use rustc_hash::{FxHashMap, FxHashSet};
 use rustc_next_trait_solver::solve::HasChanged;
+use rustc_type_ir::inherent::IntoKind;
 use rustc_type_ir::{
     AliasRelationDirection, FloatVid, IntVid, TyVid,
     inherent::{Span, Term as _},
     relate::{Relate, solver_relating::RelateExt},
     solve::{Certainty, NoSolution},
 };
+use rustc_type_ir::{TypeSuperFoldable, TypeVisitableExt};
 use smallvec::SmallVec;
 use triomphe::Arc;
 
@@ -31,11 +33,8 @@ use crate::{
     db::HirDatabase,
     fold_generic_args, fold_tys_and_consts,
     next_solver::{
-        self, Binder, DbInterner, ParamEnvAnd, Predicate, PredicateKind, SolverDefIds, Term,
-        infer::{
-            DbInternerInferExt, InferCtxt, canonical::canonicalizer::OriginalQueryValues,
-            snapshot::CombinedSnapshot,
-        },
+        self, Binder, DbInterner, Predicate, PredicateKind, SolverDefIds, Term,
+        infer::{DbInternerInferExt, InferCtxt, snapshot::CombinedSnapshot},
         mapping::{ChalkToNextSolver, InferenceVarExt, NextSolverToChalk},
     },
     to_chalk_trait_id,
@@ -305,116 +304,21 @@ impl<'a> InferenceTable<'a> {
     /// type annotation (e.g. from a let type annotation, field type or function
     /// call). `make_ty` handles this already, but e.g. for field types we need
     /// to do it as well.
-    #[tracing::instrument(skip(self), ret)]
-    pub(crate) fn normalize_associated_types_in<T>(&mut self, ty: T) -> T
+    pub(crate) fn normalize_associated_types_in<T, U>(&mut self, ty: T) -> T
     where
-        T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+        T: ChalkToNextSolver<'a, U>,
+        U: NextSolverToChalk<'a, T> + rustc_type_ir::TypeFoldable<DbInterner<'a>>,
     {
-        fold_tys_and_consts(
-            ty,
-            |e, _| match e {
-                Either::Left(ty) => {
-                    let ty = self.resolve_ty_shallow(&ty);
-                    tracing::debug!(?ty);
-                    Either::Left(match ty.kind(Interner) {
-                        TyKind::Alias(AliasTy::Projection(proj_ty)) => {
-                            let ty = self.normalize_projection_ty(proj_ty.clone());
-                            self.resolve_ty_shallow(&ty)
-                        }
-                        TyKind::AssociatedType(id, subst) => {
-                            // return Either::Left(self.resolve_ty_shallow(&ty));
-                            if ty.data(Interner).flags.intersects(
-                                chalk_ir::TypeFlags::HAS_TY_INFER
-                                    | chalk_ir::TypeFlags::HAS_CT_INFER,
-                            ) {
-                                return Either::Left(ty);
-                            }
-                            let var = self.new_type_var();
-                            let proj_ty = chalk_ir::ProjectionTy {
-                                associated_ty_id: *id,
-                                substitution: subst.clone(),
-                            };
-                            let normalize = chalk_ir::Normalize {
-                                alias: AliasTy::Projection(proj_ty),
-                                ty: var.clone(),
-                            };
-                            let goal = chalk_ir::Goal::new(
-                                Interner,
-                                chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Normalize(
-                                    normalize,
-                                )),
-                            );
-                            let in_env = InEnvironment::new(&self.trait_env.env, goal);
-                            let goal = in_env.to_nextsolver(self.interner);
-                            let goal =
-                                ParamEnvAnd { param_env: goal.param_env, value: goal.predicate };
-
-                            let (canonical_goal, orig_values) = {
-                                let mut orig_values = OriginalQueryValues::default();
-                                let result =
-                                    self.infer_ctxt.canonicalize_query(goal, &mut orig_values);
-                                (result.canonical, orig_values)
-                            };
-                            let canonical_goal = rustc_type_ir::Canonical {
-                                max_universe: canonical_goal.max_universe,
-                                variables: canonical_goal.variables,
-                                value: crate::next_solver::Goal {
-                                    param_env: canonical_goal.value.param_env,
-                                    predicate: canonical_goal.value.value,
-                                },
-                            };
-                            let solution = next_trait_solve_canonical_in_ctxt(
-                                &self.infer_ctxt,
-                                canonical_goal,
-                            );
-                            if let NextTraitSolveResult::Certain(canonical_subst) = solution {
-                                let subst = self.instantiate_canonical(canonical_subst).subst;
-                                if subst.len(Interner) != orig_values.var_values.len() {
-                                    ty
-                                } else {
-                                    let target_ty = var.to_nextsolver(self.interner);
-                                    subst
-                                        .iter(Interner)
-                                        .zip(orig_values.var_values.iter())
-                                        .find_map(|(new, orig)| {
-                                            if orig.ty() == Some(target_ty) {
-                                                Some(new.assert_ty_ref(Interner).clone())
-                                            } else {
-                                                None
-                                            }
-                                        })
-                                        .unwrap_or(ty)
-                                }
-                            } else {
-                                ty
-                            }
-                        }
-                        _ => ty,
-                    })
-                }
-                Either::Right(c) => Either::Right(match &c.data(Interner).value {
-                    chalk_ir::ConstValue::Concrete(cc) => match &cc.interned {
-                        crate::ConstScalar::UnevaluatedConst(c_id, subst) => {
-                            // FIXME: Ideally here we should do everything that we do with type alias, i.e. adding a variable
-                            // and registering an obligation. But it needs chalk support, so we handle the most basic
-                            // case (a non associated const without generic parameters) manually.
-                            if subst.len(Interner) == 0 {
-                                if let Ok(eval) = self.db.const_eval(*c_id, subst.clone(), None) {
-                                    eval
-                                } else {
-                                    unknown_const(c.data(Interner).ty.clone())
-                                }
-                            } else {
-                                unknown_const(c.data(Interner).ty.clone())
-                            }
-                        }
-                        _ => c,
-                    },
-                    _ => c,
-                }),
-            },
-            DebruijnIndex::INNERMOST,
-        )
+        self.normalize_associated_types_in_ns(ty.to_nextsolver(self.interner))
+            .to_chalk(self.interner)
+    }
+
+    pub(crate) fn normalize_associated_types_in_ns<T>(&mut self, ty: T) -> T
+    where
+        T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
+    {
+        let ty = self.resolve_vars_with_obligations(ty);
+        ty.fold_with(&mut Normalizer { table: self })
     }
 
     /// Works almost same as [`Self::normalize_associated_types_in`], but this also resolves shallow
@@ -476,11 +380,27 @@ impl<'a> InferenceTable<'a> {
     }
 
     pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
-        let var = self.new_type_var();
-        let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
-        let obligation: Goal = alias_eq.cast(Interner);
-        self.register_obligation(obligation.to_nextsolver(self.interner));
-        var
+        let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(proj_ty))
+            .intern(Interner)
+            .to_nextsolver(self.interner);
+        self.normalize_alias_ty(ty).to_chalk(self.interner)
+    }
+
+    pub(crate) fn normalize_alias_ty(
+        &mut self,
+        alias: crate::next_solver::Ty<'a>,
+    ) -> crate::next_solver::Ty<'a> {
+        let infer_term = self.infer_ctxt.next_ty_var();
+        let obligation = crate::next_solver::Predicate::new(
+            self.interner,
+            crate::next_solver::Binder::dummy(crate::next_solver::PredicateKind::AliasRelate(
+                alias.into(),
+                infer_term.into(),
+                rustc_type_ir::AliasRelationDirection::Equate,
+            )),
+        );
+        self.register_obligation(obligation);
+        self.resolve_vars_with_obligations(infer_term)
     }
 
     fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
@@ -591,9 +511,10 @@ impl<'a> InferenceTable<'a> {
         )
     }
 
-    pub(crate) fn resolve_completely<T>(&mut self, t: T) -> T
+    pub(crate) fn resolve_completely<T, U>(&mut self, t: T) -> T
     where
-        T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
+        T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'a, U>,
+        U: NextSolverToChalk<'a, T> + rustc_type_ir::TypeFoldable<DbInterner<'a>>,
     {
         let t = self.resolve_with_fallback(t, &|_, _, d, _| d);
         let t = self.normalize_associated_types_in(t);
@@ -1045,6 +966,30 @@ impl<'a> InferenceTable<'a> {
         }
     }
 
+    /// Whenever you lower a user-written type, you should call this.
+    pub(crate) fn process_user_written_ty<T, U>(&mut self, ty: T) -> T
+    where
+        T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'a, U>,
+        U: NextSolverToChalk<'a, T> + rustc_type_ir::TypeFoldable<DbInterner<'a>>,
+    {
+        self.process_remote_user_written_ty(ty)
+        // FIXME: Register a well-formed obligation.
+    }
+
+    /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
+    /// while `process_user_written_ty()` should (but doesn't currently).
+    pub(crate) fn process_remote_user_written_ty<T, U>(&mut self, ty: T) -> T
+    where
+        T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + ChalkToNextSolver<'a, U>,
+        U: NextSolverToChalk<'a, T> + rustc_type_ir::TypeFoldable<DbInterner<'a>>,
+    {
+        let ty = self.insert_type_vars(ty);
+        // See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495:
+        // Even though the new solver only lazily normalizes usually, here we eagerly normalize so that not everything needs
+        // to normalize before inspecting the `TyKind`.
+        self.normalize_associated_types_in(ty)
+    }
+
     /// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it.
     pub(super) fn insert_const_vars_shallow(&mut self, c: Const) -> Const {
         let data = c.data(Interner);
@@ -1319,3 +1264,62 @@ mod resolve {
         }
     }
 }
+
+/// This expects its input to be resolved.
+struct Normalizer<'a, 'b> {
+    table: &'a mut InferenceTable<'b>,
+}
+
+impl<'db> Normalizer<'_, 'db> {
+    fn normalize_alias_term(
+        &mut self,
+        alias_term: crate::next_solver::Term<'db>,
+    ) -> crate::next_solver::Term<'db> {
+        let infer_term = self.table.infer_ctxt.next_term_var_of_kind(alias_term);
+        let obligation = crate::next_solver::Predicate::new(
+            self.table.interner,
+            crate::next_solver::Binder::dummy(crate::next_solver::PredicateKind::AliasRelate(
+                alias_term,
+                infer_term,
+                rustc_type_ir::AliasRelationDirection::Equate,
+            )),
+        );
+        self.table.register_obligation(obligation);
+        let term = self.table.resolve_vars_with_obligations(infer_term);
+        // Now normalize the result, because maybe it contains more aliases.
+        match term {
+            Term::Ty(term) => term.super_fold_with(self).into(),
+            Term::Const(term) => term.super_fold_with(self).into(),
+        }
+    }
+}
+
+impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for Normalizer<'_, 'db> {
+    fn cx(&self) -> DbInterner<'db> {
+        self.table.interner
+    }
+
+    fn fold_ty(&mut self, ty: crate::next_solver::Ty<'db>) -> crate::next_solver::Ty<'db> {
+        if !ty.has_aliases() {
+            return ty;
+        }
+
+        let crate::next_solver::TyKind::Alias(..) = ty.kind() else {
+            return ty.super_fold_with(self);
+        };
+        // FIXME: Handle escaping bound vars by replacing them with placeholders (relevant to when we handle HRTB only).
+        self.normalize_alias_term(ty.into()).expect_type()
+    }
+
+    fn fold_const(&mut self, ct: crate::next_solver::Const<'db>) -> crate::next_solver::Const<'db> {
+        if !ct.has_aliases() {
+            return ct;
+        }
+
+        let crate::next_solver::ConstKind::Unevaluated(..) = ct.kind() else {
+            return ct.super_fold_with(self);
+        };
+        // FIXME: Handle escaping bound vars by replacing them with placeholders (relevant to when we handle HRTB only).
+        self.normalize_alias_term(ct.into()).expect_const()
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index fa80567b1ec..a234312173a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -22,10 +22,9 @@ use stdx::never;
 use triomphe::Arc;
 
 use crate::{
-    AdtId, AliasTy, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId,
-    GenericArgData, Goal, InEnvironment, Interner, Mutability, Scalar, Substitution,
-    TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind,
-    VariableKind, WhereClause,
+    AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
+    Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef,
+    TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, VariableKind, WhereClause,
     autoderef::{self, AutoderefKind},
     db::HirDatabase,
     from_chalk_trait_id, from_foreign_def_id,
@@ -106,8 +105,12 @@ impl TyFingerprint {
                 }
             }
             TyKind::AssociatedType(_, _)
+            // FIXME(next-solver): Putting `Alias` here is *probably* incorrect, AFAIK it should return `None`. But this breaks
+            // flyimport, which uses an incorrect but fast method resolution algorithm. Therefore we put it here,
+            // because this function is only called by flyimport, and anyway we should get rid of `TyFingerprint`
+            // and switch to `rustc_type_ir`'s `SimplifiedType`.
+            | TyKind::Alias(_)
             | TyKind::OpaqueType(_, _)
-            | TyKind::Alias(AliasTy::Opaque(_))
             | TyKind::FnDef(_, _)
             | TyKind::Closure(_, _)
             | TyKind::Coroutine(..)
@@ -115,8 +118,7 @@ impl TyFingerprint {
             TyKind::Function(fn_ptr) => {
                 TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32)
             }
-            TyKind::Alias(_)
-            | TyKind::Placeholder(_)
+            TyKind::Placeholder(_)
             | TyKind::BoundVar(_)
             | TyKind::InferenceVar(_, _)
             | TyKind::Error => return None,
@@ -908,7 +910,10 @@ fn find_matching_impl(
                 }
                 table.register_obligation(goal.to_nextsolver(table.interner));
             }
-            Some((impl_.impl_items(db), table.resolve_completely(impl_substs)))
+            Some((
+                impl_.impl_items(db),
+                table.resolve_completely::<_, crate::next_solver::GenericArgs<'_>>(impl_substs),
+            ))
         })
     })
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs
index 6490554b22b..5d088e40cde 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs
@@ -202,7 +202,7 @@ fn expr_macro_def_expanded_in_various_places() {
             100..119 'for _ ...!() {}': {unknown}
             100..119 'for _ ...!() {}': &'? mut {unknown}
             100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            100..119 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item>
+            100..119 'for _ ...!() {}': Option<{unknown}>
             100..119 'for _ ...!() {}': ()
             100..119 'for _ ...!() {}': ()
             100..119 'for _ ...!() {}': ()
@@ -296,7 +296,7 @@ fn expr_macro_rules_expanded_in_various_places() {
             114..133 'for _ ...!() {}': {unknown}
             114..133 'for _ ...!() {}': &'? mut {unknown}
             114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            114..133 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item>
+            114..133 'for _ ...!() {}': Option<{unknown}>
             114..133 'for _ ...!() {}': ()
             114..133 'for _ ...!() {}': ()
             114..133 'for _ ...!() {}': ()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs
index baca7f2318e..6a9135622de 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs
@@ -362,12 +362,12 @@ fn diverging_expression_3_break() {
             140..141 'x': u32
             149..175 '{ for ...; }; }': u32
             151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
-            151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter
+            151..172 'for a ...eak; }': {unknown}
             151..172 'for a ...eak; }': !
-            151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter
-            151..172 'for a ...eak; }': &'? mut <{unknown} as IntoIterator>::IntoIter
+            151..172 'for a ...eak; }': {unknown}
+            151..172 'for a ...eak; }': &'? mut {unknown}
             151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            151..172 'for a ...eak; }': Option<<{unknown} as Iterator>::Item>
+            151..172 'for a ...eak; }': Option<{unknown}>
             151..172 'for a ...eak; }': ()
             151..172 'for a ...eak; }': ()
             151..172 'for a ...eak; }': ()
@@ -379,12 +379,12 @@ fn diverging_expression_3_break() {
             226..227 'x': u32
             235..253 '{ for ... {}; }': u32
             237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
-            237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
+            237..250 'for a in b {}': {unknown}
             237..250 'for a in b {}': !
-            237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
-            237..250 'for a in b {}': &'? mut <{unknown} as IntoIterator>::IntoIter
+            237..250 'for a in b {}': {unknown}
+            237..250 'for a in b {}': &'? mut {unknown}
             237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            237..250 'for a in b {}': Option<<{unknown} as Iterator>::Item>
+            237..250 'for a in b {}': Option<{unknown}>
             237..250 'for a in b {}': ()
             237..250 'for a in b {}': ()
             237..250 'for a in b {}': ()
@@ -395,12 +395,12 @@ fn diverging_expression_3_break() {
             304..305 'x': u32
             313..340 '{ for ...; }; }': u32
             315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
-            315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter
+            315..337 'for a ...urn; }': {unknown}
             315..337 'for a ...urn; }': !
-            315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter
-            315..337 'for a ...urn; }': &'? mut <{unknown} as IntoIterator>::IntoIter
+            315..337 'for a ...urn; }': {unknown}
+            315..337 'for a ...urn; }': &'? mut {unknown}
             315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            315..337 'for a ...urn; }': Option<<{unknown} as Iterator>::Item>
+            315..337 'for a ...urn; }': Option<{unknown}>
             315..337 'for a ...urn; }': ()
             315..337 'for a ...urn; }': ()
             315..337 'for a ...urn; }': ()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
index 60a2641e1a2..02cb0370691 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
@@ -48,12 +48,12 @@ fn infer_pattern() {
             83..84 '1': i32
             86..93 '"hello"': &'static str
             101..151 'for (e...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
-            101..151 'for (e...     }': <{unknown} as IntoIterator>::IntoIter
+            101..151 'for (e...     }': {unknown}
             101..151 'for (e...     }': !
-            101..151 'for (e...     }': <{unknown} as IntoIterator>::IntoIter
-            101..151 'for (e...     }': &'? mut <{unknown} as IntoIterator>::IntoIter
+            101..151 'for (e...     }': {unknown}
+            101..151 'for (e...     }': &'? mut {unknown}
             101..151 'for (e...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            101..151 'for (e...     }': Option<<{unknown} as Iterator>::Item>
+            101..151 'for (e...     }': Option<({unknown}, {unknown})>
             101..151 'for (e...     }': ()
             101..151 'for (e...     }': ()
             101..151 'for (e...     }': ()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index eacc4603ea1..6a3f2286215 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
@@ -268,12 +268,12 @@ fn infer_std_crash_5() {
         expect![[r#"
             26..322 '{     ...   } }': ()
             32..320 'for co...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
-            32..320 'for co...     }': <{unknown} as IntoIterator>::IntoIter
+            32..320 'for co...     }': {unknown}
             32..320 'for co...     }': !
-            32..320 'for co...     }': <{unknown} as IntoIterator>::IntoIter
-            32..320 'for co...     }': &'? mut <{unknown} as IntoIterator>::IntoIter
+            32..320 'for co...     }': {unknown}
+            32..320 'for co...     }': &'? mut {unknown}
             32..320 'for co...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            32..320 'for co...     }': Option<<{unknown} as Iterator>::Item>
+            32..320 'for co...     }': Option<{unknown}>
             32..320 'for co...     }': ()
             32..320 'for co...     }': ()
             32..320 'for co...     }': ()
@@ -628,7 +628,7 @@ fn issue_4053_diesel_where_clauses() {
             65..69 'self': Self
             267..271 'self': Self
             466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
-            488..522 '{     ...     }': <SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> as BoxedDsl<DB>>::Output
+            488..522 '{     ...     }': ()
             498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
             498..508 'self.order': O
             498..515 'self.o...into()': dyn QueryFragment<DB> + '?
@@ -1248,7 +1248,7 @@ fn test() {
             16..66 'for _ ...     }': {unknown}
             16..66 'for _ ...     }': &'? mut {unknown}
             16..66 'for _ ...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
-            16..66 'for _ ...     }': Option<<{unknown} as Iterator>::Item>
+            16..66 'for _ ...     }': Option<{unknown}>
             16..66 'for _ ...     }': ()
             16..66 'for _ ...     }': ()
             16..66 'for _ ...     }': ()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
index 471108d964f..6d6c56696a3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -20,7 +20,7 @@ impl<'a> IntoIterator for &'a Grid {
     "#,
         expect![[r#"
             150..154 'self': &'a Grid
-            174..181 '{     }': impl Iterator<Item = &'? ()>
+            174..181 '{     }': impl Iterator<Item = &'a ()>
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index e7357ed5aa7..60ad0f49c6a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -2000,7 +2000,7 @@ fn test() {
             225..360 'match ...     }': ()
             231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str>
             231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str>
-            231..262 'Pin::n...usize)': CoroutineState<i64, &'? str>
+            231..262 'Pin::n...usize)': CoroutineState<i64, &'static str>
             240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str
             245..246 'g': |usize| yields i64 -> &'static str
             255..261 '0usize': usize
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 7a946f7ec7c..22332fdc2b8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -4190,8 +4190,6 @@ fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) {
     );
 }
 
-// FIXME(next-solver): Was `&'a T` but now getting error lifetime.
-// This might be fixed once we migrate into next-solver fully without chalk-ir in lowering.
 #[test]
 fn gats_with_impl_trait() {
     // FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
@@ -4215,21 +4213,21 @@ fn f<T>(v: impl Trait) {
 }
 fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
     let a = v.get::<T>();
-      //^ &'? T
+      //^ &'a T
     let a = v.get::<()>();
       //^ <impl Trait<Assoc<T> = &'a T> as Trait>::Assoc<()>
 }
 fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
     let a = v.get::<i32>();
-      //^ &'? i32
+      //^ &'a i32
     let a = v.get::<i64>();
-      //^ &'? i64
+      //^ &'a i64
 }
 fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
     let a = v.get::<i32>();
-      //^ &'? i32
+      //^ &'a i32
     let a = v.get::<i64>();
-      //^ &'? i64
+      //^ &'a i64
 }
     "#,
     );
@@ -4259,8 +4257,8 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
             127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
             164..195 '{     ...f(); }': ()
             170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
-            170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + '? as Trait>::Assoc<i32>
-            170..192 'v.get:...eref()': {unknown}
+            170..184 'v.get::<i32>()': {unknown}
+            170..192 'v.get:...eref()': &'? {unknown}
         "#]],
     );
 }
@@ -4953,7 +4951,7 @@ where
 "#,
         expect![[r#"
             84..86 'de': D
-            135..138 '{ }': <D as Deserializer<'?>>::Error
+            135..138 '{ }': <D as Deserializer<'de>>::Error
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 52ab808d228..888392b0ff2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -76,7 +76,7 @@ use hir_expand::{
 };
 use hir_ty::{
     AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
-    GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
+    GenericArgData, Interner, ParamKind, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution,
     TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic,
     ValueTyDefId, WhereClause, all_super_traits, autoderef, check_orphan_rules,
     consteval::{ConstExt, try_const_usize, unknown_const_as_generic},
@@ -4973,6 +4973,7 @@ impl<'db> Type<'db> {
                 | TyKind::Tuple(_, substitution)
                 | TyKind::OpaqueType(_, substitution)
                 | TyKind::AssociatedType(_, substitution)
+                | TyKind::Alias(AliasTy::Projection(ProjectionTy { substitution, .. }))
                 | TyKind::FnDef(_, substitution) => {
                     substitution.iter(Interner).filter_map(|x| x.ty(Interner)).any(|ty| go(db, ty))
                 }
@@ -5819,7 +5820,11 @@ impl<'db> Type<'db> {
                     cb(type_.derived(ty.clone()));
                     walk_substs(db, type_, substs, cb);
                 }
-                TyKind::AssociatedType(_, substs) => {
+                TyKind::AssociatedType(_, substs)
+                | TyKind::Alias(AliasTy::Projection(hir_ty::ProjectionTy {
+                    substitution: substs,
+                    ..
+                })) => {
                     if ty.associated_type_parent_trait(db).is_some() {
                         cb(type_.derived(ty.clone()));
                     }