@@ -3,8 +3,7 @@ use std::collections::BTreeMap;
33use std:: io;
44use std:: path:: PathBuf ;
55use std:: rc:: Rc ;
6- use std:: sync:: mpsc:: { channel, Receiver } ;
7- use std:: sync:: Arc ;
6+ use std:: sync:: mpsc:: channel;
87
98use rustc_data_structures:: fx:: FxHashMap ;
109use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
@@ -41,35 +40,44 @@ use crate::html::{layout, sources};
4140/// It is intended that this context is a lightweight object which can be fairly
4241/// easily cloned because it is cloned per work-job (about once per item in the
4342/// rustdoc tree).
44- #[ derive( Clone ) ]
4543crate struct Context < ' tcx > {
4644 /// Current hierarchy of components leading down to what's currently being
4745 /// rendered
48- crate current : Vec < String > ,
46+ pub ( super ) current : Vec < String > ,
4947 /// The current destination folder of where HTML artifacts should be placed.
5048 /// This changes as the context descends into the module hierarchy.
51- crate dst : PathBuf ,
49+ pub ( super ) dst : PathBuf ,
5250 /// A flag, which when `true`, will render pages which redirect to the
5351 /// real location of an item. This is used to allow external links to
5452 /// 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 ,
6054 /// 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 > ,
6256 /// Tracks section IDs for `Deref` targets so they match in both the main
6357 /// 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 > ,
7175}
7276
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+
7381impl < ' tcx > Context < ' tcx > {
7482 pub ( super ) fn path ( & self , filename : & str ) -> PathBuf {
7583 // We use splitn vs Path::extension here because we might get a filename
@@ -148,11 +156,6 @@ impl<'tcx> Context<'tcx> {
148156 static_extra_scripts : & [ ] ,
149157 } ;
150158
151- {
152- self . id_map . borrow_mut ( ) . reset ( ) ;
153- self . id_map . borrow_mut ( ) . populate ( & INITIAL_IDS ) ;
154- }
155-
156159 if !self . render_redirect_pages {
157160 layout:: render (
158161 & self . shared . layout ,
@@ -169,7 +172,7 @@ impl<'tcx> Context<'tcx> {
169172 path. push ( '/' ) ;
170173 }
171174 path. push_str ( & item_path ( ty, names. last ( ) . unwrap ( ) ) ) ;
172- match self . redirections {
175+ match self . shared . redirections {
173176 Some ( ref redirections) => {
174177 let mut current_path = String :: new ( ) ;
175178 for name in & self . current {
@@ -383,6 +386,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
383386 edition,
384387 codes : ErrorCodes :: from ( unstable_features. is_nightly_build ( ) ) ,
385388 playground,
389+ all : RefCell :: new ( AllTypes :: new ( ) ) ,
390+ errors : receiver,
391+ redirections : if generate_redirect_map { Some ( Default :: default ( ) ) } else { None } ,
386392 } ;
387393
388394 // Add the default themes to the `Vec` of stylepaths
@@ -409,24 +415,36 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
409415 current : Vec :: new ( ) ,
410416 dst,
411417 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) ,
417421 cache : Rc :: new ( cache) ,
418- redirections : if generate_redirect_map { Some ( Default :: default ( ) ) } else { None } ,
419422 } ;
420423
421424 CURRENT_DEPTH . with ( |s| s. set ( 0 ) ) ;
422425
423426 // 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 ) ;
425428 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 ) ;
427430 Ok ( ( cx, krate) )
428431 }
429432
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+
430448 fn after_krate (
431449 & mut self ,
432450 krate : & clean:: Crate ,
@@ -464,7 +482,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
464482 } else {
465483 String :: new ( )
466484 } ;
467- let all = self . all . replace ( AllTypes :: new ( ) ) ;
485+ let all = self . shared . all . replace ( AllTypes :: new ( ) ) ;
468486 let v = layout:: render (
469487 & self . shared . layout ,
470488 & page,
@@ -494,7 +512,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
494512 & style_files,
495513 ) ;
496514 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 {
498516 if !redirections. borrow ( ) . is_empty ( ) {
499517 let redirect_map_path =
500518 self . dst . join ( & * krate. name . as_str ( ) ) . join ( "redirect-map.json" ) ;
@@ -505,8 +523,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
505523 }
506524
507525 // 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 ( ) ;
510528 if nb_errors > 0 {
511529 Err ( Error :: new ( io:: Error :: new ( io:: ErrorKind :: Other , "I/O error" ) , "" ) )
512530 } else {
@@ -585,13 +603,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
585603 self . shared . fs . write ( & joint_dst, buf. as_bytes ( ) ) ?;
586604
587605 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) ;
589607 }
590608 // If the item is a macro, redirect from the old macro URL (with !)
591609 // to the new one (without).
592610 if item_type == ItemType :: Macro {
593611 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 {
595613 let crate_name = & self . shared . layout . krate ;
596614 redirections. borrow_mut ( ) . insert (
597615 format ! ( "{}/{}" , crate_name, redir_name) ,
0 commit comments