Update chalk

This commit is contained in:
jackh726 2025-04-19 05:52:28 +00:00
parent 150bb4a00f
commit 6daa791fab
16 changed files with 168 additions and 175 deletions

16
Cargo.lock generated
View file

@ -200,9 +200,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "chalk-derive" name = "chalk-derive"
version = "0.100.0" version = "0.102.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2d131019373f0d0d1f2af0abd4f719739f6583c1b33965112455f643a910af" checksum = "feb14e3ff0ebac26d8e58b6ed1417afb60c4a0a44b6425546ee7eb9c75ebb336"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -212,9 +212,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-ir" name = "chalk-ir"
version = "0.100.0" version = "0.102.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f114996bda14c0213f014a4ef31a7867dcf5f539a3900477fc6b20138e7a17b" checksum = "72f0a61621a088af69fee8df39ec63cf5b6d0b9ab663a740cdeb376aabf2f244"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"chalk-derive", "chalk-derive",
@ -222,9 +222,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-recursive" name = "chalk-recursive"
version = "0.100.0" version = "0.102.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "551e956e031c09057c7b21f17d48d91de99c9b6b6e34bceaf5e7202d71021268" checksum = "cbd3415cc540015533aa4a8ad007696d585dd9c5f81e7c099872f1dd4bf14894"
dependencies = [ dependencies = [
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",
@ -235,9 +235,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-solve" name = "chalk-solve"
version = "0.100.0" version = "0.102.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd7ca50181156ce649efe8e5dd00580f573651554e4dcd11afa4e2ac93f53324" checksum = "747707b0c082b3ecf4b1ae28d0d8df708a46cddd22a386f9cc85a312a4de25ff"
dependencies = [ dependencies = [
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",

View file

@ -104,10 +104,10 @@ arrayvec = "0.7.6"
bitflags = "2.9.0" bitflags = "2.9.0"
cargo_metadata = "0.19.2" cargo_metadata = "0.19.2"
camino = "1.1.9" camino = "1.1.9"
chalk-solve = { version = "0.100.0", default-features = false } chalk-solve = { version = "0.102.0", default-features = false }
chalk-ir = "0.100.0" chalk-ir = "0.102.0"
chalk-recursive = { version = "0.100.0", default-features = false } chalk-recursive = { version = "0.102.0", default-features = false }
chalk-derive = "0.100.0" chalk-derive = "0.102.0"
crossbeam-channel = "0.5.15" crossbeam-channel = "0.5.15"
dissimilar = "1.0.10" dissimilar = "1.0.10"
dot = "0.1.4" dot = "0.1.4"

View file

@ -76,7 +76,7 @@ impl<D> TyBuilder<D> {
} }
let subst = Substitution::from_iter( let subst = Substitution::from_iter(
Interner, Interner,
self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()), self.parent_subst.iter(Interner).cloned().chain(self.vec),
); );
(self.data, subst) (self.data, subst)
} }
@ -278,8 +278,10 @@ impl TyBuilder<()> {
}; };
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
self_subst generics(db, parent)
.chain(generics(db, parent).placeholder_subst(db).iter(Interner)) .placeholder_subst(db)
.iter(Interner)
.chain(self_subst)
.cloned() .cloned()
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
) )

View file

