about summary refs log tree commit diff
diff options
context:
space:
mode:
authorjackh726 <git@jackhuey.me>2025-04-19 05:52:28 +0000
committerjackh726 <git@jackhuey.me>2025-04-20 16:20:08 +0000
commit3eb6485151408e35befe9cb8c25e78ec3c5bcba5 (patch)
tree30e1ae8ebd2aff5f7fef0bfad93a5a52828da9fa
parent824d33dc7c8de13eb929fd855be9de46871acbc7 (diff)
downloadrust-3eb6485151408e35befe9cb8c25e78ec3c5bcba5.tar.gz
rust-3eb6485151408e35befe9cb8c25e78ec3c5bcba5.zip
Update chalk
-rw-r--r--src/tools/rust-analyzer/Cargo.lock16
-rw-r--r--src/tools/rust-analyzer/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/builder.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs32
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs38
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs29
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs75
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tls.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs27
16 files changed, 166 insertions, 173 deletions
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index b017b37a38e..2cf6731aad7 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -200,9 +200,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
 [[package]]
 name = "chalk-derive"
-version = "0.100.0"
+version = "0.102.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab2d131019373f0d0d1f2af0abd4f719739f6583c1b33965112455f643a910af"
+checksum = "feb14e3ff0ebac26d8e58b6ed1417afb60c4a0a44b6425546ee7eb9c75ebb336"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -212,9 +212,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-ir"
-version = "0.100.0"
+version = "0.102.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f114996bda14c0213f014a4ef31a7867dcf5f539a3900477fc6b20138e7a17b"
+checksum = "72f0a61621a088af69fee8df39ec63cf5b6d0b9ab663a740cdeb376aabf2f244"
 dependencies = [
  "bitflags 2.9.0",
  "chalk-derive",
@@ -222,9 +222,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-recursive"
-version = "0.100.0"
+version = "0.102.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "551e956e031c09057c7b21f17d48d91de99c9b6b6e34bceaf5e7202d71021268"
+checksum = "cbd3415cc540015533aa4a8ad007696d585dd9c5f81e7c099872f1dd4bf14894"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -235,9 +235,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-solve"
-version = "0.100.0"
+version = "0.102.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd7ca50181156ce649efe8e5dd00580f573651554e4dcd11afa4e2ac93f53324"
+checksum = "747707b0c082b3ecf4b1ae28d0d8df708a46cddd22a386f9cc85a312a4de25ff"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 1fdc6b3896c..851235eb99d 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -104,10 +104,10 @@ arrayvec = "0.7.6"
 bitflags = "2.9.0"
 cargo_metadata = "0.19.2"
 camino = "1.1.9"
-chalk-solve = { version = "0.100.0", default-features = false }
-chalk-ir = "0.100.0"
-chalk-recursive = { version = "0.100.0", default-features = false }
-chalk-derive = "0.100.0"
+chalk-solve = { version = "0.102.0", default-features = false }
+chalk-ir = "0.102.0"
+chalk-recursive = { version = "0.102.0", default-features = false }
+chalk-derive = "0.102.0"
 crossbeam-channel = "0.5.15"
 dissimilar = "1.0.10"
 dot = "0.1.4"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
index 163510602b6..8c3665dfc83 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -76,7 +76,7 @@ impl<D> TyBuilder<D> {
         }
         let subst = Substitution::from_iter(
             Interner,
-            self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()),
+            self.parent_subst.iter(Interner).cloned().chain(self.vec),
         );
         (self.data, subst)
     }
@@ -278,8 +278,10 @@ impl TyBuilder<()> {
         };
         Substitution::from_iter(
             Interner,
-            self_subst
-                .chain(generics(db, parent).placeholder_subst(db).iter(Interner))
+            generics(db, parent)
+                .placeholder_subst(db)
+                .iter(Interner)
+                .chain(self_subst)
                 .cloned()
                 .collect::<Vec<_>>(),
         )
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 24deb00b385..db23847e0b8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -55,6 +55,22 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
     fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
         self.db.associated_ty_data(from_assoc_type_id(id))
     }
