@@ -176,7 +176,6 @@ pub fn iterate_method_candidates<T>(
176
176
mode : LookupMode ,
177
177
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
178
178
) -> Option < T > {
179
- let krate = resolver. krate ( ) ?;
180
179
match mode {
181
180
LookupMode :: MethodCall => {
182
181
// For method calls, rust first does any number of autoderef, and then one
@@ -189,57 +188,125 @@ pub fn iterate_method_candidates<T>(
189
188
// rustc does an autoderef and then autoref again).
190
189
let environment = TraitEnvironment :: lower ( db, resolver) ;
191
190
let ty = InEnvironment { value : ty. clone ( ) , environment } ;
192
- for derefed_ty in autoderef:: autoderef ( db, resolver. krate ( ) , ty) {
193
- if let Some ( result) =
194
- iterate_inherent_methods ( & derefed_ty, db, name, mode, krate, & mut callback)
195
- {
196
- return Some ( result) ;
197
- }
198
- if let Some ( result) = iterate_trait_method_candidates (
199
- & derefed_ty,
191
+ let krate = resolver. krate ( ) ?;
192
+
193
+ // We have to be careful about the order of operations here.
194
+ // Consider the case where we're resolving `x.clone()` where `x:
195
+ // &Vec<_>`. This resolves to the clone method with self type
196
+ // `Vec<_>`, *not* `&_`. I.e. we need to consider methods where the
197
+ // receiver type exactly matches before cases where we have to do
198
+ // autoref. But in the autoderef steps, the `&_` self type comes up
199
+ // *before* the `Vec<_>` self type.
200
+ //
201
+ // On the other hand, we don't want to just pick any by-value method
202
+ // before any by-autoref method; it's just that we need to consider
203
+ // the methods by autoderef order of *receiver types*, not *self
204
+ // types*.
205
+
206
+ let deref_chain: Vec < _ > = autoderef:: autoderef ( db, Some ( krate) , ty. clone ( ) ) . collect ( ) ;
207
+ for i in 0 ..deref_chain. len ( ) {
208
+ if let Some ( result) = iterate_method_candidates_autoref (
209
+ & deref_chain[ i..] ,
200
210
db,
201
211
resolver,
202
212
name,
203
- mode,
204
213
& mut callback,
205
214
) {
206
215
return Some ( result) ;
207
216
}
208
217
}
218
+ None
209
219
}
210
220
LookupMode :: Path => {
211
221
// No autoderef for path lookups
212
- if let Some ( result) =
213
- iterate_inherent_methods ( & ty, db, name, mode, krate. into ( ) , & mut callback)
214
- {
215
- return Some ( result) ;
216
- }
217
- if let Some ( result) =
218
- iterate_trait_method_candidates ( & ty, db, resolver, name, mode, & mut callback)
219
- {
220
- return Some ( result) ;
221
- }
222
+ iterate_method_candidates_inner ( & ty, db, resolver, name, None , & mut callback)
223
+ }
224
+ }
225
+ }
226
+
227
+ fn iterate_method_candidates_autoref < T > (
228
+ deref_chain : & [ Canonical < Ty > ] ,
229
+ db : & impl HirDatabase ,
230
+ resolver : & Resolver ,
231
+ name : Option < & Name > ,
232
+ mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
233
+ ) -> Option < T > {
234
+ if let Some ( result) = iterate_method_candidates_by_receiver ( & deref_chain[ 0 ] , & deref_chain[ 1 ..] , db, resolver, name, & mut callback) {
235
+ return Some ( result) ;
236
+ }
237
+ let refed = Canonical {
238
+ num_vars : deref_chain[ 0 ] . num_vars ,
239
+ value : Ty :: apply_one ( TypeCtor :: Ref ( Mutability :: Shared ) , deref_chain[ 0 ] . value . clone ( ) ) ,
240
+ } ;
241
+ if let Some ( result) = iterate_method_candidates_by_receiver ( & refed, deref_chain, db, resolver, name, & mut callback) {
242
+ return Some ( result) ;
243
+ }
244
+ let ref_muted = Canonical {
245
+ num_vars : deref_chain[ 0 ] . num_vars ,
246
+ value : Ty :: apply_one ( TypeCtor :: Ref ( Mutability :: Mut ) , deref_chain[ 0 ] . value . clone ( ) ) ,
247
+ } ;
248
+ if let Some ( result) = iterate_method_candidates_by_receiver ( & ref_muted, deref_chain, db, resolver, name, & mut callback) {
249
+ return Some ( result) ;
250
+ }
251
+ None
252
+ }
253
+
254
+ fn iterate_method_candidates_by_receiver < T > (
255
+ receiver_ty : & Canonical < Ty > ,
256
+ deref_chain : & [ Canonical < Ty > ] ,
257
+ db : & impl HirDatabase ,
258
+ resolver : & Resolver ,
259
+ name : Option < & Name > ,
260
+ mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
261
+ ) -> Option < T > {
262
+ // TODO: do we need to do the whole loop for inherents before traits?
263
+ // We're looking for methods with *receiver* type receiver_ty. These could
264
+ // be found in any of the derefs of receiver_ty, so we have to go through
265
+ // that.
266
+ for self_ty in std:: iter:: once ( receiver_ty) . chain ( deref_chain) {
267
+ if let Some ( result) = iterate_method_candidates_inner ( self_ty, db, resolver, name, Some ( receiver_ty) , & mut callback) {
268
+ return Some ( result) ;
222
269
}
223
270
}
224
271
None
225
272
}
226
273
274
+ fn iterate_method_candidates_inner < T > (
275
+ self_ty : & Canonical < Ty > ,
276
+ db : & impl HirDatabase ,
277
+ resolver : & Resolver ,
278
+ name : Option < & Name > ,
279
+ receiver_ty : Option < & Canonical < Ty > > ,
280
+ mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
281
+ ) -> Option < T > {
282
+ let krate = resolver. krate ( ) ?;
283
+ if let Some ( result) = iterate_inherent_methods ( self_ty, db, name, receiver_ty, krate, & mut callback) {
284
+ return Some ( result) ;
285
+ }
286
+ if let Some ( result) =
287
+ iterate_trait_method_candidates ( self_ty, db, resolver, name, receiver_ty, & mut callback)
288
+ {
289
+ return Some ( result) ;
290
+ }
291
+ None
292
+ }
293
+
227
294
fn iterate_trait_method_candidates < T > (
228
- ty : & Canonical < Ty > ,
295
+ self_ty : & Canonical < Ty > ,
229
296
db : & impl HirDatabase ,
230
297
resolver : & Resolver ,
231
298
name : Option < & Name > ,
232
- mode : LookupMode ,
299
+ receiver_ty : Option < & Canonical < Ty > > ,
233
300
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
234
301
) -> Option < T > {
235
302
let krate = resolver. krate ( ) ?;
236
303
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
237
304
let env = TraitEnvironment :: lower ( db, resolver) ;
238
305
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
239
- let inherent_trait = ty . value . inherent_trait ( ) . into_iter ( ) ;
306
+ let inherent_trait = self_ty . value . inherent_trait ( ) . into_iter ( ) ;
240
307
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
241
308
let traits_from_env = env
242
- . trait_predicates_for_self_ty ( & ty . value )
309
+ . trait_predicates_for_self_ty ( & self_ty . value )
243
310
. map ( |tr| tr. trait_ )
244
311
. flat_map ( |t| all_super_traits ( db, t) ) ;
245
312
let traits =
@@ -252,17 +319,17 @@ fn iterate_trait_method_candidates<T>(
252
319
// iteration
253
320
let mut known_implemented = false ;
254
321
for ( _name, item) in data. items . iter ( ) {
255
- if !is_valid_candidate ( db, name, mode , ( * item) . into ( ) ) {
322
+ if !is_valid_candidate ( db, name, receiver_ty , ( * item) . into ( ) , self_ty ) {
256
323
continue ;
257
324
}
258
325
if !known_implemented {
259
- let goal = generic_implements_goal ( db, env. clone ( ) , t, ty . clone ( ) ) ;
326
+ let goal = generic_implements_goal ( db, env. clone ( ) , t, self_ty . clone ( ) ) ;
260
327
if db. trait_solve ( krate. into ( ) , goal) . is_none ( ) {
261
328
continue ' traits;
262
329
}
263
330
}
264
331
known_implemented = true ;
265
- if let Some ( result) = callback ( & ty . value , ( * item) . into ( ) ) {
332
+ if let Some ( result) = callback ( & self_ty . value , ( * item) . into ( ) ) {
266
333
return Some ( result) ;
267
334
}
268
335
}
@@ -271,22 +338,22 @@ fn iterate_trait_method_candidates<T>(
271
338
}
272
339
273
340
fn iterate_inherent_methods < T > (
274
- ty : & Canonical < Ty > ,
341
+ self_ty : & Canonical < Ty > ,
275
342
db : & impl HirDatabase ,
276
343
name : Option < & Name > ,
277
- mode : LookupMode ,
344
+ receiver_ty : Option < & Canonical < Ty > > ,
278
345
krate : CrateId ,
279
346
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
280
347
) -> Option < T > {
281
- for krate in ty . value . def_crates ( db, krate) ? {
348
+ for krate in self_ty . value . def_crates ( db, krate) ? {
282
349
let impls = db. impls_in_crate ( krate) ;
283
350
284
- for impl_block in impls. lookup_impl_blocks ( & ty . value ) {
351
+ for impl_block in impls. lookup_impl_blocks ( & self_ty . value ) {
285
352
for & item in db. impl_data ( impl_block) . items . iter ( ) {
286
- if !is_valid_candidate ( db, name, mode , item) {
353
+ if !is_valid_candidate ( db, name, receiver_ty , item, self_ty ) {
287
354
continue ;
288
355
}
289
- if let Some ( result) = callback ( & ty . value , item. into ( ) ) {
356
+ if let Some ( result) = callback ( & self_ty . value , item) {
290
357
return Some ( result) ;
291
358
}
292
359
}
@@ -298,18 +365,29 @@ fn iterate_inherent_methods<T>(
298
365
fn is_valid_candidate (
299
366
db : & impl HirDatabase ,
300
367
name : Option < & Name > ,
301
- mode : LookupMode ,
368
+ receiver_ty : Option < & Canonical < Ty > > ,
302
369
item : AssocItemId ,
370
+ self_ty : & Canonical < Ty > ,
303
371
) -> bool {
304
372
match item {
305
373
AssocItemId :: FunctionId ( m) => {
306
374
let data = db. function_data ( m) ;
307
- name. map_or ( true , |name| & data. name == name)
308
- && ( data. has_self_param || mode == LookupMode :: Path )
375
+ if let Some ( name) = name {
376
+ if & data. name != name {
377
+ return false ;
378
+ }
379
+ }
380
+ if let Some ( receiver_ty) = receiver_ty {
381
+ if !data. has_self_param {
382
+ return false ;
383
+ }
384
+ // TODO compare receiver ty
385
+ }
386
+ true
309
387
}
310
388
AssocItemId :: ConstId ( c) => {
311
389
let data = db. const_data ( c) ;
312
- name. map_or ( true , |name| data. name . as_ref ( ) == Some ( name) ) && ( mode == LookupMode :: Path )
390
+ name. map_or ( true , |name| data. name . as_ref ( ) == Some ( name) ) && receiver_ty . is_none ( )
313
391
}
314
392
_ => false ,
315
393
}
0 commit comments