aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs92
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) => {