@@ -305,16 +305,15 @@ crate enum FragmentKind {
305305
306306impl ItemFragment {
307307 /// Create a fragment for an associated item.
308- ///
309- /// `is_prototype` is whether this associated item is a trait method
310- /// without a default definition.
311- fn from_assoc_item ( def_id : DefId , kind : ty:: AssocKind , is_prototype : bool ) -> Self {
312- match kind {
308+ #[ instrument( level = "debug" ) ]
309+ fn from_assoc_item ( item : & ty:: AssocItem ) -> Self {
310+ let def_id = item. def_id ;
311+ match item. kind {
313312 ty:: AssocKind :: Fn => {
314- if is_prototype {
315- ItemFragment ( FragmentKind :: TyMethod , def_id)
316- } else {
313+ if item. defaultness . has_value ( ) {
317314 ItemFragment ( FragmentKind :: Method , def_id)
315+ } else {
316+ ItemFragment ( FragmentKind :: TyMethod , def_id)
318317 }
319318 }
320319 ty:: AssocKind :: Const => ItemFragment ( FragmentKind :: AssociatedConstant , def_id) ,
@@ -473,8 +472,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
473472 tcx. associated_items ( impl_)
474473 . find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, impl_)
475474 . map ( |item| {
476- let kind = item. kind ;
477- let fragment = ItemFragment :: from_assoc_item ( item. def_id , kind, false ) ;
475+ let fragment = ItemFragment :: from_assoc_item ( item) ;
478476 ( Res :: Primitive ( prim_ty) , fragment)
479477 } )
480478 } )
@@ -726,8 +724,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
726724 . flatten ( ) ;
727725
728726 assoc_item. map ( |item| {
729- let kind = item. kind ;
730- let fragment = ItemFragment :: from_assoc_item ( item. def_id , kind, false ) ;
727+ let fragment = ItemFragment :: from_assoc_item ( & item) ;
731728 ( root_res, fragment)
732729 } )
733730 } )
@@ -765,20 +762,19 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
765762 // To handle that properly resolve() would have to support
766763 // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
767764 . or_else ( || {
768- let item = resolve_associated_trait_item (
765+ resolve_associated_trait_item (
769766 tcx. type_of ( did) ,
770767 module_id,
771768 item_name,
772769 ns,
773770 self . cx ,
774- ) ;
775- debug ! ( "got associated item {:?}" , item) ;
776- item
771+ )
777772 } ) ;
778773
774+ debug ! ( "got associated item {:?}" , assoc_item) ;
775+
779776 if let Some ( item) = assoc_item {
780- let kind = item. kind ;
781- let fragment = ItemFragment :: from_assoc_item ( item. def_id , kind, false ) ;
777+ let fragment = ItemFragment :: from_assoc_item ( & item) ;
782778 return Some ( ( root_res, fragment) ) ;
783779 }
784780
@@ -813,11 +809,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
813809 . associated_items ( did)
814810 . find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, did)
815811 . map ( |item| {
816- let fragment = ItemFragment :: from_assoc_item (
817- item. def_id ,
818- item. kind ,
819- !item. defaultness . has_value ( ) ,
820- ) ;
812+ let fragment = ItemFragment :: from_assoc_item ( item) ;
821813 let res = Res :: Def ( item. kind . as_def_kind ( ) , item. def_id ) ;
822814 ( res, fragment)
823815 } ) ,
@@ -883,30 +875,56 @@ fn resolve_associated_trait_item<'a>(
883875
884876 // Next consider explicit impls: `impl MyTrait for MyType`
885877 // Give precedence to inherent impls.
886- let traits = traits_implemented_by ( cx, ty, module) ;
878+ let traits = trait_impls_for ( cx, ty, module) ;
887879 debug ! ( "considering traits {:?}" , traits) ;
888- let mut candidates = traits. iter ( ) . filter_map ( |& trait_| {
889- cx. tcx . associated_items ( trait_) . find_by_name_and_namespace (
890- cx. tcx ,
891- Ident :: with_dummy_span ( item_name) ,
892- ns,
893- trait_,
894- )
880+ let mut candidates = traits. iter ( ) . filter_map ( |& ( impl_, trait_) | {
881+ cx. tcx
882+ . associated_items ( trait_)
883+ . find_by_name_and_namespace ( cx. tcx , Ident :: with_dummy_span ( item_name) , ns, trait_)
884+ . map ( |trait_assoc| {
885+ trait_assoc_to_impl_assoc_item ( cx. tcx , impl_, trait_assoc. def_id )
886+ . unwrap_or ( trait_assoc)
887+ } )
895888 } ) ;
896889 // FIXME(#74563): warn about ambiguity
897890 debug ! ( "the candidates were {:?}" , candidates. clone( ) . collect:: <Vec <_>>( ) ) ;
898891 candidates. next ( ) . copied ( )
899892}
900893
901- /// Given a type, return all traits in scope in `module` implemented by that type.
894+ /// Find the associated item in the impl `impl_id` that corresponds to the
895+ /// trait associated item `trait_assoc_id`.
896+ ///
897+ /// This function returns `None` if no associated item was found in the impl.
898+ /// This can occur when the trait associated item has a default value that is
899+ /// not overriden in the impl.
900+ ///
901+ /// This is just a wrapper around [`TyCtxt::impl_item_implementor_ids()`] and
902+ /// [`TyCtxt::associated_item()`] (with some helpful logging added).
903+ #[ instrument( level = "debug" , skip( tcx) ) ]
904+ fn trait_assoc_to_impl_assoc_item < ' tcx > (
905+ tcx : TyCtxt < ' tcx > ,
906+ impl_id : DefId ,
907+ trait_assoc_id : DefId ,
908+ ) -> Option < & ' tcx ty:: AssocItem > {
909+ let trait_to_impl_assoc_map = tcx. impl_item_implementor_ids ( impl_id) ;
910+ debug ! ( ?trait_to_impl_assoc_map) ;
911+ let impl_assoc_id = * trait_to_impl_assoc_map. get ( & trait_assoc_id) ?;
912+ debug ! ( ?impl_assoc_id) ;
913+ let impl_assoc = tcx. associated_item ( impl_assoc_id) ;
914+ debug ! ( ?impl_assoc) ;
915+ Some ( impl_assoc)
916+ }
917+
918+ /// Given a type, return all trait impls in scope in `module` for that type.
919+ /// Returns a set of pairs of `(impl_id, trait_id)`.
902920///
903921/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
904922/// So it is not stable to serialize cross-crate.
905- fn traits_implemented_by < ' a > (
923+ fn trait_impls_for < ' a > (
906924 cx : & mut DocContext < ' a > ,
907925 ty : Ty < ' a > ,
908926 module : DefId ,
909- ) -> FxHashSet < DefId > {
927+ ) -> FxHashSet < ( DefId , DefId ) > {
910928 let mut resolver = cx. resolver . borrow_mut ( ) ;
911929 let in_scope_traits = cx. module_trait_cache . entry ( module) . or_insert_with ( || {
912930 resolver. access ( |resolver| {
@@ -948,7 +966,7 @@ fn traits_implemented_by<'a>(
948966 _ => false ,
949967 } ;
950968
951- if saw_impl { Some ( trait_) } else { None }
969+ if saw_impl { Some ( ( impl_ , trait_) ) } else { None }
952970 } )
953971 } ) ;
954972 iter. collect ( )
0 commit comments