diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 188 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 159 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 98 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 6 |
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 | ||
55 | mod unify; | 54 | mod 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 | |||
11 | use crate::{ | 11 | use 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#" |
2615 | trait Trait { | 2615 | trait Trait { |
2616 | fn method() -> u32; | 2616 | fn method(&self) -> u32; |
2617 | } | 2617 | } |
2618 | fn test<T: Trait>(t: T) { | 2618 | fn 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#" |
2636 | trait Trait<T> { | 2636 | trait Trait<T> { |
2637 | fn method() -> T; | 2637 | fn method(&self) -> T; |
2638 | } | 2638 | } |
2639 | fn test<U, T: Trait<U>>(t: T) { | 2639 | fn 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] |
2687 | fn infer_project_associated_type() { | 2687 | fn 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#" |
2690 | trait Iterable { | 2691 | trait 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; | |||
2721 | impl Iterable for S { type Item = u32; } | 2725 | impl Iterable for S { type Item = u32; } |
2722 | fn foo1<T: Iterable>(t: T) -> T::Item {} | 2726 | fn foo1<T: Iterable>(t: T) -> T::Item {} |
2723 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} | 2727 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} |
2728 | fn foo3<T: Iterable>(t: T) -> <T>::Item {} | ||
2724 | fn test() { | 2729 | fn 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] | ||
4066 | fn unselected_projection_in_trait_env() { | ||
4067 | let t = type_at( | ||
4068 | r#" | ||
4069 | //- /main.rs | ||
4070 | trait Trait { | ||
4071 | type Item; | ||
4072 | } | ||
4073 | |||
4074 | trait Trait2 { | ||
4075 | fn foo(&self) -> u32; | ||
4076 | } | ||
4077 | |||
4078 | fn 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] | ||
4088 | fn unselected_projection_in_trait_env_cycle() { | ||
4089 | let t = type_at( | ||
4090 | r#" | ||
4091 | //- /main.rs | ||
4092 | trait Trait { | ||
4093 | type Item; | ||
4094 | } | ||
4095 | |||
4096 | trait Trait2<T> {} | ||
4097 | |||
4098 | fn 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 | |||
4053 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 4107 | fn 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| { |