diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 651a78fe5..fe6553f79 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -459,6 +459,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
459 | if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; | 459 | if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; |
460 | 460 | ||
461 | let remaining_index = remaining_index.unwrap_or(path.segments.len()); | 461 | let remaining_index = remaining_index.unwrap_or(path.segments.len()); |
462 | let mut actual_def_ty: Option<Ty> = None; | ||
462 | 463 | ||
463 | // resolve intermediate segments | 464 | // resolve intermediate segments |
464 | for segment in &path.segments[remaining_index..] { | 465 | for segment in &path.segments[remaining_index..] { |
@@ -468,9 +469,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
468 | let typable: Option<TypableDef> = def.into(); | 469 | let typable: Option<TypableDef> = def.into(); |
469 | let typable = typable?; | 470 | let typable = typable?; |
470 | 471 | ||
471 | let substs = | 472 | let mut substs = |
472 | Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable); | 473 | Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable); |
473 | self.db.type_for_def(typable, Namespace::Types).subst(&substs) | 474 | |
475 | if remaining_index > 0 { | ||
476 | substs = Ty::substs_from_path_segment( | ||
477 | self.db, | ||
478 | &self.resolver, | ||
479 | &path.segments[remaining_index - 1], | ||
480 | typable, | ||
481 | ); | ||
482 | } | ||
483 | |||
484 | let ty = self.db.type_for_def(typable, Namespace::Types); | ||
485 | ty.subst(&substs) | ||
474 | } | 486 | } |
475 | Resolution::LocalBinding(_) => { | 487 | Resolution::LocalBinding(_) => { |
476 | // can't have a local binding in an associated item path | 488 | // can't have a local binding in an associated item path |
@@ -489,6 +501,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
489 | // Attempt to find an impl_item for the type which has a name matching | 501 | // Attempt to find an impl_item for the type which has a name matching |
490 | // the current segment | 502 | // the current segment |
491 | log::debug!("looking for path segment: {:?}", segment); | 503 | log::debug!("looking for path segment: {:?}", segment); |
504 | actual_def_ty = Some(ty.clone()); | ||
505 | |||
492 | let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| { | 506 | let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| { |
493 | let matching_def: Option<crate::ModuleDef> = match item { | 507 | let matching_def: Option<crate::ModuleDef> = match item { |
494 | crate::ImplItem::Method(func) => { | 508 | crate::ImplItem::Method(func) => { |
@@ -528,9 +542,40 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
528 | Resolution::Def(def) => { | 542 | Resolution::Def(def) => { |
529 | let typable: Option<TypableDef> = def.into(); | 543 | let typable: Option<TypableDef> = def.into(); |
530 | let typable = typable?; | 544 | let typable = typable?; |
545 | |||
546 | let ty = self.db.type_for_def(typable, Namespace::Values); | ||
531 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | 547 | 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); | 548 | let ty = ty.subst(&substs); |
533 | let ty = self.insert_type_vars(ty); | 549 | let ty = self.insert_type_vars(ty); |
550 | |||
551 | // plug the old parent_ty in | ||
552 | if let Some(actual_def_ty) = actual_def_ty { | ||
553 | if let crate::ModuleDef::Function(func) = def { | ||
554 | let gen = func.generic_params(self.db); | ||
555 | if let Some(target_ty) = func.impl_block(self.db) { | ||
556 | let target_ty = target_ty.target_ty(self.db); | ||
557 | let old_params = target_ty.substs().unwrap().clone(); | ||
558 | |||
559 | let target_ty = target_ty.subst(&substs); | ||
560 | let target_ty = self.insert_type_vars(target_ty); | ||
561 | |||
562 | if gen.count_parent_params() > 0 { | ||
563 | self.unify(&target_ty, &actual_def_ty); | ||
564 | |||
565 | if let Ty::Apply(ty) = &ty { | ||
566 | for (param, pty) in | ||
567 | old_params.iter().zip(target_ty.substs().unwrap().iter()) | ||
568 | { | ||
569 | if let Ty::Param { idx, .. } = param { | ||
570 | self.unify(pty, &ty.parameters.0[*idx as usize]); | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | } | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | |||
534 | Some(ty) | 579 | Some(ty) |
535 | } | 580 | } |
536 | Resolution::LocalBinding(pat) => { | 581 | Resolution::LocalBinding(pat) => { |