+    fn associated_ty_from_impl(
+        &self,
+        impl_id: chalk_ir::ImplId<Interner>,
+        assoc_type_id: chalk_ir::AssocTypeId<Interner>,
+    ) -> Option<rust_ir::AssociatedTyValueId<Interner>> {
+        let alias_id = from_assoc_type_id(assoc_type_id);
+        let trait_sig = self.db.type_alias_signature(alias_id);
+        self.db.impl_items(hir_def::ImplId::from_chalk(self.db, impl_id)).items.iter().find_map(
+            |(name, item)| match item {
+                AssocItemId::TypeAliasId(alias) if &trait_sig.name == name => {
+                    Some(TypeAliasAsValue(*alias).to_chalk(self.db))
+                }
+                _ => None,
+            },
+        )
+    }
     fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> {
         self.db.trait_datum(self.krate, trait_id)
     }
@@ -467,12 +483,13 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
         // `resume_type`, `yield_type`, and `return_type` of the coroutine in question.
         let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
 
+        let len = subst.len(Interner);
         let input_output = rust_ir::CoroutineInputOutputDatum {
-            resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
+            resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 3))
                 .intern(Interner),
-            yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1))
+            yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 2))
                 .intern(Interner),
-            return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 2))
+            return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 1))
                 .intern(Interner),
             // FIXME: calculate upvars
             upvars: vec![],
@@ -619,10 +636,10 @@ pub(crate) fn associated_ty_data_query(
             .with_type_param_mode(crate::lower::ParamLoweringMode::Variable);
 
     let trait_subst = TyBuilder::subst_for_def(db, trait_, None)
-        .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
+        .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
         .build();
     let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst))
-        .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
+        .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
         .build();
     let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);
 
@@ -1021,8 +1038,9 @@ pub(super) fn generic_predicate_to_inline_bound(
         }
         WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
             let generics = generics(db, from_assoc_type_id(projection_ty.associated_ty_id).into());
-            let (assoc_args, trait_args) =
-                projection_ty.substitution.as_slice(Interner).split_at(generics.len_self());
+            let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
+            let (trait_args, assoc_args) =
+                projection_ty.substitution.as_slice(Interner).split_at(parent_len);
             let (self_ty, args_no_self) =
                 trait_args.split_first().expect("projection without trait self type");
             if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index 0b304014db7..0f0cf6ae7ae 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -418,10 +418,9 @@ impl ProjectionTyExt for ProjectionTy {
     fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
         // FIXME: something like `Split` trait from chalk-solve might be nice.
         let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into());
-        let substitution = Substitution::from_iter(
-            Interner,
-            self.substitution.iter(Interner).skip(generics.len_self()),
-        );
+        let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
+        let substitution =
+            Substitution::from_iter(Interner, self.substitution.iter(Interner).take(parent_len));
         TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 5950d7b8b81..93d427b9662 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -621,9 +621,8 @@ impl HirDisplay for ProjectionTy {
                 .name
                 .display(f.db, f.edition())
         )?;
-        let proj_params_count =
-            self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
-        let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
+        let proj_params =
+            &self.substitution.as_slice(Interner)[trait_ref.substitution.len(Interner)..];
         hir_fmt_generics(f, proj_params, None, None)
     }
 }
@@ -1196,27 +1195,31 @@ impl HirDisplay for Ty {
 
                         // Normally, functions cannot have default parameters, but they can,
                         // for function-like things such as struct names or enum variants.
-                        // The former cannot have defaults but parents, and the later cannot have
-                        // parents but defaults.
-                        // So, if `parent_len` > 0, it have a parent and thus it doesn't have any
-                        // default. Therefore, we shouldn't subtract defaults because those defaults
-                        // are from their parents.
-                        // And if `parent_len` == 0, either parents don't exists or they don't have
-                        // any defaults. Thus, we can - and should - subtract defaults.
-                        let without_impl = if parent_len > 0 {
-                            params_len - parent_len - impl_
+                        // The former cannot have defaults but does have parents,
+                        // but the latter cannot have parents but can have defaults.
+                        //
+                        // However, it's also true that *traits* can have defaults too.
+                        // In this case, there can be no function params.
+                        let parent_end = if parent_len > 0 {
+                            // If `parent_len` > 0, then there cannot be defaults on the function
+                            // and all defaults must come from the parent.
+                            parent_len - defaults
                         } else {
-                            params_len - parent_len - impl_ - defaults
+                            parent_len
                         };
-                        // parent's params (those from enclosing impl or trait, if any).
-                        let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
+                        let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_;
+                        let (parent_params, fn_params) = parameters.split_at(parent_end);
 
                         write!(f, "<")?;
                         hir_fmt_generic_arguments(f, parent_params, None)?;
                         if !parent_params.is_empty() && !fn_params.is_empty() {
                             write!(f, ", ")?;
                         }
-                        hir_fmt_generic_arguments(f, &fn_params[0..without_impl], None)?;
+                        hir_fmt_generic_arguments(
+                            f,
+                            &fn_params[..fn_params_no_impl_or_defaults],
+                            None,
+                        )?;
                         write!(f, ">")?;
                     }
                 }
@@ -1873,11 +1876,12 @@ fn write_bounds_like_dyn_trait(
                     f.end_location_link();
 
                     let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self();
+                    let parent_len = proj.substitution.len(Interner) - proj_arg_count;
                     if proj_arg_count > 0 {
                         write!(f, "<")?;
                         hir_fmt_generic_arguments(
                             f,
-                            &proj.substitution.as_slice(Interner)[..proj_arg_count],
+                            &proj.substitution.as_slice(Interner)[parent_len..],
                             None,
                         )?;
                         write!(f, ">")?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index d174da9997a..42fe129f91f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -65,7 +65,7 @@ impl Generics {
     }
 
     pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
-        self.iter_self_id().chain(self.iter_parent_id())
+        self.iter_parent_id().chain(self.iter_self_id())
     }
 
     pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
@@ -82,11 +82,11 @@ impl Generics {
         self.params.iter_type_or_consts().map(from_toc_id(self)).map(TupleExt::head)
     }
 
-    /// Iterate over the params followed by the parent params.
+    /// Iterate over the parent params followed by self params.
     pub(crate) fn iter(
         &self,
     ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
-        self.iter_self().chain(self.iter_parent())
+        self.iter_parent().chain(self.iter_self())
     }
 
     pub(crate) fn iter_parents_with_store(
@@ -166,13 +166,10 @@ impl Generics {
             if self.params.trait_self_param() == Some(param.local_id) {
                 return Some(idx);
             }
-            Some(self.params.len_lifetimes() + idx)
+            Some(self.parent_generics().map_or(0, |g| g.len()) + self.params.len_lifetimes() + idx)
         } else {
             debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent));
-            self.parent_generics()
-                .and_then(|g| g.find_type_or_const_param(param))
-                // Remember that parent parameters come after parameters for self.
-                .map(|idx| self.len_self() + idx)
+            self.parent_generics().and_then(|g| g.find_type_or_const_param(param))
         }
     }
 
@@ -184,12 +181,14 @@ impl Generics {
         if lifetime.parent == self.def {
             let idx = lifetime.local_id.into_raw().into_u32() as usize;
             debug_assert!(idx <= self.params.len_lifetimes());
-            Some(self.params.trait_self_param().is_some() as usize + idx)
+            Some(
+                self.parent_generics().map_or(0, |g| g.len())
+                    + self.params.trait_self_param().is_some() as usize
+                    + idx,
+            )
         } else {
             debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
-            self.parent_generics()
-                .and_then(|g| g.find_lifetime(lifetime))
-                .map(|idx| self.len_self() + idx)
+            self.parent_generics().and_then(|g| g.find_lifetime(lifetime))
         }
     }
 
