Skip to content

Update chalk #19624

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ arrayvec = "0.7.6"
bitflags = "2.9.0"
cargo_metadata = "0.19.2"
camino = "1.1.9"
chalk-solve = { version = "0.100.0", default-features = false }
chalk-ir = "0.100.0"
chalk-recursive = { version = "0.100.0", default-features = false }
chalk-derive = "0.100.0"
chalk-solve = { version = "0.102.0", default-features = false }
chalk-ir = "0.102.0"
chalk-recursive = { version = "0.102.0", default-features = false }
chalk-derive = "0.102.0"
crossbeam-channel = "0.5.15"
dissimilar = "1.0.10"
dot = "0.1.4"
Expand Down
8 changes: 5 additions & 3 deletions crates/hir-ty/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<D> TyBuilder<D> {
}
let subst = Substitution::from_iter(
Interner,
self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()),
self.parent_subst.iter(Interner).cloned().chain(self.vec),
);
(self.data, subst)
}
Expand Down Expand Up @@ -278,8 +278,10 @@ impl TyBuilder<()> {
};
Substitution::from_iter(
Interner,
self_subst
.chain(generics(db, parent).placeholder_subst(db).iter(Interner))
generics(db, parent)
.placeholder_subst(db)
.iter(Interner)
.chain(self_subst)
.cloned()
.collect::<Vec<_>>(),
)
Expand Down
32 changes: 25 additions & 7 deletions crates/hir-ty/src/chalk_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
self.db.associated_ty_data(from_assoc_type_id(id))
}
fn associated_ty_from_impl(
&self,
impl_id: chalk_ir::ImplId<Interner>,
assoc_type_id: chalk_ir::AssocTypeId<Interner>,
) -> Option<rust_ir::AssociatedTyValueId<Interner>> {
let alias_id = from_assoc_type_id(assoc_type_id);
let trait_sig = self.db.type_alias_signature(alias_id);
self.db.impl_items(hir_def::ImplId::from_chalk(self.db, impl_id)).items.iter().find_map(
|(name, item)| match item {
AssocItemId::TypeAliasId(alias) if &trait_sig.name == name => {
Some(TypeAliasAsValue(*alias).to_chalk(self.db))
}
_ => None,
},
)
}
fn trait_datum(&self, trait_id: TraitId) -> Arc<TraitDatum> {
self.db.trait_datum(self.krate, trait_id)
}
Expand Down Expand Up @@ -467,12 +483,13 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
// `resume_type`, `yield_type`, and `return_type` of the coroutine in question.
let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();

let len = subst.len(Interner);
let input_output = rust_ir::CoroutineInputOutputDatum {
resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 3))
.intern(Interner),
yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1))
yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 2))
.intern(Interner),
return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 2))
return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, len - 1))
.intern(Interner),
// FIXME: calculate upvars
upvars: vec![],
Expand Down Expand Up @@ -619,10 +636,10 @@ pub(crate) fn associated_ty_data_query(
.with_type_param_mode(crate::lower::ParamLoweringMode::Variable);

let trait_subst = TyBuilder::subst_for_def(db, trait_, None)
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
.build();
let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst))
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
.build();
let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);

Expand Down Expand Up @@ -1021,8 +1038,9 @@ pub(super) fn generic_predicate_to_inline_bound(
}
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
let generics = generics(db, from_assoc_type_id(projection_ty.associated_ty_id).into());
let (assoc_args, trait_args) =
projection_ty.substitution.as_slice(Interner).split_at(generics.len_self());
let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
let (trait_args, assoc_args) =
projection_ty.substitution.as_slice(Interner).split_at(parent_len);
let (self_ty, args_no_self) =
trait_args.split_first().expect("projection without trait self type");
if self_ty.assert_ty_ref(Interner) != &self_ty_shifted_in {
Expand Down
7 changes: 3 additions & 4 deletions crates/hir-ty/src/chalk_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,9 @@ impl ProjectionTyExt for ProjectionTy {
fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
// FIXME: something like `Split` trait from chalk-solve might be nice.
let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into());
let substitution = Substitution::from_iter(
Interner,
self.substitution.iter(Interner).skip(generics.len_self()),
);
let parent_len = generics.parent_generics().map_or(0, |g| g.len_self());
let substitution =
Substitution::from_iter(Interner, self.substitution.iter(Interner).take(parent_len));
TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution }
}

