about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorShoyu Vanilla (Flint) <modulo641@gmail.com>2025-09-03 06:00:29 +0000
committerGitHub <noreply@github.com>2025-09-03 06:00:29 +0000
commit2127c2df5d669bbed19f7a184ad90c8e2cb671d3 (patch)
tree1c25f75f2a80198458d0a3a3883ac6da34321462 /src
parentdfaff28ce155e8172654b48e26c5c22c71ebeb71 (diff)
parenta324fe956981f4ad736ffc268f222037fd853e83 (diff)
downloadrust-2127c2df5d669bbed19f7a184ad90c8e2cb671d3.tar.gz
rust-2127c2df5d669bbed19f7a184ad90c8e2cb671d3.zip
Merge pull request #20586 from ChayimFriedman2/placeholder-ns
fix: Make sense of the mess that were (are) different kind of generics in the solver
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs29
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs46
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs36
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs38
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs63
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs191
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/variance.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs6
26 files changed, 324 insertions, 233 deletions
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 8fa1aff0ef6..33ae099c690 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
@@ -306,7 +306,7 @@ impl TyExt for Ty {
                 predicates.map(|it| it.into_value_and_skipped_binders().0)
             }
             TyKind::Placeholder(idx) => {
-                let id = from_placeholder_idx(db, *idx);
+                let id = from_placeholder_idx(db, *idx).0;
                 let generic_params = db.generic_params(id.parent);
                 let param_data = &generic_params[id.local_id];
                 match param_data {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index abf97f3d0e3..0f2cc17f563 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -107,25 +107,24 @@ pub(crate) fn path_to_const<'g>(
     match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) {
         Some(ValueNs::GenericParam(p)) => {
             let ty = db.const_param_ty(p);
+            let args = args();
             let value = match mode {
                 ParamLoweringMode::Placeholder => {
-                    ConstValue::Placeholder(to_placeholder_idx(db, p.into()))
+                    let idx = args.type_or_const_param_idx(p.into()).unwrap();
+                    ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32))
                 }
-                ParamLoweringMode::Variable => {
-                    let args = args();
-                    match args.type_or_const_param_idx(p.into()) {
-                        Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
-                        None => {
-                            never!(
-                                "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
-                                args,
-                                path,
-                                p
-                            );
-                            return None;
-                        }
+                ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) {
+                    Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)),
+                    None => {
+                        never!(
+                            "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
+                            args,
+                            path,
+                            p
+                        );
+                        return None;
                     }
-                }
+                },
             };
             Some(ConstData { ty, value }.intern(Interner))
         }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs
index 00fc4e5610d..4f95c9a13ac 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval_nextsolver.rs
@@ -49,7 +49,7 @@ pub(crate) fn path_to_const<'a, 'g>(
                 .and_then(|(idx, p)| p.const_param().map(|p| (idx, p.clone())))
             {
                 Some((idx, _param)) => {
-                    Some(Const::new_param(interner, ParamConst { index: idx as u32 }))
+                    Some(Const::new_param(interner, ParamConst { index: idx as u32, id: p }))
                 }
                 None => {
                     never!(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 97754f47233..0b7213d785c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -410,13 +410,15 @@ fn hir_database_is_dyn_compatible() {
 #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
 #[derive(PartialOrd, Ord)]
 pub struct InternedTypeOrConstParamId {
-    pub loc: TypeOrConstParamId,
+    /// This stores the param and its index.
+    pub loc: (TypeOrConstParamId, u32),
 }
 
 #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
 #[derive(PartialOrd, Ord)]
 pub struct InternedLifetimeParamId {
-    pub loc: LifetimeParamId,
+    /// This stores the param and its index.
+    pub loc: (LifetimeParamId, u32),
 }
 
 #[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
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 0df727a8e5c..5b8093f6b72 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -61,9 +61,8 @@ use crate::{
     next_solver::{
         BoundExistentialPredicate, Ctor, DbInterner, GenericArgs, SolverDefId,
         mapping::{
-            ChalkToNextSolver, bound_var_to_lifetime_idx, bound_var_to_type_or_const_param_idx,
-            convert_args_for_result, convert_const_for_result, convert_region_for_result,
-            convert_ty_for_result,
+            ChalkToNextSolver, convert_args_for_result, convert_const_for_result,
+            convert_region_for_result, convert_ty_for_result,
         },
     },
     primitive, to_assoc_type_id,
@@ -641,7 +640,7 @@ impl HirDisplay for ProjectionTy {
             && !f.bounds_formatting_ctx.contains(self)
         {
             let db = f.db;
-            let id = from_placeholder_idx(db, *idx);
+            let id = from_placeholder_idx(db, *idx).0;
             let generics = generics(db, id.parent);
 
             let substs = generics.placeholder_subst(db);
@@ -736,14 +735,14 @@ impl HirDisplay for Const {
 impl<'db> HirDisplay for crate::next_solver::Const<'db> {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         match self.kind() {
+            rustc_type_ir::ConstKind::Placeholder(_) => write!(f, "<placeholder>"),
             rustc_type_ir::ConstKind::Bound(db, bound_const) => {
                 write!(f, "?{}.{}", db.as_u32(), bound_const.as_u32())
             }
             rustc_type_ir::ConstKind::Infer(..) => write!(f, "#c#"),
-            rustc_type_ir::ConstKind::Placeholder(idx) => {
-                let id = bound_var_to_type_or_const_param_idx(f.db, idx.bound);
-                let generics = generics(f.db, id.parent);
-                let param_data = &generics[id.local_id];
+            rustc_type_ir::ConstKind::Param(param) => {
+                let generics = generics(f.db, param.id.parent());
+                let param_data = &generics[param.id.local_id()];
                 write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;
                 Ok(())
             }
@@ -765,7 +764,6 @@ impl<'db> HirDisplay for crate::next_solver::Const<'db> {
             }
             rustc_type_ir::ConstKind::Error(..) => f.write_char('_'),
             rustc_type_ir::ConstKind::Expr(..) => write!(f, "<const-expr>"),
-            rustc_type_ir::ConstKind::Param(_) => write!(f, "<param>"),
         }
     }
 }
@@ -1178,7 +1176,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
                 if let TyKind::Ref(l, _, _) = kind {
                     f.write_char('&')?;
                     if f.render_region(l) {
-                        convert_region_for_result(l).hir_fmt(f)?;
+                        convert_region_for_result(interner, l).hir_fmt(f)?;
                         f.write_char(' ')?;
                     }
                     match m {
@@ -1611,14 +1609,10 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
                     write!(f, "{{closure}}")?;
                 }
             }
-            TyKind::Placeholder(idx) => {
-                let placeholder_index = chalk_ir::PlaceholderIndex {
-                    idx: idx.bound.var.as_usize(),
-                    ui: chalk_ir::UniverseIndex { counter: idx.universe.as_usize() },
-                };
-                let id = from_placeholder_idx(db, placeholder_index);
-                let generics = generics(db, id.parent);
-                let param_data = &generics[id.local_id];
+            TyKind::Placeholder(_) => write!(f, "{{placeholder}}")?,
+            TyKind::Param(param) => {
+                let generics = generics(db, param.id.parent());
+                let param_data = &generics[param.id.local_id()];
                 match param_data {
                     TypeOrConstParamData::TypeParamData(p) => match p.provenance {
                         TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
@@ -1634,7 +1628,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
                         TypeParamProvenance::ArgumentImplTrait => {
                             let substs = generics.placeholder_subst(db);
                             let bounds = db
-                                .generic_predicates(id.parent)
+                                .generic_predicates(param.id.parent())
                                 .iter()
                                 .map(|pred| pred.clone().substitute(Interner, &substs))
                                 .filter(|wc| match wc.skip_binders() {
@@ -1656,7 +1650,7 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
                                     WhereClause::LifetimeOutlives(_) => false,
                                 })
                                 .collect::<Vec<_>>();
-                            let krate = id.parent.module(db).krate();
+                            let krate = param.id.parent().module(db).krate();
                             write_bounds_like_dyn_trait_with_prefix(
                                 f,
                                 "impl",
@@ -1671,7 +1665,6 @@ impl<'db> HirDisplay for crate::next_solver::Ty<'db> {
                     }
                 }
             }
-            TyKind::Param(_) => write!(f, "{{param}}")?,
             TyKind::Bound(debruijn_index, ty) => {
                 let idx = chalk_ir::BoundVar {
                     debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
@@ -2294,7 +2287,7 @@ impl HirDisplay for LifetimeData {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         match self {
             LifetimeData::Placeholder(idx) => {
-                let id = lt_from_placeholder_idx(f.db, *idx);
+                let id = lt_from_placeholder_idx(f.db, *idx).0;
                 let generics = generics(f.db, id.parent);
                 let param_data = &generics[id.local_id];
                 write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
@@ -2319,10 +2312,9 @@ impl HirDisplay for LifetimeData {
 impl<'db> HirDisplay for crate::next_solver::Region<'db> {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         match self.kind() {
-            rustc_type_ir::RegionKind::RePlaceholder(idx) => {
-                let id = bound_var_to_lifetime_idx(f.db, idx.bound.var);
-                let generics = generics(f.db, id.parent);
-                let param_data = &generics[id.local_id];
+            rustc_type_ir::RegionKind::ReEarlyParam(param) => {
+                let generics = generics(f.db, param.id.parent);
+                let param_data = &generics[param.id.local_id];
                 write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
                 Ok(())
             }
@@ -2339,7 +2331,7 @@ impl<'db> HirDisplay for crate::next_solver::Region<'db> {
                 }
             }
             rustc_type_ir::RegionKind::ReErased => write!(f, "'<erased>"),
-            rustc_type_ir::RegionKind::ReEarlyParam(_) => write!(f, "<param>"),
+            rustc_type_ir::RegionKind::RePlaceholder(_) => write!(f, "<placeholder>"),
             rustc_type_ir::RegionKind::ReLateParam(_) => write!(f, "<late-param>"),
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index b0c61c29db0..23280b1f3b4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -2,10 +2,12 @@
 
 use std::ops::ControlFlow;
 
+use hir_def::hir::generics::LocalTypeOrConstParamId;
 use hir_def::{
     AssocItemId, ConstId, CrateRootModuleId, FunctionId, GenericDefId, HasModule, TraitId,
     TypeAliasId, lang_item::LangItem, signatures::TraitFlags,
 };
+use hir_def::{TypeOrConstParamId, TypeParamId};
 use intern::Symbol;
 use rustc_hash::FxHashSet;
 use rustc_type_ir::{
@@ -384,7 +386,6 @@ where
         }
 
         // Allow `impl AutoTrait` predicates
-        let interner = DbInterner::new_with(db, Some(trait_.krate(db)), None);
         if let ClauseKind::Trait(TraitPredicate {
             trait_ref: pred_trait_ref,
             polarity: PredicatePolarity::Positive,
@@ -392,11 +393,8 @@ where
             && let SolverDefId::TraitId(trait_id) = pred_trait_ref.def_id
             && let trait_data = db.trait_signature(trait_id)
             && trait_data.flags.contains(TraitFlags::AUTO)
-            && pred_trait_ref.self_ty()
-                == crate::next_solver::Ty::new(
-                    interner,
-                    rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0 }),
-                )
+            && let rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, .. }) =
+                pred_trait_ref.self_ty().kind()
         {
             continue;
         }
@@ -422,9 +420,13 @@ fn receiver_is_dispatchable<'db>(
     let sig = sig.instantiate_identity();
 
     let interner: DbInterner<'_> = DbInterner::new_with(db, Some(trait_.krate(db)), None);
+    let self_param_id = TypeParamId::from_unchecked(TypeOrConstParamId {
+        parent: trait_.into(),
+        local_id: LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)),
+    });
     let self_param_ty = crate::next_solver::Ty::new(
         interner,
-        rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0 }),
+        rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, id: self_param_id }),
     );
 
     // `self: Self` can't be dispatched on, but this is already considered dyn-compatible
@@ -452,7 +454,9 @@ fn receiver_is_dispatchable<'db>(
     };
 
     // Type `U`
-    let unsized_self_ty = crate::next_solver::Ty::new_param(interner, u32::MAX, Symbol::empty());
+    // FIXME: That seems problematic to fake a generic param like that?
+    let unsized_self_ty =
+        crate::next_solver::Ty::new_param(interner, self_param_id, u32::MAX, Symbol::empty());
     // `Receiver[Self => U]`
     let unsized_receiver_ty = receiver_for_self_ty(interner, func, receiver_ty, unsized_self_ty);
 
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 412b3ac4250..e179e41b1cb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -256,15 +256,15 @@ impl Generics {
     pub fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution {
         Substitution::from_iter(
             Interner,
-            self.iter_id().map(|id| match id {
+            self.iter_id().enumerate().map(|(index, id)| match id {
                 GenericParamId::TypeParamId(id) => {
-                    to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
+                    to_placeholder_idx(db, id.into(), index as u32).to_ty(Interner).cast(Interner)
                 }
-                GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into())
+                GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into(), index as u32)
                     .to_const(Interner, db.const_param_ty(id))
                     .cast(Interner),
                 GenericParamId::LifetimeParamId(id) => {
-                    lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
+                    lt_to_placeholder_idx(db, id, index as u32).to_lifetime(Interner).cast(Interner)
                 }
             }),
         )
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 38ac2e11707..9ef046afdb3 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
@@ -866,7 +866,7 @@ impl CapturedItemWithoutTy {
                     idx: chalk_ir::PlaceholderIndex,
                     outer_binder: DebruijnIndex,
                 ) -> Result<chalk_ir::Const<Interner>, Self::Error> {
-                    let x = from_placeholder_idx(self.db, idx);
+                    let x = from_placeholder_idx(self.db, idx).0;
                     let Some(idx) = self.generics.type_or_const_param_idx(x) else {
                         return Err(());
                     };
@@ -878,7 +878,7 @@ impl CapturedItemWithoutTy {
                     idx: chalk_ir::PlaceholderIndex,
                     outer_binder: DebruijnIndex,
                 ) -> std::result::Result<Ty, Self::Error> {
-                    let x = from_placeholder_idx(self.db, idx);
+                    let x = from_placeholder_idx(self.db, idx).0;
                     let Some(idx) = self.generics.type_or_const_param_idx(x) else {
                         return Err(());
                     };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index e2ee8935a88..f8abb3b7f6f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -19,14 +19,15 @@ use rustc_type_ir::{
 };
 use triomphe::Arc;
 
+use crate::utils::ClosureSubst;
 use crate::{
-    TraitEnvironment,
+    Interner, TraitEnvironment,
     consteval_nextsolver::try_const_usize,
     db::HirDatabase,
     next_solver::{
         DbInterner, GenericArgs, ParamEnv, SolverDefId, Ty, TyKind, TypingMode,
         infer::{DbInternerInferExt, traits::ObligationCause},
-        mapping::{ChalkToNextSolver, convert_binder_to_early_binder},
+        mapping::{ChalkToNextSolver, convert_args_for_result},
         project::solve_normalize::deeply_normalize,
     },
 };
@@ -333,9 +334,15 @@ pub fn layout_of_ty_query<'db>(
             let fields = captures
                 .iter()
                 .map(|it| {
-                    let ty =
-                        convert_binder_to_early_binder(interner, it.ty.to_nextsolver(interner))
-                            .instantiate(interner, args);
+                    let ty = it
+                        .ty
+                        .clone()
+                        .substitute(
+                            Interner,
+                            ClosureSubst(&convert_args_for_result(interner, args.inner()))
+                                .parent_subst(),
+                        )
+                        .to_nextsolver(interner);
                     db.layout_of_ty(ty, trait_env.clone())
                 })
                 .collect::<Result<Vec<_>, _>>()?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 7fdfb205721..c16bbb7b992 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -124,7 +124,7 @@ pub use lower_nextsolver::associated_type_shorthand_candidates;
 pub use mapping::{
     ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
     lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
-    to_foreign_def_id, to_placeholder_idx,
+    to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index,
 };
 pub use method_resolution::check_orphan_rules;
 pub use target_feature::TargetFeatures;
@@ -1007,7 +1007,7 @@ struct PlaceholderCollector<'db> {
 
 impl PlaceholderCollector<'_> {
     fn collect(&mut self, idx: PlaceholderIndex) {
-        let id = from_placeholder_idx(self.db, idx);
+        let id = from_placeholder_idx(self.db, idx).0;
         self.placeholders.insert(id);
     }
 }
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 098c62ba97a..79f78c545e5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -340,7 +340,13 @@ impl<'a> TyLoweringContext<'a> {
                 res = Some(TypeNs::GenericParam(type_param_id));
                 match self.type_param_mode {
                     ParamLoweringMode::Placeholder => {
-                        TyKind::Placeholder(to_placeholder_idx(self.db, type_param_id.into()))
+                        let generics = self.generics();
+                        let idx = generics.type_or_const_param_idx(type_param_id.into()).unwrap();
+                        TyKind::Placeholder(to_placeholder_idx(
+                            self.db,
+                            type_param_id.into(),
+                            idx as u32,
+                        ))
                     }
                     ParamLoweringMode::Variable => {
                         let idx =
@@ -777,7 +783,9 @@ impl<'a> TyLoweringContext<'a> {
                 LifetimeNs::Static => static_lifetime(),
                 LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
                     ParamLoweringMode::Placeholder => {
-                        LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
+                        let generics = self.generics();
+                        let idx = generics.lifetime_idx(id).unwrap();
+                        LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id, idx as u32))
                     }
                     ParamLoweringMode::Variable => {
                         let idx = match self.generics().lifetime_idx(id) {
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 fb85909d7f4..b0132e4dcbc 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
@@ -222,7 +222,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
             }
             TypeNs::GenericParam(param_id) => match self.ctx.type_param_mode {
                 ParamLoweringMode::Placeholder => {
-                    TyKind::Placeholder(to_placeholder_idx(self.ctx.db, param_id.into()))
+                    let generics = self.ctx.generics();
+                    let idx = generics.type_or_const_param_idx(param_id.into()).unwrap();
+                    TyKind::Placeholder(to_placeholder_idx(
+                        self.ctx.db,
+                        param_id.into(),
+                        idx as u32,
+                    ))
                 }
                 ParamLoweringMode::Variable => {
                     let idx = match self.ctx.generics().type_or_const_param_idx(param_id.into()) {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs
index d87181f545d..4578922ce32 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs
@@ -64,8 +64,7 @@ use crate::{
         AdtDef, AliasTy, Binder, BoundExistentialPredicates, BoundRegionKind, BoundTyKind,
         BoundVarKind, BoundVarKinds, Clause, Clauses, Const, DbInterner, EarlyBinder,
         EarlyParamRegion, ErrorGuaranteed, GenericArgs, PolyFnSig, Predicate, Region, SolverDefId,
-        TraitPredicate, TraitRef, Ty, Tys, abi::Safety, generics::GenericParamDefKind,
-        mapping::ChalkToNextSolver,
+        TraitPredicate, TraitRef, Ty, Tys, abi::Safety, mapping::ChalkToNextSolver,
     },
 };
 
@@ -322,6 +321,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
                 };
                 Ty::new_param(
                     self.interner,
+                    type_param_id,
                     idx as u32,
                     type_data
                         .name
@@ -866,7 +866,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
                         None => return Region::error(self.interner),
                         Some(idx) => idx,
                     };
-                    Region::new_early_param(self.interner, EarlyParamRegion { index: idx as u32 })
+                    Region::new_early_param(
+                        self.interner,
+                        EarlyParamRegion { index: idx as u32, id },
+                    )
                 }
             },
             None => Region::error(self.interner),
@@ -1344,11 +1347,11 @@ where
                     {
                         continue;
                     }
-                    let GenericParamDefKind::Type = p.kind else {
+                    let GenericParamId::TypeParamId(param_id) = p.id else {
                         continue;
                     };
                     let idx = idx as u32 + generics.parent_count as u32;
-                    let param_ty = Ty::new_param(interner, idx, p.name.clone());
+                    let param_ty = Ty::new_param(interner, param_id, idx, p.name.clone());
                     if explicitly_unsized_tys.contains(&param_ty) {
                         continue;
                     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs
index e3efb383064..ccdb5a0bdb4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs
@@ -281,6 +281,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
                         };
                         Ty::new_param(
                             self.ctx.interner,
+                            param_id,
                             idx as u32,
                             p.name
                                 .as_ref()
@@ -758,6 +759,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
                     self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| {
                         convert_binder_to_early_binder(
                             self.ctx.ctx.interner,
+                            def,
                             default.to_nextsolver(self.ctx.ctx.interner),
                         )
                         .instantiate(self.ctx.ctx.interner, preceding_args)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
index 448fbdf6736..5125a38825c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
@@ -104,7 +104,10 @@ pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
     FromId::from_id(id.0)
 }
 
-pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId {
+pub fn from_placeholder_idx(
+    db: &dyn HirDatabase,
+    idx: PlaceholderIndex,
+) -> (TypeOrConstParamId, u32) {
     assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
     // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
     let interned_id =
@@ -112,15 +115,32 @@ pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> Type
     interned_id.loc(db)
 }
 
-pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex {
-    let interned_id = InternedTypeOrConstParamId::new(db, id);
+pub fn to_placeholder_idx(
+    db: &dyn HirDatabase,
+    id: TypeOrConstParamId,
+    idx: u32,
+) -> PlaceholderIndex {
+    let interned_id = InternedTypeOrConstParamId::new(db, (id, idx));
     PlaceholderIndex {
         ui: chalk_ir::UniverseIndex::ROOT,
         idx: interned_id.as_id().index() as usize,
     }
 }
 
-pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
+pub fn to_placeholder_idx_no_index(
+    db: &dyn HirDatabase,
+    id: TypeOrConstParamId,
+) -> PlaceholderIndex {
+    let index = crate::generics::generics(db, id.parent)
+        .type_or_const_param_idx(id)
+        .expect("param not found");
+    to_placeholder_idx(db, id, index as u32)
+}
+
+pub fn lt_from_placeholder_idx(
+    db: &dyn HirDatabase,
+    idx: PlaceholderIndex,
+) -> (LifetimeParamId, u32) {
     assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
     // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
     let interned_id =
@@ -128,8 +148,12 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
     interned_id.loc(db)
 }
 
-pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
-    let interned_id = InternedLifetimeParamId::new(db, id);
+pub fn lt_to_placeholder_idx(
+    db: &dyn HirDatabase,
+    id: LifetimeParamId,
+    idx: u32,
+) -> PlaceholderIndex {
+    let interned_id = InternedLifetimeParamId::new(db, (id, idx));
     PlaceholderIndex {
         ui: chalk_ir::UniverseIndex::ROOT,
         idx: interned_id.as_id().index() as usize,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
index d8f443145ca..b0b92231691 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
@@ -99,7 +99,7 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
         idx: chalk_ir::PlaceholderIndex,
         _outer_binder: DebruijnIndex,
     ) -> std::result::Result<chalk_ir::Const<Interner>, Self::Error> {
-        let it = from_placeholder_idx(self.db, idx);
+        let it = from_placeholder_idx(self.db, idx).0;
         let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else {
             not_supported!("missing idx in generics");
         };
@@ -117,7 +117,7 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
         idx: chalk_ir::PlaceholderIndex,
         _outer_binder: DebruijnIndex,
     ) -> std::result::Result<Ty, Self::Error> {
-        let it = from_placeholder_idx(self.db, idx);
+        let it = from_placeholder_idx(self.db, idx).0;
         let Some(idx) = self.generics.as_ref().and_then(|g| g.type_or_const_param_idx(it)) else {
             not_supported!("missing idx in generics");
         };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs
index ce581cfad4b..cfafc65d184 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs
@@ -2,6 +2,7 @@
 
 use std::hash::Hash;
 
+use hir_def::{ConstParamId, TypeOrConstParamId};
 use intern::{Interned, Symbol};
 use rustc_ast_ir::try_visit;
 use rustc_ast_ir::visit::VisitorResult;
@@ -84,6 +85,8 @@ pub type PlaceholderConst = Placeholder<rustc_type_ir::BoundVar>;
 
 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
 pub struct ParamConst {
+    // FIXME: See `ParamTy`.
+    pub id: ConstParamId,
     pub index: u32,
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs
index 76186e37460..d284eb9c6b4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs
@@ -1,5 +1,6 @@
 //! Things related to generic args in the next-trait-solver.
 
+use hir_def::GenericParamId;
 use intern::{Interned, Symbol};
 use rustc_type_ir::{
     ClosureArgs, CollectAndApply, ConstVid, CoroutineArgs, CoroutineClosureArgs, FnSig, FnSigTys,
@@ -14,7 +15,7 @@ use crate::db::HirDatabase;
 
 use super::{
     Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty, Tys,
-    generics::{GenericParamDef, GenericParamDefKind, Generics},
+    generics::{GenericParamDef, Generics},
     interned_vec_db,
 };
 
@@ -203,7 +204,7 @@ impl<'db> GenericArgs<'db> {
         mut mk_kind: F,
     ) -> GenericArgs<'db>
     where
-        F: FnMut(&Symbol, u32, GenericParamDefKind, &[GenericArg<'db>]) -> GenericArg<'db>,
+        F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
     {
         let defs = interner.generics_of(def_id);
         let count = defs.count();
@@ -218,7 +219,7 @@ impl<'db> GenericArgs<'db> {
         defs: Generics,
         mk_kind: &mut F,
     ) where
-        F: FnMut(&Symbol, u32, GenericParamDefKind, &[GenericArg<'db>]) -> GenericArg<'db>,
+        F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
     {
         let self_len = defs.own_params.len() as u32;
         if let Some(def_id) = defs.parent {
@@ -230,12 +231,12 @@ impl<'db> GenericArgs<'db> {
 
     fn fill_single<F>(args: &mut SmallVec<[GenericArg<'db>; 8]>, defs: &Generics, mk_kind: &mut F)
     where
-        F: FnMut(&Symbol, u32, GenericParamDefKind, &[GenericArg<'db>]) -> GenericArg<'db>,
+        F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>,
     {
         let start_len = args.len();
         args.reserve(defs.own_params.len());
         for param in &defs.own_params {
-            let kind = mk_kind(&param.name, args.len() as u32, param.kind, args);
+            let kind = mk_kind(&param.name, args.len() as u32, param.id, args);
             args.push(kind);
         }
     }
@@ -412,26 +413,25 @@ pub fn mk_param<'db>(
     interner: DbInterner<'db>,
     index: u32,
     name: &Symbol,
-    kind: GenericParamDefKind,
+    id: GenericParamId,
 ) -> GenericArg<'db> {
     let name = name.clone();
-    match kind {
-        GenericParamDefKind::Lifetime => {
-            Region::new_early_param(interner, EarlyParamRegion { index }).into()
+    match id {
+        GenericParamId::LifetimeParamId(id) => {
+            Region::new_early_param(interner, EarlyParamRegion { index, id }).into()
+        }
+        GenericParamId::TypeParamId(id) => Ty::new_param(interner, id, index, name).into(),
+        GenericParamId::ConstParamId(id) => {
+            Const::new_param(interner, ParamConst { index, id }).into()
         }
-        GenericParamDefKind::Type => Ty::new_param(interner, index, name).into(),
-        GenericParamDefKind::Const => Const::new_param(interner, ParamConst { index }).into(),
     }
 }
 
-pub fn error_for_param_kind<'db>(
-    kind: GenericParamDefKind,
-    interner: DbInterner<'db>,
-) -> GenericArg<'db> {
-    match kind {
-        GenericParamDefKind::Lifetime => Region::error(interner).into(),
-        GenericParamDefKind::Type => Ty::new_error(interner, ErrorGuaranteed).into(),
-        GenericParamDefKind::Const => Const::error(interner).into(),
+pub fn error_for_param_kind<'db>(id: GenericParamId, interner: DbInterner<'db>) -> GenericArg<'db> {
+    match id {
+        GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
+        GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
+        GenericParamId::ConstParamId(_) => Const::error(interner).into(),
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs
index a3ba8eb8345..5ec9a18a6c2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generics.rs
@@ -24,35 +24,40 @@ use super::{Const, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, Solver
 use super::{DbInterner, GenericArg};
 
 pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
-    let mk_lt = |index, lt: &LifetimeParamData| {
+    let mk_lt = |parent, index, local_id, lt: &LifetimeParamData| {
         let name = lt.name.symbol().clone();
-        let kind = GenericParamDefKind::Lifetime;
-        GenericParamDef { name, index, kind }
+        let id = GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id });
+        GenericParamDef { name, index, id }
     };
-    let mk_ty = |index, p: &TypeOrConstParamData| {
+    let mk_ty = |parent, index, local_id, p: &TypeOrConstParamData| {
         let name = p.name().map(|n| n.symbol().clone()).unwrap_or_else(|| sym::MISSING_NAME);
-        let kind = match p {
-            TypeOrConstParamData::TypeParamData(_) => GenericParamDefKind::Type,
-            TypeOrConstParamData::ConstParamData(_) => GenericParamDefKind::Const,
+        let id = TypeOrConstParamId { parent, local_id };
+        let id = match p {
+            TypeOrConstParamData::TypeParamData(_) => {
+                GenericParamId::TypeParamId(TypeParamId::from_unchecked(id))
+            }
+            TypeOrConstParamData::ConstParamData(_) => {
+                GenericParamId::ConstParamId(ConstParamId::from_unchecked(id))
+            }
         };
-        GenericParamDef { name, index, kind }
+        GenericParamDef { name, index, id }
     };
-    let own_params_for_generic_params = |params: &GenericParams| {
+    let own_params_for_generic_params = |parent, params: &GenericParams| {
         let mut result = Vec::with_capacity(params.len());
         let mut type_and_consts = params.iter_type_or_consts();
         let mut index = 0;
         if let Some(self_param) = params.trait_self_param() {
-            result.push(mk_ty(0, &params[self_param]));
+            result.push(mk_ty(parent, 0, self_param, &params[self_param]));
             type_and_consts.next();
             index += 1;
         }
-        result.extend(params.iter_lt().map(|(_, data)| {
-            let lt = mk_lt(index, data);
+        result.extend(params.iter_lt().map(|(local_id, data)| {
+            let lt = mk_lt(parent, index, local_id, data);
             index += 1;
             lt
         }));
-        result.extend(type_and_consts.map(|(_, data)| {
-            let ty = mk_ty(index, data);
+        result.extend(type_and_consts.map(|(local_id, data)| {
+            let ty = mk_ty(parent, index, local_id, data);
             index += 1;
             ty
         }));
@@ -60,9 +65,10 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
     };
 
     let (parent, own_params) = match (def.try_into(), def) {
-        (Ok(def), _) => {
-            (parent_generic_def(db, def), own_params_for_generic_params(&db.generic_params(def)))
-        }
+        (Ok(def), _) => (
+            parent_generic_def(db, def),
+            own_params_for_generic_params(def, &db.generic_params(def)),
+        ),
         (_, SolverDefId::InternedOpaqueTyId(id)) => {
             match db.lookup_intern_impl_trait_id(id) {
                 crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => {
@@ -79,7 +85,19 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
                         provenance: TypeParamProvenance::TypeParamList,
                     });
                     // Yes, there is a parent but we don't include it in the generics
-                    (None, vec![mk_ty(0, &param)])
+                    // FIXME: It seems utterly sensitive to fake a generic param here.
+                    // Also, what a horrible mess!
+                    (
+                        None,
+                        vec![mk_ty(
+                            GenericDefId::FunctionId(salsa::plumbing::FromId::from_id(unsafe {
+                                salsa::Id::from_index(salsa::Id::MAX_U32 - 1)
+                            })),
+                            0,
+                            LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)),
+                            &param,
+                        )],
+                    )
                 }
             }
         }
@@ -106,7 +124,7 @@ pub struct GenericParamDef {
     pub(crate) name: Symbol,
     //def_id: GenericDefId,
     index: u32,
-    pub(crate) kind: GenericParamDefKind,
+    pub(crate) id: GenericParamId,
 }
 
 impl GenericParamDef {
@@ -117,13 +135,6 @@ impl GenericParamDef {
     }
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum GenericParamDefKind {
-    Lifetime,
-    Type,
-    Const,
-}
-
 impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics {
     fn count(&self) -> usize {
         self.parent_count + self.own_params.len()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs
index 19ae76f7e35..58832aef895 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -8,6 +8,7 @@ pub use BoundRegionConversionTime::*;
 pub use at::DefineOpaqueTypes;
 use ena::undo_log::UndoLogs;
 use ena::unify as ut;
+use hir_def::GenericParamId;
 use intern::Symbol;
 use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
 use region_constraints::{
@@ -38,7 +39,7 @@ use crate::next_solver::fold::BoundVarReplacerDelegate;
 use crate::next_solver::infer::opaque_types::table::OpaqueTypeStorageEntries;
 use crate::next_solver::{BoundRegion, BoundTy, BoundVarKind};
 
-use super::generics::{GenericParamDef, GenericParamDefKind};
+use super::generics::GenericParamDef;
 use super::{
     AliasTerm, Binder, BoundRegionKind, CanonicalQueryInput, CanonicalVarValues, Const, ConstKind,
     DbInterner, ErrorGuaranteed, FxIndexMap, GenericArg, GenericArgs, OpaqueTypeKey, ParamEnv,
@@ -600,14 +601,14 @@ impl<'db> InferCtxt<'db> {
         self.next_region_var_in_universe(universe)
     }
 
-    fn var_for_def(&self, kind: GenericParamDefKind, name: &Symbol) -> GenericArg<'db> {
-        match kind {
-            GenericParamDefKind::Lifetime => {
+    fn var_for_def(&self, id: GenericParamId, name: &Symbol) -> GenericArg<'db> {
+        match id {
+            GenericParamId::LifetimeParamId(_) => {
                 // Create a region inference variable for the given
                 // region parameter definition.
                 self.next_region_var().into()
             }
-            GenericParamDefKind::Type => {
+            GenericParamId::TypeParamId(_) => {
                 // Create a type inference variable for the given
                 // type parameter definition. The generic parameters are
                 // for actual parameters that may be referred to by
@@ -624,7 +625,7 @@ impl<'db> InferCtxt<'db> {
 
                 Ty::new_var(self.interner, ty_var_id).into()
             }
-            GenericParamDefKind::Const => {
+            GenericParamId::ConstParamId(_) => {
                 let origin = ConstVariableOrigin { param_def_id: None };
                 let const_var_id = self
                     .inner
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs
index 203f030dfd6..6755d065e10 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs
@@ -9,6 +9,7 @@ use hir_def::{
     CallableDefId, ConstParamId, FunctionId, GeneralConstId, LifetimeParamId, TypeAliasId,
     TypeOrConstParamId, TypeParamId, signatures::TraitFlags,
 };
+use hir_def::{GenericDefId, GenericParamId};
 use intern::sym;
 use rustc_type_ir::{
     AliasTerm, BoundVar, DebruijnIndex, ExistentialProjection, ExistentialTraitRef, Interner as _,
@@ -35,6 +36,9 @@ use crate::{
     },
     to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
 };
+use crate::{
+    from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_placeholder_idx,
+};
 
 use super::{
     BoundExistentialPredicate, BoundExistentialPredicates, BoundRegion, BoundRegionKind, BoundTy,
@@ -44,47 +48,24 @@ use super::{
     Region, SolverDefId, SubtypePredicate, Term, TraitRef, Ty, Tys, ValueConst, VariancesOf,
 };
 
-pub fn to_placeholder_idx<T: Clone + std::fmt::Debug>(
-    db: &dyn HirDatabase,
-    id: TypeOrConstParamId,
-    map: impl Fn(BoundVar) -> T,
-) -> Placeholder<T> {
-    let interned_id = InternedTypeOrConstParamId::new(db, id);
-    Placeholder {
-        universe: UniverseIndex::ZERO,
-        bound: map(BoundVar::from_usize(interned_id.as_id().index() as usize)),
-    }
-}
-
-pub fn bound_var_to_type_or_const_param_idx(
-    db: &dyn HirDatabase,
-    var: rustc_type_ir::BoundVar,
-) -> TypeOrConstParamId {
-    // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
-    let interned_id = InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(var.as_u32()) });
-    interned_id.loc(db)
-}
-
-pub fn bound_var_to_lifetime_idx(
-    db: &dyn HirDatabase,
-    var: rustc_type_ir::BoundVar,
-) -> LifetimeParamId {
-    // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
-    let interned_id = InternedLifetimeParamId::from_id(unsafe { Id::from_index(var.as_u32()) });
-    interned_id.loc(db)
-}
-
+// FIXME: This should urgently go (as soon as we finish the migration off Chalk, that is).
 pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable<DbInterner<'db>>>(
     interner: DbInterner<'db>,
+    def: GenericDefId,
     binder: rustc_type_ir::Binder<DbInterner<'db>, T>,
 ) -> rustc_type_ir::EarlyBinder<DbInterner<'db>, T> {
-    let mut folder = BinderToEarlyBinder { interner, debruijn: rustc_type_ir::DebruijnIndex::ZERO };
+    let mut folder = BinderToEarlyBinder {
+        interner,
+        debruijn: rustc_type_ir::DebruijnIndex::ZERO,
+        params: crate::generics::generics(interner.db, def).iter_id().collect(),
+    };
     rustc_type_ir::EarlyBinder::bind(binder.skip_binder().fold_with(&mut folder))
 }
 
 struct BinderToEarlyBinder<'db> {
     interner: DbInterner<'db>,
     debruijn: rustc_type_ir::DebruijnIndex,
+    params: Vec<GenericParamId>,
 }
 
 impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db> {
@@ -109,7 +90,13 @@ impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db
         match t.kind() {
             rustc_type_ir::TyKind::Bound(debruijn, bound_ty) if self.debruijn == debruijn => {
                 let var: rustc_type_ir::BoundVar = bound_ty.var();
-                Ty::new(self.cx(), rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32() }))
+                let GenericParamId::TypeParamId(id) = self.params[bound_ty.var.as_usize()] else {
+                    unreachable!()
+                };
+                Ty::new(
+                    self.cx(),
+                    rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32(), id }),
+                )
             }
             _ => t.super_fold_with(self),
         }
@@ -119,10 +106,15 @@ impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db
         match r.kind() {
             rustc_type_ir::ReBound(debruijn, bound_region) if self.debruijn == debruijn => {
                 let var: rustc_type_ir::BoundVar = bound_region.var();
+                let GenericParamId::LifetimeParamId(id) = self.params[bound_region.var.as_usize()]
+                else {
+                    unreachable!()
+                };
                 Region::new(
                     self.cx(),
                     rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion {
                         index: var.as_u32(),
+                        id,
                     }),
                 )
             }
@@ -133,9 +125,12 @@ impl<'db> rustc_type_ir::TypeFolder<DbInterner<'db>> for BinderToEarlyBinder<'db
     fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
         match c.kind() {
             rustc_type_ir::ConstKind::Bound(debruijn, var) if self.debruijn == debruijn => {
+                let GenericParamId::ConstParamId(id) = self.params[var.as_usize()] else {
+                    unreachable!()
+                };
                 Const::new(
                     self.cx(),
-                    rustc_type_ir::ConstKind::Param(ParamConst { index: var.as_u32() }),
+                    rustc_type_ir::ConstKind::Param(ParamConst { index: var.as_u32(), id }),
                 )
             }
             _ => c.super_fold_with(self),
@@ -274,12 +269,6 @@ impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty<Interner> {
                     SolverDefId::TypeAliasId(crate::from_foreign_def_id(*foreign_def_id)),
                 ),
                 chalk_ir::TyKind::Error => rustc_type_ir::TyKind::Error(ErrorGuaranteed),
-                chalk_ir::TyKind::Placeholder(placeholder_index) => {
-                    rustc_type_ir::TyKind::Placeholder(PlaceholderTy::new_anon(
-                        placeholder_index.ui.to_nextsolver(interner),
-                        rustc_type_ir::BoundVar::from_usize(placeholder_index.idx),
-                    ))
-                }
                 chalk_ir::TyKind::Dyn(dyn_ty) => {
                     // exists<type> { for<...> ^1.0: ... }
                     let bounds = BoundExistentialPredicates::new_from_iter(
@@ -405,6 +394,26 @@ impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty<Interner> {
 
                     rustc_type_ir::TyKind::FnPtr(sig_tys, header)
                 }
+                // The schema here is quite confusing.
+                // The new solver, like rustc, uses `Param` and `EarlyBinder` for generic params. It uses `BoundVar`
+                // and `Placeholder` together with `Binder` for HRTB, which we mostly don't handle.
+                // Chalk uses `Placeholder` for generic params and `BoundVar` quite liberally, and this is quite a
+                // problem. `chalk_ir::TyKind::BoundVar` can represent either HRTB or generic params, depending on the
+                // context. When returned from signature queries, the outer `Binders` represent the generic params.
+                // But there are also inner `Binders` for HRTB.
+                // AFAIK there is no way to tell which of the meanings is relevant, so we just use `rustc_type_ir::Bound`
+                // here, and hope for the best. If you are working with new solver types, therefore, use the new solver
+                // lower queries.
+                // Hopefully sooner than later Chalk will be ripped from the codebase and we can avoid that problem.
+                // For details about the rustc setup, read: https://rustc-dev-guide.rust-lang.org/generic_parameters_summary.html
+                // and the following chapters.
+                chalk_ir::TyKind::Placeholder(placeholder_index) => {
+                    let (id, index) = from_placeholder_idx(interner.db, *placeholder_index);
+                    rustc_type_ir::TyKind::Param(ParamTy {
+                        id: TypeParamId::from_unchecked(id),
+                        index,
+                    })
+                }
                 chalk_ir::TyKind::BoundVar(bound_var) => rustc_type_ir::TyKind::Bound(
                     bound_var.debruijn.to_nextsolver(interner),
                     BoundTy {
@@ -440,10 +449,8 @@ impl<'db> ChalkToNextSolver<'db, Region<'db>> for chalk_ir::Lifetime<Interner> {
                     ))
                 }
                 chalk_ir::LifetimeData::Placeholder(placeholder_index) => {
-                    rustc_type_ir::RegionKind::RePlaceholder(PlaceholderRegion::new_anon(
-                        rustc_type_ir::UniverseIndex::from_u32(placeholder_index.ui.counter as u32),
-                        rustc_type_ir::BoundVar::from_u32(placeholder_index.idx as u32),
-                    ))
+                    let (id, index) = lt_from_placeholder_idx(interner.db, *placeholder_index);
+                    rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { id, index })
                 }
                 chalk_ir::LifetimeData::Static => rustc_type_ir::RegionKind::ReStatic,
                 chalk_ir::LifetimeData::Erased => rustc_type_ir::RegionKind::ReErased,
@@ -474,10 +481,11 @@ impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const<Interner> {
                     ))
                 }
                 chalk_ir::ConstValue::Placeholder(placeholder_index) => {
-                    rustc_type_ir::ConstKind::Placeholder(PlaceholderConst::new(
-                        placeholder_index.ui.to_nextsolver(interner),
-                        rustc_type_ir::BoundVar::from_usize(placeholder_index.idx),
-                    ))
+                    let (id, index) = from_placeholder_idx(interner.db, *placeholder_index);
+                    rustc_type_ir::ConstKind::Param(ParamConst {
+                        id: ConstParamId::from_unchecked(id),
+                        index,
+                    })
                 }
                 chalk_ir::ConstValue::Concrete(concrete_const) => match &concrete_const.interned {
                     ConstScalar::Bytes(bytes, memory) => {
@@ -971,7 +979,7 @@ pub fn convert_args_for_result<'db>(
                 substs.push(chalk_ir::GenericArgData::Ty(ty).intern(Interner));
             }
             rustc_type_ir::GenericArgKind::Lifetime(region) => {
-                let lifetime = convert_region_for_result(region);
+                let lifetime = convert_region_for_result(interner, region);
                 substs.push(chalk_ir::GenericArgData::Lifetime(lifetime).intern(Interner));
             }
             rustc_type_ir::GenericArgKind::Const(const_) => {
@@ -1074,7 +1082,7 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>)
                 rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut,
                 rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not,
             };
-            let r = convert_region_for_result(r);
+            let r = convert_region_for_result(interner, r);
             let ty = convert_ty_for_result(interner, ty);
             TyKind::Ref(mutability, r, ty)
         }
@@ -1122,17 +1130,23 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>)
             rustc_type_ir::AliasTyKind::Free => unimplemented!(),
         },
 
+        // For `Placeholder`, `Bound` and `Param`, see the comment on the reverse conversion.
         rustc_type_ir::TyKind::Placeholder(placeholder) => {
-            let ui = chalk_ir::UniverseIndex { counter: placeholder.universe.as_usize() };
-            let placeholder_index =
-                chalk_ir::PlaceholderIndex { idx: placeholder.bound.var.as_usize(), ui };
-            TyKind::Placeholder(placeholder_index)
+            unimplemented!(
+                "A `rustc_type_ir::TyKind::Placeholder` doesn't have a direct \
+                correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
+                It therefore feels safer to leave it panicking, but if you hit this panic \
+                feel free to do the same as in `rustc_type_ir::TyKind::Bound` here."
+            )
         }
-
         rustc_type_ir::TyKind::Bound(debruijn_index, ty) => TyKind::BoundVar(chalk_ir::BoundVar {
             debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
             index: ty.var.as_usize(),
         }),
+        rustc_type_ir::TyKind::Param(param) => {
+            let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index);
+            TyKind::Placeholder(placeholder)
+        }
 
         rustc_type_ir::TyKind::FnPtr(bound_sig, fn_header) => {
             let num_binders = bound_sig.bound_vars().len();
@@ -1254,7 +1268,8 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>)
                 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
             );
             let bounds = chalk_ir::Binders::new(binders, bounds);
-            let dyn_ty = chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(region) };
+            let dyn_ty =
+                chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(interner, region) };
             TyKind::Dyn(dyn_ty)
         }
 
@@ -1316,7 +1331,6 @@ pub(crate) fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>)
             TyKind::CoroutineWitness(id.into(), subst)
         }
 
-        rustc_type_ir::TyKind::Param(_) => unimplemented!(),
         rustc_type_ir::TyKind::UnsafeBinder(_) => unimplemented!(),
     }
     .intern(Interner)
@@ -1327,13 +1341,16 @@ pub fn convert_const_for_result<'db>(
     const_: Const<'db>,
 ) -> crate::Const {
     let value: chalk_ir::ConstValue<Interner> = match const_.kind() {
-        rustc_type_ir::ConstKind::Param(_) => unimplemented!(),
         rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(var)) => {
             chalk_ir::ConstValue::InferenceVar(chalk_ir::InferenceVar::from(var.as_u32()))
         }
         rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Fresh(fresh)) => {
             panic!("Vars should not be freshened.")
         }
+        rustc_type_ir::ConstKind::Param(param) => {
+            let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index);
+            chalk_ir::ConstValue::Placeholder(placeholder)
+        }
         rustc_type_ir::ConstKind::Bound(debruijn_index, var) => {
             chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new(
                 chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()),
@@ -1341,10 +1358,12 @@ pub fn convert_const_for_result<'db>(
             ))
         }
         rustc_type_ir::ConstKind::Placeholder(placeholder_const) => {
-            chalk_ir::ConstValue::Placeholder(chalk_ir::PlaceholderIndex {
-                ui: chalk_ir::UniverseIndex { counter: placeholder_const.universe.as_usize() },
-                idx: placeholder_const.bound.as_usize(),
-            })
+            unimplemented!(
+                "A `rustc_type_ir::ConstKind::Placeholder` doesn't have a direct \
+                correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
+                It therefore feels safer to leave it panicking, but if you hit this panic \
+                feel free to do the same as in `rustc_type_ir::ConstKind::Bound` here."
+            )
         }
         rustc_type_ir::ConstKind::Unevaluated(unevaluated_const) => {
             let id = match unevaluated_const.def {
@@ -1381,36 +1400,34 @@ pub fn convert_const_for_result<'db>(
     chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner)
 }
 
-pub fn convert_region_for_result<'db>(region: Region<'db>) -> crate::Lifetime {
-    match region.kind() {
-        rustc_type_ir::RegionKind::ReEarlyParam(early) => unimplemented!(),
-        rustc_type_ir::RegionKind::ReBound(db, bound) => chalk_ir::Lifetime::new(
-            Interner,
+pub fn convert_region_for_result<'db>(
+    interner: DbInterner<'db>,
+    region: Region<'db>,
+) -> crate::Lifetime {
+    let lifetime = match region.kind() {
+        rustc_type_ir::RegionKind::ReEarlyParam(early) => {
+            let placeholder = lt_to_placeholder_idx(interner.db, early.id, early.index);
+            chalk_ir::LifetimeData::Placeholder(placeholder)
+        }
+        rustc_type_ir::RegionKind::ReBound(db, bound) => {
             chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
                 chalk_ir::DebruijnIndex::new(db.as_u32()),
                 bound.var.as_usize(),
-            )),
-        ),
-        rustc_type_ir::RegionKind::ReLateParam(_) => unimplemented!(),
-        rustc_type_ir::RegionKind::ReStatic => {
-            chalk_ir::Lifetime::new(Interner, chalk_ir::LifetimeData::Static)
+            ))
         }
-        rustc_type_ir::RegionKind::ReVar(vid) => chalk_ir::Lifetime::new(
-            Interner,
-            chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32())),
-        ),
-        rustc_type_ir::RegionKind::RePlaceholder(placeholder) => chalk_ir::Lifetime::new(
-            Interner,
-            chalk_ir::LifetimeData::Placeholder(chalk_ir::PlaceholderIndex {
-                idx: placeholder.bound.var.as_usize(),
-                ui: chalk_ir::UniverseIndex { counter: placeholder.universe.as_usize() },
-            }),
+        rustc_type_ir::RegionKind::RePlaceholder(placeholder) => unimplemented!(
+            "A `rustc_type_ir::RegionKind::RePlaceholder` doesn't have a direct \
+            correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\
+            It therefore feels safer to leave it panicking, but if you hit this panic \
+            feel free to do the same as in `rustc_type_ir::RegionKind::ReBound` here."
         ),
-        rustc_type_ir::RegionKind::ReErased => {
-            chalk_ir::Lifetime::new(Interner, chalk_ir::LifetimeData::Erased)
-        }
-        rustc_type_ir::RegionKind::ReError(_) => {
-            chalk_ir::Lifetime::new(Interner, chalk_ir::LifetimeData::Error)
+        rustc_type_ir::RegionKind::ReLateParam(_) => unimplemented!(),
+        rustc_type_ir::RegionKind::ReStatic => chalk_ir::LifetimeData::Static,
+        rustc_type_ir::RegionKind::ReVar(vid) => {
+            chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32()))
         }
-    }
+        rustc_type_ir::RegionKind::ReErased => chalk_ir::LifetimeData::Erased,
+        rustc_type_ir::RegionKind::ReError(_) => chalk_ir::LifetimeData::Error,
+    };
+    chalk_ir::Lifetime::new(Interner, lifetime)
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs
index c59cdac5f99..d6214d99156 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs
@@ -1,5 +1,6 @@
 //! Things related to regions.
 
+use hir_def::LifetimeParamId;
 use intern::{Interned, Symbol};
 use rustc_type_ir::{
     BoundVar, Flags, INNERMOST, RegionVid, TypeFlags, TypeFoldable, TypeVisitable, VisitorResult,
@@ -110,6 +111,8 @@ pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct EarlyParamRegion {
+    // FIXME: See `ParamTy`.
+    pub id: LifetimeParamId,
     pub index: u32,
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs
index 5ffae981a60..92f1076e75e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs
@@ -1,5 +1,6 @@
 //! Things related to tys in the next-trait-solver.
 
+use hir_def::{GenericDefId, TypeOrConstParamId, TypeParamId};
 use intern::{Interned, Symbol, sym};
 use rustc_abi::{Float, Integer, Size};
 use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult};
@@ -64,8 +65,8 @@ impl<'db> Ty<'db> {
         .unwrap()
     }
 
-    pub fn new_param(interner: DbInterner<'db>, index: u32, name: Symbol) -> Self {
-        Ty::new(interner, TyKind::Param(ParamTy { index }))
+    pub fn new_param(interner: DbInterner<'db>, id: TypeParamId, index: u32, name: Symbol) -> Self {
+        Ty::new(interner, TyKind::Param(ParamTy { id, index }))
     }
 
     pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderTy) -> Self {
@@ -847,12 +848,16 @@ pub type PlaceholderTy = Placeholder<BoundTy>;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct ParamTy {
+    // FIXME: I'm not pleased with this. Ideally a `Param` should only know its index - the defining item
+    // is known from the `EarlyBinder`. This should also be beneficial for memory usage. But code currently
+    // assumes it can get the definition from `Param` alone - so that's what we got.
+    pub id: TypeParamId,
     pub index: u32,
 }
 
 impl ParamTy {
     pub fn to_ty<'db>(self, interner: DbInterner<'db>) -> Ty<'db> {
-        Ty::new_param(interner, self.index, sym::MISSING_NAME.clone())
+        Ty::new_param(interner, self.id, self.index, sym::MISSING_NAME.clone())
     }
 }
 
@@ -865,6 +870,7 @@ impl std::fmt::Debug for ParamTy {
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct BoundTy {
     pub var: BoundVar,
+    // FIXME: This is for diagnostics in rustc, do we really need it?
     pub kind: BoundTyKind,
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
index d8a058533f7..a1ebff04bbd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
@@ -344,7 +344,7 @@ impl Context<'_> {
 
             // Chalk has no params, so use placeholders for now?
             TyKind::Placeholder(index) => {
-                let idx = crate::from_placeholder_idx(self.db, *index);
+                let idx = crate::from_placeholder_idx(self.db, *index).0;
                 let index = self.generics.type_or_const_param_idx(idx).unwrap();
                 self.constrain(index, variance);
             }
@@ -445,7 +445,7 @@ impl Context<'_> {
         );
         match region.data(Interner) {
             LifetimeData::Placeholder(index) => {
-                let idx = crate::lt_from_placeholder_idx(self.db, *index);
+                let idx = crate::lt_from_placeholder_idx(self.db, *index).0;
                 let inferred = self.generics.lifetime_idx(idx).unwrap();
                 self.constrain(inferred, variance);
             }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index b9c5131ffbb..833a9ef0306 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -474,8 +474,8 @@ impl HirDisplay for TypeParam {
         let param_data = &params[self.id.local_id()];
         let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
         let krate = self.id.parent().krate(f.db).id;
-        let ty =
-            TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())).intern(Interner);
+        let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(f.db, self.id.into()))
+            .intern(Interner);
         let predicates = f.db.generic_predicates(self.id.parent());
         let predicates = predicates
             .iter()
@@ -528,8 +528,11 @@ impl HirDisplay for TypeParam {
                 f,
                 ":",
                 Either::Left(
-                    &hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into()))
-                        .intern(Interner),
+                    &hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(
+                        f.db,
+                        self.id.into(),
+                    ))
+                    .intern(Interner),
                 ),
                 &predicates,
                 default_sized,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index f03f542e5bc..46d3a2bcd67 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -4239,8 +4239,8 @@ impl TypeParam {
 
     pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
         let resolver = self.id.parent().resolver(db);
-        let ty =
-            TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
+        let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(db, self.id.into()))
+            .intern(Interner);
         Type::new_with_resolver_inner(db, &resolver, ty)
     }
 
@@ -5933,7 +5933,7 @@ impl<'db> Type<'db> {
     pub fn as_type_param(&self, db: &'db dyn HirDatabase) -> Option<TypeParam> {
         match self.ty.kind(Interner) {
             TyKind::Placeholder(p) => Some(TypeParam {
-                id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
+                id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p).0),
             }),
             _ => None,
         }