@ -55,6 +55,22 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
self.db.associated_ty_data(from_assoc_type_id(id)) self.db.associated_ty_data(from_assoc_type_id(id))
} }
fn associated_ty_from_impl(
&self,
impl_id: chalk_ir::ImplId<Interner>,
assoc_type_id: chalk_ir::AssocTypeId<Interner>,
) -> Option<rust_ir::AssociatedTyValueId<Interner>> {
let alias_id = from_assoc_type_id(assoc_type_id);
let trait_sig = self.db.type_alias_signature(alias_id);
self.db.impl_items(hir_def::ImplId::from_chalk(self.db, impl_id)).items.iter().find_map(
|(name, item)| match item {
AssocItemId::TypeAliasId(alias) if &trait_sig.name == name => {
Some(TypeAliasAsValue(*alias).to_chalk(self.db))
}
_ => None,
},
)
}
fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> { fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> {
self.db.trait_datum(self.krate, trait_id) self.db.trait_datum(self.krate, trait_id)
} }
@ -467,12 +483,13 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
// `resume_type`, `yield_type`, and `return_type` of the coroutine in question. // `resume_type`, `yield_type`, and `return_type` of the coroutine in question.
let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build(); let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
let len = subst.len(Interner);
let input_output = rust_ir::CoroutineInputOutputDatum { let input_output = rust_ir::CoroutineInputOutputDatum {
resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 3))
.intern(Interner), .intern(Interner),
yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1)) yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 2))
.intern(Interner), .intern(Interner),
return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 2)) return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 1))
.intern(Interner), .intern(Interner),
// FIXME: calculate upvars // FIXME: calculate upvars
upvars: vec![], upvars: vec![],
@ -619,10 +636,10 @@ pub(crate) fn associated_ty_data_query(
.with_type_param_mode(crate::lower::ParamLoweringMode::Variable); .with_type_param_mode(crate::lower::ParamLoweringMode::Variable);
let trait_subst = TyBuilder::subst_for_def(db, trait_, None) let trait_subst = TyBuilder::subst_for_def(db, trait_, None)
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self()) .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
.build(); .build();
let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst)) let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst))
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0) .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
.build(); .build();
let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner); let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);
@ -1021,8 +1038,9 @@ pub(super) fn generic_predicate_to_inline_bound(
} }
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
let generics = generics(db, from_assoc_type_id(projection_ty.associated_ty_id).into()); let generics = generics(db, from_assoc_type_id(projection_ty.associated_ty_id).into());
let (assoc_args, trait_args) = let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
projection_ty.substitution.as_slice(Interner).split_at(generics.len_self()); let (trait_args, assoc_args) =
projection_ty.substitution.as_slice(Interner).split_at(parent_len);
let (self_ty, args_no_self) = let (self_ty, args_no_self) =
trait_args.split_first().expect("projection without trait self type"); trait_args.split_first().expect("projection without trait self type");
if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in { if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in {

View file

@ -418,10 +418,9 @@ impl ProjectionTyExt for ProjectionTy {
fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
// FIXME: something like `Split` trait from chalk-solve might be nice. // FIXME: something like `Split` trait from chalk-solve might be nice.
let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into()); let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into());
let substitution = Substitution::from_iter( let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
Interner, let substitution =
self.substitution.iter(Interner).skip(generics.len_self()), Substitution::from_iter(Interner, self.substitution.iter(Interner).take(parent_len));
);
TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution } TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution }
} }

View file

