Unnamed repository; edit this file 'description' to name the repository.
Make sense of the mess that were (are) different kind of generics in the solver
To the extent possible. Previously they were confused. Sometimes generic params were treated as `Param` and sometimes as `Placeholder`. A completely redundant (in the new solver) mapping of salsa::Id to ints to intern some info where we could just store it uninterned (not in Chalk though, for some weird reason). Plus fix a cute bug in closure substitution that was caught by the assertions of Chalk but the next solver did not have such assertions. Do we need more assertions?
Chayim Refael Friedman 8 months ago
parent 21614ed · commit 41611b1
-rw-r--r--crates/hir-ty/src/chalk_ext.rs2
-rw-r--r--crates/hir-ty/src/consteval.rs29
-rw-r--r--crates/hir-ty/src/consteval_nextsolver.rs2
-rw-r--r--crates/hir-ty/src/db.rs6
-rw-r--r--crates/hir-ty/src/display.rs46
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs20
-rw-r--r--crates/hir-ty/src/generics.rs8
-rw-r--r--crates/hir-ty/src/infer/closure.rs4
-rw-r--r--crates/hir-ty/src/layout.rs17
-rw-r--r--crates/hir-ty/src/lib.rs4
-rw-r--r--crates/hir-ty/src/lower.rs12
-rw-r--r--crates/hir-ty/src/lower/path.rs8
-rw-r--r--crates/hir-ty/src/lower_nextsolver.rs13
-rw-r--r--crates/hir-ty/src/lower_nextsolver/path.rs2
-rw-r--r--crates/hir-ty/src/mapping.rs36
-rw-r--r--crates/hir-ty/src/mir/monomorphization.rs4
-rw-r--r--crates/hir-ty/src/next_solver/consts.rs3
-rw-r--r--crates/hir-ty/src/next_solver/generic_arg.rs38
-rw-r--r--crates/hir-ty/src/next_solver/generics.rs63
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs13
-rw-r--r--crates/hir-ty/src/next_solver/mapping.rs191
-rw-r--r--crates/hir-ty/src/next_solver/region.rs3
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs12
-rw-r--r--crates/hir-ty/src/variance.rs4
-rw-r--r--crates/hir/src/display.rs11
-rw-r--r--crates/hir/src/lib.rs6
26 files changed, 324 insertions, 233 deletions
diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs
index 8fa1aff0ef..33ae099c69 100644
--- a/crates/hir-ty/src/chalk_ext.rs
+++ b/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/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index abf97f3d0e..0f2cc17f56 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/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/crates/hir-ty/src/consteval_nextsolver.rs b/crates/hir-ty/src/consteval_nextsolver.rs
index 00fc4e5610..4f95c9a13a 100644
--- a/crates/hir-ty/src/consteval_nextsolver.rs
+++ b/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/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 97754f4723..0b7213d785 100644
--- a/crates/hir-ty/src/db.rs
+++ b/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/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 0df727a8e5..5b8093f6b7 100644
--- a/crates/hir-ty/src/display.rs
+++ b/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/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index b0c61c29db..23280b1f3b 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/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/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index 412b3ac425..e179e41b1c 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/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/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 38ac2e1170..9ef046afdb 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/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/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index e2ee8935a8..f8abb3b7f6 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/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/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 7fdfb20572..c16bbb7b99 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/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/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 098c62ba97..79f78c545e 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/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/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index fb85909d7f..b0132e4dcb 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/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/crates/hir-ty/src/lower_nextsolver.rs b/crates/hir-ty/src/lower_nextsolver.rs
index d87181f545..4578922ce3 100644
--- a/crates/hir-ty/src/lower_nextsolver.rs
+++ b/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/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs
index e3efb38306..ccdb5a0bdb 100644
--- a/crates/hir-ty/src/lower_nextsolver/path.rs
+++ b/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/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs
index 448fbdf673..5125a38825 100644
--- a/crates/hir-ty/src/mapping.rs
+++ b/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/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index d8f443145c..b0b9223169 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/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/crates/hir-ty/src/next_solver/consts.rs b/crates/hir-ty/src/next_solver/consts.rs
index ce581cfad4..cfafc65d18 100644
--- a/crates/hir-ty/src/next_solver/consts.rs
+++ b/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/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs
index 76186e3746..d284eb9c6b 100644
--- a/crates/hir-ty/src/next_solver/generic_arg.rs
+++ b/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/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs
index a3ba8eb834..5ec9a18a6c 100644
--- a/crates/hir-ty/src/next_solver/generics.rs
+++ b/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/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index 19ae76f7e3..58832aef89 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/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/crates/hir-ty/src/next_solver/mapping.rs b/crates/hir-ty/src/next_solver/mapping.rs
index 203f030dfd..6755d065e1 100644
--- a/crates/hir-ty/src/next_solver/mapping.rs
+++ b/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/crates/hir-ty/src/next_solver/region.rs b/crates/hir-ty/src/next_solver/region.rs
index c59cdac5f9..d6214d9915 100644
--- a/crates/hir-ty/src/next_solver/region.rs
+++ b/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/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 5ffae981a6..92f1076e75 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/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/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs
index d8a058533f..a1ebff04bb 100644
--- a/crates/hir-ty/src/variance.rs
+++ b/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/crates/hir/src/display.rs b/crates/hir/src/display.rs
index b9c5131ffb..833a9ef030 100644
--- a/crates/hir/src/display.rs
+++ b/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/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index f03f542e5b..46d3a2bcd6 100644
--- a/crates/hir/src/lib.rs
+++ b/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,
}