aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs100
1 files changed, 61 insertions, 39 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index f33479dc4..181be0fcc 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -48,8 +48,7 @@ use crate::{
48 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 48 resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
49 ty::infer::diagnostics::InferenceDiagnostic, 49 ty::infer::diagnostics::InferenceDiagnostic,
50 type_ref::{Mutability, TypeRef}, 50 type_ref::{Mutability, TypeRef},
51 Adt, AssocItem, ConstData, DefWithBody, Either, FnData, Function, HasBody, Name, Path, 51 Adt, AssocItem, ConstData, DefWithBody, FnData, Function, HasBody, Name, Path, StructField,
52 StructField,
53}; 52};
54 53
55mod unify; 54mod unify;
@@ -468,16 +467,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
468 } 467 }
469 468
470 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> { 469 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> {
471 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; 470 let (value, self_subst) = if let crate::PathKind::Type(type_ref) = &path.kind {
472 471 if path.segments.is_empty() {
473 let (value, self_subst) = match value_or_partial { 472 // This can't actually happen syntax-wise
474 ResolveValueResult::ValueNs(it) => (it, None), 473 return None;
475 ResolveValueResult::Partial(def, remaining_index) => {
476 self.resolve_assoc_item(Either::A(def), path, remaining_index, id)?
477 } 474 }
478 ResolveValueResult::TypeRef(type_ref) => { 475 let ty = self.make_ty(type_ref);
479 let ty = self.make_ty(type_ref); 476 let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1];
480 self.resolve_assoc_item(Either::B(ty), path, 0, id)? 477 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
478 self.resolve_ty_assoc_item(
479 ty,
480 path.segments.last().expect("path had at least one segment"),
481 id,
482 )?
483 } else {
484 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?;
485
486 match value_or_partial {
487 ResolveValueResult::ValueNs(it) => (it, None),
488 ResolveValueResult::Partial(def, remaining_index) => {
489 self.resolve_assoc_item(def, path, remaining_index, id)?
490 }
481 } 491 }
482 }; 492 };
483 493
@@ -508,15 +518,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
508 518
509 fn resolve_assoc_item( 519 fn resolve_assoc_item(
510 &mut self, 520 &mut self,
511 // mut def_or_ty: Either<TypeNs, Ty>,
512 def: TypeNs, 521 def: TypeNs,
513 path: &Path, 522 path: &Path,
514 remaining_index: usize, 523 remaining_index: usize,
515 id: ExprOrPatId, 524 id: ExprOrPatId,
516 ) -> Option<(ValueNs, Option<Substs>)> { 525 ) -> Option<(ValueNs, Option<Substs>)> {
517 assert!(remaining_index < path.segments.len()); 526 assert!(remaining_index < path.segments.len());
518 let krate = self.resolver.krate()?;
519
520 // there may be more intermediate segments between the resolved one and 527 // there may be more intermediate segments between the resolved one and
521 // the end. Only the last segment needs to be resolved to a value; from 528 // the end. Only the last segment needs to be resolved to a value; from
522 // the segments before that, we need to get either a type or a trait ref. 529 // the segments before that, we need to get either a type or a trait ref.
@@ -525,11 +532,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
525 let remaining_segments = &path.segments[remaining_index..]; 532 let remaining_segments = &path.segments[remaining_index..];
526 let is_before_last = remaining_segments.len() == 1; 533 let is_before_last = remaining_segments.len() == 1;
527 534
528 let (def, substs) = match (def, is_before_last) { 535 match (def, is_before_last) {
529 (TypeNs::Trait(_trait), true) => { 536 (TypeNs::Trait(_trait), true) => {
530 // Associated item of trait, e.g. `Default::default` 537 // FIXME Associated item of trait, e.g. `Default::default`
531 // FIXME 538 None
532 return None;
533 } 539 }
534 (def, _) => { 540 (def, _) => {
535 // Either we already have a type (e.g. `Vec::new`), or we have a 541 // Either we already have a type (e.g. `Vec::new`), or we have a
@@ -550,29 +556,45 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
550 556
551 let segment = 557 let segment =
552 remaining_segments.last().expect("there should be at least one segment here"); 558 remaining_segments.last().expect("there should be at least one segment here");
553 // Find impl
554 let def = ty.clone().iterate_impl_items(self.db, krate, |item| match item {
555 crate::ImplItem::Method(func) => {
556 if segment.name == func.name(self.db) {
557 Some(ValueNs::Function(func))
558 } else {
559 None
560 }
561 }
562 559
563 crate::ImplItem::Const(konst) => { 560 self.resolve_ty_assoc_item(ty, segment, id)
564 if segment.name == konst.name(self.db) {
565 Some(ValueNs::Const(konst))
566 } else {
567 None
568 }
569 }
570 crate::ImplItem::TypeAlias(_) => None,
571 })?;
572 let self_types = self.find_self_types(&def, ty);
573 (def, self_types)
574 } 561 }
575 }; 562 }
563 }
564
565 fn resolve_ty_assoc_item(
566 &mut self,
567 ty: Ty,
568 segment: &crate::path::PathSegment,
569 id: ExprOrPatId,
570 ) -> Option<(ValueNs, Option<Substs>)> {
571 if let Ty::Unknown = ty {
572 return None;
573 }
574
575 let krate = self.resolver.krate()?;
576
577 // Find impl
578 // FIXME: consider trait candidates
579 let def = ty.clone().iterate_impl_items(self.db, krate, |item| match item {
580 crate::ImplItem::Method(func) => {
581 if segment.name == func.name(self.db) {
582 Some(ValueNs::Function(func))
583 } else {
584 None
585 }
586 }
587
588 crate::ImplItem::Const(konst) => {
589 if konst.name(self.db).map_or(false, |n| n == segment.name) {
590 Some(ValueNs::Const(konst))
591 } else {
592 None
593 }
594 }
595 crate::ImplItem::TypeAlias(_) => None,
596 })?;
597 let substs = self.find_self_types(&def, ty);
576 598
577 self.write_assoc_resolution( 599 self.write_assoc_resolution(
578 id, 600 id,