diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 103 |
3 files changed, 90 insertions, 41 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 3af05394c..d6a17e469 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -569,12 +569,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
569 | ) -> Ty { | 569 | ) -> Ty { |
570 | let receiver_ty = self.infer_expr(receiver, &Expectation::none()); | 570 | let receiver_ty = self.infer_expr(receiver, &Expectation::none()); |
571 | let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone()); | 571 | let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone()); |
572 | let resolved = method_resolution::lookup_method( | 572 | |
573 | &canonicalized_receiver.value, | 573 | let traits_in_scope = self.resolver.traits_in_scope(self.db); |
574 | self.db, | 574 | |
575 | method_name, | 575 | let resolved = self.resolver.krate().and_then(|krate| { |
576 | &self.resolver, | 576 | method_resolution::lookup_method( |
577 | ); | 577 | &canonicalized_receiver.value, |
578 | self.db, | ||
579 | self.trait_env.clone(), | ||
580 | krate, | ||
581 | &traits_in_scope, | ||
582 | method_name, | ||
583 | ) | ||
584 | }); | ||
578 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | 585 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { |
579 | Some((ty, func)) => { | 586 | Some((ty, func)) => { |
580 | let ty = canonicalized_receiver.decanonicalize_ty(ty); | 587 | let ty = canonicalized_receiver.decanonicalize_ty(ty); |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index ffd358367..2c1d4831d 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -11,7 +11,7 @@ use hir_expand::name::Name; | |||
11 | 11 | ||
12 | use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; | 12 | use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; |
13 | 13 | ||
14 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 14 | use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef}; |
15 | 15 | ||
16 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 16 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
17 | pub(super) fn infer_path( | 17 | pub(super) fn infer_path( |
@@ -193,11 +193,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
193 | } | 193 | } |
194 | 194 | ||
195 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); | 195 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); |
196 | let env = TraitEnvironment::lower(self.db, &self.resolver); | ||
197 | let krate = self.resolver.krate()?; | ||
198 | let traits_in_scope = self.resolver.traits_in_scope(self.db); | ||
196 | 199 | ||
197 | method_resolution::iterate_method_candidates( | 200 | method_resolution::iterate_method_candidates( |
198 | &canonical_ty.value, | 201 | &canonical_ty.value, |
199 | self.db, | 202 | self.db, |
200 | &self.resolver.clone(), | 203 | env, |
204 | krate, | ||
205 | &traits_in_scope, | ||
201 | Some(name), | 206 | Some(name), |
202 | method_resolution::LookupMode::Path, | 207 | method_resolution::LookupMode::Path, |
203 | move |_ty, item| { | 208 | move |_ty, item| { |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 55435e6ea..5bacbbd7c 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -6,13 +6,13 @@ use std::sync::Arc; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use hir_def::{ |
9 | lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId, | 9 | lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId, |
10 | AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, | 10 | HasModule, ImplId, Lookup, TraitId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 13 | use ra_db::CrateId; |
14 | use ra_prof::profile; | 14 | use ra_prof::profile; |
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
16 | 16 | ||
17 | use super::Substs; | 17 | use super::Substs; |
18 | use crate::{ | 18 | use crate::{ |
@@ -144,14 +144,24 @@ impl Ty { | |||
144 | pub(crate) fn lookup_method( | 144 | pub(crate) fn lookup_method( |
145 | ty: &Canonical<Ty>, | 145 | ty: &Canonical<Ty>, |
146 | db: &impl HirDatabase, | 146 | db: &impl HirDatabase, |
147 | env: Arc<TraitEnvironment>, | ||
148 | krate: CrateId, | ||
149 | traits_in_scope: &FxHashSet<TraitId>, | ||
147 | name: &Name, | 150 | name: &Name, |
148 | resolver: &Resolver, | ||
149 | ) -> Option<(Ty, FunctionId)> { | 151 | ) -> Option<(Ty, FunctionId)> { |
150 | iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f | 152 | iterate_method_candidates( |
151 | { | 153 | ty, |
152 | AssocItemId::FunctionId(f) => Some((ty.clone(), f)), | 154 | db, |
153 | _ => None, | 155 | env, |
154 | }) | 156 | krate, |
157 | &traits_in_scope, | ||
158 | Some(name), | ||
159 | LookupMode::MethodCall, | ||
160 | |ty, f| match f { | ||
161 | AssocItemId::FunctionId(f) => Some((ty.clone(), f)), | ||
162 | _ => None, | ||
163 | }, | ||
164 | ) | ||
155 | } | 165 | } |
156 | 166 | ||
157 | /// Whether we're looking up a dotted method call (like `v.len()`) or a path | 167 | /// Whether we're looking up a dotted method call (like `v.len()`) or a path |
@@ -172,7 +182,9 @@ pub enum LookupMode { | |||
172 | pub fn iterate_method_candidates<T>( | 182 | pub fn iterate_method_candidates<T>( |
173 | ty: &Canonical<Ty>, | 183 | ty: &Canonical<Ty>, |
174 | db: &impl HirDatabase, | 184 | db: &impl HirDatabase, |
175 | resolver: &Resolver, | 185 | env: Arc<TraitEnvironment>, |
186 | krate: CrateId, | ||
187 | traits_in_scope: &FxHashSet<TraitId>, | ||
176 | name: Option<&Name>, | 188 | name: Option<&Name>, |
177 | mode: LookupMode, | 189 | mode: LookupMode, |
178 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 190 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
@@ -187,9 +199,7 @@ pub fn iterate_method_candidates<T>( | |||
187 | // Also note that when we've got a receiver like &S, even if the method we | 199 | // Also note that when we've got a receiver like &S, even if the method we |
188 | // find in the end takes &self, we still do the autoderef step (just as | 200 | // find in the end takes &self, we still do the autoderef step (just as |
189 | // rustc does an autoderef and then autoref again). | 201 | // rustc does an autoderef and then autoref again). |
190 | let environment = TraitEnvironment::lower(db, resolver); | 202 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; |
191 | let ty = InEnvironment { value: ty.clone(), environment }; | ||
192 | let krate = resolver.krate()?; | ||
193 | 203 | ||
194 | // We have to be careful about the order we're looking at candidates | 204 | // We have to be careful about the order we're looking at candidates |
195 | // in here. Consider the case where we're resolving `x.clone()` | 205 | // in here. Consider the case where we're resolving `x.clone()` |
@@ -209,7 +219,9 @@ pub fn iterate_method_candidates<T>( | |||
209 | if let Some(result) = iterate_method_candidates_with_autoref( | 219 | if let Some(result) = iterate_method_candidates_with_autoref( |
210 | &deref_chain[i..], | 220 | &deref_chain[i..], |
211 | db, | 221 | db, |
212 | resolver, | 222 | env.clone(), |
223 | krate, | ||
224 | traits_in_scope, | ||
213 | name, | 225 | name, |
214 | &mut callback, | 226 | &mut callback, |
215 | ) { | 227 | ) { |
@@ -220,7 +232,15 @@ pub fn iterate_method_candidates<T>( | |||
220 | } | 232 | } |
221 | LookupMode::Path => { | 233 | LookupMode::Path => { |
222 | // No autoderef for path lookups | 234 | // No autoderef for path lookups |
223 | iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback) | 235 | iterate_method_candidates_for_self_ty( |
236 | &ty, | ||
237 | db, | ||
238 | env, | ||
239 | krate, | ||
240 | traits_in_scope, | ||
241 | name, | ||
242 | &mut callback, | ||
243 | ) | ||
224 | } | 244 | } |
225 | } | 245 | } |
226 | } | 246 | } |
@@ -228,7 +248,9 @@ pub fn iterate_method_candidates<T>( | |||
228 | fn iterate_method_candidates_with_autoref<T>( | 248 | fn iterate_method_candidates_with_autoref<T>( |
229 | deref_chain: &[Canonical<Ty>], | 249 | deref_chain: &[Canonical<Ty>], |
230 | db: &impl HirDatabase, | 250 | db: &impl HirDatabase, |
231 | resolver: &Resolver, | 251 | env: Arc<TraitEnvironment>, |
252 | krate: CrateId, | ||
253 | traits_in_scope: &FxHashSet<TraitId>, | ||
232 | name: Option<&Name>, | 254 | name: Option<&Name>, |
233 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 255 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
234 | ) -> Option<T> { | 256 | ) -> Option<T> { |
@@ -236,7 +258,9 @@ fn iterate_method_candidates_with_autoref<T>( | |||
236 | &deref_chain[0], | 258 | &deref_chain[0], |
237 | &deref_chain[1..], | 259 | &deref_chain[1..], |
238 | db, | 260 | db, |
239 | resolver, | 261 | env.clone(), |
262 | krate, | ||
263 | &traits_in_scope, | ||
240 | name, | 264 | name, |
241 | &mut callback, | 265 | &mut callback, |
242 | ) { | 266 | ) { |
@@ -250,7 +274,9 @@ fn iterate_method_candidates_with_autoref<T>( | |||
250 | &refed, | 274 | &refed, |
251 | deref_chain, | 275 | deref_chain, |
252 | db, | 276 | db, |
253 | resolver, | 277 | env.clone(), |
278 | krate, | ||
279 | &traits_in_scope, | ||
254 | name, | 280 | name, |
255 | &mut callback, | 281 | &mut callback, |
256 | ) { | 282 | ) { |
@@ -264,7 +290,9 @@ fn iterate_method_candidates_with_autoref<T>( | |||
264 | &ref_muted, | 290 | &ref_muted, |
265 | deref_chain, | 291 | deref_chain, |
266 | db, | 292 | db, |
267 | resolver, | 293 | env.clone(), |
294 | krate, | ||
295 | &traits_in_scope, | ||
268 | name, | 296 | name, |
269 | &mut callback, | 297 | &mut callback, |
270 | ) { | 298 | ) { |
@@ -277,14 +305,15 @@ fn iterate_method_candidates_by_receiver<T>( | |||
277 | receiver_ty: &Canonical<Ty>, | 305 | receiver_ty: &Canonical<Ty>, |
278 | rest_of_deref_chain: &[Canonical<Ty>], | 306 | rest_of_deref_chain: &[Canonical<Ty>], |
279 | db: &impl HirDatabase, | 307 | db: &impl HirDatabase, |
280 | resolver: &Resolver, | 308 | env: Arc<TraitEnvironment>, |
309 | krate: CrateId, | ||
310 | traits_in_scope: &FxHashSet<TraitId>, | ||
281 | name: Option<&Name>, | 311 | name: Option<&Name>, |
282 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 312 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
283 | ) -> Option<T> { | 313 | ) -> Option<T> { |
284 | // We're looking for methods with *receiver* type receiver_ty. These could | 314 | // We're looking for methods with *receiver* type receiver_ty. These could |
285 | // be found in any of the derefs of receiver_ty, so we have to go through | 315 | // be found in any of the derefs of receiver_ty, so we have to go through |
286 | // that. | 316 | // that. |
287 | let krate = resolver.krate()?; | ||
288 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { | 317 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { |
289 | if let Some(result) = | 318 | if let Some(result) = |
290 | iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) | 319 | iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) |
@@ -296,7 +325,9 @@ fn iterate_method_candidates_by_receiver<T>( | |||
296 | if let Some(result) = iterate_trait_method_candidates( | 325 | if let Some(result) = iterate_trait_method_candidates( |
297 | self_ty, | 326 | self_ty, |
298 | db, | 327 | db, |
299 | resolver, | 328 | env.clone(), |
329 | krate, | ||
330 | &traits_in_scope, | ||
300 | name, | 331 | name, |
301 | Some(receiver_ty), | 332 | Some(receiver_ty), |
302 | &mut callback, | 333 | &mut callback, |
@@ -310,17 +341,25 @@ fn iterate_method_candidates_by_receiver<T>( | |||
310 | fn iterate_method_candidates_for_self_ty<T>( | 341 | fn iterate_method_candidates_for_self_ty<T>( |
311 | self_ty: &Canonical<Ty>, | 342 | self_ty: &Canonical<Ty>, |
312 | db: &impl HirDatabase, | 343 | db: &impl HirDatabase, |
313 | resolver: &Resolver, | 344 | env: Arc<TraitEnvironment>, |
345 | krate: CrateId, | ||
346 | traits_in_scope: &FxHashSet<TraitId>, | ||
314 | name: Option<&Name>, | 347 | name: Option<&Name>, |
315 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 348 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
316 | ) -> Option<T> { | 349 | ) -> Option<T> { |
317 | let krate = resolver.krate()?; | ||
318 | if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { | 350 | if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { |
319 | return Some(result); | 351 | return Some(result); |
320 | } | 352 | } |
321 | if let Some(result) = | 353 | if let Some(result) = iterate_trait_method_candidates( |
322 | iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback) | 354 | self_ty, |
323 | { | 355 | db, |
356 | env, | ||
357 | krate, | ||
358 | traits_in_scope, | ||
359 | name, | ||
360 | None, | ||
361 | &mut callback, | ||
362 | ) { | ||
324 | return Some(result); | 363 | return Some(result); |
325 | } | 364 | } |
326 | None | 365 | None |
@@ -329,14 +368,13 @@ fn iterate_method_candidates_for_self_ty<T>( | |||
329 | fn iterate_trait_method_candidates<T>( | 368 | fn iterate_trait_method_candidates<T>( |
330 | self_ty: &Canonical<Ty>, | 369 | self_ty: &Canonical<Ty>, |
331 | db: &impl HirDatabase, | 370 | db: &impl HirDatabase, |
332 | resolver: &Resolver, | 371 | env: Arc<TraitEnvironment>, |
372 | krate: CrateId, | ||
373 | traits_in_scope: &FxHashSet<TraitId>, | ||
333 | name: Option<&Name>, | 374 | name: Option<&Name>, |
334 | receiver_ty: Option<&Canonical<Ty>>, | 375 | receiver_ty: Option<&Canonical<Ty>>, |
335 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 376 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
336 | ) -> Option<T> { | 377 | ) -> Option<T> { |
337 | let krate = resolver.krate()?; | ||
338 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | ||
339 | let env = TraitEnvironment::lower(db, resolver); | ||
340 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 378 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope |
341 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); | 379 | let inherent_trait = self_ty.value.inherent_trait().into_iter(); |
342 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 380 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
@@ -344,8 +382,7 @@ fn iterate_trait_method_candidates<T>( | |||
344 | .trait_predicates_for_self_ty(&self_ty.value) | 382 | .trait_predicates_for_self_ty(&self_ty.value) |
345 | .map(|tr| tr.trait_) | 383 | .map(|tr| tr.trait_) |
346 | .flat_map(|t| all_super_traits(db, t)); | 384 | .flat_map(|t| all_super_traits(db, t)); |
347 | let traits = | 385 | let traits = inherent_trait.chain(traits_from_env).chain(traits_in_scope.iter().copied()); |
348 | inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter()); | ||
349 | 'traits: for t in traits { | 386 | 'traits: for t in traits { |
350 | let data = db.trait_data(t); | 387 | let data = db.trait_data(t); |
351 | 388 | ||