aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs62
1 files changed, 56 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 651a78fe5..7ca1ff595 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -35,16 +35,17 @@ use crate::{
35 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self}, 35 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self},
36 generics::{GenericParams, HasGenericParams}, 36 generics::{GenericParams, HasGenericParams},
37 path::{GenericArgs, GenericArg}, 37 path::{GenericArgs, GenericArg},
38 ModuleDef,
38 adt::VariantDef, 39 adt::VariantDef,
39 resolve::{Resolver, Resolution}, 40 resolve::{Resolver, Resolution},
40 nameres::Namespace, 41 nameres::Namespace,
42 ty::infer::diagnostics::InferenceDiagnostic,
41 diagnostics::DiagnosticSink, 43 diagnostics::DiagnosticSink,
42}; 44};
43use super::{ 45use super::{
44 Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef, 46 Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef,
45 traits::{ Solution, Obligation, Guidance}, 47 traits::{ Solution, Obligation, Guidance},
46}; 48};
47use self::diagnostics::InferenceDiagnostic;
48 49
49/// The entry point of type inference. 50/// The entry point of type inference.
50pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 51pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
@@ -459,18 +460,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
459 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; 460 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
460 461
461 let remaining_index = remaining_index.unwrap_or(path.segments.len()); 462 let remaining_index = remaining_index.unwrap_or(path.segments.len());
463 let mut actual_def_ty: Option<Ty> = None;
462 464
463 // resolve intermediate segments 465 // resolve intermediate segments
464 for segment in &path.segments[remaining_index..] { 466 for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
465 let ty = match resolved { 467 let ty = match resolved {
466 Resolution::Def(def) => { 468 Resolution::Def(def) => {
467 // FIXME resolve associated items from traits as well 469 // FIXME resolve associated items from traits as well
468 let typable: Option<TypableDef> = def.into(); 470 let typable: Option<TypableDef> = def.into();
469 let typable = typable?; 471 let typable = typable?;
470 472
471 let substs = 473 let ty = self.db.type_for_def(typable, Namespace::Types);
472 Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable); 474
473 self.db.type_for_def(typable, Namespace::Types).subst(&substs) 475 // For example, this substs will take `Gen::*<u32>*::make`
476 assert!(remaining_index > 0);
477 let substs = Ty::substs_from_path_segment(
478 self.db,
479 &self.resolver,
480 &path.segments[remaining_index + i - 1],
481 typable,
482 );
483
484 ty.subst(&substs)
474 } 485 }
475 Resolution::LocalBinding(_) => { 486 Resolution::LocalBinding(_) => {
476 // can't have a local binding in an associated item path 487 // can't have a local binding in an associated item path
@@ -489,6 +500,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
489 // Attempt to find an impl_item for the type which has a name matching 500 // Attempt to find an impl_item for the type which has a name matching
490 // the current segment 501 // the current segment
491 log::debug!("looking for path segment: {:?}", segment); 502 log::debug!("looking for path segment: {:?}", segment);
503 actual_def_ty = Some(ty.clone());
504
492 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| { 505 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| {
493 let matching_def: Option<crate::ModuleDef> = match item { 506 let matching_def: Option<crate::ModuleDef> = match item {
494 crate::ImplItem::Method(func) => { 507 crate::ImplItem::Method(func) => {
@@ -528,8 +541,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
528 Resolution::Def(def) => { 541 Resolution::Def(def) => {
529 let typable: Option<TypableDef> = def.into(); 542 let typable: Option<TypableDef> = def.into();
530 let typable = typable?; 543 let typable = typable?;
544 let mut ty = self.db.type_for_def(typable, Namespace::Values);
545 if let Some(sts) = self.find_self_types(&def, actual_def_ty) {
546 ty = ty.subst(&sts);
547 }
548
531 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 549 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
532 let ty = self.db.type_for_def(typable, Namespace::Values).subst(&substs); 550 let ty = ty.subst(&substs);
533 let ty = self.insert_type_vars(ty); 551 let ty = self.insert_type_vars(ty);
534 Some(ty) 552 Some(ty)
535 } 553 }
@@ -549,6 +567,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
549 } 567 }
550 } 568 }
551 569
570 fn find_self_types(&self, def: &ModuleDef, actual_def_ty: Option<Ty>) -> Option<Substs> {
571 let actual_def_ty = actual_def_ty?;
572
573 if let crate::ModuleDef::Function(func) = def {
574 // We only do the infer if parent has generic params
575 let gen = func.generic_params(self.db);
576 if gen.count_parent_params() == 0 {
577 return None;
578 }
579
580 let impl_block = func.impl_block(self.db)?.target_ty(self.db);
581 let impl_block_substs = impl_block.substs()?;
582 let actual_substs = actual_def_ty.substs()?;
583
584 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
585
586 // The following code *link up* the function actual parma type
587 // and impl_block type param index
588 impl_block_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
589 if let Ty::Param { idx, .. } = param {
590 if let Some(s) = new_substs.get_mut(*idx as usize) {
591 *s = pty.clone();
592 }
593 }
594 });
595
596 Some(Substs(new_substs.into()))
597 } else {
598 None
599 }
600 }
601
552 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { 602 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
553 let path = match path { 603 let path = match path {
554 Some(path) => path, 604 Some(path) => path,