diff options
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 97 |
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 | }; |
43 | use super::{ | 45 | use 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 | }; |
47 | use self::diagnostics::InferenceDiagnostic; | ||
48 | 49 | ||
49 | /// The entry point of type inference. | 50 | /// The entry point of type inference. |
50 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { | 51 | pub 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, |