@@ -287,14 +287,53 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
287
287
DefKind :: Struct | DefKind :: Union | DefKind :: Enum | DefKind :: TyAlias ,
288
288
did,
289
289
) => {
290
+ debug ! ( "looking for associated item named {} for item {:?}" , item_name, did) ;
291
+ let ty = cx. tcx . type_of ( did) ;
290
292
// Checks if item_name belongs to `impl SomeItem`
291
- let impl_item = cx
292
- . tcx
293
- . inherent_impls ( did)
294
- . iter ( )
295
- . flat_map ( |imp| cx. tcx . associated_items ( * imp) . in_definition_order ( ) )
296
- . find ( |item| item. ident . name == item_name) ;
297
- let trait_item = item_opt
293
+ let impls = crate :: clean:: get_auto_trait_and_blanket_impls ( cx, ty, did) ;
294
+ let impl_kind = impls
295
+ . flat_map ( |impl_outer| {
296
+ match impl_outer. inner {
297
+ ImplItem ( impl_) => {
298
+ debug ! ( "considering trait {:?}" , impl_. trait_) ;
299
+ // Give precedence to methods that were overridden
300
+ if !impl_. provided_trait_methods . contains ( & * item_name. as_str ( ) ) {
301
+ impl_. items . into_iter ( )
302
+ . filter ( |assoc| assoc. name . as_deref ( ) == Some ( & * item_name. as_str ( ) ) )
303
+ . map ( |assoc| {
304
+ trace ! ( "considering associated item {:?}" , assoc. inner) ;
305
+ // We have a slight issue: normal methods come from `clean` types,
306
+ // but provided methods come directly from `tcx`.
307
+ // Fortunately, we don't need the whole method, we just need to know
308
+ // what kind of associated item it is.
309
+ assoc. inner . as_assoc_kind ( )
310
+ . expect ( "inner items for a trait should be associated items" )
311
+ } )
312
+ // TODO: this collect seems a shame
313
+ . collect ( )
314
+ } else {
315
+ // These are provided methods or default types:
316
+ // ```
317
+ // trait T {
318
+ // type A = usize;
319
+ // fn has_default() -> A { 0 }
320
+ // }
321
+ // ```
322
+ // TODO: this is wrong, it should look at the trait, not the impl
323
+ cx. tcx . associated_items ( impl_outer. def_id )
324
+ . filter_by_name ( cx. tcx , Ident :: with_dummy_span ( item_name) , impl_outer. def_id )
325
+ . map ( |assoc| assoc. kind )
326
+ // TODO: this collect seems a shame
327
+ . collect :: < Vec < _ > > ( )
328
+ }
329
+ }
330
+ _ => panic ! ( "get_impls returned something that wasn't an impl" ) ,
331
+ }
332
+ } )
333
+ // TODO: give a warning if this is ambiguous
334
+ . next ( ) ;
335
+ // TODO: is this necessary? It doesn't look right, and also only works for local items
336
+ let trait_kind = item_opt
298
337
. and_then ( |item| self . cx . as_local_hir_id ( item. def_id ) )
299
338
. and_then ( |item_hir| {
300
339
// Checks if item_name belongs to `impl SomeTrait for SomeItem`
@@ -312,32 +351,34 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
312
351
let associated_item = cx. tcx . associated_item ( * child) ;
313
352
associated_item
314
353
} )
315
- . find ( |child| child. ident . name == item_name) ,
354
+ . find ( |child| child. ident . name == item_name)
355
+ . map ( |child| child. kind ) ,
316
356
_ => None ,
317
357
}
318
358
} ) ;
319
- let item = match ( impl_item, trait_item) {
320
- ( Some ( from_impl) , Some ( _) ) => {
359
+ debug ! ( "considering items {:?} and {:?}" , impl_kind, trait_kind) ;
360
+ let kind = match ( impl_kind, trait_kind) {
361
+ ( Some ( from_kind) , Some ( _) ) => {
321
362
// Although it's ambiguous, return impl version for compat. sake.
322
363
// To handle that properly resolve() would have to support
323
364
// something like
324
365
// [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
325
- Some ( from_impl )
366
+ Some ( from_kind )
326
367
}
327
- ( None , Some ( from_trait ) ) => Some ( from_trait ) ,
328
- ( Some ( from_impl ) , None ) => Some ( from_impl ) ,
368
+ ( None , Some ( from_kind ) ) => Some ( from_kind ) ,
369
+ ( Some ( from_kind ) , None ) => Some ( from_kind ) ,
329
370
_ => None ,
330
371
} ;
331
372
332
- if let Some ( item ) = item {
333
- let out = match item . kind {
373
+ if let Some ( kind ) = kind {
374
+ let out = match kind {
334
375
ty:: AssocKind :: Fn if ns == ValueNS => "method" ,
335
376
ty:: AssocKind :: Const if ns == ValueNS => "associatedconstant" ,
336
377
ty:: AssocKind :: Type if ns == ValueNS => "associatedtype" ,
337
378
_ => return self . variant_field ( path_str, current_item, module_id) ,
338
379
} ;
339
380
if extra_fragment. is_some ( ) {
340
- Err ( ErrorKind :: AnchorFailure ( if item . kind == ty:: AssocKind :: Fn {
381
+ Err ( ErrorKind :: AnchorFailure ( if kind == ty:: AssocKind :: Fn {
341
382
"methods cannot be followed by anchors"
342
383
} else {
343
384
"associated constants cannot be followed by anchors"
0 commit comments