aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs256
-rw-r--r--crates/ra_hir/src/ty/lower.rs108
2 files changed, 176 insertions, 188 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 {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 946e9e9fb..3fdb2ca92 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -19,7 +19,7 @@ use crate::{
19 generics::{GenericDef, WherePredicate}, 19 generics::{GenericDef, WherePredicate},
20 nameres::Namespace, 20 nameres::Namespace,
21 path::{GenericArg, PathSegment}, 21 path::{GenericArg, PathSegment},
22 resolve::{Resolution, Resolver}, 22 resolve::{Resolver, TypeNs},
23 ty::Adt, 23 ty::Adt,
24 type_ref::{TypeBound, TypeRef}, 24 type_ref::{TypeBound, TypeRef},
25 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, 25 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField,
@@ -88,16 +88,47 @@ impl Ty {
88 88
89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
90 // Resolve the path (in type namespace) 90 // Resolve the path (in type namespace)
91 let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner(); 91 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) {
92 let resolution = resolution.take_types(); 92 Some(it) => it,
93 93 None => return Ty::Unknown,
94 let def = match resolution { 94 };
95 Some(Resolution::Def(def)) => def, 95
96 Some(Resolution::LocalBinding(..)) => { 96 let typable: TypableDef = match resolution {
97 // this should never happen 97 TypeNs::Trait(trait_) => {
98 panic!("path resolved to local binding in type ns"); 98 let segment = match remaining_index {
99 None => path.segments.last().expect("resolved path has at least one element"),
100 Some(i) => &path.segments[i - 1],
101 };
102 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
103 return if let Some(remaining_index) = remaining_index {
104 if remaining_index == path.segments.len() - 1 {
105 let segment = &path.segments[remaining_index];
106 match trait_ref
107 .trait_
108 .associated_type_by_name_including_super_traits(db, &segment.name)
109 {
110 Some(associated_ty) => {
111 // FIXME handle type parameters on the segment
112 Ty::Projection(ProjectionTy {
113 associated_ty,
114 parameters: trait_ref.substs,
115 })
116 }
117 None => {
118 // associated type not found
119 Ty::Unknown
120 }
121 }
122 } else {
123 // FIXME more than one segment remaining, is this possible?
124 Ty::Unknown
125 }
126 } else {
127 // FIXME dyn Trait without the dyn
128 Ty::Unknown
129 };
99 } 130 }
100 Some(Resolution::GenericParam(idx)) => { 131 TypeNs::GenericParam(idx) => {
101 if remaining_index.is_some() { 132 if remaining_index.is_some() {
102 // e.g. T::Item 133 // e.g. T::Item
103 return Ty::Unknown; 134 return Ty::Unknown;
@@ -111,57 +142,24 @@ impl Ty {
111 .clone(), 142 .clone(),
112 }; 143 };
113 } 144 }
114 Some(Resolution::SelfType(impl_block)) => { 145 TypeNs::SelfType(impl_block) => {
115 if remaining_index.is_some() { 146 if remaining_index.is_some() {
116 // e.g. Self::Item 147 // e.g. Self::Item
117 return Ty::Unknown; 148 return Ty::Unknown;
118 } 149 }
119 return impl_block.target_ty(db); 150 return impl_block.target_ty(db);
120 } 151 }
121 None => { 152
122 // path did not resolve 153 TypeNs::Adt(it) => it.into(),
123 return Ty::Unknown; 154 TypeNs::BuiltinType(it) => it.into(),
124 } 155 TypeNs::TypeAlias(it) => it.into(),
156 // FIXME: report error
157 TypeNs::EnumVariant(_) => return Ty::Unknown,
125 }; 158 };
126 159
127 if let ModuleDef::Trait(trait_) = def { 160 let ty = db.type_for_def(typable, Namespace::Types);
128 let segment = match remaining_index { 161 let substs = Ty::substs_from_path(db, resolver, path, typable);
129 None => path.segments.last().expect("resolved path has at least one element"), 162 ty.subst(&substs)
130 Some(i) => &path.segments[i - 1],
131 };
132 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None);
133 if let Some(remaining_index) = remaining_index {
134 if remaining_index == path.segments.len() - 1 {
135 let segment = &path.segments[remaining_index];
136 let associated_ty = match trait_ref
137 .trait_
138 .associated_type_by_name_including_super_traits(db, &segment.name)
139 {
140 Some(t) => t,
141 None => {
142 // associated type not found
143 return Ty::Unknown;
144 }
145 };
146 // FIXME handle type parameters on the segment
147 Ty::Projection(ProjectionTy { associated_ty, parameters: trait_ref.substs })
148 } else {
149 // FIXME more than one segment remaining, is this possible?
150 Ty::Unknown
151 }
152 } else {
153 // FIXME dyn Trait without the dyn
154 Ty::Unknown
155 }
156 } else {
157 let typable: TypableDef = match def.into() {
158 None => return Ty::Unknown,
159 Some(it) => it,
160 };
161 let ty = db.type_for_def(typable, Namespace::Types);
162 let substs = Ty::substs_from_path(db, resolver, path, typable);
163 ty.subst(&substs)
164 }
165 } 163 }
166 164
167 pub(super) fn substs_from_path_segment( 165 pub(super) fn substs_from_path_segment(
@@ -278,8 +276,8 @@ impl TraitRef {
278 path: &Path, 276 path: &Path,
279 explicit_self_ty: Option<Ty>, 277 explicit_self_ty: Option<Ty>,
280 ) -> Option<Self> { 278 ) -> Option<Self> {
281 let resolved = match resolver.resolve_path_without_assoc_items(db, &path).take_types()? { 279 let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? {
282 Resolution::Def(ModuleDef::Trait(tr)) => tr, 280 TypeNs::Trait(tr) => tr,
283 _ => return None, 281 _ => return None,
284 }; 282 };
285 let segment = path.segments.last().expect("path should have at least one segment"); 283 let segment = path.segments.last().expect("path should have at least one segment");