@@ -305,16 +305,15 @@ crate enum FragmentKind {
305
305
306
306
impl ItemFragment {
307
307
/// 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 {
313
312
ty:: AssocKind :: Fn => {
314
- if is_prototype {
315
- ItemFragment ( FragmentKind :: TyMethod , def_id)
316
- } else {
313
+ if item. defaultness . has_value ( ) {
317
314
ItemFragment ( FragmentKind :: Method , def_id)
315
+ } else {
316
+ ItemFragment ( FragmentKind :: TyMethod , def_id)
318
317
}
319
318
}
320
319
ty:: AssocKind :: Const => ItemFragment ( FragmentKind :: AssociatedConstant , def_id) ,
@@ -473,8 +472,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
473
472
tcx. associated_items ( impl_)
474
473
. find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, impl_)
475
474
. 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) ;
478
476
( Res :: Primitive ( prim_ty) , fragment)
479
477
} )
480
478
} )
@@ -726,8 +724,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
726
724
. flatten ( ) ;
727
725
728
726
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) ;
731
728
( root_res, fragment)
732
729
} )
733
730
} )
@@ -765,20 +762,19 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
765
762
// To handle that properly resolve() would have to support
766
763
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
767
764
. or_else ( || {
768
- let item = resolve_associated_trait_item (
765
+ resolve_associated_trait_item (
769
766
tcx. type_of ( did) ,
770
767
module_id,
771
768
item_name,
772
769
ns,
773
770
self . cx ,
774
- ) ;
775
- debug ! ( "got associated item {:?}" , item) ;
776
- item
771
+ )
777
772
} ) ;
778
773
774
+ debug ! ( "got associated item {:?}" , assoc_item) ;
775
+
779
776
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) ;
782
778
return Some ( ( root_res, fragment) ) ;
783
779
}
784
780
@@ -813,11 +809,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
813
809
. associated_items ( did)
814
810
. find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, did)
815
811
. 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) ;
821
813
let res = Res :: Def ( item. kind . as_def_kind ( ) , item. def_id ) ;
822
814
( res, fragment)
823
815
} ) ,
@@ -883,30 +875,56 @@ fn resolve_associated_trait_item<'a>(
883
875
884
876
// Next consider explicit impls: `impl MyTrait for MyType`
885
877
// Give precedence to inherent impls.
886
- let traits = traits_implemented_by ( cx, ty, module) ;
878
+ let traits = trait_impls_for ( cx, ty, module) ;
887
879
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
+ } )
895
888
} ) ;
896
889
// FIXME(#74563): warn about ambiguity
897
890
debug ! ( "the candidates were {:?}" , candidates. clone( ) . collect:: <Vec <_>>( ) ) ;
898
891
candidates. next ( ) . copied ( )
899
892
}
900
893
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)`.
902
920
///
903
921
/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
904
922
/// So it is not stable to serialize cross-crate.
905
- fn traits_implemented_by < ' a > (
923
+ fn trait_impls_for < ' a > (
906
924
cx : & mut DocContext < ' a > ,
907
925
ty : Ty < ' a > ,
908
926
module : DefId ,
909
- ) -> FxHashSet < DefId > {
927
+ ) -> FxHashSet < ( DefId , DefId ) > {
910
928
let mut resolver = cx. resolver . borrow_mut ( ) ;
911
929
let in_scope_traits = cx. module_trait_cache . entry ( module) . or_insert_with ( || {
912
930
resolver. access ( |resolver| {
@@ -948,7 +966,7 @@ fn traits_implemented_by<'a>(
948
966
_ => false ,
949
967
} ;
950
968
951
- if saw_impl { Some ( trait_) } else { None }
969
+ if saw_impl { Some ( ( impl_ , trait_) ) } else { None }
952
970
} )
953
971
} ) ;
954
972
iter. collect ( )
0 commit comments