Simpliy code
This commit is contained in:
parent
0edb5ce97a
commit
039ab2e820
1 changed files with 32 additions and 60 deletions
|
@ -469,38 +469,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let typable: Option<TypableDef> = def.into();
|
let typable: Option<TypableDef> = def.into();
|
||||||
let typable = typable?;
|
let typable = typable?;
|
||||||
|
|
||||||
// For example, this substs will take `Gen::make::*<u32>*`
|
let mut ty = self.db.type_for_def(typable, Namespace::Types);
|
||||||
let mut substs =
|
|
||||||
Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable);
|
|
||||||
|
|
||||||
if remaining_index > 0 {
|
if remaining_index > 0 {
|
||||||
// For example, this substs will take `Gen::*<u32>*::make`
|
// For example, this substs will take `Gen::*<u32>*::make`
|
||||||
let parent_substs = Ty::substs_from_path_segment(
|
let substs = Ty::substs_from_path_segment(
|
||||||
self.db,
|
self.db,
|
||||||
&self.resolver,
|
&self.resolver,
|
||||||
&path.segments[remaining_index - 1],
|
&path.segments[remaining_index - 1],
|
||||||
typable,
|
typable,
|
||||||
);
|
);
|
||||||
|
|
||||||
// merge parent and child substs
|
ty = ty.subst(&substs);
|
||||||
let max_len = std::cmp::max(substs.len(), parent_substs.len());
|
|
||||||
let mut merged = vec![];
|
|
||||||
for i in 0..max_len {
|
|
||||||
let s = match (substs.0.get(i), parent_substs.0.get(i)) {
|
|
||||||
(Some(s @ Ty::Apply(_)), _) => s,
|
|
||||||
(_, Some(s @ Ty::Apply(_))) => s,
|
|
||||||
(Some(s), _) => s,
|
|
||||||
(_, Some(s)) => s,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
merged.push(s.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
substs = Substs(merged.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = self.db.type_for_def(typable, Namespace::Types);
|
ty
|
||||||
ty.subst(&substs)
|
|
||||||
}
|
}
|
||||||
Resolution::LocalBinding(_) => {
|
Resolution::LocalBinding(_) => {
|
||||||
// can't have a local binding in an associated item path
|
// can't have a local binding in an associated item path
|
||||||
|
@ -558,16 +541,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
|
|
||||||
match resolved {
|
match resolved {
|
||||||
Resolution::Def(def) => {
|
Resolution::Def(def) => {
|
||||||
let typable: Option<TypableDef> = def.into();
|
// Helpper function for finding self types
|
||||||
let typable = typable?;
|
let find_self_types = || -> Option<Substs> {
|
||||||
|
|
||||||
let ty = self.db.type_for_def(typable, Namespace::Values);
|
|
||||||
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
|
|
||||||
let ty = ty.subst(&substs);
|
|
||||||
let ty = self.insert_type_vars(ty);
|
|
||||||
|
|
||||||
// plug the old parent_ty in
|
|
||||||
let plug_self_types = || -> Option<()> {
|
|
||||||
let actual_def_ty = actual_def_ty?;
|
let actual_def_ty = actual_def_ty?;
|
||||||
|
|
||||||
if let crate::ModuleDef::Function(func) = def {
|
if let crate::ModuleDef::Function(func) = def {
|
||||||
|
@ -577,43 +552,40 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let impl_block = func.impl_block(self.db)?;
|
let impl_block = func.impl_block(self.db)?.target_ty(self.db);
|
||||||
let impl_block = impl_block.target_ty(self.db);
|
let impl_block_substs = impl_block.substs()?;
|
||||||
|
let actual_substs = actual_def_ty.substs()?;
|
||||||
|
|
||||||
// We save the impl block type params for later use
|
let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
|
||||||
let old_params = impl_block.substs().unwrap().clone();
|
|
||||||
|
|
||||||
// Turn the impl block generic params to unknown
|
// The following code *link up* the function actual parma type
|
||||||
let mut subst = vec![];
|
// and impl_block type param index
|
||||||
for _ in 0..impl_block.substs().map(|x| x.len()).unwrap_or(0) {
|
impl_block_substs.iter().zip(actual_substs.iter()).for_each(
|
||||||
subst.push(Ty::Unknown);
|
|(param, pty)| {
|
||||||
}
|
if let Ty::Param { idx, .. } = param {
|
||||||
let impl_block = impl_block.subst(&Substs(subst.into()));
|
if let Some(s) = new_substs.get_mut(*idx as usize) {
|
||||||
let impl_block = self.insert_type_vars(impl_block);
|
*s = pty.clone();
|
||||||
|
|
||||||
// Unify *self type* and impl_block
|
|
||||||
// e.g. Gen::<u32,u64> <=> Gen::<u64, T>
|
|
||||||
self.unify(&impl_block, &actual_def_ty);
|
|
||||||
|
|
||||||
// The following code *link up* the function parent generic param
|
|
||||||
// and the impl_block generic param by unify them one by one
|
|
||||||
if let Ty::Apply(ty) = &ty {
|
|
||||||
old_params.iter().zip(impl_block.substs()?.iter()).for_each(
|
|
||||||
|(param, pty)| {
|
|
||||||
if let Ty::Param { idx, .. } = param {
|
|
||||||
self.unify(pty, &ty.parameters.0[*idx as usize]);
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
},
|
||||||
}
|
);
|
||||||
|
|
||||||
return Some(());
|
Some(Substs(new_substs.into()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
plug_self_types();
|
let typable: Option<TypableDef> = def.into();
|
||||||
|
let typable = typable?;
|
||||||
|
let mut ty = self.db.type_for_def(typable, Namespace::Values);
|
||||||
|
if let Some(sts) = find_self_types() {
|
||||||
|
ty = ty.subst(&sts);
|
||||||
|
}
|
||||||
|
|
||||||
|
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
|
||||||
|
let ty = ty.subst(&substs);
|
||||||
|
let ty = self.insert_type_vars(ty);
|
||||||
Some(ty)
|
Some(ty)
|
||||||
}
|
}
|
||||||
Resolution::LocalBinding(pat) => {
|
Resolution::LocalBinding(pat) => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue