@@ -291,65 +291,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
291291 did,
292292 ) => {
293293 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 ) ?;
353295 // TODO: is this necessary? It doesn't look right, and also only works for local items
354296 let trait_kind = self . cx . as_local_hir_id ( item. def_id )
355297 . and_then ( |item_hir| {
@@ -484,6 +426,68 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
484426 }
485427}
486428
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+
487491/// Check for resolve collisions between a trait and its derive
488492///
489493/// These are common and we should just resolve to the trait in that case
0 commit comments