@@ -337,6 +337,15 @@ pub struct Cache {
337
337
// and their parent id here and indexes them at the end of crate parsing.
338
338
orphan_impl_items : Vec < ( DefId , clean:: Item ) > ,
339
339
340
+ // Similarly to `orphan_impl_items`, sometimes trait impls are picked up
341
+ // even though the trait itself is not exported. This can happen if a trait
342
+ // was defined in function/expression scope, since the impl will be picked
343
+ // up by `collect-trait-impls` but the trait won't be scraped out in the HIR
344
+ // crawl. In order to prevent crashes when looking for spotlight traits or
345
+ // when gathering trait documentation on a type, hold impls here while
346
+ // folding and add them to the cache later on if we find the trait.
347
+ orphan_trait_impls : Vec < ( DefId , FxHashSet < DefId > , Impl ) > ,
348
+
340
349
/// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
341
350
/// we need the alias element to have an array of items.
342
351
aliases : FxHashMap < String , Vec < IndexItem > > ,
@@ -594,6 +603,7 @@ pub fn run(mut krate: clean::Crate,
594
603
access_levels : krate. access_levels . clone ( ) ,
595
604
crate_version : krate. version . take ( ) ,
596
605
orphan_impl_items : Vec :: new ( ) ,
606
+ orphan_trait_impls : Vec :: new ( ) ,
597
607
traits : mem:: replace ( & mut krate. external_traits , FxHashMap ( ) ) ,
598
608
deref_trait_did,
599
609
deref_mut_trait_did,
@@ -636,6 +646,14 @@ pub fn run(mut krate: clean::Crate,
636
646
cache. stack . push ( krate. name . clone ( ) ) ;
637
647
krate = cache. fold_crate ( krate) ;
638
648
649
+ for ( trait_did, dids, impl_) in cache. orphan_trait_impls . drain ( ..) {
650
+ if cache. traits . contains_key ( & trait_did) {
651
+ for did in dids {
652
+ cache. impls . entry ( did) . or_insert ( vec ! [ ] ) . push ( impl_. clone ( ) ) ;
653
+ }
654
+ }
655
+ }
656
+
639
657
// Build our search index
640
658
let index = build_index ( & krate, & mut cache) ;
641
659
@@ -1224,7 +1242,7 @@ impl<'a> SourceCollector<'a> {
1224
1242
impl DocFolder for Cache {
1225
1243
fn fold_item ( & mut self , item : clean:: Item ) -> Option < clean:: Item > {
1226
1244
if item. def_id . is_local ( ) {
1227
- debug ! ( "folding item \" {:?}\" , a { }" , item. name, item. type_ ( ) ) ;
1245
+ debug ! ( "folding {} \" {:?}\" , id {:? }" , item. type_ ( ) , item . name, item. def_id ) ;
1228
1246
}
1229
1247
1230
1248
// If this is a stripped module,
@@ -1457,10 +1475,16 @@ impl DocFolder for Cache {
1457
1475
} else {
1458
1476
unreachable ! ( )
1459
1477
} ;
1460
- for did in dids {
1461
- self . impls . entry ( did) . or_default ( ) . push ( Impl {
1462
- impl_item : item. clone ( ) ,
1463
- } ) ;
1478
+ let impl_item = Impl {
1479
+ impl_item : item,
1480
+ } ;
1481
+ if impl_item. trait_did ( ) . map_or ( true , |d| self . traits . contains_key ( & d) ) {
1482
+ for did in dids {
1483
+ self . impls . entry ( did) . or_insert ( vec ! [ ] ) . push ( impl_item. clone ( ) ) ;
1484
+ }
1485
+ } else {
1486
+ let trait_did = impl_item. trait_did ( ) . unwrap ( ) ;
1487
+ self . orphan_trait_impls . push ( ( trait_did, dids, impl_item) ) ;
1464
1488
}
1465
1489
None
1466
1490
} else {
0 commit comments