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.rs188
-rw-r--r--crates/ra_hir/src/ty/lower.rs159
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs11
-rw-r--r--crates/ra_hir/src/ty/tests.rs98
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs6
5 files changed, 281 insertions, 181 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index bf9609d8c..70da7f311 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, ConstData, DefWithBody, Either, FnData, Function, HasBody, ImplItem, Name, Path, 51 Adt, AssocItem, ConstData, DefWithBody, FnData, Function, HasBody, Name, Path, StructField,
52 StructField,
53}; 52};
54 53
55mod unify; 54mod unify;
@@ -121,7 +120,7 @@ pub struct InferenceResult {
121 /// For each struct literal, records the variant it resolves to. 120 /// For each struct literal, records the variant it resolves to.
122 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, 121 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>,
123 /// For each associated item record what it resolves to 122 /// For each associated item record what it resolves to
124 assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, 123 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItem>,
125 diagnostics: Vec<InferenceDiagnostic>, 124 diagnostics: Vec<InferenceDiagnostic>,
126 pub(super) type_of_expr: ArenaMap<ExprId, Ty>, 125 pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
127 pub(super) type_of_pat: ArenaMap<PatId, Ty>, 126 pub(super) type_of_pat: ArenaMap<PatId, Ty>,
@@ -141,10 +140,10 @@ impl InferenceResult {
141 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantDef> { 140 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantDef> {
142 self.variant_resolutions.get(&id.into()).copied() 141 self.variant_resolutions.get(&id.into()).copied()
143 } 142 }
144 pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<ImplItem> { 143 pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItem> {
145 self.assoc_resolutions.get(&id.into()).copied() 144 self.assoc_resolutions.get(&id.into()).copied()
146 } 145 }
147 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> { 146 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<AssocItem> {
148 self.assoc_resolutions.get(&id.into()).copied() 147 self.assoc_resolutions.get(&id.into()).copied()
149 } 148 }
150 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> { 149 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
@@ -235,7 +234,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
235 self.result.variant_resolutions.insert(id, variant); 234 self.result.variant_resolutions.insert(id, variant);
236 } 235 }
237 236
238 fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: ImplItem) { 237 fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItem) {
239 self.result.assoc_resolutions.insert(id, item); 238 self.result.assoc_resolutions.insert(id, item);
240 } 239 }
241 240
@@ -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,101 +518,91 @@ 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>, 521 def: TypeNs,
512 path: &Path, 522 path: &Path,
513 remaining_index: usize, 523 remaining_index: usize,
514 id: ExprOrPatId, 524 id: ExprOrPatId,
515 ) -> Option<(ValueNs, Option<Substs>)> { 525 ) -> Option<(ValueNs, Option<Substs>)> {
516 assert!(remaining_index < path.segments.len()); 526 assert!(remaining_index < path.segments.len());
517 let krate = self.resolver.krate()?; 527 // there may be more intermediate segments between the resolved one and
518 528 // the end. Only the last segment needs to be resolved to a value; from
519 let mut ty = Ty::Unknown; 529 // the segments before that, we need to get either a type or a trait ref.
520 530
521 // resolve intermediate segments 531 let resolved_segment = &path.segments[remaining_index - 1];
522 for (i, segment) in path.segments[remaining_index..].iter().enumerate() { 532 let remaining_segments = &path.segments[remaining_index..];
523 let is_last_segment = i == path.segments[remaining_index..].len() - 1; 533 let is_before_last = remaining_segments.len() == 1;
524 ty = match def_or_ty { 534
525 Either::A(def) => { 535 match (def, is_before_last) {
526 let typable: TypableDef = match def { 536 (TypeNs::Trait(_trait), true) => {
527 TypeNs::Adt(it) => it.into(), 537 // FIXME Associated item of trait, e.g. `Default::default`
528 TypeNs::TypeAlias(it) => it.into(), 538 None
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 } 539 }
540 (def, _) => {
541 // Either we already have a type (e.g. `Vec::new`), or we have a
542 // trait but it's not the last segment, so the next segment
543 // should resolve to an associated type of that trait (e.g. `<T
544 // as Iterator>::Item::default`)
545 let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1];
546 let ty = Ty::from_partly_resolved_hir_path(
547 self.db,
548 &self.resolver,
549 def,
550 resolved_segment,
551 remaining_segments_for_ty,
552 );
553 if let Ty::Unknown = ty {
554 return None;
555 }
555 556
556 // Attempt to find an impl_item for the type which has a name matching 557 let segment =
557 // the current segment 558 remaining_segments.last().expect("there should be at least one segment here");
558 log::debug!("looking for path segment: {:?}", segment);
559 559
560 let ty = mem::replace(&mut ty, Ty::Unknown); 560 self.resolve_ty_assoc_item(ty, segment, id)
561 def_or_ty = ty.iterate_impl_items(self.db, krate, |item| { 561 }
562 match item { 562 }
563 crate::ImplItem::Method(_) => None, 563 }
564 crate::ImplItem::Const(_) => None,
565 564
566 // FIXME: Resolve associated types 565 fn resolve_ty_assoc_item(
567 crate::ImplItem::TypeAlias(_) => { 566 &mut self,
568 // Some(Either::A(TypeNs::TypeAlias(..))) 567 ty: Ty,
569 None 568 segment: &crate::path::PathSegment,
570 } 569 id: ExprOrPatId,
571 } 570 ) -> Option<(ValueNs, Option<Substs>)> {
572 })?; 571 if let Ty::Unknown = ty {
572 return None;
573 } 573 }
574 574
575 let segment = path.segments.last().unwrap(); 575 let krate = self.resolver.krate()?;
576 let def = ty.clone().iterate_impl_items(self.db, krate, |item| {
577 let matching_def: Option<ValueNs> = match item {
578 crate::ImplItem::Method(func) => {
579 if segment.name == func.name(self.db) {
580 Some(ValueNs::Function(func))
581 } else {
582 None
583 }
584 }
585 576
586 crate::ImplItem::Const(konst) => { 577 // Find impl
587 let data = konst.data(self.db); 578 // FIXME: consider trait candidates
588 if Some(&segment.name) == data.name() { 579 let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item {
589 Some(ValueNs::Const(konst)) 580 AssocItem::Function(func) => {
590 } else { 581 if segment.name == func.name(self.db) {
591 None 582 Some(AssocItem::Function(func))
592 } 583 } else {
584 None
593 } 585 }
594 crate::ImplItem::TypeAlias(_) => None, 586 }
595 }; 587
596 match matching_def { 588 AssocItem::Const(konst) => {
597 Some(_) => { 589 if konst.name(self.db).map_or(false, |n| n == segment.name) {
598 self.write_assoc_resolution(id, item); 590 Some(AssocItem::Const(konst))
599 matching_def 591 } else {
592 None
600 } 593 }
601 None => None,
602 } 594 }
595 AssocItem::TypeAlias(_) => None,
603 })?; 596 })?;
604 let self_types = self.find_self_types(&def, ty); 597 let def = match item {
605 Some((def, self_types)) 598 AssocItem::Function(f) => ValueNs::Function(f),
599 AssocItem::Const(c) => ValueNs::Const(c),
600 AssocItem::TypeAlias(_) => unreachable!(),
601 };
602 let substs = self.find_self_types(&def, ty);
603
604 self.write_assoc_resolution(id, item);
605 Some((def, substs))
606 } 606 }
607 607
608 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { 608 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 6ead3846a..a83842b0f 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -86,78 +86,125 @@ impl Ty {
86 } 86 }
87 } 87 }
88 88
89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 89 pub(crate) fn from_type_relative_path(
90 // Resolve the path (in type namespace) 90 db: &impl HirDatabase,
91 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { 91 resolver: &Resolver,
92 Some(it) => it, 92 ty: Ty,
93 None => return Ty::Unknown, 93 remaining_segments: &[PathSegment],
94 }; 94 ) -> Ty {
95 if remaining_segments.len() == 1 {
96 // resolve unselected assoc types
97 let segment = &remaining_segments[0];
98 Ty::select_associated_type(db, resolver, ty, segment)
99 } else if remaining_segments.len() > 1 {
100 // FIXME report error (ambiguous associated type)
101 Ty::Unknown
102 } else {
103 ty
104 }
105 }
95 106
96 let typable: TypableDef = match resolution { 107 pub(crate) fn from_partly_resolved_hir_path(
108 db: &impl HirDatabase,
109 resolver: &Resolver,
110 resolution: TypeNs,
111 resolved_segment: &PathSegment,
112 remaining_segments: &[PathSegment],
113 ) -> Ty {
114 let ty = match resolution {
97 TypeNs::Trait(trait_) => { 115 TypeNs::Trait(trait_) => {
98 let segment = match remaining_index { 116 let trait_ref =
99 None => path.segments.last().expect("resolved path has at least one element"), 117 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None);
100 Some(i) => &path.segments[i - 1], 118 return if remaining_segments.len() == 1 {
101 }; 119 let segment = &remaining_segments[0];
102 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None); 120 match trait_ref
103 return if let Some(remaining_index) = remaining_index { 121 .trait_
104 if remaining_index == path.segments.len() - 1 { 122 .associated_type_by_name_including_super_traits(db, &segment.name)
105 let segment = &path.segments[remaining_index]; 123 {
106 match trait_ref 124 Some(associated_ty) => {
107 .trait_ 125 // FIXME handle type parameters on the segment
108 .associated_type_by_name_including_super_traits(db, &segment.name) 126 Ty::Projection(ProjectionTy {
109 { 127 associated_ty,
110 Some(associated_ty) => { 128 parameters: trait_ref.substs,
111 // FIXME handle type parameters on the segment 129 })
112 Ty::Projection(ProjectionTy { 130 }
113 associated_ty, 131 None => {
114 parameters: trait_ref.substs, 132 // FIXME: report error (associated type not found)
115 }) 133 Ty::Unknown
116 }
117 None => {
118 // associated type not found
119 Ty::Unknown
120 }
121 } 134 }
122 } else {
123 // FIXME more than one segment remaining, is this possible?
124 Ty::Unknown
125 } 135 }
136 } else if remaining_segments.len() > 1 {
137 // FIXME report error (ambiguous associated type)
138 Ty::Unknown
126 } else { 139 } else {
127 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) 140 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
128 }; 141 };
129 } 142 }
130 TypeNs::GenericParam(idx) => { 143 TypeNs::GenericParam(idx) => {
131 if remaining_index.is_some() { 144 // FIXME: maybe return name in resolution?
132 // e.g. T::Item 145 let name = resolved_segment.name.clone();
133 return Ty::Unknown; 146 Ty::Param { idx, name }
134 }
135 return Ty::Param {
136 idx,
137 // FIXME: maybe return name in resolution?
138 name: path
139 .as_ident()
140 .expect("generic param should be single-segment path")
141 .clone(),
142 };
143 }
144 TypeNs::SelfType(impl_block) => {
145 if remaining_index.is_some() {
146 // e.g. Self::Item
147 return Ty::Unknown;
148 }
149 return impl_block.target_ty(db);
150 } 147 }
148 TypeNs::SelfType(impl_block) => impl_block.target_ty(db),
151 149
152 TypeNs::Adt(it) => it.into(), 150 TypeNs::Adt(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
153 TypeNs::BuiltinType(it) => it.into(), 151 TypeNs::BuiltinType(it) => {
154 TypeNs::TypeAlias(it) => it.into(), 152 Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into())
153 }
154 TypeNs::TypeAlias(it) => {
155 Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into())
156 }
155 // FIXME: report error 157 // FIXME: report error
156 TypeNs::EnumVariant(_) => return Ty::Unknown, 158 TypeNs::EnumVariant(_) => return Ty::Unknown,
157 }; 159 };
158 160
161 Ty::from_type_relative_path(db, resolver, ty, remaining_segments)
162 }
163
164 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
165 // Resolve the path (in type namespace)
166 if let crate::PathKind::Type(type_ref) = &path.kind {
167 let ty = Ty::from_hir(db, resolver, &type_ref);
168 let remaining_segments = &path.segments[..];
169 return Ty::from_type_relative_path(db, resolver, ty, remaining_segments);
170 }
171 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) {
172 Some(it) => it,
173 None => return Ty::Unknown,
174 };
175 let (resolved_segment, remaining_segments) = match remaining_index {
176 None => (
177 path.segments.last().expect("resolved path has at least one element"),
178 &[] as &[PathSegment],
179 ),
180 Some(i) => (&path.segments[i - 1], &path.segments[i..]),
181 };
182 Ty::from_partly_resolved_hir_path(
183 db,
184 resolver,
185 resolution,
186 resolved_segment,
187 remaining_segments,
188 )
189 }
190
191 fn select_associated_type(
192 _db: &impl HirDatabase,
193 _resolver: &Resolver,
194 _self_ty: Ty,
195 _segment: &PathSegment,
196 ) -> Ty {
197 Ty::Unknown
198 }
199
200 fn from_hir_path_inner(
201 db: &impl HirDatabase,
202 resolver: &Resolver,
203 segment: &PathSegment,
204 typable: TypableDef,
205 ) -> Ty {
159 let ty = db.type_for_def(typable, Namespace::Types); 206 let ty = db.type_for_def(typable, Namespace::Types);
160 let substs = Ty::substs_from_path(db, resolver, path, typable); 207 let substs = Ty::substs_from_path_segment(db, resolver, segment, typable);
161 ty.subst(&substs) 208 ty.subst(&substs)
162 } 209 }
163 210
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index be63806d4..8b46b11a9 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -11,13 +11,12 @@ use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitR
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 generics::HasGenericParams, 13 generics::HasGenericParams,
14 impl_block::{ImplBlock, ImplId, ImplItem}, 14 impl_block::{ImplBlock, ImplId},
15 nameres::CrateModuleId, 15 nameres::CrateModuleId,
16 resolve::Resolver, 16 resolve::Resolver,
17 traits::TraitItem,
18 ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, 17 ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy},
19 ty::{Ty, TypeCtor}, 18 ty::{Ty, TypeCtor},
20 Crate, Function, Module, Name, Trait, 19 AssocItem, Crate, Function, Module, Name, Trait,
21}; 20};
22 21
23/// This is used as a key for indexing impls. 22/// This is used as a key for indexing impls.
@@ -232,7 +231,7 @@ fn iterate_trait_method_candidates<T>(
232 // iteration 231 // iteration
233 let mut known_implemented = inherently_implemented; 232 let mut known_implemented = inherently_implemented;
234 for item in data.items() { 233 for item in data.items() {
235 if let TraitItem::Function(m) = *item { 234 if let AssocItem::Function(m) = *item {
236 let data = m.data(db); 235 let data = m.data(db);
237 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 236 if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
238 if !known_implemented { 237 if !known_implemented {
@@ -264,7 +263,7 @@ fn iterate_inherent_methods<T>(
264 263
265 for impl_block in impls.lookup_impl_blocks(&ty.value) { 264 for impl_block in impls.lookup_impl_blocks(&ty.value) {
266 for item in impl_block.items(db) { 265 for item in impl_block.items(db) {
267 if let ImplItem::Method(f) = item { 266 if let AssocItem::Function(f) = item {
268 let data = f.data(db); 267 let data = f.data(db);
269 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 268 if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
270 if let Some(result) = callback(&ty.value, f) { 269 if let Some(result) = callback(&ty.value, f) {
@@ -304,7 +303,7 @@ impl Ty {
304 self, 303 self,
305 db: &impl HirDatabase, 304 db: &impl HirDatabase,
306 krate: Crate, 305 krate: Crate,
307 mut callback: impl FnMut(ImplItem) -> Option<T>, 306 mut callback: impl FnMut(AssocItem) -> Option<T>,
308 ) -> Option<T> { 307 ) -> Option<T> {
309 for krate in def_crates(db, krate, &self)? { 308 for krate in def_crates(db, krate, &self)? {
310 let impls = db.impls_in_crate(krate); 309 let impls = db.impls_in_crate(krate);
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 1bd677cab..09c17fdf4 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2613,18 +2613,18 @@ fn infer_call_trait_method_on_generic_param_1() {
2613 assert_snapshot!( 2613 assert_snapshot!(
2614 infer(r#" 2614 infer(r#"
2615trait Trait { 2615trait Trait {
2616 fn method() -> u32; 2616 fn method(&self) -> u32;
2617} 2617}
2618fn test<T: Trait>(t: T) { 2618fn test<T: Trait>(t: T) {
2619 t.method(); 2619 t.method();
2620} 2620}
2621"#), 2621"#),
2622 @r###" 2622 @r###"
2623 2623 [30; 34) 'self': &Self
2624 [59; 60) 't': T 2624 [64; 65) 't': T
2625 [65; 84) '{ ...d(); }': () 2625 [70; 89) '{ ...d(); }': ()
2626 [71; 72) 't': T 2626 [76; 77) 't': T
2627 [71; 81) 't.method()': {unknown} 2627 [76; 86) 't.method()': u32
2628 "### 2628 "###
2629 ); 2629 );
2630} 2630}
@@ -2634,18 +2634,18 @@ fn infer_call_trait_method_on_generic_param_2() {
2634 assert_snapshot!( 2634 assert_snapshot!(
2635 infer(r#" 2635 infer(r#"
2636trait Trait<T> { 2636trait Trait<T> {
2637 fn method() -> T; 2637 fn method(&self) -> T;
2638} 2638}
2639fn test<U, T: Trait<U>>(t: T) { 2639fn test<U, T: Trait<U>>(t: T) {
2640 t.method(); 2640 t.method();
2641} 2641}
2642"#), 2642"#),
2643 @r###" 2643 @r###"
2644 2644 [33; 37) 'self': &Self
2645 [66; 67) 't': T 2645 [71; 72) 't': T
2646 [72; 91) '{ ...d(); }': () 2646 [77; 96) '{ ...d(); }': ()
2647 [78; 79) 't': T 2647 [83; 84) 't': T
2648 [78; 88) 't.method()': {unknown} 2648 [83; 93) 't.method()': [missing name]
2649 "### 2649 "###
2650 ); 2650 );
2651} 2651}
@@ -2685,6 +2685,7 @@ fn test() {
2685 2685
2686#[test] 2686#[test]
2687fn infer_project_associated_type() { 2687fn infer_project_associated_type() {
2688 // y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234
2688 assert_snapshot!( 2689 assert_snapshot!(
2689 infer(r#" 2690 infer(r#"
2690trait Iterable { 2691trait Iterable {
@@ -2696,16 +2697,19 @@ fn test<T: Iterable>() {
2696 let x: <S as Iterable>::Item = 1; 2697 let x: <S as Iterable>::Item = 1;
2697 let y: <T as Iterable>::Item = no_matter; 2698 let y: <T as Iterable>::Item = no_matter;
2698 let z: T::Item = no_matter; 2699 let z: T::Item = no_matter;
2700 let a: <T>::Item = no_matter;
2699} 2701}
2700"#), 2702"#),
2701 @r###" 2703 @r###"
2702 [108; 227) '{ ...ter; }': () 2704 [108; 261) '{ ...ter; }': ()
2703 [118; 119) 'x': u32 2705 [118; 119) 'x': u32
2704 [145; 146) '1': u32 2706 [145; 146) '1': u32
2705 [156; 157) 'y': {unknown} 2707 [156; 157) 'y': {unknown}
2706 [183; 192) 'no_matter': {unknown} 2708 [183; 192) 'no_matter': {unknown}
2707 [202; 203) 'z': {unknown} 2709 [202; 203) 'z': {unknown}
2708 [215; 224) 'no_matter': {unknown} 2710 [215; 224) 'no_matter': {unknown}
2711 [234; 235) 'a': {unknown}
2712 [249; 258) 'no_matter': {unknown}
2709 "### 2713 "###
2710 ); 2714 );
2711} 2715}
@@ -2721,9 +2725,11 @@ struct S;
2721impl Iterable for S { type Item = u32; } 2725impl Iterable for S { type Item = u32; }
2722fn foo1<T: Iterable>(t: T) -> T::Item {} 2726fn foo1<T: Iterable>(t: T) -> T::Item {}
2723fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} 2727fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
2728fn foo3<T: Iterable>(t: T) -> <T>::Item {}
2724fn test() { 2729fn test() {
2725 let x = foo1(S); 2730 let x = foo1(S);
2726 let y = foo2(S); 2731 let y = foo2(S);
2732 let z = foo3(S);
2727} 2733}
2728"#), 2734"#),
2729 @r###" 2735 @r###"
@@ -2731,15 +2737,21 @@ fn test() {
2731 [123; 125) '{}': () 2737 [123; 125) '{}': ()
2732 [147; 148) 't': T 2738 [147; 148) 't': T
2733 [178; 180) '{}': () 2739 [178; 180) '{}': ()
2734 [191; 236) '{ ...(S); }': () 2740 [202; 203) 't': T
2735 [201; 202) 'x': {unknown} 2741 [221; 223) '{}': ()
2736 [205; 209) 'foo1': fn foo1<S>(T) -> {unknown} 2742 [234; 300) '{ ...(S); }': ()
2737 [205; 212) 'foo1(S)': {unknown} 2743 [244; 245) 'x': {unknown}
2738 [210; 211) 'S': S 2744 [248; 252) 'foo1': fn foo1<S>(T) -> {unknown}
2739 [222; 223) 'y': u32 2745 [248; 255) 'foo1(S)': {unknown}
2740 [226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item 2746 [253; 254) 'S': S
2741 [226; 233) 'foo2(S)': u32 2747 [265; 266) 'y': u32
2742 [231; 232) 'S': S 2748 [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
2749 [269; 276) 'foo2(S)': u32
2750 [274; 275) 'S': S
2751 [286; 287) 'z': {unknown}
2752 [290; 294) 'foo3': fn foo3<S>(T) -> {unknown}
2753 [290; 297) 'foo3(S)': {unknown}
2754 [295; 296) 'S': S
2743 "### 2755 "###
2744 ); 2756 );
2745} 2757}
@@ -4050,6 +4062,48 @@ fn test<F: FnOnce(u32) -> u64>(f: F) {
4050 ); 4062 );
4051} 4063}
4052 4064
4065#[test]
4066fn unselected_projection_in_trait_env() {
4067 let t = type_at(
4068 r#"
4069//- /main.rs
4070trait Trait {
4071 type Item;
4072}
4073
4074trait Trait2 {
4075 fn foo(&self) -> u32;
4076}
4077
4078fn test<T: Trait>() where T::Item: Trait2 {
4079 let x: T::Item = no_matter;
4080 x.foo()<|>;
4081}
4082"#,
4083 );
4084 assert_eq!(t, "u32");
4085}
4086
4087#[test]
4088fn unselected_projection_in_trait_env_cycle() {
4089 let t = type_at(
4090 r#"
4091//- /main.rs
4092trait Trait {
4093 type Item;
4094}
4095
4096trait Trait2<T> {}
4097
4098fn test<T: Trait>() where T: Trait2<T::Item> {
4099 let x: T::Item = no_matter<|>;
4100}
4101"#,
4102 );
4103 // this is a legitimate cycle
4104 assert_eq!(t, "{unknown}");
4105}
4106
4053fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 4107fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
4054 let file = db.parse(pos.file_id).ok().unwrap(); 4108 let file = db.parse(pos.file_id).ok().unwrap();
4055 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 4109 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index c748e9d84..693d9b28f 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -21,7 +21,7 @@ use crate::{
21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22 TypeWalk, 22 TypeWalk,
23 }, 23 },
24 Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias, 24 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias,
25}; 25};
26 26
27/// This represents a trait whose name we could not resolve. 27/// This represents a trait whose name we could not resolve.
@@ -496,7 +496,7 @@ pub(crate) fn trait_datum_query(
496 .items(db) 496 .items(db)
497 .into_iter() 497 .into_iter()
498 .filter_map(|trait_item| match trait_item { 498 .filter_map(|trait_item| match trait_item {
499 crate::traits::TraitItem::TypeAlias(type_alias) => Some(type_alias), 499 crate::AssocItem::TypeAlias(type_alias) => Some(type_alias),
500 _ => None, 500 _ => None,
501 }) 501 })
502 .map(|type_alias| type_alias.to_chalk(db)) 502 .map(|type_alias| type_alias.to_chalk(db))
@@ -616,7 +616,7 @@ pub(crate) fn impl_datum_query(
616 .items(db) 616 .items(db)
617 .into_iter() 617 .into_iter()
618 .filter_map(|item| match item { 618 .filter_map(|item| match item {
619 ImplItem::TypeAlias(t) => Some(t), 619 AssocItem::TypeAlias(t) => Some(t),
620 _ => None, 620 _ => None,
621 }) 621 })
622 .filter_map(|t| { 622 .filter_map(|t| {