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.rs256
1 files changed, 123 insertions, 133 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 540a99b15..3ee083a04 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -45,11 +45,10 @@ use crate::{
45 name, 45 name,
46 nameres::Namespace, 46 nameres::Namespace,
47 path::{GenericArg, GenericArgs, PathKind, PathSegment}, 47 path::{GenericArg, GenericArgs, PathKind, PathSegment},
48 resolve::{Resolution, Resolver}, 48 resolve::{Resolver, TypeNs, ValueNs, ValueOrPartial},
49 ty::infer::diagnostics::InferenceDiagnostic, 49 ty::infer::diagnostics::InferenceDiagnostic,
50 type_ref::{Mutability, TypeRef}, 50 type_ref::{Mutability, TypeRef},
51 Adt, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, ModuleDef, Name, Path, 51 Adt, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, Name, Path, StructField,
52 StructField,
53}; 52};
54 53
55mod unify; 54mod unify;
@@ -472,141 +471,138 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
472 } 471 }
473 472
474 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> { 473 fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path, id: ExprOrPatId) -> Option<Ty> {
475 let resolved = resolver.resolve_path_segments(self.db, &path); 474 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?;
476 475
477 let (def, remaining_index) = resolved.into_inner(); 476 let (value, self_subst) = match value_or_partial {
477 ValueOrPartial::ValueNs(it) => (it, None),
478 ValueOrPartial::Partial(def, remaining_index) => {
479 self.resolve_assoc_item(def, path, remaining_index, id)?
480 }
481 };
478 482
479 log::debug!( 483 let typable: TypableDef = match value {
480 "path {:?} resolved to {:?} with remaining index {:?}", 484 ValueNs::LocalBinding(pat) => {
481 path, 485 let ty = self.result.type_of_pat.get(pat)?.clone();
482 def, 486 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
483 remaining_index 487 return Some(ty);
484 ); 488 }
489 ValueNs::Function(it) => it.into(),
490 ValueNs::Const(it) => it.into(),
491 ValueNs::Static(it) => it.into(),
492 ValueNs::Struct(it) => it.into(),
493 ValueNs::EnumVariant(it) => it.into(),
494 };
485 495
486 // if the remaining_index is None, we expect the path 496 let mut ty = self.db.type_for_def(typable, Namespace::Values);
487 // to be fully resolved, in this case we continue with 497 if let Some(self_subst) = self_subst {
488 // the default by attempting to `take_values´ from the resolution. 498 ty = ty.subst(&self_subst);
489 // Otherwise the path was partially resolved, which means 499 }
490 // we might have resolved into a type for which
491 // we may find some associated item starting at the
492 // path.segment pointed to by `remaining_index´
493 let mut resolved =
494 if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
495 500
496 let remaining_index = remaining_index.unwrap_or_else(|| path.segments.len()); 501 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
497 let mut actual_def_ty: Option<Ty> = None; 502 let ty = ty.subst(&substs);
503 let ty = self.insert_type_vars(ty);
504 let ty = self.normalize_associated_types_in(ty);
505 Some(ty)
506 }
507
508 fn resolve_assoc_item(
509 &mut self,
510 mut def: TypeNs,
511 path: &Path,
512 remaining_index: usize,
513 id: ExprOrPatId,
514 ) -> Option<(ValueNs, Option<Substs>)> {
515 assert!(remaining_index < path.segments.len());
516 let krate = self.resolver.krate()?;
517
518 let mut ty = Ty::Unknown;
498 519
499 let krate = resolver.krate()?;
500 // resolve intermediate segments 520 // resolve intermediate segments
501 for (i, segment) in path.segments[remaining_index..].iter().enumerate() { 521 for (i, segment) in path.segments[remaining_index..].iter().enumerate() {
502 let ty = match resolved { 522 let is_last_segment = i == path.segments[remaining_index..].len() - 1;
503 Resolution::Def(def) => { 523 ty = {
504 // FIXME resolve associated items from traits as well 524 let typable: TypableDef = match def {
505 let typable: Option<TypableDef> = def.into(); 525 TypeNs::Adt(it) => it.into(),
506 let typable = typable?; 526 TypeNs::TypeAlias(it) => it.into(),
507 527 TypeNs::BuiltinType(it) => it.into(),
508 let ty = self.db.type_for_def(typable, Namespace::Types); 528 // FIXME associated item of traits, generics, and Self
509 529 TypeNs::Trait(_) | TypeNs::GenericParam(_) | TypeNs::SelfType(_) => {
510 // For example, this substs will take `Gen::*<u32>*::make` 530 return None;
511 assert!(remaining_index > 0); 531 }
512 let substs = Ty::substs_from_path_segment( 532 // FIXME: report error here
513 self.db, 533 TypeNs::EnumVariant(_) => return None,
514 &self.resolver, 534 };
515 &path.segments[remaining_index + i - 1], 535
516 typable, 536 let ty = self.db.type_for_def(typable, Namespace::Types);
517 ); 537
518 538 // For example, this substs will take `Gen::*<u32>*::make`
519 ty.subst(&substs) 539 assert!(remaining_index > 0);
520 } 540 let substs = Ty::substs_from_path_segment(
521 Resolution::LocalBinding(_) => { 541 self.db,
522 // can't have a local binding in an associated item path 542 &self.resolver,
523 return None; 543 &path.segments[remaining_index + i - 1],
524 } 544 typable,
525 Resolution::GenericParam(..) => { 545 );
526 // FIXME associated item of generic param 546 ty.subst(&substs)
527 return None;
528 }
529 Resolution::SelfType(_) => {
530 // FIXME associated item of self type
531 return None;
532 }
533 }; 547 };
548 if is_last_segment {
549 break;
550 }
534 551
535 // Attempt to find an impl_item for the type which has a name matching 552 // Attempt to find an impl_item for the type which has a name matching
536 // the current segment 553 // the current segment
537 log::debug!("looking for path segment: {:?}", segment); 554 log::debug!("looking for path segment: {:?}", segment);
538 555
539 actual_def_ty = Some(ty.clone()); 556 let ty = mem::replace(&mut ty, Ty::Unknown);
540 557 def = ty.iterate_impl_items(self.db, krate, |item| {
541 let item: crate::ModuleDef = ty.iterate_impl_items(self.db, krate, |item| { 558 match item {
542 let matching_def: Option<crate::ModuleDef> = match item { 559 crate::ImplItem::Method(_) => None,
543 crate::ImplItem::Method(func) => { 560 crate::ImplItem::Const(_) => None,
544 if segment.name == func.name(self.db) {
545 Some(func.into())
546 } else {
547 None
548 }
549 }
550
551 crate::ImplItem::Const(konst) => {
552 let data = konst.data(self.db);
553 if segment.name == *data.name() {
554 Some(konst.into())
555 } else {
556 None
557 }
558 }
559 561
560 // FIXME: Resolve associated types 562 // FIXME: Resolve associated types
561 crate::ImplItem::TypeAlias(_) => None, 563 crate::ImplItem::TypeAlias(_) => {
562 }; 564 // Some(TypeNs::TypeAlias(..))
563 match matching_def { 565 None::<TypeNs>
564 Some(_) => {
565 self.write_assoc_resolution(id, item);
566 matching_def
567 } 566 }
568 None => None,
569 } 567 }
570 })?; 568 })?;
571
572 resolved = Resolution::Def(item);
573 } 569 }
574 570
575 match resolved { 571 let segment = path.segments.last().unwrap();
576 Resolution::Def(def) => { 572 let def = ty.clone().iterate_impl_items(self.db, krate, |item| {
577 let typable: Option<TypableDef> = def.into(); 573 let matching_def: Option<ValueNs> = match item {
578 let typable = typable?; 574 crate::ImplItem::Method(func) => {
579 let mut ty = self.db.type_for_def(typable, Namespace::Values); 575 if segment.name == func.name(self.db) {
580 if let Some(sts) = self.find_self_types(&def, actual_def_ty) { 576 Some(ValueNs::Function(func))
581 ty = ty.subst(&sts); 577 } else {
578 None
579 }
582 } 580 }
583 581
584 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 582 crate::ImplItem::Const(konst) => {
585 let ty = ty.subst(&substs); 583 let data = konst.data(self.db);
586 let ty = self.insert_type_vars(ty); 584 if segment.name == *data.name() {
587 let ty = self.normalize_associated_types_in(ty); 585 Some(ValueNs::Const(konst))
588 Some(ty) 586 } else {
589 } 587 None
590 Resolution::LocalBinding(pat) => { 588 }
591 let ty = self.result.type_of_pat.get(pat)?.clone(); 589 }
592 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 590 crate::ImplItem::TypeAlias(_) => None,
593 Some(ty) 591 };
594 } 592 match matching_def {
595 Resolution::GenericParam(..) => { 593 Some(_) => {
596 // generic params can't refer to values... yet 594 self.write_assoc_resolution(id, item);
597 None 595 matching_def
598 } 596 }
599 Resolution::SelfType(_) => { 597 None => None,
600 log::error!("path expr {:?} resolved to Self type in values ns", path);
601 None
602 } 598 }
603 } 599 })?;
600 let self_types = self.find_self_types(&def, ty);
601 Some((def, self_types))
604 } 602 }
605 603
606 fn find_self_types(&self, def: &ModuleDef, actual_def_ty: Option<Ty>) -> Option<Substs> { 604 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
607 let actual_def_ty = actual_def_ty?; 605 if let ValueNs::Function(func) = def {
608
609 if let crate::ModuleDef::Function(func) = def {
610 // We only do the infer if parent has generic params 606 // We only do the infer if parent has generic params
611 let gen = func.generic_params(self.db); 607 let gen = func.generic_params(self.db);
612 if gen.count_parent_params() == 0 { 608 if gen.count_parent_params() == 0 {
@@ -641,30 +637,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
641 None => return (Ty::Unknown, None), 637 None => return (Ty::Unknown, None),
642 }; 638 };
643 let resolver = &self.resolver; 639 let resolver = &self.resolver;
644 let typable: Option<TypableDef> = 640 let def: TypableDef =
645 // FIXME: this should resolve assoc items as well, see this example: 641 // FIXME: this should resolve assoc items as well, see this example:
646 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 642 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
647 match resolver.resolve_path_without_assoc_items(self.db, &path).take_types() { 643 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
648 Some(Resolution::Def(def)) => def.into(), 644 Some(TypeNs::Adt(Adt::Struct(it))) => it.into(),
649 Some(Resolution::LocalBinding(..)) => { 645 Some(TypeNs::Adt(Adt::Union(it))) => it.into(),
650 // this cannot happen 646 Some(TypeNs::EnumVariant(it)) => it.into(),
651 log::error!("path resolved to local binding in type ns"); 647 Some(TypeNs::TypeAlias(it)) => it.into(),
652 return (Ty::Unknown, None); 648
653 } 649 Some(TypeNs::SelfType(_)) |
654 Some(Resolution::GenericParam(..)) => { 650 Some(TypeNs::GenericParam(_)) |
655 // generic params can't be used in struct literals 651 Some(TypeNs::BuiltinType(_)) |
656 return (Ty::Unknown, None); 652 Some(TypeNs::Trait(_)) |
657 } 653 Some(TypeNs::Adt(Adt::Enum(_))) |
658 Some(Resolution::SelfType(..)) => { 654 None => {
659 // FIXME this is allowed in an impl for a struct, handle this 655 return (Ty::Unknown, None)
660 return (Ty::Unknown, None);
661 } 656 }
662 None => return (Ty::Unknown, None),
663 }; 657 };
664 let def = match typable {
665 None => return (Ty::Unknown, None),
666 Some(it) => it,
667 };
668 // FIXME remove the duplication between here and `Ty::from_path`? 658 // FIXME remove the duplication between here and `Ty::from_path`?
669 let substs = Ty::substs_from_path(self.db, resolver, path, def); 659 let substs = Ty::substs_from_path(self.db, resolver, path, def);
670 match def { 660 match def {