@@ -49,6 +49,10 @@ pub(crate) struct Context<'tcx> {
49
49
/// Current hierarchy of components leading down to what's currently being
50
50
/// rendered
51
51
pub ( crate ) current : Vec < Symbol > ,
52
+ /// Set of visible DefIds in the current module.
53
+ /// This generates optimal link hrefs in the common case when
54
+ /// an entire module is glob-inlined and its children link to each other.
55
+ pub ( crate ) current_module_linkable_items : DefIdMap < ( ItemType , Symbol ) > ,
52
56
/// The current destination folder of where HTML artifacts should be placed.
53
57
/// This changes as the context descends into the module hierarchy.
54
58
pub ( crate ) dst : PathBuf ,
@@ -79,7 +83,7 @@ pub(crate) struct Context<'tcx> {
79
83
80
84
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
81
85
#[ cfg( all( not( windows) , target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
82
- rustc_data_structures:: static_assert_size!( Context <' _>, 160 ) ;
86
+ rustc_data_structures:: static_assert_size!( Context <' _>, 192 ) ;
83
87
84
88
/// Shared mutable state used in [`Context`] and elsewhere.
85
89
pub ( crate ) struct SharedContext < ' tcx > {
@@ -559,6 +563,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
559
563
560
564
let mut cx = Context {
561
565
current : Vec :: new ( ) ,
566
+ current_module_linkable_items : Default :: default ( ) ,
562
567
dst,
563
568
render_redirect_pages : false ,
564
569
id_map,
@@ -589,6 +594,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
589
594
fn make_child_renderer ( & self ) -> Self {
590
595
Self {
591
596
current : self . current . clone ( ) ,
597
+ current_module_linkable_items : self . current_module_linkable_items . clone ( ) ,
592
598
dst : self . dst . clone ( ) ,
593
599
render_redirect_pages : self . render_redirect_pages ,
594
600
deref_id_map : Default :: default ( ) ,
@@ -783,8 +789,29 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
783
789
info ! ( "Recursing into {}" , self . dst. display( ) ) ;
784
790
785
791
if !item. is_stripped ( ) {
792
+ // Populate a list of items that are directly in the module
793
+ // or inlined into it.
794
+ // When an intra-doc link or named type needs linked,
795
+ // these are preferred over more distant paths.
796
+ let ( clean:: StrippedItem ( box clean:: ModuleItem ( ref module) )
797
+ | clean:: ModuleItem ( ref module) ) = * item. kind
798
+ else {
799
+ unreachable ! ( )
800
+ } ;
801
+ self . current_module_linkable_items = Default :: default ( ) ;
802
+ for item in & module. items {
803
+ if item. is_stripped ( ) {
804
+ continue ;
805
+ }
806
+ if let Some ( def_id) = item. def_id ( )
807
+ && let Some ( name) = item. name
808
+ {
809
+ self . current_module_linkable_items . insert ( def_id, ( item. type_ ( ) , name) ) ;
810
+ }
811
+ }
812
+ // Render the current module to HTML.
813
+ // Buf will be empty if the module is stripped and there is no redirect for it.
786
814
let buf = self . render_item ( item, true ) ;
787
- // buf will be empty if the module is stripped and there is no redirect for it
788
815
if !buf. is_empty ( ) {
789
816
self . shared . ensure_dir ( & self . dst ) ?;
790
817
let joint_dst = self . dst . join ( "index.html" ) ;
0 commit comments