aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs19
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs9
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs103
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
12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; 12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId};
13 13
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 14use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef};
15 15
16impl<'a, D: HirDatabase> InferenceContext<'a, D> { 16impl<'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
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use 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};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
14use ra_prof::profile; 14use ra_prof::profile;
15use rustc_hash::FxHashMap; 15use rustc_hash::{FxHashMap, FxHashSet};
16 16
17use super::Substs; 17use super::Substs;
18use crate::{ 18use crate::{
@@ -144,14 +144,24 @@ impl Ty {
144pub(crate) fn lookup_method( 144pub(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 {
172pub fn iterate_method_candidates<T>( 182pub 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>(
228fn iterate_method_candidates_with_autoref<T>( 248fn 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>(
310fn iterate_method_candidates_for_self_ty<T>( 341fn 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>(
329fn iterate_trait_method_candidates<T>( 368fn 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