@@ -94,8 +94,7 @@ pub(crate) struct Cache {
94
94
95
95
// Private fields only used when initially crawling a crate to build a cache
96
96
stack : Vec < Symbol > ,
97
- parent_stack : Vec < DefId > ,
98
- parent_is_trait_impl : bool ,
97
+ parent_stack : Vec < ParentStackItem > ,
99
98
stripped_mod : bool ,
100
99
101
100
pub ( crate ) search_index : Vec < IndexItem > ,
@@ -105,7 +104,7 @@ pub(crate) struct Cache {
105
104
// then the fully qualified name of the structure isn't presented in `paths`
106
105
// yet when its implementation methods are being indexed. Caches such methods
107
106
// and their parent id here and indexes them at the end of crate parsing.
108
- pub ( crate ) orphan_impl_items : Vec < ( DefId , clean :: Item ) > ,
107
+ pub ( crate ) orphan_impl_items : Vec < OrphanImplItem > ,
109
108
110
109
// Similarly to `orphan_impl_items`, sometimes trait impls are picked up
111
110
// even though the trait itself is not exported. This can happen if a trait
@@ -261,7 +260,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
261
260
let ( parent, is_inherent_impl_item) = match * item. kind {
262
261
clean:: StrippedItem ( ..) => ( ( None , None ) , false ) ,
263
262
clean:: AssocConstItem ( ..) | clean:: AssocTypeItem ( ..)
264
- 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 ( ) ) =>
265
268
{
266
269
// skip associated items in trait impls
267
270
( ( None , None ) , false )
@@ -272,7 +275,14 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
272
275
| clean:: StructFieldItem ( ..)
273
276
| clean:: VariantItem ( ..) => (
274
277
(
275
- 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
+ ) ,
276
286
Some ( & self . cache . stack [ ..self . cache . stack . len ( ) - 1 ] ) ,
277
287
) ,
278
288
false ,
@@ -282,16 +292,19 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
282
292
( ( None , None ) , false )
283
293
} else {
284
294
let last = self . cache . parent_stack . last ( ) . expect ( "parent_stack is empty 2" ) ;
285
- let did = * last;
286
- 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) ) {
287
300
// The current stack not necessarily has correlation
288
301
// for where the type was defined. On the other
289
302
// hand, `paths` always has the right
290
303
// information if present.
291
304
Some ( & ( ref fqp, _) ) => Some ( & fqp[ ..fqp. len ( ) - 1 ] ) ,
292
305
None => None ,
293
306
} ;
294
- ( ( Some ( * last ) , path) , true )
307
+ ( ( did , path) , true )
295
308
}
296
309
}
297
310
_ => ( ( None , Some ( & * self . cache . stack ) ) , false ) ,
@@ -315,15 +328,25 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
315
328
desc,
316
329
parent,
317
330
parent_idx : None ,
318
- search_type : get_function_type_for_search ( & item, self . tcx , self . cache ) ,
331
+ search_type : get_function_type_for_search (
332
+ & item,
333
+ self . tcx ,
334
+ clean_impl_generics ( self . cache . parent_stack . last ( ) ) . as_ref ( ) ,
335
+ self . cache ,
336
+ ) ,
319
337
aliases : item. attrs . get_doc_aliases ( ) ,
320
338
} ) ;
321
339
}
322
340
}
323
341
( Some ( parent) , None ) if is_inherent_impl_item => {
324
342
// We have a parent, but we don't know where they're
325
343
// defined yet. Wait for later to index this item.
326
- self . cache . orphan_impl_items . push ( ( parent, item. clone ( ) ) ) ;
344
+ let impl_generics = clean_impl_generics ( self . cache . parent_stack . last ( ) ) ;
345
+ self . cache . orphan_impl_items . push ( OrphanImplItem {
346
+ parent,
347
+ item : item. clone ( ) ,
348
+ impl_generics,
349
+ } ) ;
327
350
}
328
351
_ => { }
329
352
}
@@ -398,51 +421,23 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
398
421
}
399
422
}
400
423
401
- // Maintain the parent stack
402
- let orig_parent_is_trait_impl = self . cache . parent_is_trait_impl ;
403
- let parent_pushed = match * item. kind {
424
+ // Maintain the parent stack.
425
+ let ( item, parent_pushed) = match * item. kind {
404
426
clean:: TraitItem ( ..)
405
427
| clean:: EnumItem ( ..)
406
428
| clean:: ForeignTypeItem
407
429
| clean:: StructItem ( ..)
408
430
| clean:: UnionItem ( ..)
409
- | clean:: VariantItem ( ..) => {
410
- self . cache . parent_stack . push ( item. item_id . expect_def_id ( ) ) ;
411
- self . cache . parent_is_trait_impl = false ;
412
- true
413
- }
414
- clean:: ImplItem ( ref i) => {
415
- self . cache . parent_is_trait_impl = i. trait_ . is_some ( ) ;
416
- match i. for_ {
417
- clean:: Type :: Path { ref path } => {
418
- self . cache . parent_stack . push ( path. def_id ( ) ) ;
419
- true
420
- }
421
- clean:: DynTrait ( ref bounds, _)
422
- | clean:: BorrowedRef { type_ : box clean:: DynTrait ( ref bounds, _) , .. } => {
423
- self . cache . parent_stack . push ( bounds[ 0 ] . trait_ . def_id ( ) ) ;
424
- true
425
- }
426
- ref t => {
427
- let prim_did = t
428
- . primitive_type ( )
429
- . and_then ( |t| self . cache . primitive_locations . get ( & t) . cloned ( ) ) ;
430
- match prim_did {
431
- Some ( did) => {
432
- self . cache . parent_stack . push ( did) ;
433
- true
434
- }
435
- None => false ,
436
- }
437
- }
438
- }
431
+ | clean:: VariantItem ( ..)
432
+ | clean:: ImplItem ( ..) => {
433
+ self . cache . parent_stack . push ( ParentStackItem :: new ( & item) ) ;
434
+ ( self . fold_item_recur ( item) , true )
439
435
}
440
- _ => false ,
436
+ _ => ( self . fold_item_recur ( item ) , false ) ,
441
437
} ;
442
438
443
439
// Once we've recursively found all the generics, hoard off all the
444
440
// implementations elsewhere.
445
- let item = self . fold_item_recur ( item) ;
446
441
let ret = if let clean:: Item { kind : box clean:: ImplItem ( ref i) , .. } = item {
447
442
// Figure out the id of this impl. This may map to a
448
443
// primitive rather than always to a struct/enum.
@@ -511,7 +506,64 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
511
506
self . cache . parent_stack . pop ( ) . expect ( "parent stack already empty" ) ;
512
507
}
513
508
self . cache . stripped_mod = orig_stripped_mod;
514
- self . cache . parent_is_trait_impl = orig_parent_is_trait_impl;
515
509
ret
516
510
}
517
511
}
512
+
513
+ pub ( crate ) struct OrphanImplItem {
514
+ pub ( crate ) parent : DefId ,
515
+ pub ( crate ) item : clean:: Item ,
516
+ pub ( crate ) impl_generics : Option < ( clean:: Type , clean:: Generics ) > ,
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
+ }
569
+ }
0 commit comments