@@ -260,153 +260,21 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
260
260
}
261
261
262
262
// Index this method for searching later on.
263
- if let Some ( s) = item. name . or_else ( || {
264
- if item. is_stripped ( ) {
265
- None
266
- } else if let clean:: ImportItem ( ref i) = * item. kind
267
- && let clean:: ImportKind :: Simple ( s) = i. kind
268
- {
269
- Some ( s)
270
- } else {
271
- None
272
- }
273
- } ) {
274
- let ( parent, is_inherent_impl_item) = match * item. kind {
275
- clean:: StrippedItem ( ..) => ( ( None , None ) , false ) ,
276
- clean:: AssocConstItem ( ..) | clean:: AssocTypeItem ( ..)
277
- if self
278
- . cache
279
- . parent_stack
280
- . last ( )
281
- . is_some_and ( |parent| parent. is_trait_impl ( ) ) =>
263
+ let search_name = if !item. is_stripped ( ) {
264
+ item. name . or_else ( || {
265
+ if let clean:: ImportItem ( ref i) = * item. kind
266
+ && let clean:: ImportKind :: Simple ( s) = i. kind
282
267
{
283
- // skip associated items in trait impls
284
- ( ( None , None ) , false )
285
- }
286
- clean:: TyMethodItem ( ..)
287
- | clean:: TyAssocConstItem ( ..)
288
- | clean:: TyAssocTypeItem ( ..)
289
- | clean:: StructFieldItem ( ..)
290
- | clean:: VariantItem ( ..) => (
291
- (
292
- Some (
293
- self . cache
294
- . parent_stack
295
- . last ( )
296
- . expect ( "parent_stack is empty" )
297
- . item_id ( )
298
- . expect_def_id ( ) ,
299
- ) ,
300
- Some ( & self . cache . stack [ ..self . cache . stack . len ( ) - 1 ] ) ,
301
- ) ,
302
- false ,
303
- ) ,
304
- clean:: MethodItem ( ..) | clean:: AssocConstItem ( ..) | clean:: AssocTypeItem ( ..) => {
305
- if self . cache . parent_stack . is_empty ( ) {
306
- ( ( None , None ) , false )
307
- } else {
308
- let last = self . cache . parent_stack . last ( ) . expect ( "parent_stack is empty 2" ) ;
309
- let did = match & * last {
310
- ParentStackItem :: Impl {
311
- // impl Trait for &T { fn method(self); }
312
- //
313
- // When generating a function index with the above shape, we want it
314
- // associated with `T`, not with the primitive reference type. It should
315
- // show up as `T::method`, rather than `reference::method`, in the search
316
- // results page.
317
- for_ : clean:: Type :: BorrowedRef { type_, .. } ,
318
- ..
319
- } => type_. def_id ( & self . cache ) ,
320
- ParentStackItem :: Impl { for_, .. } => for_. def_id ( & self . cache ) ,
321
- ParentStackItem :: Type ( item_id) => item_id. as_def_id ( ) ,
322
- } ;
323
- let path = did
324
- . and_then ( |did| self . cache . paths . get ( & did) )
325
- // The current stack not necessarily has correlation
326
- // for where the type was defined. On the other
327
- // hand, `paths` always has the right
328
- // information if present.
329
- . map ( |( fqp, _) | & fqp[ ..fqp. len ( ) - 1 ] ) ;
330
- ( ( did, path) , true )
331
- }
332
- }
333
- _ => ( ( None , Some ( & * self . cache . stack ) ) , false ) ,
334
- } ;
335
-
336
- match parent {
337
- ( parent, Some ( path) ) if is_inherent_impl_item || !self . cache . stripped_mod => {
338
- debug_assert ! ( !item. is_stripped( ) ) ;
339
-
340
- // A crate has a module at its root, containing all items,
341
- // which should not be indexed. The crate-item itself is
342
- // inserted later on when serializing the search-index.
343
- if item. item_id . as_def_id ( ) . is_some_and ( |idx| !idx. is_crate_root ( ) )
344
- && let ty = item. type_ ( )
345
- && ( ty != ItemType :: StructField
346
- || u16:: from_str_radix ( s. as_str ( ) , 10 ) . is_err ( ) )
347
- {
348
- let desc =
349
- short_markdown_summary ( & item. doc_value ( ) , & item. link_names ( self . cache ) ) ;
350
- // For searching purposes, a re-export is a duplicate if:
351
- //
352
- // - It's either an inline, or a true re-export
353
- // - It's got the same name
354
- // - Both of them have the same exact path
355
- let defid = ( match & * item. kind {
356
- & clean:: ItemKind :: ImportItem ( ref import) => import. source . did ,
357
- _ => None ,
358
- } )
359
- . or_else ( || item. item_id . as_def_id ( ) ) ;
360
- // In case this is a field from a tuple struct, we don't add it into
361
- // the search index because its name is something like "0", which is
362
- // not useful for rustdoc search.
363
- self . cache . search_index . push ( IndexItem {
364
- ty,
365
- defid,
366
- name : s,
367
- path : join_with_double_colon ( path) ,
368
- desc,
369
- parent,
370
- parent_idx : None ,
371
- exact_path : None ,
372
- impl_id : if let Some ( ParentStackItem :: Impl { item_id, .. } ) =
373
- self . cache . parent_stack . last ( )
374
- {
375
- item_id. as_def_id ( )
376
- } else {
377
- None
378
- } ,
379
- search_type : get_function_type_for_search (
380
- & item,
381
- self . tcx ,
382
- clean_impl_generics ( self . cache . parent_stack . last ( ) ) . as_ref ( ) ,
383
- parent,
384
- self . cache ,
385
- ) ,
386
- aliases : item. attrs . get_doc_aliases ( ) ,
387
- deprecation : item. deprecation ( self . tcx ) ,
388
- } ) ;
389
- }
390
- }
391
- ( Some ( parent) , None ) if is_inherent_impl_item => {
392
- // We have a parent, but we don't know where they're
393
- // defined yet. Wait for later to index this item.
394
- let impl_generics = clean_impl_generics ( self . cache . parent_stack . last ( ) ) ;
395
- self . cache . orphan_impl_items . push ( OrphanImplItem {
396
- parent,
397
- item : item. clone ( ) ,
398
- impl_generics,
399
- impl_id : if let Some ( ParentStackItem :: Impl { item_id, .. } ) =
400
- self . cache . parent_stack . last ( )
401
- {
402
- item_id. as_def_id ( )
403
- } else {
404
- None
405
- } ,
406
- } ) ;
268
+ Some ( s)
269
+ } else {
270
+ None
407
271
}
408
- _ => { }
409
- }
272
+ } )
273
+ } else {
274
+ None
275
+ } ;
276
+ if let Some ( name) = search_name {
277
+ add_item_to_search_index ( self . tcx , & mut self . cache , & item, name)
410
278
}
411
279
412
280
// Keep track of the fully qualified path for this item.
@@ -572,6 +440,152 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
572
440
}
573
441
}
574
442
443
+ fn add_item_to_search_index ( tcx : TyCtxt < ' _ > , cache : & mut Cache , item : & clean:: Item , name : Symbol ) {
444
+ // Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl).
445
+ let item_def_id = item. item_id . as_def_id ( ) . unwrap ( ) ;
446
+ let ( parent_did, parent_path) = match * item. kind {
447
+ clean:: StrippedItem ( ..) => return ,
448
+ clean:: AssocConstItem ( ..) | clean:: AssocTypeItem ( ..)
449
+ if cache. parent_stack . last ( ) . is_some_and ( |parent| parent. is_trait_impl ( ) ) =>
450
+ {
451
+ // skip associated items in trait impls
452
+ return ;
453
+ }
454
+ clean:: TyMethodItem ( ..)
455
+ | clean:: TyAssocConstItem ( ..)
456
+ | clean:: TyAssocTypeItem ( ..)
457
+ | clean:: StructFieldItem ( ..)
458
+ | clean:: VariantItem ( ..) => {
459
+ // Don't index if containing module is stripped (i.e., private),
460
+ // or if item is tuple struct/variant field (name is a number -> not useful for search).
461
+ if cache. stripped_mod
462
+ || item. type_ ( ) == ItemType :: StructField
463
+ && name. as_str ( ) . chars ( ) . all ( |c| c. is_digit ( 10 ) )
464
+ {
465
+ return ;
466
+ }
467
+ let parent_did =
468
+ cache. parent_stack . last ( ) . expect ( "parent_stack is empty" ) . item_id ( ) . expect_def_id ( ) ;
469
+ let parent_path = & cache. stack [ ..cache. stack . len ( ) - 1 ] ;
470
+ ( Some ( parent_did) , parent_path)
471
+ }
472
+ clean:: MethodItem ( ..) | clean:: AssocConstItem ( ..) | clean:: AssocTypeItem ( ..) => {
473
+ let last = cache. parent_stack . last ( ) . expect ( "parent_stack is empty 2" ) ;
474
+ let parent_did = match & * last {
475
+ // impl Trait for &T { fn method(self); }
476
+ //
477
+ // When generating a function index with the above shape, we want it
478
+ // associated with `T`, not with the primitive reference type. It should
479
+ // show up as `T::method`, rather than `reference::method`, in the search
480
+ // results page.
481
+ ParentStackItem :: Impl { for_ : clean:: Type :: BorrowedRef { type_, .. } , .. } => {
482
+ type_. def_id ( & cache)
483
+ }
484
+ ParentStackItem :: Impl { for_, .. } => for_. def_id ( & cache) ,
485
+ ParentStackItem :: Type ( item_id) => item_id. as_def_id ( ) ,
486
+ } ;
487
+ let Some ( parent_did) = parent_did else { return } ;
488
+ // The current stack reflects the CacheBuilder's recursive
489
+ // walk over HIR. For associated items, this is the module
490
+ // where the `impl` block is defined. That's an implementation
491
+ // detail that we don't want to affect the search engine.
492
+ //
493
+ // In particular, you can arrange things like this:
494
+ //
495
+ // #![crate_name="me"]
496
+ // mod private_mod {
497
+ // impl Clone for MyThing { fn clone(&self) -> MyThing { MyThing } }
498
+ // }
499
+ // pub struct MyThing;
500
+ //
501
+ // When that happens, we need to:
502
+ // - ignore the `cache.stripped_mod` flag, since the Clone impl is actually
503
+ // part of the public API even though it's defined in a private module
504
+ // - present the method as `me::MyThing::clone`, its publicly-visible path
505
+ // - deal with the fact that the recursive walk hasn't actually reached `MyThing`
506
+ // until it's already past `private_mod`, since that's first, and doesn't know
507
+ // yet if `MyThing` will actually be public or not (it could be re-exported)
508
+ //
509
+ // We accomplish the last two points by recording children of "orphan impls"
510
+ // in a field of the cache whose elements are added to the search index later,
511
+ // after cache building is complete (see `handle_orphan_impl_child`).
512
+ match cache. paths . get ( & parent_did) {
513
+ Some ( ( fqp, _) ) => ( Some ( parent_did) , & fqp[ ..fqp. len ( ) - 1 ] ) ,
514
+ None => {
515
+ handle_orphan_impl_child ( cache, item, parent_did) ;
516
+ return ;
517
+ }
518
+ }
519
+ }
520
+ _ => {
521
+ // Don't index if item is crate root, which is inserted later on when serializing the index.
522
+ // Don't index if containing module is stripped (i.e., private),
523
+ if item_def_id. is_crate_root ( ) || cache. stripped_mod {
524
+ return ;
525
+ }
526
+ ( None , & * cache. stack )
527
+ }
528
+ } ;
529
+
530
+ debug_assert ! ( !item. is_stripped( ) ) ;
531
+
532
+ let desc = short_markdown_summary ( & item. doc_value ( ) , & item. link_names ( cache) ) ;
533
+ // For searching purposes, a re-export is a duplicate if:
534
+ //
535
+ // - It's either an inline, or a true re-export
536
+ // - It's got the same name
537
+ // - Both of them have the same exact path
538
+ let defid = match & * item. kind {
539
+ clean:: ItemKind :: ImportItem ( import) => import. source . did . unwrap_or ( item_def_id) ,
540
+ _ => item_def_id,
541
+ } ;
542
+ let path = join_with_double_colon ( parent_path) ;
543
+ let impl_id = if let Some ( ParentStackItem :: Impl { item_id, .. } ) = cache. parent_stack . last ( ) {
544
+ item_id. as_def_id ( )
545
+ } else {
546
+ None
547
+ } ;
548
+ let search_type = get_function_type_for_search (
549
+ & item,
550
+ tcx,
551
+ clean_impl_generics ( cache. parent_stack . last ( ) ) . as_ref ( ) ,
552
+ parent_did,
553
+ cache,
554
+ ) ;
555
+ let aliases = item. attrs . get_doc_aliases ( ) ;
556
+ let deprecation = item. deprecation ( tcx) ;
557
+ let index_item = IndexItem {
558
+ ty : item. type_ ( ) ,
559
+ defid : Some ( defid) ,
560
+ name,
561
+ path,
562
+ desc,
563
+ parent : parent_did,
564
+ parent_idx : None ,
565
+ exact_path : None ,
566
+ impl_id,
567
+ search_type,
568
+ aliases,
569
+ deprecation,
570
+ } ;
571
+ cache. search_index . push ( index_item) ;
572
+ }
573
+
574
+ /// We have a parent, but we don't know where they're
575
+ /// defined yet. Wait for later to index this item.
576
+ /// See [`Cache::orphan_impl_items`].
577
+ fn handle_orphan_impl_child ( cache : & mut Cache , item : & clean:: Item , parent_did : DefId ) {
578
+ let impl_generics = clean_impl_generics ( cache. parent_stack . last ( ) ) ;
579
+ let impl_id = if let Some ( ParentStackItem :: Impl { item_id, .. } ) = cache. parent_stack . last ( ) {
580
+ item_id. as_def_id ( )
581
+ } else {
582
+ None
583
+ } ;
584
+ let orphan_item =
585
+ OrphanImplItem { parent : parent_did, item : item. clone ( ) , impl_generics, impl_id } ;
586
+ cache. orphan_impl_items . push ( orphan_item) ;
587
+ }
588
+
575
589
pub ( crate ) struct OrphanImplItem {
576
590
pub ( crate ) parent : DefId ,
577
591
pub ( crate ) impl_id : Option < DefId > ,
0 commit comments