aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/ty/infer.rs97
1 files changed, 46 insertions, 51 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index d426d275e..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> {
@@ -462,28 +463,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
462 let mut actual_def_ty: Option<Ty> = None; 463 let mut actual_def_ty: Option<Ty> = None;
463 464
464 // resolve intermediate segments 465 // resolve intermediate segments
465 for segment in &path.segments[remaining_index..] { 466 for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
466 let ty = match resolved { 467 let ty = match resolved {
467 Resolution::Def(def) => { 468 Resolution::Def(def) => {
468 // FIXME resolve associated items from traits as well 469 // FIXME resolve associated items from traits as well
469 let typable: Option<TypableDef> = def.into(); 470 let typable: Option<TypableDef> = def.into();
470 let typable = typable?; 471 let typable = typable?;
471 472
472 let mut ty = self.db.type_for_def(typable, Namespace::Types); 473 let ty = self.db.type_for_def(typable, Namespace::Types);
473 474
474 if remaining_index > 0 { 475 // For example, this substs will take `Gen::*<u32>*::make`
475 // For example, this substs will take `Gen::*<u32>*::make` 476 assert!(remaining_index > 0);
476 let substs = Ty::substs_from_path_segment( 477 let substs = Ty::substs_from_path_segment(
477 self.db, 478 self.db,
478 &self.resolver, 479 &self.resolver,
479 &path.segments[remaining_index - 1], 480 &path.segments[remaining_index + i - 1],
480 typable, 481 typable,
481 ); 482 );
482
483 ty = ty.subst(&substs);
484 }
485 483
486 ty 484 ty.subst(&substs)
487 } 485 }
488 Resolution::LocalBinding(_) => { 486 Resolution::LocalBinding(_) => {
489 // can't have a local binding in an associated item path 487 // can't have a local binding in an associated item path
@@ -541,45 +539,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
541 539
542 match resolved { 540 match resolved {
543 Resolution::Def(def) => { 541 Resolution::Def(def) => {
544 // Helpper function for finding self types
545 let find_self_types = || -> Option<Substs> {
546 let actual_def_ty = actual_def_ty?;
547
548 if let crate::ModuleDef::Function(func) = def {
549 // We only do the infer if parent has generic params
550 let gen = func.generic_params(self.db);
551 if gen.count_parent_params() == 0 {
552 return None;
553 }
554
555 let impl_block = func.impl_block(self.db)?.target_ty(self.db);
556 let impl_block_substs = impl_block.substs()?;
557 let actual_substs = actual_def_ty.substs()?;
558
559 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
560
561 // The following code *link up* the function actual parma type
562 // and impl_block type param index
563 impl_block_substs.iter().zip(actual_substs.iter()).for_each(
564 |(param, pty)| {
565 if let Ty::Param { idx, .. } = param {
566 if let Some(s) = new_substs.get_mut(*idx as usize) {
567 *s = pty.clone();
568 }
569 }
570 },
571 );
572
573 Some(Substs(new_substs.into()))
574 } else {
575 None
576 }
577 };
578
579 let typable: Option<TypableDef> = def.into(); 542 let typable: Option<TypableDef> = def.into();
580 let typable = typable?; 543 let typable = typable?;
581 let mut ty = self.db.type_for_def(typable, Namespace::Values); 544 let mut ty = self.db.type_for_def(typable, Namespace::Values);
582 if let Some(sts) = find_self_types() { 545 if let Some(sts) = self.find_self_types(&def, actual_def_ty) {
583 ty = ty.subst(&sts); 546 ty = ty.subst(&sts);
584 } 547 }
585 548
@@ -604,6 +567,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
604 } 567 }
605 } 568 }
606 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
607 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { 602 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
608 let path = match path { 603 let path = match path {
609 Some(path) => path, 604 Some(path) => path,