@@ -94,10 +94,7 @@ pub(crate) struct Cache {
9494
9595 // Private fields only used when initially crawling a crate to build a cache
9696 stack : Vec < Symbol > ,
97- parent_stack : Vec < DefId > ,
98- impl_generics_stack : Vec < ( clean:: Type , clean:: Generics ) > ,
99- parent_is_trait_impl : bool ,
100- parent_is_blanket_or_auto_impl : bool ,
97+ parent_stack : Vec < ParentStackItem > ,
10198 stripped_mod : bool ,
10299
103100 pub ( crate ) search_index : Vec < IndexItem > ,
@@ -263,7 +260,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
263260 let ( parent, is_inherent_impl_item) = match * item. kind {
264261 clean:: StrippedItem ( ..) => ( ( None , None ) , false ) ,
265262 clean:: AssocConstItem ( ..) | clean:: AssocTypeItem ( ..)
266- if self . cache . parent_is_trait_impl =>
263+ if self
264+ . cache
265+ . parent_stack
266+ . last ( )
267+ . map_or ( false , |parent| parent. is_trait_impl ( ) ) =>
267268 {
268269 // skip associated items in trait impls
269270 ( ( None , None ) , false )
@@ -274,7 +275,14 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
274275 | clean:: StructFieldItem ( ..)
275276 | clean:: VariantItem ( ..) => (
276277 (
277- Some ( * self . cache . parent_stack . last ( ) . expect ( "parent_stack is empty" ) ) ,
278+ Some (
279+ self . cache
280+ . parent_stack
281+ . last ( )
282+ . expect ( "parent_stack is empty" )
283+ . item_id ( )
284+ . expect_def_id ( ) ,
285+ ) ,
278286 Some ( & self . cache . stack [ ..self . cache . stack . len ( ) - 1 ] ) ,
279287 ) ,
280288 false ,
@@ -284,16 +292,19 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
284292 ( ( None , None ) , false )
285293 } else {
286294 let last = self . cache . parent_stack . last ( ) . expect ( "parent_stack is empty 2" ) ;
287- let did = * last;
288- let path = match self . cache . paths . get ( & did) {
295+ let did = match & * last {
296+ ParentStackItem :: Impl { for_, .. } => for_. def_id ( & self . cache ) ,
297+ ParentStackItem :: Type ( item_id) => item_id. as_def_id ( ) ,
298+ } ;
299+ let path = match did. and_then ( |did| self . cache . paths . get ( & did) ) {
289300 // The current stack not necessarily has correlation
290301 // for where the type was defined. On the other
291302 // hand, `paths` always has the right
292303 // information if present.
293304 Some ( & ( ref fqp, _) ) => Some ( & fqp[ ..fqp. len ( ) - 1 ] ) ,
294305 None => None ,
295306 } ;
296- ( ( Some ( * last ) , path) , true )
307+ ( ( did , path) , true )
297308 }
298309 }
299310 _ => ( ( None , Some ( & * self . cache . stack ) ) , false ) ,
@@ -320,8 +331,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
320331 search_type : get_function_type_for_search (
321332 & item,
322333 self . tcx ,
323- self . cache . impl_generics_stack . last ( ) ,
324- self . cache . parent_is_blanket_or_auto_impl ,
334+ clean_impl_generics ( self . cache . parent_stack . last ( ) ) . as_ref ( ) ,
325335 self . cache ,
326336 ) ,
327337 aliases : item. attrs . get_doc_aliases ( ) ,
@@ -331,11 +341,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
331341 ( Some ( parent) , None ) if is_inherent_impl_item => {
332342 // We have a parent, but we don't know where they're
333343 // defined yet. Wait for later to index this item.
344+ let impl_generics = clean_impl_generics ( self . cache . parent_stack . last ( ) ) ;
334345 self . cache . orphan_impl_items . push ( OrphanImplItem {
335346 parent,
336347 item : item. clone ( ) ,
337- impl_generics : self . cache . impl_generics_stack . last ( ) . cloned ( ) ,
338- parent_is_blanket_or_auto_impl : self . cache . parent_is_blanket_or_auto_impl ,
348+ impl_generics,
339349 } ) ;
340350 }
341351 _ => { }
@@ -411,72 +421,19 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
411421 }
412422 }
413423
414- // Maintain the parent stack
415- let orig_parent_is_trait_impl = self . cache . parent_is_trait_impl ;
416- let parent_pushed = match * item. kind {
424+ // Maintain the parent stack.
425+ let ( item, parent_pushed) = match * item. kind {
417426 clean:: TraitItem ( ..)
418427 | clean:: EnumItem ( ..)
419428 | clean:: ForeignTypeItem
420429 | clean:: StructItem ( ..)
421430 | clean:: UnionItem ( ..)
422- | clean:: VariantItem ( ..) => {
423- self . cache . parent_stack . push ( item. item_id . expect_def_id ( ) ) ;
424- self . cache . parent_is_trait_impl = false ;
425- true
426- }
427- clean:: ImplItem ( ref i) => {
428- self . cache . parent_is_trait_impl = i. trait_ . is_some ( ) ;
429- match i. for_ {
430- clean:: Type :: Path { ref path } => {
431- self . cache . parent_stack . push ( path. def_id ( ) ) ;
432- true
433- }
434- clean:: DynTrait ( ref bounds, _)
435- | clean:: BorrowedRef { type_ : box clean:: DynTrait ( ref bounds, _) , .. } => {
436- self . cache . parent_stack . push ( bounds[ 0 ] . trait_ . def_id ( ) ) ;
437- true
438- }
439- ref t => {
440- let prim_did = t
441- . primitive_type ( )
442- . and_then ( |t| self . cache . primitive_locations . get ( & t) . cloned ( ) ) ;
443- match prim_did {
444- Some ( did) => {
445- self . cache . parent_stack . push ( did) ;
446- true
447- }
448- None => false ,
449- }
450- }
451- }
452- }
453- _ => false ,
454- } ;
455-
456- // When recursing into an impl item, make the generics context visible
457- // to the child items.
458- let item = {
459- let mut item = item;
460- let mut old_parent_is_blanket_or_auto_impl = false ;
461- if let clean:: Item { kind : box clean:: ImplItem ( ref mut i) , .. } = item {
462- old_parent_is_blanket_or_auto_impl = mem:: replace (
463- & mut self . cache . parent_is_blanket_or_auto_impl ,
464- !matches ! ( i. kind, clean:: ImplKind :: Normal ) ,
465- ) ;
466- self . cache . impl_generics_stack . push ( (
467- mem:: replace ( & mut i. for_ , clean:: Type :: Infer ) ,
468- mem:: replace (
469- & mut i. generics ,
470- clean:: Generics { params : Vec :: new ( ) , where_predicates : Vec :: new ( ) } ,
471- ) ,
472- ) ) ;
473- }
474- let mut item = self . fold_item_recur ( item) ;
475- if let clean:: Item { kind : box clean:: ImplItem ( ref mut i) , .. } = item {
476- self . cache . parent_is_blanket_or_auto_impl = old_parent_is_blanket_or_auto_impl;
477- ( i. for_ , i. generics ) = self . cache . impl_generics_stack . pop ( ) . expect ( "pushed above" ) ;
431+ | clean:: VariantItem ( ..)
432+ | clean:: ImplItem ( ..) => {
433+ self . cache . parent_stack . push ( ParentStackItem :: new ( & item) ) ;
434+ ( self . fold_item_recur ( item) , true )
478435 }
479- item
436+ _ => ( self . fold_item_recur ( item) , false ) ,
480437 } ;
481438
482439 // Once we've recursively found all the generics, hoard off all the
@@ -549,7 +506,6 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
549506 self . cache . parent_stack . pop ( ) . expect ( "parent stack already empty" ) ;
550507 }
551508 self . cache . stripped_mod = orig_stripped_mod;
552- self . cache . parent_is_trait_impl = orig_parent_is_trait_impl;
553509 ret
554510 }
555511}
@@ -558,5 +514,56 @@ pub(crate) struct OrphanImplItem {
558514 pub ( crate ) parent : DefId ,
559515 pub ( crate ) item : clean:: Item ,
560516 pub ( crate ) impl_generics : Option < ( clean:: Type , clean:: Generics ) > ,
561- pub ( crate ) parent_is_blanket_or_auto_impl : bool ,
517+ }
518+
519+ /// Information about trait and type parents is tracked while traversing the item tree to build
520+ /// the cache.
521+ ///
522+ /// We don't just store `Item` in there, because `Item` contains the list of children being
523+ /// traversed and it would be wasteful to clone all that. We also need the item id, so just
524+ /// storing `ItemKind` won't work, either.
525+ enum ParentStackItem {
526+ Impl {
527+ for_ : clean:: Type ,
528+ trait_ : Option < clean:: Path > ,
529+ generics : clean:: Generics ,
530+ kind : clean:: ImplKind ,
531+ item_id : ItemId ,
532+ } ,
533+ Type ( ItemId ) ,
534+ }
535+
536+ impl ParentStackItem {
537+ fn new ( item : & clean:: Item ) -> Self {
538+ match & * item. kind {
539+ clean:: ItemKind :: ImplItem ( clean:: Impl { for_, trait_, generics, kind, .. } ) => {
540+ ParentStackItem :: Impl {
541+ for_ : for_. clone ( ) ,
542+ trait_ : trait_. clone ( ) ,
543+ generics : generics. clone ( ) ,
544+ kind : kind. clone ( ) ,
545+ item_id : item. item_id ,
546+ }
547+ }
548+ _ => ParentStackItem :: Type ( item. item_id ) ,
549+ }
550+ }
551+ fn is_trait_impl ( & self ) -> bool {
552+ matches ! ( self , ParentStackItem :: Impl { trait_: Some ( ..) , .. } )
553+ }
554+ fn item_id ( & self ) -> ItemId {
555+ match self {
556+ ParentStackItem :: Impl { item_id, .. } => * item_id,
557+ ParentStackItem :: Type ( item_id) => * item_id,
558+ }
559+ }
560+ }
561+
562+ fn clean_impl_generics ( item : Option < & ParentStackItem > ) -> Option < ( clean:: Type , clean:: Generics ) > {
563+ if let Some ( ParentStackItem :: Impl { for_, generics, kind : clean:: ImplKind :: Normal , .. } ) = item
564+ {
565+ Some ( ( for_. clone ( ) , generics. clone ( ) ) )
566+ } else {
567+ None
568+ }
562569}
0 commit comments