Expand Down
38 changes: 21 additions & 17 deletions crates/hir-ty/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,9 +621,8 @@ impl HirDisplay for ProjectionTy {
.name
.display(f.db, f.edition())
)?;
let proj_params_count =
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
let proj_params = &self.substitution.as_slice(Interner)[..proj_params_count];
let proj_params =
&self.substitution.as_slice(Interner)[trait_ref.substitution.len(Interner)..];
hir_fmt_generics(f, proj_params, None, None)
}
}
Expand Down Expand Up @@ -1196,27 +1195,31 @@ impl HirDisplay for Ty {

// Normally, functions cannot have default parameters, but they can,
// for function-like things such as struct names or enum variants.
// The former cannot have defaults but parents, and the later cannot have
// parents but defaults.
// So, if `parent_len` > 0, it have a parent and thus it doesn't have any
// default. Therefore, we shouldn't subtract defaults because those defaults
// are from their parents.
// And if `parent_len` == 0, either parents don't exists or they don't have
// any defaults. Thus, we can - and should - subtract defaults.
let without_impl = if parent_len > 0 {
params_len - parent_len - impl_
// The former cannot have defaults but does have parents,
// but the latter cannot have parents but can have defaults.
//
// However, it's also true that *traits* can have defaults too.
// In this case, there can be no function params.
let parent_end = if parent_len > 0 {
// If `parent_len` > 0, then there cannot be defaults on the function
// and all defaults must come from the parent.
parent_len - defaults
} else {
params_len - parent_len - impl_ - defaults
parent_len
};
// parent's params (those from enclosing impl or trait, if any).
let (fn_params, parent_params) = parameters.split_at(without_impl + impl_);
let fn_params_no_impl_or_defaults = parameters.len() - parent_end - impl_;
let (parent_params, fn_params) = parameters.split_at(parent_end);

write!(f, "<")?;
hir_fmt_generic_arguments(f, parent_params, None)?;
if !parent_params.is_empty() && !fn_params.is_empty() {
write!(f, ", ")?;
}
hir_fmt_generic_arguments(f, &fn_params[0..without_impl], None)?;
hir_fmt_generic_arguments(
f,
&fn_params[..fn_params_no_impl_or_defaults],
None,
)?;
write!(f, ">")?;
}
}
Expand Down Expand Up @@ -1873,11 +1876,12 @@ fn write_bounds_like_dyn_trait(
f.end_location_link();

let proj_arg_count = generics(f.db, assoc_ty_id.into()).len_self();
let parent_len = proj.substitution.len(Interner) - proj_arg_count;
if proj_arg_count > 0 {
write!(f, "<")?;
hir_fmt_generic_arguments(
f,
&proj.substitution.as_slice(Interner)[..proj_arg_count],
&proj.substitution.as_slice(Interner)[parent_len..],
None,
)?;
write!(f, ">")?;
Expand Down
26 changes: 12 additions & 14 deletions crates/hir-ty/src/generics.rs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a comment at the top of this file that needs to be adjusted now I think

Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Generics {
}

pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
self.iter_self_id().chain(self.iter_parent_id())
self.iter_parent_id().chain(self.iter_self_id())
}

pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
Expand All @@ -82,11 +82,11 @@ impl Generics {
self.params.iter_type_or_consts().map(from_toc_id(self)).map(TupleExt::head)
}

/// Iterate over the params followed by the parent params.
/// Iterate over the parent params followed by self params.
pub(crate) fn iter(
&self,
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
self.iter_self().chain(self.iter_parent())
self.iter_parent().chain(self.iter_self())
}

pub(crate) fn iter_parents_with_store(
Expand Down Expand Up @@ -166,13 +166,10 @@ impl Generics {
if self.params.trait_self_param() == Some(param.local_id) {
return Some(idx);
}
Some(self.params.len_lifetimes() + idx)
Some(self.parent_generics().map_or(0, |g| g.len()) + self.params.len_lifetimes() + idx)
} else {
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent));
self.parent_generics()
.and_then(|g| g.find_type_or_const_param(param))
// Remember that parent parameters come after parameters for self.
.map(|idx| self.len_self() + idx)
self.parent_generics().and_then(|g| g.find_type_or_const_param(param))
}
}

