Refactoring
This commit is contained in:
parent
039ab2e820
commit
8747c903a2
1 changed files with 46 additions and 51 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue