aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-04-14 19:26:21 +0100
committerEdwin Cheng <[email protected]>2019-04-17 02:31:52 +0100
commit180655077a4d582d49d4aa14bed67b382f336cf0 (patch)
treec56007d36c734876481a5312bc79effd83f23bfe /crates/ra_hir
parent546d9be2a7bf7b3942c125f922a01321aea6ad26 (diff)
Fix 1099
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/ty/infer.rs51
-rw-r--r--crates/ra_hir/src/ty/tests.rs63
2 files changed, 109 insertions, 5 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) => {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 82c4aeddb..8d8a0eaaa 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1427,6 +1427,65 @@ fn test() {
1427} 1427}
1428 1428
1429#[test] 1429#[test]
1430fn infer_associated_method_generics_without_args() {
1431 assert_snapshot_matches!(
1432 infer(r#"
1433struct Gen<T> {
1434 val: T
1435}
1436
1437impl<T> Gen<T> {
1438 pub fn make() -> Gen<T> {
1439 loop { }
1440 }
1441}
1442
1443fn test() {
1444 let a = Gen::<u32>::make();
1445}
1446"#),
1447 @r###"
1448[76; 100) '{ ... }': !
1449[86; 94) 'loop { }': !
1450[91; 94) '{ }': ()
1451[114; 149) '{ ...e(); }': ()
1452[124; 125) 'a': Gen<u32>
1453[128; 144) 'Gen::<...::make': fn make<u32>() -> Gen<T>
1454[128; 146) 'Gen::<...make()': Gen<u32>"###
1455 );
1456}
1457
1458#[test]
1459fn infer_associated_method_generics_2_type_params_without_args() {
1460 assert_snapshot_matches!(
1461 infer(r#"
1462struct Gen<T, U> {
1463 val: T,
1464 val2: U,
1465}
1466
1467impl<T> Gen<u32, T> {
1468 pub fn make() -> Gen<u32,T> {
1469 loop { }
1470 }
1471}
1472
1473fn test() {
1474 let a = Gen::<u32, u64>::make();
1475}
1476"#),
1477 @r###"
1478[102; 126) '{ ... }': !
1479[112; 120) 'loop { }': !
1480[117; 120) '{ }': ()
1481[140; 180) '{ ...e(); }': ()
1482[150; 151) 'a': Gen<u32, u64>
1483[154; 175) 'Gen::<...::make': fn make<u64>() -> Gen<u32, T>
1484[154; 177) 'Gen::<...make()': Gen<u32, u64>"###
1485 );
1486}
1487
1488#[test]
1430fn infer_type_alias() { 1489fn infer_type_alias() {
1431 assert_snapshot_matches!( 1490 assert_snapshot_matches!(
1432 infer(r#" 1491 infer(r#"
@@ -1814,8 +1873,8 @@ pub fn main_loop() {
1814 @r###" 1873 @r###"
1815[144; 146) '{}': () 1874[144; 146) '{}': ()
1816[169; 198) '{ ...t(); }': () 1875[169; 198) '{ ...t(); }': ()
1817[175; 193) 'FxHash...efault': fn default<{unknown}, {unknown}>() -> HashSet<T, H> 1876[175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<T, H>
1818[175; 195) 'FxHash...ault()': HashSet<{unknown}, {unknown}>"### 1877[175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher>"###
1819 ); 1878 );
1820} 1879}
1821 1880