@@ -3,8 +3,7 @@ use std::collections::BTreeMap;
3
3
use std:: io;
4
4
use std:: path:: PathBuf ;
5
5
use std:: rc:: Rc ;
6
- use std:: sync:: mpsc:: { channel, Receiver } ;
7
- use std:: sync:: Arc ;
6
+ use std:: sync:: mpsc:: channel;
8
7
9
8
use rustc_data_structures:: fx:: FxHashMap ;
10
9
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
@@ -41,35 +40,44 @@ use crate::html::{layout, sources};
41
40
/// It is intended that this context is a lightweight object which can be fairly
42
41
/// easily cloned because it is cloned per work-job (about once per item in the
43
42
/// rustdoc tree).
44
- #[ derive( Clone ) ]
45
43
crate struct Context < ' tcx > {
46
44
/// Current hierarchy of components leading down to what's currently being
47
45
/// rendered
48
- crate current : Vec < String > ,
46
+ pub ( super ) current : Vec < String > ,
49
47
/// The current destination folder of where HTML artifacts should be placed.
50
48
/// This changes as the context descends into the module hierarchy.
51
- crate dst : PathBuf ,
49
+ pub ( super ) dst : PathBuf ,
52
50
/// A flag, which when `true`, will render pages which redirect to the
53
51
/// real location of an item. This is used to allow external links to
54
52
/// publicly reused items to redirect to the right location.
55
- crate render_redirect_pages : bool ,
56
- /// `None` by default, depends on the `generate-redirect-map` option flag. If this field is set
57
- /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of
58
- /// the crate.
59
- crate redirections : Option < Rc < RefCell < FxHashMap < String , String > > > > ,
53
+ pub ( super ) render_redirect_pages : bool ,
60
54
/// The map used to ensure all generated 'id=' attributes are unique.
61
- pub ( super ) id_map : Rc < RefCell < IdMap > > ,
55
+ pub ( super ) id_map : RefCell < IdMap > ,
62
56
/// Tracks section IDs for `Deref` targets so they match in both the main
63
57
/// body and the sidebar.
64
- pub ( super ) deref_id_map : Rc < RefCell < FxHashMap < DefId , String > > > ,
65
- crate shared : Arc < SharedContext < ' tcx > > ,
66
- all : Rc < RefCell < AllTypes > > ,
67
- /// Storage for the errors produced while generating documentation so they
68
- /// can be printed together at the end.
69
- crate errors : Rc < Receiver < String > > ,
70
- crate cache : Rc < Cache > ,
58
+ pub ( super ) deref_id_map : RefCell < FxHashMap < DefId , String > > ,
59
+ /// Shared mutable state.
60
+ ///
61
+ /// Issue for improving the situation: [#82381][]
62
+ ///
63
+ /// [#82381]: https://github.com/rust-lang/rust/issues/82381
64
+ pub ( super ) shared : Rc < SharedContext < ' tcx > > ,
65
+ /// The [`Cache`] used during rendering.
66
+ ///
67
+ /// Ideally the cache would be in [`SharedContext`], but it's mutated
68
+ /// between when the `SharedContext` is created and when `Context`
69
+ /// is created, so more refactoring would be needed.
70
+ ///
71
+ /// It's immutable once in `Context`, so it's not as bad that it's not in
72
+ /// `SharedContext`.
73
+ // FIXME: move `cache` to `SharedContext`
74
+ pub ( super ) cache : Rc < Cache > ,
71
75
}
72
76
77
+ // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
78
+ #[ cfg( target_arch = "x86_64" ) ]
79
+ rustc_data_structures:: static_assert_size!( Context <' _>, 152 ) ;
80
+
73
81
impl < ' tcx > Context < ' tcx > {
74
82
pub ( super ) fn path ( & self , filename : & str ) -> PathBuf {
75
83
// We use splitn vs Path::extension here because we might get a filename
@@ -148,11 +156,6 @@ impl<'tcx> Context<'tcx> {
148
156
static_extra_scripts : & [ ] ,
149
157
} ;
150
158
151
- {
152
- self . id_map . borrow_mut ( ) . reset ( ) ;
153
- self . id_map . borrow_mut ( ) . populate ( & INITIAL_IDS ) ;
154
- }
155
-
156
159
if !self . render_redirect_pages {
157
160
layout:: render (
158
161
& self . shared . layout ,
@@ -169,7 +172,7 @@ impl<'tcx> Context<'tcx> {
169
172
path. push ( '/' ) ;
170
173
}
171
174
path. push_str ( & item_path ( ty, names. last ( ) . unwrap ( ) ) ) ;
172
- match self . redirections {
175
+ match self . shared . redirections {
173
176
Some ( ref redirections) => {
174
177
let mut current_path = String :: new ( ) ;
175
178
for name in & self . current {
@@ -383,6 +386,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
383
386
edition,
384
387
codes : ErrorCodes :: from ( unstable_features. is_nightly_build ( ) ) ,
385
388
playground,
389
+ all : RefCell :: new ( AllTypes :: new ( ) ) ,
390
+ errors : receiver,
391
+ redirections : if generate_redirect_map { Some ( Default :: default ( ) ) } else { None } ,
386
392
} ;
387
393
388
394
// Add the default themes to the `Vec` of stylepaths
@@ -409,24 +415,36 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
409
415
current : Vec :: new ( ) ,
410
416
dst,
411
417
render_redirect_pages : false ,
412
- id_map : Rc :: new ( RefCell :: new ( id_map) ) ,
413
- deref_id_map : Rc :: new ( RefCell :: new ( FxHashMap :: default ( ) ) ) ,
414
- shared : Arc :: new ( scx) ,
415
- all : Rc :: new ( RefCell :: new ( AllTypes :: new ( ) ) ) ,
416
- errors : Rc :: new ( receiver) ,
418
+ id_map : RefCell :: new ( id_map) ,
419
+ deref_id_map : RefCell :: new ( FxHashMap :: default ( ) ) ,
420
+ shared : Rc :: new ( scx) ,
417
421
cache : Rc :: new ( cache) ,
418
- redirections : if generate_redirect_map { Some ( Default :: default ( ) ) } else { None } ,
419
422
} ;
420
423
421
424
CURRENT_DEPTH . with ( |s| s. set ( 0 ) ) ;
422
425
423
426
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
424
- Arc :: get_mut ( & mut cx. shared ) . unwrap ( ) . fs . set_sync_only ( true ) ;
427
+ Rc :: get_mut ( & mut cx. shared ) . unwrap ( ) . fs . set_sync_only ( true ) ;
425
428
write_shared ( & cx, & krate, index, & md_opts) ?;
426
- Arc :: get_mut ( & mut cx. shared ) . unwrap ( ) . fs . set_sync_only ( false ) ;
429
+ Rc :: get_mut ( & mut cx. shared ) . unwrap ( ) . fs . set_sync_only ( false ) ;
427
430
Ok ( ( cx, krate) )
428
431
}
429
432
433
+ fn make_child_renderer ( & self ) -> Self {
434
+ let mut id_map = IdMap :: new ( ) ;
435
+ id_map. populate ( & INITIAL_IDS ) ;
436
+
437
+ Self {
438
+ current : self . current . clone ( ) ,
439
+ dst : self . dst . clone ( ) ,
440
+ render_redirect_pages : self . render_redirect_pages ,
441
+ id_map : RefCell :: new ( id_map) ,
442
+ deref_id_map : RefCell :: new ( FxHashMap :: default ( ) ) ,
443
+ shared : Rc :: clone ( & self . shared ) ,
444
+ cache : Rc :: clone ( & self . cache ) ,
445
+ }
446
+ }
447
+
430
448
fn after_krate (
431
449
& mut self ,
432
450
krate : & clean:: Crate ,
@@ -464,7 +482,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
464
482
} else {
465
483
String :: new ( )
466
484
} ;
467
- let all = self . all . replace ( AllTypes :: new ( ) ) ;
485
+ let all = self . shared . all . replace ( AllTypes :: new ( ) ) ;
468
486
let v = layout:: render (
469
487
& self . shared . layout ,
470
488
& page,
@@ -494,7 +512,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
494
512
& style_files,
495
513
) ;
496
514
self . shared . fs . write ( & settings_file, v. as_bytes ( ) ) ?;
497
- if let Some ( redirections) = self . redirections . take ( ) {
515
+ if let Some ( ref redirections) = self . shared . redirections {
498
516
if !redirections. borrow ( ) . is_empty ( ) {
499
517
let redirect_map_path =
500
518
self . dst . join ( & * krate. name . as_str ( ) ) . join ( "redirect-map.json" ) ;
@@ -505,8 +523,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
505
523
}
506
524
507
525
// Flush pending errors.
508
- Arc :: get_mut ( & mut self . shared ) . unwrap ( ) . fs . close ( ) ;
509
- let nb_errors = self . errors . iter ( ) . map ( |err| diag. struct_err ( & err) . emit ( ) ) . count ( ) ;
526
+ Rc :: get_mut ( & mut self . shared ) . unwrap ( ) . fs . close ( ) ;
527
+ let nb_errors = self . shared . errors . iter ( ) . map ( |err| diag. struct_err ( & err) . emit ( ) ) . count ( ) ;
510
528
if nb_errors > 0 {
511
529
Err ( Error :: new ( io:: Error :: new ( io:: ErrorKind :: Other , "I/O error" ) , "" ) )
512
530
} else {
@@ -585,13 +603,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
585
603
self . shared . fs . write ( & joint_dst, buf. as_bytes ( ) ) ?;
586
604
587
605
if !self . render_redirect_pages {
588
- self . all . borrow_mut ( ) . append ( full_path ( self , & item) , & item_type) ;
606
+ self . shared . all . borrow_mut ( ) . append ( full_path ( self , & item) , & item_type) ;
589
607
}
590
608
// If the item is a macro, redirect from the old macro URL (with !)
591
609
// to the new one (without).
592
610
if item_type == ItemType :: Macro {
593
611
let redir_name = format ! ( "{}.{}!.html" , item_type, name) ;
594
- if let Some ( ref redirections) = self . redirections {
612
+ if let Some ( ref redirections) = self . shared . redirections {
595
613
let crate_name = & self . shared . layout . krate ;
596
614
redirections. borrow_mut ( ) . insert (
597
615
format ! ( "{}/{}" , crate_name, redir_name) ,
0 commit comments