@ -621,9 +621,8 @@ impl HirDisplay for ProjectionTy {
.name .name
.display(f.db, f.edition()) .display(f.db, f.edition())
)?; )?;
let proj_params_count = let proj_params =
self.substitution.len(Interner) - trait_ref.substitution.len(Interner); &self.substitution.as_slice(Interner)[trait_ref.substitution.len(Interner)..];
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
hir_fmt_generics(f, proj_params, None, None) hir_fmt_generics(f, proj_params, None, None)
} }
} }
@ -1196,27 +1195,31 @@ impl HirDisplay for Ty {
// Normally, functions cannot have default parameters, but they can, // Normally, functions cannot have default parameters, but they can,
// for function-like things such as struct names or enum variants. // for function-like things such as struct names or enum variants.
// The former cannot have defaults but parents, and the later cannot have // The former cannot have defaults but does have parents,
// parents but defaults. // but the latter cannot have parents but can have defaults.
// So, if `parent_len` > 0, it have a parent and thus it doesn't have any //
// default. Therefore, we shouldn't subtract defaults because those defaults // However, it's also true that *traits* can have defaults too.
// are from their parents. // In this case, there can be no function params.
// And if `parent_len` == 0, either parents don't exists or they don't have let parent_end = if parent_len > 0 {
// any defaults. Thus, we can - and should - subtract defaults. // If `parent_len` > 0, then there cannot be defaults on the function
let without_impl = if parent_len > 0 { // and all defaults must come from the parent.
params_len - parent_len - impl_ parent_len - defaults
} else { } else {
params_len - parent_len - impl_ - defaults parent_len
}; };
// parent's params (those from enclosing impl or trait, if any). let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_;
let (fn_params, parent_params) = parameters.split_at(without_impl + impl_); let (parent_params, fn_params) = parameters.split_at(parent_end);
write!(f, "<")?; write!(f, "<")?;
hir_fmt_generic_arguments(f, parent_params, None)?; hir_fmt_generic_arguments(f, parent_params, None)?;
if !parent_params.is_empty() && !fn_params.is_empty() { if !parent_params.is_empty() && !fn_params.is_empty() {
write!(f, ", ")?; write!(f, ", ")?;
} }
hir_fmt_generic_arguments(f, &fn_params[0..without_impl], None)?; hir_fmt_generic_arguments(
f,
&fn_params[..fn_params_no_impl_or_defaults],
None,
)?;
write!(f, ">")?; write!(f, ">")?;
} }
} }
@ -1873,11 +1876,12 @@ fn write_bounds_like_dyn_trait(
f.end_location_link(); f.end_location_link();
let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self(); let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self();
let parent_len = proj.substitution.len(Interner) - proj_arg_count;
if proj_arg_count > 0 { if proj_arg_count > 0 {
write!(f, "<")?; write!(f, "<")?;
hir_fmt_generic_arguments( hir_fmt_generic_arguments(
f, f,
&proj.substitution.as_slice(Interner)[..proj_arg_count], &proj.substitution.as_slice(Interner)[parent_len..],
None, None,
)?; )?;
write!(f, ">")?; write!(f, ">")?;

View file

@ -65,7 +65,7 @@ impl Generics {
} }
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ { pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
self.iter_self_id().chain(self.iter_parent_id()) self.iter_parent_id().chain(self.iter_self_id())
} }
pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ { pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
@ -82,11 +82,11 @@ impl Generics {
self.params.iter_type_or_consts().map(from_toc_id(self)).map(TupleExt::head) self.params.iter_type_or_consts().map(from_toc_id(self)).map(TupleExt::head)
} }
/// Iterate over the params followed by the parent params. /// Iterate over the parent params followed by self params.
pub(crate) fn iter( pub(crate) fn iter(
&self, &self,
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ { ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
self.iter_self().chain(self.iter_parent()) self.iter_parent().chain(self.iter_self())
} }
pub(crate) fn iter_parents_with_store( pub(crate) fn iter_parents_with_store(
@ -166,13 +166,10 @@ impl Generics {
if self.params.trait_self_param() == Some(param.local_id) { if self.params.trait_self_param() == Some(param.local_id) {
return Some(idx); return Some(idx);
} }
Some(self.params.len_lifetimes() + idx) Some(self.parent_generics().map_or(0, |g| g.len()) + self.params.len_lifetimes() + idx)
} else { } else {
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent)); debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent));
self.parent_generics() self.parent_generics().and_then(|g| g.find_type_or_const_param(param))
.and_then(|g| g.find_type_or_const_param(param))
// Remember that parent parameters come after parameters for self.
.map(|idx| self.len_self() + idx)
} }
} }
@ -184,12 +181,14 @@ impl Generics {
if lifetime.parent == self.def { if lifetime.parent == self.def {
let idx = lifetime.local_id.into_raw().into_u32() as usize; let idx = lifetime.local_id.into_raw().into_u32() as usize;
debug_assert!(idx <= self.params.len_lifetimes()); debug_assert!(idx <= self.params.len_lifetimes());
Some(self.params.trait_self_param().is_some() as usize + idx) Some(
self.parent_generics().map_or(0, |g| g.len())
+ self.params.trait_self_param().is_some() as usize
+ idx,
)
} else { } else {
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent)); debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
self.parent_generics() self.parent_generics().and_then(|g| g.find_lifetime(lifetime))
.and_then(|g| g.find_lifetime(lifetime))
.map(|idx| self.len_self() + idx)
} }
} }
@ -253,8 +252,7 @@ pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> O
let parent_def = parent_generic_def(db, def)?; let parent_def = parent_generic_def(db, def)?;
let parent_params = db.generic_params(parent_def); let parent_params = db.generic_params(parent_def);
let parent_self_idx = parent_params.trait_self_param()?.into_raw().into_u32() as usize; let parent_self_idx = parent_params.trait_self_param()?.into_raw().into_u32() as usize;
let self_params = db.generic_params(def); Some(parent_self_idx)
Some(self_params.len() + parent_self_idx)
} }
} }
} }

View file