@@ -253,8 +252,7 @@ pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> O
             let parent_def = parent_generic_def(db, def)?;
             let parent_params = db.generic_params(parent_def);
             let parent_self_idx = parent_params.trait_self_param()?.into_raw().into_u32() as usize;
-            let self_params = db.generic_params(def);
-            Some(self_params.len() + parent_self_idx)
+            Some(parent_self_idx)
         }
     }
 }
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 068d9a59da7..a5074b86889 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
@@ -2065,7 +2065,16 @@ impl InferenceContext<'_> {
         assert!(!has_self_param); // method shouldn't have another Self param
         let total_len =
             parent_params + type_params + const_params + impl_trait_params + lifetime_params;
-        let mut substs = Vec::with_capacity(total_len);
+
+        let param_to_var = |id| match id {
+            GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner),
+            GenericParamId::ConstParamId(id) => {
+                self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)
+            }
+            GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner),
+        };
+
+        let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_var).collect();
 
         // handle provided arguments
         if let Some(generic_args) = generic_args {
@@ -2105,20 +2114,17 @@ impl InferenceContext<'_> {
             }
         };
 
-        // Handle everything else as unknown. This also handles generic arguments for the method's
-        // parent (impl or trait), which should come after those for the method.
-        for (id, _data) in def_generics.iter().skip(substs.len()) {
-            match id {
-                GenericParamId::TypeParamId(_) => {
-                    substs.push(self.table.new_type_var().cast(Interner))
-                }
-                GenericParamId::ConstParamId(id) => {
-                    substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
-                }
-                GenericParamId::LifetimeParamId(_) => {
-                    substs.push(self.table.new_lifetime_var().cast(Interner))
-                }
+        let mut param_to_var = |id| match id {
+            GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner),
+            GenericParamId::ConstParamId(id) => {
+                self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)
             }
+            GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner),
+        };
+
+        // Handle everything else as unknown.
+        for (id, _data) in def_generics.iter().skip(substs.len()) {
+            substs.push(param_to_var(id));
         }
         assert_eq!(substs.len(), total_len);
         Substitution::from_iter(Interner, substs)
@@ -2143,13 +2149,12 @@ impl InferenceContext<'_> {
                 CallableDefId::FunctionId(f) => {
                     if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container {
                         // construct a TraitRef
-                        let params_len = parameters.len(Interner);
                         let trait_params_len = generics(self.db, trait_.into()).len();
                         let substs = Substitution::from_iter(
                             Interner,
                             // The generic parameters for the trait come after those for the
                             // function.
-                            &parameters.as_slice(Interner)[params_len - trait_params_len..],
+                            &parameters.as_slice(Interner)[..trait_params_len],
                         );
                         self.push_obligation(
                             TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
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 7e9cf9f7674..461cea4f143 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
@@ -105,11 +105,9 @@ impl InferenceContext<'_> {
         let substs = substs.as_slice(Interner);
 
         if let ValueNs::EnumVariantId(_) = value {
-            let mut it = self_subst
-                .as_ref()
-                .map_or(&[][..], |s| s.as_slice(Interner))
+            let mut it = substs
                 .iter()
-                .chain(substs)
+                .chain(self_subst.as_ref().map_or(&[][..], |s| s.as_slice(Interner)))
                 .cloned();
             let builder = TyBuilder::subst_for_def(self.db, generic_def, None);
             let substs = builder
@@ -130,11 +128,11 @@ impl InferenceContext<'_> {
         let parent_substs = self_subst.or_else(|| {
             let generics = generics(self.db, generic_def);
             let parent_params_len = generics.parent_generics()?.len();
-            let parent_args = &substs[substs.len() - parent_params_len..];
+            let parent_args = &substs[..parent_params_len];
             Some(Substitution::from_iter(Interner, parent_args))
         });
         let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner));
-        let mut it = substs.iter().take(substs.len() - parent_substs_len).cloned();
+        let mut it = substs.iter().skip(parent_substs_len).cloned();
         let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs);
         let substs = builder
             .fill(|x| {
@@ -261,9 +259,9 @@ impl InferenceContext<'_> {
         };
 
         if let ItemContainerId::TraitId(trait_) = container {
-            let param_len = generics(self.db, def).len_self();
+            let parent_len = generics(self.db, def).parent_generics().map_or(0, |g| g.len_self());
             let parent_subst =
-                Substitution::from_iter(Interner, subst.iter(Interner).skip(param_len));
+                Substitution::from_iter(Interner, subst.iter(Interner).take(parent_len));
             let trait_ref =
                 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: parent_subst };
             self.push_obligation(trait_ref.cast(Interner));
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 2d2ec2866e8..57849ff9139 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -769,14 +769,8 @@ fn named_associated_type_shorthand_candidates<R>(
 
             let impl_id_as_generic_def: GenericDefId = impl_id.into();
             if impl_id_as_generic_def != def {
-                // `trait_ref` contains `BoundVar`s bound by impl's `Binders`, but here we need
-                // `BoundVar`s from `def`'s point of view.
-                // FIXME: A `HirDatabase` query may be handy if this process is needed in more
-                // places. It'd be almost identical as `impl_trait_query` where `resolver` would be
-                // of `def` instead of `impl_id`.
-                let starting_idx = generics(db, def).len_self();
                 let subst = TyBuilder::subst_for_def(db, impl_id, None)
-                    .fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
+                    .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
                     .build();
                 let trait_ref = subst.apply(trait_ref, Interner);
                 search(trait_ref)
@@ -802,16 +796,8 @@ fn named_associated_type_shorthand_candidates<R>(
             if let GenericDefId::TraitId(trait_id) = param_id.parent() {
                 let trait_generics = generics(db, trait_id.into());
                 if trait_generics[param_id.local_id()].is_trait_self() {
-                    let def_generics = generics(db, def);
-                    let starting_idx = match def {
-                        GenericDefId::TraitId(_) => 0,
-                        // `def` is an item within trait. We need to substitute `BoundVar`s but
-                        // remember that they are for parent (i.e. trait) generic params so they
-                        // come after our own params.
-                        _ => def_generics.len_self(),
-                    };
                     let trait_ref = TyBuilder::trait_ref(db, trait_id)
-                        .fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
+                        .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
                         .build();
                     return search(trait_ref);
                 }
@@ -1181,7 +1167,6 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
         return (GenericDefaults(None), None);
     }
     let resolver = def.resolver(db);
-    let parent_start_idx = generic_params.len_self();
 
     let mut ctx = TyLoweringContext::new(db, &resolver, generic_params.store(), def)
         .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
@@ -1190,8 +1175,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
     let mut defaults = generic_params
         .iter_self()
         .map(|(id, p)| {
-            let result =
-                handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
+            let result = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
             idx += 1;
             result
         })
@@ -1199,7 +1183,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
     let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
     defaults.extend(generic_params.iter_parents_with_store().map(|((id, p), store)| {
         ctx.store = store;
-        let result = handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
+        let result = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
         idx += 1;
         result
     }));
@@ -1211,7 +1195,6 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
         idx: usize,
         id: GenericParamId,
         p: GenericParamDataRef<'_>,
-        parent_start_idx: usize,
         generic_params: &Generics,
     ) -> Binders<crate::GenericArg> {
         match p {
@@ -1220,7 +1203,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
                     // Each default can only refer to previous parameters.
                     // Type variable default referring to parameter coming
                     // after it is forbidden (FIXME: report diagnostic)
-                    fallback_bound_vars(ctx.lower_ty(*ty), idx, parent_start_idx)
+                    fallback_bound_vars(ctx.lower_ty(*ty), idx, 0)
                 });
                 crate::make_binders(ctx.db, generic_params, ty.cast(Interner))
             }
@@ -1238,7 +1221,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
                     },
                 );
                 // Each default can only refer to previous parameters, see above.
-                val = fallback_bound_vars(val, idx, parent_start_idx);
+                val = fallback_bound_vars(val, idx, 0);
                 make_binders(ctx.db, generic_params, val)
             }
             GenericParamDataRef::LifetimeParamData(_) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
