@@ -287,14 +287,53 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
287287 DefKind :: Struct | DefKind :: Union | DefKind :: Enum | DefKind :: TyAlias ,
288288 did,
289289 ) => {
290+ debug ! ( "looking for associated item named {} for item {:?}" , item_name, did) ;
291+ let ty = cx. tcx . type_of ( did) ;
290292 // 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
298337 . and_then ( |item| self . cx . as_local_hir_id ( item. def_id ) )
299338 . and_then ( |item_hir| {
300339 // Checks if item_name belongs to `impl SomeTrait for SomeItem`
@@ -312,32 +351,34 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
312351 let associated_item = cx. tcx . associated_item ( * child) ;
313352 associated_item
314353 } )
315- . find ( |child| child. ident . name == item_name) ,
354+ . find ( |child| child. ident . name == item_name)
355+ . map ( |child| child. kind ) ,
316356 _ => None ,
317357 }
318358 } ) ;
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 ( _) ) => {
321362 // Although it's ambiguous, return impl version for compat. sake.
322363 // To handle that properly resolve() would have to support
323364 // something like
324365 // [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
325- Some ( from_impl )
366+ Some ( from_kind )
326367 }
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 ) ,
329370 _ => None ,
330371 } ;
331372
332- if let Some ( item ) = item {
333- let out = match item . kind {
373+ if let Some ( kind ) = kind {
374+ let out = match kind {
334375 ty:: AssocKind :: Fn if ns == ValueNS => "method" ,
335376 ty:: AssocKind :: Const if ns == ValueNS => "associatedconstant" ,
336377 ty:: AssocKind :: Type if ns == ValueNS => "associatedtype" ,
337378 _ => return self . variant_field ( path_str, current_item, module_id) ,
338379 } ;
339380 if extra_fragment. is_some ( ) {
340- Err ( ErrorKind :: AnchorFailure ( if item . kind == ty:: AssocKind :: Fn {
381+ Err ( ErrorKind :: AnchorFailure ( if kind == ty:: AssocKind :: Fn {
341382 "methods cannot be followed by anchors"
342383 } else {
343384 "associated constants cannot be followed by anchors"
0 commit comments