@ -2065,7 +2065,16 @@ impl InferenceContext<'_> {
assert!(!has_self_param); // method shouldn't have another Self param assert!(!has_self_param); // method shouldn't have another Self param
let total_len = let total_len =
parent_params + type_params + const_params + impl_trait_params + lifetime_params; parent_params + type_params + const_params + impl_trait_params + lifetime_params;
let mut substs = Vec::with_capacity(total_len);
let param_to_var = |id| match id {
GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner),
GenericParamId::ConstParamId(id) => {
self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)
}
GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner),
};
let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_var).collect();
// handle provided arguments // handle provided arguments
if let Some(generic_args) = generic_args { if let Some(generic_args) = generic_args {
@ -2105,20 +2114,17 @@ impl InferenceContext<'_> {
} }
}; };
// Handle everything else as unknown. This also handles generic arguments for the method's let mut param_to_var = |id| match id {
// parent (impl or trait), which should come after those for the method. GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner),
for (id, _data) in def_generics.iter().skip(substs.len()) {
match id {
GenericParamId::TypeParamId(_) => {
substs.push(self.table.new_type_var().cast(Interner))
}
GenericParamId::ConstParamId(id) => { GenericParamId::ConstParamId(id) => {
substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)) self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)
}
GenericParamId::LifetimeParamId(_) => {
substs.push(self.table.new_lifetime_var().cast(Interner))
}
} }
GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner),
};
// Handle everything else as unknown.
for (id, _data) in def_generics.iter().skip(substs.len()) {
substs.push(param_to_var(id));
} }
assert_eq!(substs.len(), total_len); assert_eq!(substs.len(), total_len);
Substitution::from_iter(Interner, substs) Substitution::from_iter(Interner, substs)
@ -2143,13 +2149,12 @@ impl InferenceContext<'_> {
CallableDefId::FunctionId(f) => { CallableDefId::FunctionId(f) => {
if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container { if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container {
// construct a TraitRef // construct a TraitRef
let params_len = parameters.len(Interner);
let trait_params_len = generics(self.db, trait_.into()).len(); let trait_params_len = generics(self.db, trait_.into()).len();
let substs = Substitution::from_iter( let substs = Substitution::from_iter(
Interner, Interner,
// The generic parameters for the trait come after those for the // The generic parameters for the trait come after those for the
// function. // function.
&parameters.as_slice(Interner)[params_len - trait_params_len..], &parameters.as_slice(Interner)[..trait_params_len],
); );
self.push_obligation( self.push_obligation(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }

View file

@ -105,11 +105,9 @@ impl InferenceContext<'_> {
let substs = substs.as_slice(Interner); let substs = substs.as_slice(Interner);
if let ValueNs::EnumVariantId(_) = value { if let ValueNs::EnumVariantId(_) = value {
let mut it = self_subst let mut it = substs
.as_ref()
.map_or(&[][..], |s| s.as_slice(Interner))
.iter() .iter()
.chain(substs) .chain(self_subst.as_ref().map_or(&[][..], |s| s.as_slice(Interner)))
.cloned(); .cloned();
let builder = TyBuilder::subst_for_def(self.db, generic_def, None); let builder = TyBuilder::subst_for_def(self.db, generic_def, None);
let substs = builder let substs = builder
@ -130,11 +128,11 @@ impl InferenceContext<'_> {
let parent_substs = self_subst.or_else(|| { let parent_substs = self_subst.or_else(|| {
let generics = generics(self.db, generic_def); let generics = generics(self.db, generic_def);
let parent_params_len = generics.parent_generics()?.len(); let parent_params_len = generics.parent_generics()?.len();
let parent_args = &substs[substs.len() - parent_params_len..]; let parent_args = &substs[..parent_params_len];
Some(Substitution::from_iter(Interner, parent_args)) Some(Substitution::from_iter(Interner, parent_args))
}); });
let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner)); let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner));
let mut it = substs.iter().take(substs.len() - parent_substs_len).cloned(); let mut it = substs.iter().skip(parent_substs_len).cloned();
let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs); let builder = TyBuilder::subst_for_def(self.db, generic_def, parent_substs);
let substs = builder let substs = builder
.fill(|x| { .fill(|x| {
@ -261,9 +259,9 @@ impl InferenceContext<'_> {
}; };
if let ItemContainerId::TraitId(trait_) = container { if let ItemContainerId::TraitId(trait_) = container {
let param_len = generics(self.db, def).len_self(); let parent_len = generics(self.db, def).parent_generics().map_or(0, |g| g.len_self());
let parent_subst = let parent_subst =
Substitution::from_iter(Interner, subst.iter(Interner).skip(param_len)); Substitution::from_iter(Interner, subst.iter(Interner).take(parent_len));
let trait_ref = let trait_ref =
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: parent_subst }; TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: parent_subst };
self.push_obligation(trait_ref.cast(Interner)); self.push_obligation(trait_ref.cast(Interner));

View file

@ -769,14 +769,8 @@ fn named_associated_type_shorthand_candidates<R>(
let impl_id_as_generic_def: GenericDefId = impl_id.into(); let impl_id_as_generic_def: GenericDefId = impl_id.into();
if impl_id_as_generic_def != def { if impl_id_as_generic_def != def {
// `trait_ref` contains `BoundVar`s bound by impl's `Binders`, but here we need
// `BoundVar`s from `def`'s point of view.
// FIXME: A `HirDatabase` query may be handy if this process is needed in more
// places. It'd be almost identical as `impl_trait_query` where `resolver` would be
// of `def` instead of `impl_id`.
let starting_idx = generics(db, def).len_self();
let subst = TyBuilder::subst_for_def(db, impl_id, None) let subst = TyBuilder::subst_for_def(db, impl_id, None)
.fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx) .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
.build(); .build();
let trait_ref = subst.apply(trait_ref, Interner); let trait_ref = subst.apply(trait_ref, Interner);
search(trait_ref) search(trait_ref)
@ -802,16 +796,8 @@ fn named_associated_type_shorthand_candidates<R>(
if let GenericDefId::TraitId(trait_id) = param_id.parent() { if let GenericDefId::TraitId(trait_id) = param_id.parent() {
let trait_generics = generics(db, trait_id.into()); let trait_generics = generics(db, trait_id.into());
if trait_generics[param_id.local_id()].is_trait_self() { if trait_generics[param_id.local_id()].is_trait_self() {
let def_generics = generics(db, def);
let starting_idx = match def {
GenericDefId::TraitId(_) => 0,
// `def` is an item within trait. We need to substitute `BoundVar`s but
// remember that they are for parent (i.e. trait) generic params so they
// come after our own params.
_ => def_generics.len_self(),
};
let trait_ref = TyBuilder::trait_ref(db, trait_id) let trait_ref = TyBuilder::trait_ref(db, trait_id)
.fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx) .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
.build(); .build();
return search(trait_ref); return search(trait_ref);
} }
@ -1181,7 +1167,6 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
return (GenericDefaults(None), None); return (GenericDefaults(None), None);
} }
let resolver = def.resolver(db); let resolver = def.resolver(db);
let parent_start_idx = generic_params.len_self();
let mut ctx = TyLoweringContext::new(db, &resolver, generic_params.store(), def) let mut ctx = TyLoweringContext::new(db, &resolver, generic_params.store(), def)
.with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
@ -1190,8 +1175,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
let mut defaults = generic_params let mut defaults = generic_params
.iter_self() .iter_self()
.map(|(id, p)| { .map(|(id, p)| {
let result = let result = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params);
idx += 1; idx += 1;
result result
}) })
@ -1199,7 +1183,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
defaults.extend(generic_params.iter_parents_with_store().map(|((id, p), store)| { defaults.extend(generic_params.iter_parents_with_store().map(|((id, p), store)| {
ctx.store = store; ctx.store = store;
let result = handle_generic_param(&mut ctx, idx, id, p, parent_start_idx, &generic_params); let result = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
idx += 1; idx += 1;
result result
})); }));
@ -1211,7 +1195,6 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
idx: usize, idx: usize,
id: GenericParamId, id: GenericParamId,
p: GenericParamDataRef<'_>, p: GenericParamDataRef<'_>,
parent_start_idx: usize,
generic_params: &Generics, generic_params: &Generics,
) -> Binders<crate::GenericArg> { ) -> Binders<crate::GenericArg> {
match p { match p {
@ -1220,7 +1203,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
// Each default can only refer to previous parameters. // Each default can only refer to previous parameters.
// Type variable default referring to parameter coming // Type variable default referring to parameter coming
// after it is forbidden (FIXME: report diagnostic) // after it is forbidden (FIXME: report diagnostic)
fallback_bound_vars(ctx.lower_ty(*ty), idx, parent_start_idx) fallback_bound_vars(ctx.lower_ty(*ty), idx, 0)
}); });
crate::make_binders(ctx.db, generic_params, ty.cast(Interner)) crate::make_binders(ctx.db, generic_params, ty.cast(Interner))
} }
@ -1238,7 +1221,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
}, },
); );
// Each default can only refer to previous parameters, see above. // Each default can only refer to previous parameters, see above.
val = fallback_bound_vars(val, idx, parent_start_idx); val = fallback_bound_vars(val, idx, 0);
make_binders(ctx.db, generic_params, val) make_binders(ctx.db, generic_params, val)
} }
GenericParamDataRef::LifetimeParamData(_) => { GenericParamDataRef::LifetimeParamData(_) => {

View file

@ -184,14 +184,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
false, false,
None, None,
); );
let len_self =
generics(self.ctx.db, associated_ty.into()).len_self();
let substitution = Substitution::from_iter( let substitution = Substitution::from_iter(
Interner, Interner,
trait_ref.substitution.iter(Interner).chain(
substitution substitution
.iter(Interner) .iter(Interner)
.take(len_self) .skip(trait_ref.substitution.len(Interner)),
.chain(trait_ref.substitution.iter(Interner)), ),
); );
TyKind::Alias(AliasTy::Projection(ProjectionTy { TyKind::Alias(AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(associated_ty), associated_ty_id: to_assoc_type_id(associated_ty),
@ -250,18 +249,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
let subst = generics.placeholder_subst(self.ctx.db); let subst = generics.placeholder_subst(self.ctx.db);
self.ctx.db.impl_self_ty(impl_id).substitute(Interner, &subst) self.ctx.db.impl_self_ty(impl_id).substitute(Interner, &subst)
} }
ParamLoweringMode::Variable => { ParamLoweringMode::Variable => TyBuilder::impl_self_ty(self.ctx.db, impl_id)
let starting_from = match generics.def() { .fill_with_bound_vars(self.ctx.in_binders, 0)
GenericDefId::ImplId(_) => 0, .build(),
// `def` is an item within impl. We need to substitute `BoundVar`s but
// remember that they are for parent (i.e. impl) generic params so they
// come after our own params.
_ => generics.len_self(),
};
TyBuilder::impl_self_ty(self.ctx.db, impl_id)
.fill_with_bound_vars(self.ctx.in_binders, starting_from)
.build()
}
} }
} }
TypeNs::AdtSelfType(adt) => { TypeNs::AdtSelfType(adt) => {
@ -512,12 +502,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
// this point (`t.substitution`). // this point (`t.substitution`).
let substs = self.substs_from_path_segment(associated_ty.into(), false, None); let substs = self.substs_from_path_segment(associated_ty.into(), false, None);
let len_self =
crate::generics::generics(self.ctx.db, associated_ty.into()).len_self();
let substs = Substitution::from_iter( let substs = Substitution::from_iter(
Interner, Interner,
substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)), parent_subst
.iter(Interner)
.chain(substs.iter(Interner).skip(parent_subst.len(Interner))),
); );
Some( Some(
@ -637,10 +626,10 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
explicit_self_ty: Option<Ty>, explicit_self_ty: Option<Ty>,
) -> Substitution { ) -> Substitution {
// Order is // Order is
// - Parent parameters
// - Optional Self parameter // - Optional Self parameter
// - Lifetime parameters // - Lifetime parameters
// - Type or Const parameters // - Type or Const parameters
// - Parent parameters
let def_generics = generics(self.ctx.db, def); let def_generics = generics(self.ctx.db, def);
let ( let (
parent_params, parent_params,
@ -654,12 +643,22 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
self_param as usize + type_params + const_params + impl_trait_params + lifetime_params; self_param as usize + type_params + const_params + impl_trait_params + lifetime_params;
let total_len = parent_params + item_len; let total_len = parent_params + item_len;
let mut substs = Vec::new(); let ty_error = || TyKind::Error.intern(Interner).cast(Interner);
let param_to_err = |id| match id {
GenericParamId::ConstParamId(x) => {
unknown_const_as_generic(self.ctx.db.const_param_ty(x))
}
GenericParamId::TypeParamId(_) => ty_error(),
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
};
let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_err).collect();
tracing::debug!(?substs, ?parent_params);
// we need to iterate the lifetime and type/const params separately as our order of them // we need to iterate the lifetime and type/const params separately as our order of them
// differs from the supplied syntax // differs from the supplied syntax
let ty_error = || TyKind::Error.intern(Interner).cast(Interner);
let mut def_toc_iter = def_generics.iter_self_type_or_consts_id(); let mut def_toc_iter = def_generics.iter_self_type_or_consts_id();
let fill_self_param = || { let fill_self_param = || {
if self_param { if self_param {
@ -730,13 +729,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
fill_self_param(); fill_self_param();
} }
let param_to_err = |id| match id {
GenericParamId::ConstParamId(x) => {
unknown_const_as_generic(self.ctx.db.const_param_ty(x))
}
GenericParamId::TypeParamId(_) => ty_error(),
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
};
// handle defaults. In expression or pattern path segments without // handle defaults. In expression or pattern path segments without
// explicitly specified type arguments, missing type arguments are inferred // explicitly specified type arguments, missing type arguments are inferred
// (i.e. defaults aren't used). // (i.e. defaults aren't used).
@ -751,13 +743,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty(); let fill_defaults = (!infer_args || had_explicit_args) && !is_assoc_ty();
if fill_defaults { if fill_defaults {
let defaults = &*self.ctx.db.generic_defaults(def); let defaults = &*self.ctx.db.generic_defaults(def);
let (item, _parent) = defaults.split_at(item_len);
let parent_from = item_len - substs.len();
let mut rem = let rem =
def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::<Vec<_>>(); def_generics.iter_id().skip(substs.len()).map(param_to_err).collect::<Vec<_>>();
// Fill in defaults for type/const params // Fill in defaults for type/const params
for (idx, default_ty) in item[substs.len()..].iter().enumerate() { for (idx, default_ty) in defaults[substs.len()..].iter().enumerate() {
// each default can depend on the previous parameters // each default can depend on the previous parameters
let substs_so_far = Substitution::from_iter( let substs_so_far = Substitution::from_iter(
Interner, Interner,
@ -765,8 +755,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
); );
substs.push(default_ty.clone().substitute(Interner, &substs_so_far)); substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
} }
// Fill in remaining parent params
substs.extend(rem.drain(parent_from..));
} else { } else {
// Fill in remaining def params and parent params // Fill in remaining def params and parent params
substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err)); substs.extend(def_generics.iter_id().skip(substs.len()).map(param_to_err));
@ -818,14 +806,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
false, // this is not relevant false, // this is not relevant
Some(super_trait_ref.self_type_parameter(Interner)), Some(super_trait_ref.self_type_parameter(Interner)),
); );
let generics = generics(self.ctx.db, associated_ty.into());
let self_params = generics.len_self();
let substitution = Substitution::from_iter( let substitution = Substitution::from_iter(
Interner, Interner,
super_trait_ref.substitution.iter(Interner).chain(
substitution substitution
.iter(Interner) .iter(Interner)
.take(self_params) .skip(super_trait_ref.substitution.len(Interner)),
.chain(super_trait_ref.substitution.iter(Interner)), ),
); );
let projection_ty = ProjectionTy { let projection_ty = ProjectionTy {
associated_ty_id: to_assoc_type_id(associated_ty), associated_ty_id: to_assoc_type_id(associated_ty),

View file

@ -655,7 +655,7 @@ pub fn is_dyn_method(
let fn_params = fn_subst.len(Interner) - trait_params; let fn_params = fn_subst.len(Interner) - trait_params;
let trait_ref = TraitRef { let trait_ref = TraitRef {
trait_id: to_chalk_trait_id(trait_id), trait_id: to_chalk_trait_id(trait_id),
substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)), substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
}; };
let self_ty = trait_ref.self_type_parameter(Interner); let self_ty = trait_ref.self_type_parameter(Interner);
if let TyKind::Dyn(d) = self_ty.kind(Interner) { if let TyKind::Dyn(d) = self_ty.kind(Interner) {
@ -694,10 +694,9 @@ pub(crate) fn lookup_impl_method_query(
return (func, fn_subst); return (func, fn_subst);
}; };
let trait_params = db.generic_params(trait_id.into()).len(); let trait_params = db.generic_params(trait_id.into()).len();
let fn_params = fn_subst.len(Interner) - trait_params;
let trait_ref = TraitRef { let trait_ref = TraitRef {
trait_id: to_chalk_trait_id(trait_id), trait_id: to_chalk_trait_id(trait_id),
substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)), substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
}; };
let name = &db.function_signature(func).name; let name = &db.function_signature(func).name;
@ -713,7 +712,7 @@ pub(crate) fn lookup_impl_method_query(
impl_fn, impl_fn,
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
fn_subst.iter(Interner).take(fn_params).chain(impl_subst.iter(Interner)), impl_subst.iter(Interner).chain(fn_subst.iter(Interner).skip(trait_params)),
), ),
) )
} }

View file

@ -4213,7 +4213,7 @@ fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
let a = v.get::<T>(); let a = v.get::<T>();
//^ &'a T //^ &'a T
let a = v.get::<()>(); let a = v.get::<()>();
//^ Trait::Assoc<(), impl Trait<Assoc<T> = &'a T>> //^ Trait::Assoc<impl Trait<Assoc<T> = &'a T>, ()>
} }
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) { fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
let a = v.get::<i32>(); let a = v.get::<i32>();
@ -4280,7 +4280,7 @@ where
let a = t.get::<isize>(); let a = t.get::<isize>();
//^ usize //^ usize
let a = t.get::<()>(); let a = t.get::<()>();
//^ Trait::Assoc<(), T> //^ Trait::Assoc<T, ()>
} }
"#, "#,

View file

@ -86,8 +86,7 @@ impl DebugContext<'_> {
} }
write!(fmt, ">::{}", type_alias_data.name.display(self.0, Edition::LATEST))?; write!(fmt, ">::{}", type_alias_data.name.display(self.0, Edition::LATEST))?;
let proj_params_count = projection_ty.substitution.len(Interner) - trait_params.len(); let proj_params = &projection_ty.substitution.as_slice(Interner)[trait_params.len()..];
let proj_params = &projection_ty.substitution.as_slice(Interner)[..proj_params_count];
if !proj_params.is_empty() { if !proj_params.is_empty() {
write!( write!(
fmt, fmt,

View file

@ -230,8 +230,8 @@ pub(super) fn associated_type_by_name_including_super_traits(
} }
/// It is a bit different from the rustc equivalent. Currently it stores: /// It is a bit different from the rustc equivalent. Currently it stores:
/// - 0: the function signature, encoded as a function pointer type /// - 0..n-1: generics of the parent
/// - 1..n: generics of the parent /// - n: the function signature, encoded as a function pointer type
/// ///
/// and it doesn't store the closure types and fields. /// and it doesn't store the closure types and fields.
/// ///
@ -242,7 +242,7 @@ pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution);
impl<'a> ClosureSubst<'a> { impl<'a> ClosureSubst<'a> {
pub(crate) fn parent_subst(&self) -> &'a [GenericArg] { pub(crate) fn parent_subst(&self) -> &'a [GenericArg] {
match self.0.as_slice(Interner) { match self.0.as_slice(Interner) {
[_, x @ ..] => x, [x @ .., _] => x,
_ => { _ => {
never!("Closure missing parameter"); never!("Closure missing parameter");
&[] &[]
@ -252,7 +252,7 @@ impl<'a> ClosureSubst<'a> {
pub(crate) fn sig_ty(&self) -> &'a Ty { pub(crate) fn sig_ty(&self) -> &'a Ty {
match self.0.as_slice(Interner) { match self.0.as_slice(Interner) {
[x, ..] => x.assert_ty_ref(Interner), [.., x] => x.assert_ty_ref(Interner),
_ => { _ => {
unreachable!("Closure missing sig_ty parameter"); unreachable!("Closure missing sig_ty parameter");
} }

View file

@ -3774,24 +3774,25 @@ impl GenericSubstitution {
TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()), TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
TypeOrConstParamData::ConstParamData(_) => None, TypeOrConstParamData::ConstParamData(_) => None,
}); });
// The `Substitution` is first self then container, we want the reverse order. let parent_len = self.subst.len(Interner)
let subst_type_params = self.subst.type_parameters(Interner).collect::<Vec<_>>(); - generics
let mut self_params = subst_type_params .iter_type_or_consts()
.filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..)))
.count();
let container_params = self.subst.as_slice(Interner)[..parent_len]
.iter() .iter()
.zip(type_params) .filter_map(|param| param.ty(Interner).cloned())
.filter_map(|(ty, name)| { .zip(container_type_params.into_iter().flatten());
Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() })) let self_params = self.subst.as_slice(Interner)[parent_len..]
})
.collect::<Vec<_>>();
let mut container_params = subst_type_params[self_params.len()..]
.iter() .iter()
.zip(container_type_params.into_iter().flatten()) .filter_map(|param| param.ty(Interner).cloned())
.filter_map(|(ty, name)| { .zip(type_params);
Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() }))
})
.collect::<Vec<_>>();
container_params.append(&mut self_params);
container_params container_params
.chain(self_params)
.filter_map(|(ty, name)| {
Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() }))
})
.collect()
} }
} }