diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 125 |
1 files changed, 54 insertions, 71 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 6aaf61c0e..f33479dc4 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -48,7 +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, ImplItem, Name, Path, | 51 | Adt, AssocItem, ConstData, DefWithBody, Either, FnData, Function, HasBody, Name, Path, |
52 | StructField, | 52 | StructField, |
53 | }; | 53 | }; |
54 | 54 | ||
@@ -508,7 +508,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
508 | 508 | ||
509 | fn resolve_assoc_item( | 509 | fn resolve_assoc_item( |
510 | &mut self, | 510 | &mut self, |
511 | mut def_or_ty: Either<TypeNs, Ty>, | 511 | // mut def_or_ty: Either<TypeNs, Ty>, |
512 | def: TypeNs, | ||
512 | path: &Path, | 513 | path: &Path, |
513 | remaining_index: usize, | 514 | remaining_index: usize, |
514 | id: ExprOrPatId, | 515 | id: ExprOrPatId, |
@@ -516,80 +517,63 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
516 | assert!(remaining_index < path.segments.len()); | 517 | assert!(remaining_index < path.segments.len()); |
517 | let krate = self.resolver.krate()?; | 518 | let krate = self.resolver.krate()?; |
518 | 519 | ||
519 | let mut ty = Ty::Unknown; | 520 | // there may be more intermediate segments between the resolved one and |
520 | 521 | // the end. Only the last segment needs to be resolved to a value; from | |
521 | // resolve intermediate segments | 522 | // the segments before that, we need to get either a type or a trait ref. |
522 | for (i, segment) in path.segments[remaining_index..].iter().enumerate() { | ||
523 | let is_last_segment = i == path.segments[remaining_index..].len() - 1; | ||
524 | ty = match def_or_ty { | ||
525 | Either::A(def) => { | ||
526 | let typable: TypableDef = match def { | ||
527 | TypeNs::Adt(it) => it.into(), | ||
528 | TypeNs::TypeAlias(it) => it.into(), | ||
529 | TypeNs::BuiltinType(it) => it.into(), | ||
530 | // FIXME associated item of traits, generics, and Self | ||
531 | TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => { | ||
532 | return None; | ||
533 | } | ||
534 | // FIXME: report error here | ||
535 | TypeNs::EnumVariant(_) => return None, | ||
536 | }; | ||
537 | |||
538 | let ty = self.db.type_for_def(typable, Namespace::Types); | ||
539 | |||
540 | // For example, this substs will take `Gen::*<u32>*::make` | ||
541 | assert!(remaining_index > 0); | ||
542 | let substs = Ty::substs_from_path_segment( | ||
543 | self.db, | ||
544 | &self.resolver, | ||
545 | &path.segments[remaining_index + i - 1], | ||
546 | typable, | ||
547 | ); | ||
548 | ty.subst(&substs) | ||
549 | } | ||
550 | Either::B(ty) => ty, | ||
551 | }; | ||
552 | if is_last_segment { | ||
553 | break; | ||
554 | } | ||
555 | 523 | ||
556 | // Attempt to find an impl_item for the type which has a name matching | 524 | let resolved_segment = &path.segments[remaining_index - 1]; |
557 | // the current segment | 525 | let remaining_segments = &path.segments[remaining_index..]; |
558 | log::debug!("looking for path segment: {:?}", segment); | 526 | let is_before_last = remaining_segments.len() == 1; |
559 | 527 | ||
560 | let ty = mem::replace(&mut ty, Ty::Unknown); | 528 | let (def, substs) = match (def, is_before_last) { |
561 | def_or_ty = ty.iterate_impl_items(self.db, krate, |item| { | 529 | (TypeNs::Trait(_trait), true) => { |
562 | match item { | 530 | // Associated item of trait, e.g. `Default::default` |
563 | crate::ImplItem::Method(_) | crate::ImplItem::Const(_) => None, | 531 | // FIXME |
532 | return None; | ||
533 | } | ||
534 | (def, _) => { | ||
535 | // Either we already have a type (e.g. `Vec::new`), or we have a | ||
536 | // trait but it's not the last segment, so the next segment | ||
537 | // should resolve to an associated type of that trait (e.g. `<T | ||
538 | // as Iterator>::Item::default`) | ||
539 | let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1]; | ||
540 | let ty = Ty::from_partly_resolved_hir_path( | ||
541 | self.db, | ||
542 | &self.resolver, | ||
543 | def, | ||
544 | resolved_segment, | ||
545 | remaining_segments_for_ty, | ||
546 | ); | ||
547 | if let Ty::Unknown = ty { | ||
548 | return None; | ||
549 | } | ||
564 | 550 | ||
565 | // FIXME: Resolve associated types | 551 | let segment = |
566 | crate::ImplItem::TypeAlias(_) => { | 552 | remaining_segments.last().expect("there should be at least one segment here"); |
567 | // Some(Either::A(TypeNs::TypeAlias(..))) | 553 | // Find impl |
568 | None | 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 | } | ||
569 | } | 561 | } |
570 | } | ||
571 | })?; | ||
572 | } | ||
573 | 562 | ||
574 | let segment = path.segments.last().unwrap(); | 563 | crate::ImplItem::Const(konst) => { |
575 | let def = ty.clone().iterate_impl_items(self.db, krate, |item| match item { | 564 | if segment.name == konst.name(self.db) { |
576 | crate::ImplItem::Method(func) => { | 565 | Some(ValueNs::Const(konst)) |
577 | if segment.name == func.name(self.db) { | 566 | } else { |
578 | Some(ValueNs::Function(func)) | 567 | None |
579 | } else { | 568 | } |
580 | None | 569 | } |
581 | } | 570 | crate::ImplItem::TypeAlias(_) => None, |
571 | })?; | ||
572 | let self_types = self.find_self_types(&def, ty); | ||
573 | (def, self_types) | ||
582 | } | 574 | } |
575 | }; | ||
583 | 576 | ||
584 | crate::ImplItem::Const(konst) => { | ||
585 | if konst.name(self.db).map_or(false, |n| n == segment.name) { | ||
586 | Some(ValueNs::Const(konst)) | ||
587 | } else { | ||
588 | None | ||
589 | } | ||
590 | } | ||
591 | crate::ImplItem::TypeAlias(_) => None, | ||
592 | })?; | ||
593 | self.write_assoc_resolution( | 577 | self.write_assoc_resolution( |
594 | id, | 578 | id, |
595 | match def { | 579 | match def { |
@@ -598,8 +582,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
598 | _ => unreachable!(), | 582 | _ => unreachable!(), |
599 | }, | 583 | }, |
600 | ); | 584 | ); |
601 | let self_types = self.find_self_types(&def, ty); | 585 | Some((def, substs)) |
602 | Some((def, self_types)) | ||
603 | } | 586 | } |
604 | 587 | ||
605 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { | 588 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { |