diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 92 |
1 files changed, 32 insertions, 60 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index a3c4f1886..d426d275e 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -469,38 +469,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
469 | let typable: Option<TypableDef> = def.into(); | 469 | let typable: Option<TypableDef> = def.into(); |
470 | let typable = typable?; | 470 | let typable = typable?; |
471 | 471 | ||
472 | // For example, this substs will take `Gen::make::*<u32>*` | 472 | let mut ty = self.db.type_for_def(typable, Namespace::Types); |
473 | let mut substs = | ||
474 | Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable); | ||
475 | 473 | ||
476 | if remaining_index > 0 { | 474 | if remaining_index > 0 { |
477 | // For example, this substs will take `Gen::*<u32>*::make` | 475 | // For example, this substs will take `Gen::*<u32>*::make` |
478 | let parent_substs = Ty::substs_from_path_segment( | 476 | let substs = Ty::substs_from_path_segment( |
479 | self.db, | 477 | self.db, |
480 | &self.resolver, | 478 | &self.resolver, |
481 | &path.segments[remaining_index - 1], | 479 | &path.segments[remaining_index - 1], |
482 | typable, | 480 | typable, |
483 | ); | 481 | ); |
484 | 482 | ||
485 | // merge parent and child substs | 483 | ty = ty.subst(&substs); |
486 | let max_len = std::cmp::max(substs.len(), parent_substs.len()); | ||
487 | let mut merged = vec![]; | ||
488 | for i in 0..max_len { | ||
489 | let s = match (substs.0.get(i), parent_substs.0.get(i)) { | ||
490 | (Some(s @ Ty::Apply(_)), _) => s, | ||
491 | (_, Some(s @ Ty::Apply(_))) => s, | ||
492 | (Some(s), _) => s, | ||
493 | (_, Some(s)) => s, | ||
494 | _ => unreachable!(), | ||
495 | }; | ||
496 | merged.push(s.clone()); | ||
497 | } | ||
498 | |||
499 | substs = Substs(merged.into()); | ||
500 | } | 484 | } |
501 | 485 | ||
502 | let ty = self.db.type_for_def(typable, Namespace::Types); | 486 | ty |
503 | ty.subst(&substs) | ||
504 | } | 487 | } |
505 | Resolution::LocalBinding(_) => { | 488 | Resolution::LocalBinding(_) => { |
506 | // can't have a local binding in an associated item path | 489 | // can't have a local binding in an associated item path |
@@ -558,16 +541,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
558 | 541 | ||
559 | match resolved { | 542 | match resolved { |
560 | Resolution::Def(def) => { | 543 | Resolution::Def(def) => { |
561 | let typable: Option<TypableDef> = def.into(); | 544 | // Helpper function for finding self types |
562 | let typable = typable?; | 545 | let find_self_types = || -> Option<Substs> { |
563 | |||
564 | let ty = self.db.type_for_def(typable, Namespace::Values); | ||
565 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
566 | let ty = ty.subst(&substs); | ||
567 | let ty = self.insert_type_vars(ty); | ||
568 | |||
569 | // plug the old parent_ty in | ||
570 | let plug_self_types = || -> Option<()> { | ||
571 | let actual_def_ty = actual_def_ty?; | 546 | let actual_def_ty = actual_def_ty?; |
572 | 547 | ||
573 | if let crate::ModuleDef::Function(func) = def { | 548 | if let crate::ModuleDef::Function(func) = def { |
@@ -577,43 +552,40 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
577 | return None; | 552 | return None; |
578 | } | 553 | } |
579 | 554 | ||
580 | let impl_block = func.impl_block(self.db)?; | 555 | let impl_block = func.impl_block(self.db)?.target_ty(self.db); |
581 | let impl_block = impl_block.target_ty(self.db); | 556 | let impl_block_substs = impl_block.substs()?; |
557 | let actual_substs = actual_def_ty.substs()?; | ||
582 | 558 | ||
583 | // We save the impl block type params for later use | 559 | let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()]; |
584 | let old_params = impl_block.substs().unwrap().clone(); | ||
585 | 560 | ||
586 | // Turn the impl block generic params to unknown | 561 | // The following code *link up* the function actual parma type |
587 | let mut subst = vec![]; | 562 | // and impl_block type param index |
588 | for _ in 0..impl_block.substs().map(|x| x.len()).unwrap_or(0) { | 563 | impl_block_substs.iter().zip(actual_substs.iter()).for_each( |
589 | subst.push(Ty::Unknown); | 564 | |(param, pty)| { |
590 | } | 565 | if let Ty::Param { idx, .. } = param { |
591 | let impl_block = impl_block.subst(&Substs(subst.into())); | 566 | if let Some(s) = new_substs.get_mut(*idx as usize) { |
592 | let impl_block = self.insert_type_vars(impl_block); | 567 | *s = pty.clone(); |
593 | |||
594 | // Unify *self type* and impl_block | ||
595 | // e.g. Gen::<u32,u64> <=> Gen::<u64, T> | ||
596 | self.unify(&impl_block, &actual_def_ty); | ||
597 | |||
598 | // The following code *link up* the function parent generic param | ||
599 | // and the impl_block generic param by unify them one by one | ||
600 | if let Ty::Apply(ty) = &ty { | ||
601 | old_params.iter().zip(impl_block.substs()?.iter()).for_each( | ||
602 | |(param, pty)| { | ||
603 | if let Ty::Param { idx, .. } = param { | ||
604 | self.unify(pty, &ty.parameters.0[*idx as usize]); | ||
605 | } | 568 | } |
606 | }, | 569 | } |
607 | ); | 570 | }, |
608 | } | 571 | ); |
609 | 572 | ||
610 | return Some(()); | 573 | Some(Substs(new_substs.into())) |
574 | } else { | ||
575 | None | ||
611 | } | 576 | } |
612 | None | ||
613 | }; | 577 | }; |
614 | 578 | ||
615 | plug_self_types(); | 579 | let typable: Option<TypableDef> = def.into(); |
580 | let typable = typable?; | ||
581 | let mut ty = self.db.type_for_def(typable, Namespace::Values); | ||
582 | if let Some(sts) = find_self_types() { | ||
583 | ty = ty.subst(&sts); | ||
584 | } | ||
616 | 585 | ||
586 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
587 | let ty = ty.subst(&substs); | ||
588 | let ty = self.insert_type_vars(ty); | ||
617 | Some(ty) | 589 | Some(ty) |
618 | } | 590 | } |
619 | Resolution::LocalBinding(pat) => { | 591 | Resolution::LocalBinding(pat) => { |