@@ -337,6 +337,15 @@ pub struct Cache {
337337 // and their parent id here and indexes them at the end of crate parsing.
338338 orphan_impl_items : Vec < ( DefId , clean:: Item ) > ,
339339
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+
340349 /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
341350 /// we need the alias element to have an array of items.
342351 aliases : FxHashMap < String , Vec < IndexItem > > ,
@@ -594,6 +603,7 @@ pub fn run(mut krate: clean::Crate,
594603 access_levels : krate. access_levels . clone ( ) ,
595604 crate_version : krate. version . take ( ) ,
596605 orphan_impl_items : Vec :: new ( ) ,
606+ orphan_trait_impls : Vec :: new ( ) ,
597607 traits : mem:: replace ( & mut krate. external_traits , FxHashMap ( ) ) ,
598608 deref_trait_did,
599609 deref_mut_trait_did,
@@ -636,6 +646,14 @@ pub fn run(mut krate: clean::Crate,
636646 cache. stack . push ( krate. name . clone ( ) ) ;
637647 krate = cache. fold_crate ( krate) ;
638648
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+
639657 // Build our search index
640658 let index = build_index ( & krate, & mut cache) ;
641659
@@ -1224,7 +1242,7 @@ impl<'a> SourceCollector<'a> {
12241242impl DocFolder for Cache {
12251243 fn fold_item ( & mut self , item : clean:: Item ) -> Option < clean:: Item > {
12261244 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 ) ;
12281246 }
12291247
12301248 // If this is a stripped module,
@@ -1457,10 +1475,16 @@ impl DocFolder for Cache {
14571475 } else {
14581476 unreachable ! ( )
14591477 } ;
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) ) ;
14641488 }
14651489 None
14661490 } else {
0 commit comments