@@ -127,6 +127,8 @@ crate struct Cache {
127127/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
128128struct CacheBuilder < ' a , ' tcx > {
129129 cache : & ' a mut Cache ,
130+ /// This field is used to prevent duplicated impl blocks.
131+ impl_ids : FxHashMap < DefId , FxHashSet < DefId > > ,
130132 tcx : TyCtxt < ' tcx > ,
131133}
132134
@@ -170,12 +172,19 @@ impl Cache {
170172 . insert ( def_id, ( vec ! [ crate_name, prim. as_sym( ) ] , ItemType :: Primitive ) ) ;
171173 }
172174
173- krate = CacheBuilder { tcx, cache : & mut cx. cache } . fold_crate ( krate) ;
175+ let ( krate, mut impl_ids) = {
176+ let mut cache_builder =
177+ CacheBuilder { tcx, cache : & mut cx. cache , impl_ids : FxHashMap :: default ( ) } ;
178+ krate = cache_builder. fold_crate ( krate) ;
179+ ( krate, cache_builder. impl_ids )
180+ } ;
174181
175182 for ( trait_did, dids, impl_) in cx. cache . orphan_trait_impls . drain ( ..) {
176183 if cx. cache . traits . contains_key ( & trait_did) {
177184 for did in dids {
178- cx. cache . impls . entry ( did) . or_default ( ) . push ( impl_. clone ( ) ) ;
185+ if impl_ids. entry ( did) . or_default ( ) . insert ( impl_. def_id ( ) ) {
186+ cx. cache . impls . entry ( did) . or_default ( ) . push ( impl_. clone ( ) ) ;
187+ }
179188 }
180189 }
181190 }
@@ -467,7 +476,13 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
467476 let impl_item = Impl { impl_item : item } ;
468477 if impl_item. trait_did ( ) . map_or ( true , |d| self . cache . traits . contains_key ( & d) ) {
469478 for did in dids {
470- self . cache . impls . entry ( did) . or_insert_with ( Vec :: new) . push ( impl_item. clone ( ) ) ;
479+ if self . impl_ids . entry ( did) . or_default ( ) . insert ( impl_item. def_id ( ) ) {
480+ self . cache
481+ . impls
482+ . entry ( did)
483+ . or_insert_with ( Vec :: new)
484+ . push ( impl_item. clone ( ) ) ;
485+ }
471486 }
472487 } else {
473488 let trait_did = impl_item. trait_did ( ) . expect ( "no trait did" ) ;
0 commit comments