diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-11-01 19:03:05 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-11-01 19:03:05 +0000 |
commit | 9db97820f4c1c38110175f4efda2702356a4199a (patch) | |
tree | f560ab731b9da35902d3da720e19731b51ab62df /crates/ra_hir/src/ty/infer | |
parent | ed5212e1ac71e959d802a9a7ad28d06c8b18e022 (diff) | |
parent | 895238088417b292e35705e72182ff8cc3ab6f63 (diff) |
Merge #2151
2151: Resolve (and complete) trait calls like `Vec::default()` r=flodiebold a=flodiebold
Similar to rustc, we do this using the same code as the method call resolution, just without doing autoderef (and considering more potential candidates).
(Btw, we currently don't complete methods with `self` in path notation, even though they'd be legal to use, so maybe we should -- on the other hand, that will usually not be the most interesting completions...)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/infer')
-rw-r--r-- | crates/ra_hir/src/ty/infer/path.rs | 82 |
1 files changed, 46 insertions, 36 deletions
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index 77aa35ce1..59b7f7eb6 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs | |||
@@ -6,8 +6,8 @@ use super::{ExprOrPatId, InferenceContext, TraitRef}; | |||
6 | use crate::{ | 6 | use crate::{ |
7 | db::HirDatabase, | 7 | db::HirDatabase, |
8 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 8 | resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
9 | ty::{Substs, Ty, TypableDef, TypeWalk}, | 9 | ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk}, |
10 | AssocItem, HasGenericParams, Namespace, Path, | 10 | AssocItem, Container, HasGenericParams, Name, Namespace, Path, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 13 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
@@ -39,7 +39,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
39 | let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); | 39 | let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); |
40 | self.resolve_ty_assoc_item( | 40 | self.resolve_ty_assoc_item( |
41 | ty, | 41 | ty, |
42 | path.segments.last().expect("path had at least one segment"), | 42 | &path.segments.last().expect("path had at least one segment").name, |
43 | id, | 43 | id, |
44 | )? | 44 | )? |
45 | } else { | 45 | } else { |
@@ -122,10 +122,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
122 | return None; | 122 | return None; |
123 | } | 123 | } |
124 | 124 | ||
125 | let ty = self.insert_type_vars(ty); | ||
126 | let ty = self.normalize_associated_types_in(ty); | ||
127 | |||
125 | let segment = | 128 | let segment = |
126 | remaining_segments.last().expect("there should be at least one segment here"); | 129 | remaining_segments.last().expect("there should be at least one segment here"); |
127 | 130 | ||
128 | self.resolve_ty_assoc_item(ty, segment, id) | 131 | self.resolve_ty_assoc_item(ty, &segment.name, id) |
129 | } | 132 | } |
130 | } | 133 | } |
131 | } | 134 | } |
@@ -162,7 +165,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
162 | }; | 165 | }; |
163 | let substs = Substs::build_for_def(self.db, item) | 166 | let substs = Substs::build_for_def(self.db, item) |
164 | .use_parent_substs(&trait_ref.substs) | 167 | .use_parent_substs(&trait_ref.substs) |
165 | .fill_with_unknown() | 168 | .fill_with_params() |
166 | .build(); | 169 | .build(); |
167 | 170 | ||
168 | self.write_assoc_resolution(id, item); | 171 | self.write_assoc_resolution(id, item); |
@@ -172,44 +175,51 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
172 | fn resolve_ty_assoc_item( | 175 | fn resolve_ty_assoc_item( |
173 | &mut self, | 176 | &mut self, |
174 | ty: Ty, | 177 | ty: Ty, |
175 | segment: &PathSegment, | 178 | name: &Name, |
176 | id: ExprOrPatId, | 179 | id: ExprOrPatId, |
177 | ) -> Option<(ValueNs, Option<Substs>)> { | 180 | ) -> Option<(ValueNs, Option<Substs>)> { |
178 | if let Ty::Unknown = ty { | 181 | if let Ty::Unknown = ty { |
179 | return None; | 182 | return None; |
180 | } | 183 | } |
181 | 184 | ||
182 | let krate = self.resolver.krate()?; | 185 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); |
183 | 186 | ||
184 | // Find impl | 187 | method_resolution::iterate_method_candidates( |
185 | // FIXME: consider trait candidates | 188 | &canonical_ty.value, |
186 | let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item { | 189 | self.db, |
187 | AssocItem::Function(func) => { | 190 | &self.resolver.clone(), |
188 | if segment.name == func.name(self.db) { | 191 | Some(name), |
189 | Some(AssocItem::Function(func)) | 192 | method_resolution::LookupMode::Path, |
190 | } else { | 193 | move |_ty, item| { |
191 | None | 194 | let def = match item { |
192 | } | 195 | AssocItem::Function(f) => ValueNs::Function(f), |
193 | } | 196 | AssocItem::Const(c) => ValueNs::Const(c), |
194 | 197 | AssocItem::TypeAlias(_) => unreachable!(), | |
195 | AssocItem::Const(konst) => { | 198 | }; |
196 | if konst.name(self.db).map_or(false, |n| n == segment.name) { | 199 | let substs = match item.container(self.db) { |
197 | Some(AssocItem::Const(konst)) | 200 | Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), |
198 | } else { | 201 | Container::Trait(t) => { |
199 | None | 202 | // we're picking this method |
200 | } | 203 | let trait_substs = Substs::build_for_def(self.db, t) |
201 | } | 204 | .push(ty.clone()) |
202 | AssocItem::TypeAlias(_) => None, | 205 | .fill(std::iter::repeat_with(|| self.new_type_var())) |
203 | })?; | 206 | .build(); |
204 | let def = match item { | 207 | let substs = Substs::build_for_def(self.db, item) |
205 | AssocItem::Function(f) => ValueNs::Function(f), | 208 | .use_parent_substs(&trait_substs) |
206 | AssocItem::Const(c) => ValueNs::Const(c), | 209 | .fill_with_params() |
207 | AssocItem::TypeAlias(_) => unreachable!(), | 210 | .build(); |
208 | }; | 211 | self.obligations.push(super::Obligation::Trait(TraitRef { |
209 | let substs = self.find_self_types(&def, ty); | 212 | trait_: t, |
213 | substs: trait_substs, | ||
214 | })); | ||
215 | Some(substs) | ||
216 | } | ||
217 | }; | ||
210 | 218 | ||
211 | self.write_assoc_resolution(id, item); | 219 | self.write_assoc_resolution(id, item); |
212 | Some((def, substs)) | 220 | Some((def, substs)) |
221 | }, | ||
222 | ) | ||
213 | } | 223 | } |
214 | 224 | ||
215 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { | 225 | fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { |