aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/infer.rs62
-rw-r--r--crates/ra_hir/src/ty/tests.rs63
2 files changed, 117 insertions, 8 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 651a78fe5..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};
43use super::{ 45use 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};
47use self::diagnostics::InferenceDiagnostic;
48 49
49/// The entry point of type inference. 50/// The entry point of type inference.
50pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 51pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
@@ -459,18 +460,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
459 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; 460 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
460 461
461 let remaining_index = remaining_index.unwrap_or(path.segments.len()); 462 let remaining_index = remaining_index.unwrap_or(path.segments.len());
463 let mut actual_def_ty: Option<Ty> = None;
462 464
463 // resolve intermediate segments 465 // resolve intermediate segments
464 for segment in &path.segments[remaining_index..] { 466 for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
465 let ty = match resolved { 467 let ty = match resolved {
466 Resolution::Def(def) => { 468 Resolution::Def(def) => {
467 // FIXME resolve associated items from traits as well 469 // FIXME resolve associated items from traits as well
468 let typable: Option<TypableDef> = def.into(); 470 let typable: Option<TypableDef> = def.into();
469 let typable = typable?; 471 let typable = typable?;
470 472
471 let substs = 473 let ty = self.db.type_for_def(typable, Namespace::Types);
472 Ty::substs_from_path_segment(self.db, &self.resolver, segment, typable); 474
473 self.db.type_for_def(typable, Namespace::Types).subst(&substs) 475 // For example, this substs will take `Gen::*<u32>*::make`
476 assert!(remaining_index > 0);
477 let substs = Ty::substs_from_path_segment(
478 self.db,
479 &self.resolver,
480 &path.segments[remaining_index + i - 1],
481 typable,
482 );
483
484 ty.subst(&substs)
474 } 485 }
475 Resolution::LocalBinding(_) => { 486 Resolution::LocalBinding(_) => {
476 // can't have a local binding in an associated item path 487 // can't have a local binding in an associated item path
@@ -489,6 +500,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
489 // Attempt to find an impl_item for the type which has a name matching 500 // Attempt to find an impl_item for the type which has a name matching
490 // the current segment 501 // the current segment
491 log::debug!("looking for path segment: {:?}", segment); 502 log::debug!("looking for path segment: {:?}", segment);
503 actual_def_ty = Some(ty.clone());
504
492 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| { 505 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, |item| {
493 let matching_def: Option<crate::ModuleDef> = match item { 506 let matching_def: Option<crate::ModuleDef> = match item {
494 crate::ImplItem::Method(func) => { 507 crate::ImplItem::Method(func) => {
@@ -528,8 +541,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
528 Resolution::Def(def) => { 541 Resolution::Def(def) => {
529 let typable: Option<TypableDef> = def.into(); 542 let typable: Option<TypableDef> = def.into();
530 let typable = typable?; 543 let typable = typable?;
544 let mut ty = self.db.type_for_def(typable, Namespace::Values);
545 if let Some(sts) = self.find_self_types(&def, actual_def_ty) {
546 ty = ty.subst(&sts);
547 }
548
531 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 549 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); 550 let ty = ty.subst(&substs);
533 let ty = self.insert_type_vars(ty); 551 let ty = self.insert_type_vars(ty);
534 Some(ty) 552 Some(ty)
535 } 553 }
@@ -549,6 +567,38 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
549 } 567 }
550 } 568 }
551 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
552 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { 602 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
553 let path = match path { 603 let path = match path {
554 Some(path) => path, 604 Some(path) => path,
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