Refactoring

This commit is contained in:
Edwin Cheng 2019-04-17 09:26:01 +08:00
parent 039ab2e820
commit 8747c903a2

View file

@ -35,16 +35,17 @@ use crate::{
expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self},
generics::{GenericParams, HasGenericParams},
path::{GenericArgs, GenericArg},
ModuleDef,
adt::VariantDef,
resolve::{Resolver, Resolution},
nameres::Namespace,
ty::infer::diagnostics::InferenceDiagnostic,
diagnostics::DiagnosticSink,
};
use super::{
Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef,
traits::{ Solution, Obligation, Guidance},
};
use self::diagnostics::InferenceDiagnostic;
/// The entry point of type inference.
pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
@ -462,28 +463,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let mut actual_def_ty: Option<Ty> = None;
// resolve intermediate segments
for segment in &path.segments[remaining_index..] {
for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
let ty = match resolved {
Resolution::Def(def) => {
// FIXME resolve associated items from traits as well
let typable: Option<TypableDef> = def.into();
let typable = typable?;
let mut ty = self.db.type_for_def(typable, Namespace::Types);
let ty = self.db.type_for_def(typable, Namespace::Types);
if remaining_index > 0 {
// For example, this substs will take `Gen::*<u32>*::make`
let substs = Ty::substs_from_path_segment(
self.db,
&self.resolver,
&path.segments[remaining_index - 1],
typable,
);
// For example, this substs will take `Gen::*<u32>*::make`
assert!(remaining_index > 0);
let substs = Ty::substs_from_path_segment(
self.db,
&self.resolver,
&path.segments[remaining_index + i - 1],
typable,
);
ty = ty.subst(&substs);
}
ty
ty.subst(&substs)
}
Resolution::LocalBinding(_) => {
// can't have a local binding in an associated item path
@ -541,45 +539,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
match resolved {
Resolution::Def(def) => {
// Helpper function for finding self types
let find_self_types = || -> Option<Substs> {
let actual_def_ty = actual_def_ty?;
if let crate::ModuleDef::Function(func) = def {
// We only do the infer if parent has generic params
let gen = func.generic_params(self.db);
if gen.count_parent_params() == 0 {
return None;
}
let impl_block = func.impl_block(self.db)?.target_ty(self.db);
let impl_block_substs = impl_block.substs()?;
let actual_substs = actual_def_ty.substs()?;
let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
// The following code *link up* the function actual parma type
// and impl_block type param index
impl_block_substs.iter().zip(actual_substs.iter()).for_each(
|(param, pty)| {
if let Ty::Param { idx, .. } = param {
if let Some(s) = new_substs.get_mut(*idx as usize) {
*s = pty.clone();
}
}
},
);
Some(Substs(new_substs.into()))
} else {
None
}
};
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() {
if let Some(sts) = self.find_self_types(&def, actual_def_ty) {
ty = ty.subst(&sts);
}
@ -604,6 +567,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
}
}
fn find_self_types(&self, def: &ModuleDef, actual_def_ty: Option<Ty>) -> Option<Substs> {
let actual_def_ty = actual_def_ty?;
if let crate::ModuleDef::Function(func) = def {
// We only do the infer if parent has generic params
let gen = func.generic_params(self.db);
if gen.count_parent_params() == 0 {
return None;
}
let impl_block = func.impl_block(self.db)?.target_ty(self.db);
let impl_block_substs = impl_block.substs()?;
let actual_substs = actual_def_ty.substs()?;
let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
// The following code *link up* the function actual parma type
// and impl_block type param index
impl_block_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
if let Ty::Param { idx, .. } = param {
if let Some(s) = new_substs.get_mut(*idx as usize) {
*s = pty.clone();
}
}
});
Some(Substs(new_substs.into()))
} else {
None
}
}
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
let path = match path {
Some(path) => path,