index bc2d9d90807..a059d9df1c2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
@@ -184,14 +184,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
                                     false,
                                     None,
                                 );
-                                let len_self =
-                                    generics(self.ctx.db, associated_ty.into()).len_self();
                                 let substitution = Substitution::from_iter(
                                     Interner,
-                                    substitution
-                                        .iter(Interner)
-                                        .take(len_self)
-                                        .chain(trait_ref.substitution.iter(Interner)),
+                                    trait_ref.substitution.iter(Interner).chain(
+                                        substitution
+                                            .iter(Interner)
+                                            .skip(trait_ref.substitution.len(Interner)),
+                                    ),
                                 );
                                 TyKind::Alias(AliasTy::Projection(ProjectionTy {
                                     associated_ty_id: to_assoc_type_id(associated_ty),
@@ -250,18 +249,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
                         let subst = generics.placeholder_subst(self.ctx.db);
                         self.ctx.db.impl_self_ty(impl_id).substitute(Interner, &subst)
                     }
-                    ParamLoweringMode::Variable => {
-                        let starting_from = match generics.def() {
-                            GenericDefId::ImplId(_) => 0,
-                            // `def` is an item within impl. We need to substitute `BoundVar`s but
-                            // remember that they are for parent (i.e. impl) generic params so they
-                            // come after our own params.
-                            _ => generics.len_self(),
-                        };
-                        TyBuilder::impl_self_ty(self.ctx.db, impl_id)
-                            .fill_with_bound_vars(self.ctx.in_binders, starting_from)
-                            .build()
-                    }
+                    ParamLoweringMode::Variable => TyBuilder::impl_self_ty(self.ctx.db, impl_id)
+                        .fill_with_bound_vars(self.ctx.in_binders, 0)
+                        .build(),
                 }
             }
             TypeNs::AdtSelfType(adt) => {
@@ -512,12 +502,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
                 // this point (`t.substitution`).
                 let substs = self.substs_from_path_segment(associated_ty.into(), false, None);
 
-                let len_self =
-                    crate::generics::generics(self.ctx.db, associated_ty.into()).len_self();
-
                 let substs = Substitution::from_iter(
                     Interner,
-                    substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)),
+                    parent_subst
+                        .iter(Interner)
+                        .chain(substs.iter(Interner).skip(parent_subst.len(Interner))),
                 );
 
                 Some(
@@ -637,10 +626,10 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
         explicit_self_ty: Option<Ty>,
     ) -> Substitution {
         // Order is
+        // - Parent parameters
         // - Optional Self parameter
         // - Lifetime parameters
         // - Type or Const parameters
-        // - Parent parameters
         let def_generics = generics(self.ctx.db, def);
         let (
             parent_params,
@@ -654,12 +643,22 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
             self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
         let total_len = parent_params + item_len;
 
-        let mut substs = Vec::new();
+        let ty_error = || TyKind::Error.intern(Interner).cast(Interner);
+        let param_to_err = |id| match id {
+            GenericParamId::ConstParamId(x) => {
+                unknown_const_as_generic(self.ctx.db.const_param_ty(x))
+            }
+            GenericParamId::TypeParamId(_) => ty_error(),
+            GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
+        };
+
+        let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_err).collect();
+
+        tracing::debug!(?substs, ?parent_params);
 
         // we need to iterate the lifetime and type/const params separately as our order of them
         // differs from the supplied syntax
 
-        let ty_error = || TyKind::Error.intern(Interner).cast(Interner);
         let mut def_toc_iter = def_generics.iter_self_type_or_consts_id();
         let fill_self_param = || {
             if self_param {
@@ -730,13 +729,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
             fill_self_param();
         }
 
-        let param_to_err = |id| match id {
-            GenericParamId::ConstParamId(x) => {
-                unknown_const_as_generic(self.ctx.db.const_param_ty(x))
-            }
-            GenericParamId::TypeParamId(_) => ty_error(),
-            GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
-        };
         // handle defaults. In expression or pattern path segments without
         // explicitly specified type arguments, missing type arguments are inferred
         // (i.e. defaults aren't used).
@@ -751,13 +743,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
         let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty();
         if fill_defaults {
             let defaults = &*self.ctx.db.generic_defaults(def);
-            let (item, _parent) = defaults.split_at(item_len);
-            let parent_from = item_len - substs.len();
 
-            let mut rem =
+            let rem =
                 def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::<Vec<_>>();
             // Fill in defaults for type/const params
-            for (idx, default_ty) in item[substs.len()..].iter().enumerate() {
+            for (idx, default_ty) in defaults[substs.len()..].iter().enumerate() {
                 // each default can depend on the previous parameters
                 let substs_so_far = Substitution::from_iter(
                     Interner,
@@ -765,8 +755,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
                 );
                 substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
             }
-            // Fill in remaining parent params
-            substs.extend(rem.drain(parent_from..));
         } else {
             // Fill in remaining def params and parent params
             substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err));
@@ -818,14 +806,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
                     false, // this is not relevant
                     Some(super_trait_ref.self_type_parameter(Interner)),
                 );
-                let generics = generics(self.ctx.db, associated_ty.into());
-                let self_params = generics.len_self();
                 let substitution = Substitution::from_iter(
                     Interner,
-                    substitution
-                        .iter(Interner)
-                        .take(self_params)
-                        .chain(super_trait_ref.substitution.iter(Interner)),
+                    super_trait_ref.substitution.iter(Interner).chain(
+                        substitution
+                            .iter(Interner)
+                            .skip(super_trait_ref.substitution.len(Interner)),
+                    ),
                 );
                 let projection_ty = ProjectionTy {
                     associated_ty_id: to_assoc_type_id(associated_ty),
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 d591ea8fe87..52aa355a382 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
@@ -655,7 +655,7 @@ pub fn is_dyn_method(
     let fn_params = fn_subst.len(Interner) - trait_params;
     let trait_ref = TraitRef {
         trait_id: to_chalk_trait_id(trait_id),
-        substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)),
+        substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
     };
     let self_ty = trait_ref.self_type_parameter(Interner);
     if let TyKind::Dyn(d) = self_ty.kind(Interner) {
@@ -694,10 +694,9 @@ pub(crate) fn lookup_impl_method_query(
         return (func, fn_subst);
     };
     let trait_params = db.generic_params(trait_id.into()).len();
-    let fn_params = fn_subst.len(Interner) - trait_params;
     let trait_ref = TraitRef {
         trait_id: to_chalk_trait_id(trait_id),
-        substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)),
+        substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
     };
 
     let name = &db.function_signature(func).name;
@@ -713,7 +712,7 @@ pub(crate) fn lookup_impl_method_query(
         impl_fn,
         Substitution::from_iter(
             Interner,
-            fn_subst.iter(Interner).take(fn_params).chain(impl_subst.iter(Interner)),
+            impl_subst.iter(Interner).chain(fn_subst.iter(Interner).skip(trait_params)),
         ),
     )
 }
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 dda7bfb2baf..2fb51acea87 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
@@ -4213,7 +4213,7 @@ fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
     let a = v.get::<T>();
       //^ &'a T
     let a = v.get::<()>();
-      //^ Trait::Assoc<(), impl Trait<Assoc<T> = &'a T>>
+      //^ Trait::Assoc<impl Trait<Assoc<T> = &'a T>, ()>
 }
 fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
     let a = v.get::<i32>();
@@ -4280,7 +4280,7 @@ where
     let a = t.get::<isize>();
       //^ usize
     let a = t.get::<()>();
-      //^ Trait::Assoc<(), T>
+      //^ Trait::Assoc<T, ()>
 }
 
     "#,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs
index c8b64f7cbc9..f5911e2161d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs
@@ -86,8 +86,7 @@ impl DebugContext<'_> {
         }
         write!(fmt, ">::{}", type_alias_data.name.display(self.0, Edition::LATEST))?;
 
-        let proj_params_count = projection_ty.substitution.len(Interner) - trait_params.len();
-        let proj_params = &projection_ty.substitution.as_slice(Interner)[..proj_params_count];
+        let proj_params = &projection_ty.substitution.as_slice(Interner)[trait_params.len()..];
         if !proj_params.is_empty() {
             write!(
                 fmt,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 3efd9a560f2..c95c0ef55a3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -230,8 +230,8 @@ pub(super) fn associated_type_by_name_including_super_traits(
 }
 
 /// It is a bit different from the rustc equivalent. Currently it stores:
-/// - 0: the function signature, encoded as a function pointer type
-/// - 1..n: generics of the parent
+/// - 0..n-1: generics of the parent
+/// - n: the function signature, encoded as a function pointer type
 ///
 /// and it doesn't store the closure types and fields.
 ///
@@ -242,7 +242,7 @@ pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution);
 impl<'a> ClosureSubst<'a> {
     pub(crate) fn parent_subst(&self) -> &'a [GenericArg] {
         match self.0.as_slice(Interner) {
-            [_, x @ ..] => x,
+            [x @ .., _] => x,
             _ => {
                 never!("Closure missing parameter");
                 &[]
@@ -252,7 +252,7 @@ impl<'a> ClosureSubst<'a> {
 
     pub(crate) fn sig_ty(&self) -> &'a Ty {
         match self.0.as_slice(Interner) {
-            [x, ..] => x.assert_ty_ref(Interner),
+            [.., x] => x.assert_ty_ref(Interner),
             _ => {
                 unreachable!("Closure missing sig_ty parameter");
             }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 4414c79f8ba..578e9e38be2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -3774,24 +3774,25 @@ impl GenericSubstitution {
             TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
             TypeOrConstParamData::ConstParamData(_) => None,
         });
-        // The `Substitution` is first self then container, we want the reverse order.
-        let subst_type_params = self.subst.type_parameters(Interner).collect::<Vec<_>>();
-        let mut self_params = subst_type_params
+        let parent_len = self.subst.len(Interner)
+            - generics
+                .iter_type_or_consts()
+                .filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..)))
+                .count();
+        let container_params = self.subst.as_slice(Interner)[..parent_len]
             .iter()
-            .zip(type_params)
-            .filter_map(|(ty, name)| {
-                Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() }))
-            })
-            .collect::<Vec<_>>();
-        let mut container_params = subst_type_params[self_params.len()..]
+            .filter_map(|param| param.ty(Interner).cloned())
+            .zip(container_type_params.into_iter().flatten());
+        let self_params = self.subst.as_slice(Interner)[parent_len..]
             .iter()
-            .zip(container_type_params.into_iter().flatten())
+            .filter_map(|param| param.ty(Interner).cloned())
+            .zip(type_params);
+        container_params
+            .chain(self_params)
             .filter_map(|(ty, name)| {
                 Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() }))
             })
-            .collect::<Vec<_>>();
-        container_params.append(&mut self_params);
-        container_params
+            .collect()
     }
 }