Expand All @@ -184,12 +181,14 @@ impl Generics {
if lifetime.parent == self.def {
let idx = lifetime.local_id.into_raw().into_u32() as usize;
debug_assert!(idx <= self.params.len_lifetimes());
Some(self.params.trait_self_param().is_some() as usize + idx)
Some(
self.parent_generics().map_or(0, |g| g.len())
+ self.params.trait_self_param().is_some() as usize
+ idx,
)
} else {
debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
self.parent_generics()
.and_then(|g| g.find_lifetime(lifetime))
.map(|idx| self.len_self() + idx)
self.parent_generics().and_then(|g| g.find_lifetime(lifetime))
}
}

Expand Down Expand Up @@ -253,8 +252,7 @@ pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> O
let parent_def = parent_generic_def(db, def)?;
let parent_params = db.generic_params(parent_def);
let parent_self_idx = parent_params.trait_self_param()?.into_raw().into_u32() as usize;
let self_params = db.generic_params(def);
Some(self_params.len() + parent_self_idx)
Some(parent_self_idx)
}
}
}
Expand Down
37 changes: 21 additions & 16 deletions crates/hir-ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2065,7 +2065,16 @@ impl InferenceContext<'_> {
assert!(!has_self_param); // method shouldn't have another Self param
let total_len =
parent_params + type_params + const_params + impl_trait_params + lifetime_params;
let mut substs = Vec::with_capacity(total_len);

let param_to_var = |id| match id {
GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner),
GenericParamId::ConstParamId(id) => {
self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)
}
GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner),
};

let mut substs: Vec<_> = def_generics.iter_parent_id().map(param_to_var).collect();

// handle provided arguments
if let Some(generic_args) = generic_args {
Expand Down Expand Up @@ -2105,20 +2114,17 @@ impl InferenceContext<'_> {
}
};

// Handle everything else as unknown. This also handles generic arguments for the method's
// parent (impl or trait), which should come after those for the method.
for (id, _data) in def_generics.iter().skip(substs.len()) {
match id {
GenericParamId::TypeParamId(_) => {
substs.push(self.table.new_type_var().cast(Interner))
}
GenericParamId::ConstParamId(id) => {
substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
}
GenericParamId::LifetimeParamId(_) => {
substs.push(self.table.new_lifetime_var().cast(Interner))
}
let mut param_to_var = |id| match id {
GenericParamId::TypeParamId(_) => self.table.new_type_var().cast(Interner),
GenericParamId::ConstParamId(id) => {
self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner)
}
GenericParamId::LifetimeParamId(_) => self.table.new_lifetime_var().cast(Interner),
};

// Handle everything else as unknown.
for (id, _data) in def_generics.iter().skip(substs.len()) {
substs.push(param_to_var(id));
}
assert_eq!(substs.len(), total_len);
Substitution::from_iter(Interner, substs)
Expand All @@ -2143,13 +2149,12 @@ impl InferenceContext<'_> {
CallableDefId::FunctionId(f) => {
if let ItemContainerId::TraitId(trait_) = f.lookup(self.db).container {
// construct a TraitRef
let params_len = parameters.len(Interner);
let trait_params_len = generics(self.db, trait_.into()).len();
let substs = Substitution::from_iter(
Interner,
// The generic parameters for the trait come after those for the
// function.
&parameters.as_slice(Interner)[params_len - trait_params_len..],
&parameters.as_slice(Interner)[..trait_params_len],
);
self.push_obligation(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
Expand Down
Loading