@@ -291,65 +291,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
291
291
did,
292
292
) => {
293
293
debug ! ( "looking for associated item named {} for item {:?}" , item_name, did) ;
294
- let ty = cx. tcx . type_of ( did) ;
295
- // Checks if item_name belongs to `impl SomeItem`
296
- // `def_id` should be a trait
297
- let associated_items_for_def_id = |tcx : ty:: TyCtxt < ' _ > , def_id : DefId | -> Vec < _ > {
298
- tcx. associated_items ( def_id)
299
- . filter_by_name ( tcx, Ident :: with_dummy_span ( item_name) , def_id)
300
- . map ( |assoc| ( assoc. def_id , assoc. kind ) )
301
- // TODO: this collect seems a shame
302
- . collect ( )
303
- } ;
304
- let impls = crate :: clean:: get_auto_trait_and_blanket_impls ( cx, ty, did) ;
305
- let candidates: Vec < _ > = impls
306
- . flat_map ( |impl_outer| {
307
- match impl_outer. inner {
308
- ImplItem ( impl_) => {
309
- debug ! ( "considering trait {:?}" , impl_. trait_) ;
310
- // Give precedence to methods that were overridden
311
- if !impl_. provided_trait_methods . contains ( & * item_name. as_str ( ) ) {
312
- impl_. items . into_iter ( )
313
- . filter ( |assoc| assoc. name . as_deref ( ) == Some ( & * item_name. as_str ( ) ) )
314
- . map ( |assoc| {
315
- trace ! ( "considering associated item {:?}" , assoc. inner) ;
316
- // We have a slight issue: normal methods come from `clean` types,
317
- // but provided methods come directly from `tcx`.
318
- // Fortunately, we don't need the whole method, we just need to know
319
- // what kind of associated item it is.
320
- (
321
- assoc. def_id ,
322
- assoc. inner . as_assoc_kind ( )
323
- . expect ( "inner items for a trait should be associated items" )
324
- )
325
- } )
326
- // TODO: this collect seems a shame
327
- . collect :: < Vec < _ > > ( )
328
- } else {
329
- // These are provided methods or default types:
330
- // ```
331
- // trait T {
332
- // type A = usize;
333
- // fn has_default() -> A { 0 }
334
- // }
335
- // ```
336
- // TODO: this is wrong, it should look at the trait, not the impl
337
- associated_items_for_def_id ( cx. tcx , impl_outer. def_id )
338
- }
339
- }
340
- _ => panic ! ( "get_impls returned something that wasn't an impl" ) ,
341
- }
342
- } )
343
- . chain ( cx. tcx . all_impls ( did) . flat_map ( |impl_| associated_items_for_def_id ( cx. tcx , impl_) ) )
344
- //.chain(cx.tcx.all_local_trait_impls(did).flat_map(|impl_| associated_items_for_def_id(cx.tcx, impl_)))
345
- . collect ( ) ;
346
- if candidates. len ( ) > 1 {
347
- let candidates = candidates. into_iter ( )
348
- . map ( |( def_id, kind) | Res :: Def ( kind. as_def_kind ( ) , def_id) )
349
- . collect ( ) ;
350
- return Err ( ErrorKind :: Ambiguous { candidates } ) ;
351
- }
352
- let impl_kind = candidates. into_iter ( ) . next ( ) . map ( |( _, kind) | kind) ;
294
+ let impl_kind = resolve_associated_trait_item ( did, item_name, & self . cx ) ?;
353
295
// TODO: is this necessary? It doesn't look right, and also only works for local items
354
296
let trait_kind = self . cx . as_local_hir_id ( item. def_id )
355
297
. and_then ( |item_hir| {
@@ -484,6 +426,68 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
484
426
}
485
427
}
486
428
429
+ fn resolve_associated_trait_item ( did : DefId , item_name : Symbol , cx : & DocContext < ' _ > ) -> Result < Option < ty:: AssocKind > , ErrorKind > {
430
+ let ty = cx. tcx . type_of ( did) ;
431
+ // Checks if item_name belongs to `impl SomeItem`
432
+ // `def_id` should be a trait
433
+ let associated_items_for_def_id = |tcx : ty:: TyCtxt < ' _ > , def_id : DefId | -> Vec < _ > {
434
+ tcx. associated_items ( def_id)
435
+ . filter_by_name ( tcx, Ident :: with_dummy_span ( item_name) , def_id)
436
+ . map ( |assoc| ( assoc. def_id , assoc. kind ) )
437
+ // TODO: this collect seems a shame
438
+ . collect ( )
439
+ } ;
440
+ let impls = crate :: clean:: get_auto_trait_and_blanket_impls ( cx, ty, did) ;
441
+ let candidates: Vec < _ > = impls
442
+ . flat_map ( |impl_outer| {
443
+ match impl_outer. inner {
444
+ ImplItem ( impl_) => {
445
+ debug ! ( "considering trait {:?}" , impl_. trait_) ;
446
+ // Give precedence to methods that were overridden
447
+ if !impl_. provided_trait_methods . contains ( & * item_name. as_str ( ) ) {
448
+ impl_. items . into_iter ( )
449
+ . filter ( |assoc| assoc. name . as_deref ( ) == Some ( & * item_name. as_str ( ) ) )
450
+ . map ( |assoc| {
451
+ trace ! ( "considering associated item {:?}" , assoc. inner) ;
452
+ // We have a slight issue: normal methods come from `clean` types,
453
+ // but provided methods come directly from `tcx`.
454
+ // Fortunately, we don't need the whole method, we just need to know
455
+ // what kind of associated item it is.
456
+ (
457
+ assoc. def_id ,
458
+ assoc. inner . as_assoc_kind ( )
459
+ . expect ( "inner items for a trait should be associated items" )
460
+ )
461
+ } )
462
+ // TODO: this collect seems a shame
463
+ . collect :: < Vec < _ > > ( )
464
+ } else {
465
+ // These are provided methods or default types:
466
+ // ```
467
+ // trait T {
468
+ // type A = usize;
469
+ // fn has_default() -> A { 0 }
470
+ // }
471
+ // ```
472
+ // TODO: this is wrong, it should look at the trait, not the impl
473
+ associated_items_for_def_id ( cx. tcx , impl_outer. def_id )
474
+ }
475
+ }
476
+ _ => panic ! ( "get_impls returned something that wasn't an impl" ) ,
477
+ }
478
+ } )
479
+ . chain ( cx. tcx . all_impls ( did) . flat_map ( |impl_| associated_items_for_def_id ( cx. tcx , impl_) ) )
480
+ //.chain(cx.tcx.all_local_trait_impls(did).flat_map(|impl_| associated_items_for_def_id(cx.tcx, impl_)))
481
+ . collect ( ) ;
482
+ if candidates. len ( ) > 1 {
483
+ let candidates = candidates. into_iter ( )
484
+ . map ( |( def_id, kind) | Res :: Def ( kind. as_def_kind ( ) , def_id) )
485
+ . collect ( ) ;
486
+ return Err ( ErrorKind :: Ambiguous { candidates } ) ;
487
+ }
488
+ Ok ( candidates. into_iter ( ) . next ( ) . map ( |( _, kind) | kind) )
489
+ }
490
+
487
491
/// Check for resolve collisions between a trait and its derive
488
492
///
489
493
/// These are common and we should just resolve to the trait in that case
0 commit comments