Adapt to the new generic parameter/argument order

This commit is contained in:
Ryo Yoshida 2022-10-02 22:15:57 +09:00
parent 4385d3dcd0
commit 78977cd86c
No known key found for this signature in database
GPG key ID: E25698A930586171
11 changed files with 259 additions and 161 deletions

View file

@ -987,11 +987,13 @@ impl<'a> InferenceContext<'a> {
let lhs_ty = self.infer_expr(lhs, &lhs_expectation);
let rhs_ty = self.table.new_type_var();
let func = lang_names_for_bin_op(op).and_then(|(name, lang_item)| {
self.db.trait_data(self.resolve_lang_item(lang_item)?.as_trait()?).method_by_name(&name)
let trait_func = lang_names_for_bin_op(op).and_then(|(name, lang_item)| {
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
let func = self.db.trait_data(trait_id).method_by_name(&name)?;
Some((trait_id, func))
});
let func = match func {
Some(func) => func,
let (trait_, func) = match trait_func {
Some(it) => it,
None => {
let rhs_ty = self.builtin_binary_op_rhs_expectation(op, lhs_ty.clone());
let rhs_ty = self.infer_expr_coerce(rhs, &Expectation::from_option(rhs_ty));
@ -1001,7 +1003,9 @@ impl<'a> InferenceContext<'a> {
}
};
let subst = TyBuilder::subst_for_def(self.db, func)
// HACK: We can use this substitution for the function because the function itself doesn't
// have its own generic parameters.
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
.push(lhs_ty.clone())
.push(rhs_ty.clone())
.build();
@ -1280,19 +1284,7 @@ impl<'a> InferenceContext<'a> {
assert_eq!(self_params, 0); // method shouldn't have another Self param
let total_len = parent_params + type_params + const_params + impl_trait_params;
let mut substs = Vec::with_capacity(total_len);
// Parent arguments are unknown
for (id, param) in def_generics.iter_parent() {
match param {
TypeOrConstParamData::TypeParamData(_) => {
substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner));
}
TypeOrConstParamData::ConstParamData(_) => {
let ty = self.db.const_param_ty(ConstParamId::from_unchecked(id));
substs
.push(GenericArgData::Const(self.table.new_const_var(ty)).intern(Interner));
}
}
}
// handle provided arguments
if let Some(generic_args) = generic_args {
// if args are provided, it should be all of them, but we can't rely on that
@ -1301,7 +1293,7 @@ impl<'a> InferenceContext<'a> {
.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.take(type_params + const_params)
.zip(def_generics.iter_id().skip(parent_params))
.zip(def_generics.iter_id())
{
if let Some(g) = generic_arg_to_chalk(
self.db,
@ -1325,6 +1317,9 @@ impl<'a> InferenceContext<'a> {
}
}
};
// 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 data {
TypeOrConstParamData::TypeParamData(_) => {
@ -1362,9 +1357,13 @@ impl<'a> InferenceContext<'a> {
CallableDefId::FunctionId(f) => {
if let ItemContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container {
// construct a TraitRef
let substs = crate::subst_prefix(
&*parameters,
generics(self.db.upcast(), trait_.into()).len(),
let params_len = parameters.len(Interner);
let trait_params_len = generics(self.db.upcast(), 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..],
);
self.push_obligation(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }