From ea83349c9f06e13aae4a70e81d5dc470bf051bca Mon Sep 17 00:00:00 2001 From: mitaa Date: Thu, 7 Apr 2016 05:59:02 +0200 Subject: [PATCH] Retire rustdocs `ANALYSISKEY` The thread-local isn't needed and consists of mostly empty fields which were just used to move the data into `html::render::CACHE_KEY`. --- src/librustc/middle/privacy.rs | 9 ++++- src/librustdoc/clean/inline.rs | 6 +-- src/librustdoc/clean/mod.rs | 21 +++++++--- src/librustdoc/core.rs | 70 +++++++++++----------------------- src/librustdoc/html/render.rs | 50 ++++++++++++++---------- src/librustdoc/lib.rs | 21 +++------- src/librustdoc/passes.rs | 5 +-- src/librustdoc/test.rs | 9 ++--- src/librustdoc/visit_ast.rs | 10 +---- 9 files changed, 90 insertions(+), 111 deletions(-) diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index c1dc727449a..478f662d096 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -15,10 +15,11 @@ use util::nodemap::{DefIdSet, FnvHashMap}; use std::hash::Hash; +use std::fmt; use syntax::ast::NodeId; // Accessibility levels, sorted in ascending order -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum AccessLevel { // Exported items + items participating in various kinds of public interfaces, // but not directly nameable. For example, if function `fn f() -> T {...}` is @@ -56,6 +57,12 @@ impl Default for AccessLevels { } } +impl fmt::Debug for AccessLevels { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.map, f) + } +} + /// A set containing all exported definitions from external crates. /// The set does not contain any entries from local crates. pub type ExternalExports = DefIdSet; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 85097549826..6cca602466a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -116,7 +116,7 @@ fn try_inline_def(cx: &DocContext, tcx: &TyCtxt, } _ => return None, }; - cx.inlined.borrow_mut().as_mut().unwrap().insert(did); + cx.renderinfo.borrow_mut().inlined.insert(did); ret.push(clean::Item { source: clean::Span::empty(), name: Some(tcx.item_name(did).to_string()), @@ -146,7 +146,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { elem.data.to_string() }); let fqn = once(crate_name).chain(relative).collect(); - cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, kind)); + cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind)); } } @@ -295,7 +295,7 @@ pub fn build_impl(cx: &DocContext, tcx: &TyCtxt, did: DefId, ret: &mut Vec) { - if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) { + if !cx.renderinfo.borrow_mut().inlined.insert(did) { return } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d8d1472560d..bba394bb90d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -35,6 +35,7 @@ use syntax::ptr::P; use rustc_trans::back::link; use rustc::middle::cstore::{self, CrateStore}; +use rustc::middle::privacy::AccessLevels; use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace}; @@ -46,8 +47,10 @@ use rustc::hir; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::rc::Rc; +use std::sync::Arc; use std::u32; use std::env::current_dir; +use std::mem; use core::DocContext; use doctree; @@ -112,13 +115,16 @@ impl, U> Clean> for P<[T]> { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, Debug)] pub struct Crate { pub name: String, pub src: PathBuf, pub module: Option, pub externs: Vec<(ast::CrateNum, ExternalCrate)>, pub primitives: Vec, + pub access_levels: Arc>, + // These are later on moved into `CACHEKEY`, leaving the map empty. + // Only here so that they can be filtered through the rustdoc passes. pub external_traits: HashMap, } @@ -130,6 +136,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { if let Some(t) = cx.tcx_opt() { cx.deref_trait_did.set(t.lang_items.deref_trait()); + cx.renderinfo.borrow_mut().deref_trait_did = cx.deref_trait_did.get(); } let mut externs = Vec::new(); @@ -204,14 +211,17 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { Input::Str { ref name, .. } => PathBuf::from(name.clone()), }; + let mut access_levels = cx.access_levels.borrow_mut(); + let mut external_traits = cx.external_traits.borrow_mut(); + Crate { name: name.to_string(), src: src, module: Some(module), externs: externs, primitives: primitives, - external_traits: cx.external_traits.borrow_mut().take() - .unwrap_or(HashMap::new()), + access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())), + external_traits: mem::replace(&mut external_traits, Default::default()), } } } @@ -540,8 +550,7 @@ impl Clean for hir::TyParam { impl<'tcx> Clean for ty::TypeParameterDef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParam { - cx.external_typarams.borrow_mut().as_mut().unwrap() - .insert(self.def_id, self.name.clean(cx)); + cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx)); TyParam { name: self.name.clean(cx), did: self.def_id, @@ -2668,7 +2677,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId { inline::record_extern_fqn(cx, did, kind); if let TypeTrait = kind { let t = inline::build_external_trait(cx, tcx, did); - cx.external_traits.borrow_mut().as_mut().unwrap().insert(did, t); + cx.external_traits.borrow_mut().insert(did, t); } did } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6b7aa103e1d..c9773ebccb4 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -29,12 +29,13 @@ use syntax::feature_gate::UnstableFeatures; use syntax::parse::token; use std::cell::{RefCell, Cell}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::rc::Rc; use visit_ast::RustdocVisitor; use clean; use clean::Clean; +use html::render::RenderInfo; pub use rustc::session::config::Input; pub use rustc::session::search_paths::SearchPaths; @@ -45,19 +46,20 @@ pub enum MaybeTyped<'a, 'tcx: 'a> { NotTyped(&'a session::Session) } -pub type ExternalPaths = RefCell, clean::TypeKind)>>>; +pub type ExternalPaths = HashMap, clean::TypeKind)>; pub struct DocContext<'a, 'tcx: 'a> { pub map: &'a hir_map::Map<'tcx>, pub maybe_typed: MaybeTyped<'a, 'tcx>, pub input: Input, - pub external_paths: ExternalPaths, - pub external_traits: RefCell>>, - pub external_typarams: RefCell>>, - pub inlined: RefCell>>, pub all_crate_impls: RefCell>>, + // Later on moved into `clean::Crate` + pub access_levels: RefCell>, + // Later on moved into `html::render::CACHE_KEY` + pub renderinfo: RefCell, pub deref_trait_did: Cell>, + // Later on moved through `clean::Crate` into `html::render::CACHE_KEY` + pub external_traits: RefCell>, } impl<'b, 'tcx> DocContext<'b, 'tcx> { @@ -81,20 +83,14 @@ impl<'b, 'tcx> DocContext<'b, 'tcx> { } } -pub struct CrateAnalysis { - pub access_levels: AccessLevels, - pub external_paths: ExternalPaths, - pub external_typarams: RefCell>>, - pub inlined: RefCell>>, - pub deref_trait_did: Option, -} - pub type Externs = HashMap>; -pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, - input: Input, triple: Option) - -> (clean::Crate, CrateAnalysis) { - +pub fn run_core(search_paths: SearchPaths, + cfgs: Vec, + externs: Externs, + input: Input, + triple: Option) -> (clean::Crate, RenderInfo) +{ // Parse, resolve, and typecheck the given crate. let cpath = match input { @@ -148,7 +144,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, let arenas = ty::CtxtArenas::new(); let hir_map = driver::make_map(&sess, &mut hir_forest); - let krate_and_analysis = abort_on_err(driver::phase_3_run_analysis_passes(&sess, + abort_on_err(driver::phase_3_run_analysis_passes(&sess, &cstore, hir_map, &arenas, @@ -175,42 +171,20 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, map: &tcx.map, maybe_typed: Typed(tcx), input: input, - external_traits: RefCell::new(Some(HashMap::new())), - external_typarams: RefCell::new(Some(HashMap::new())), - external_paths: RefCell::new(Some(HashMap::new())), - inlined: RefCell::new(Some(HashSet::new())), all_crate_impls: RefCell::new(HashMap::new()), deref_trait_did: Cell::new(None), + access_levels: RefCell::new(access_levels), + external_traits: RefCell::new(HashMap::new()), + renderinfo: RefCell::new(Default::default()), }; debug!("crate: {:?}", ctxt.map.krate()); - let mut analysis = CrateAnalysis { - access_levels: access_levels, - external_paths: RefCell::new(None), - external_typarams: RefCell::new(None), - inlined: RefCell::new(None), - deref_trait_did: None, - }; - let krate = { - let mut v = RustdocVisitor::new(&ctxt, Some(&analysis)); + let mut v = RustdocVisitor::new(&ctxt); v.visit(ctxt.map.krate()); v.clean(&ctxt) }; - let external_paths = ctxt.external_paths.borrow_mut().take(); - *analysis.external_paths.borrow_mut() = external_paths; - - let map = ctxt.external_typarams.borrow_mut().take(); - *analysis.external_typarams.borrow_mut() = map; - - let map = ctxt.inlined.borrow_mut().take(); - *analysis.inlined.borrow_mut() = map; - - analysis.deref_trait_did = ctxt.deref_trait_did.get(); - - Some((krate, analysis)) - }), &sess); - - krate_and_analysis.unwrap() + Some((krate, ctxt.renderinfo.into_inner())) + }), &sess).unwrap() } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c5850089578..2d59747d00c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -253,7 +253,7 @@ pub struct Cache { parent_is_trait_impl: bool, search_index: Vec, stripped_mod: bool, - access_levels: AccessLevels, + access_levels: Arc>, deref_trait_did: Option, // In rare case where a structure is defined in one module but implemented @@ -264,6 +264,16 @@ pub struct Cache { orphan_methods: Vec<(DefId, clean::Item)>, } +/// Temporary storage for data obtained during `RustdocVisitor::clean()`. +/// Later on moved into `CACHE_KEY`. +#[derive(Default)] +pub struct RenderInfo { + pub inlined: HashSet, + pub external_paths: ::core::ExternalPaths, + pub external_typarams: HashMap, + pub deref_trait_did: Option, +} + /// Helper struct to render all source code to HTML pages struct SourceCollector<'a> { scx: &'a mut SharedContext, @@ -415,7 +425,8 @@ pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: PathBuf, passes: HashSet, - css_file_extension: Option) -> Result<(), Error> { + css_file_extension: Option, + renderinfo: RenderInfo) -> Result<(), Error> { let src_root = match krate.src.parent() { Some(p) => p.to_path_buf(), None => PathBuf::new(), @@ -482,19 +493,20 @@ pub fn run(mut krate: clean::Crate, }; // Crawl the crate to build various caches used for the output - let analysis = ::ANALYSISKEY.with(|a| a.clone()); - let analysis = analysis.borrow(); - let access_levels = analysis.as_ref().map(|a| a.access_levels.clone()); - let access_levels = access_levels.unwrap_or(Default::default()); - let paths: HashMap, ItemType)> = - analysis.as_ref().map(|a| { - let paths = a.external_paths.borrow_mut().take().unwrap(); - paths.into_iter().map(|(k, (v, t))| (k, (v, ItemType::from_type_kind(t)))).collect() - }).unwrap_or(HashMap::new()); + let RenderInfo { + inlined, + external_paths, + external_typarams, + deref_trait_did, + } = renderinfo; + + let paths = external_paths.into_iter() + .map(|(k, (v, t))| (k, (v, ItemType::from_type_kind(t)))) + .collect::>(); + let mut cache = Cache { impls: HashMap::new(), - external_paths: paths.iter().map(|(&k, v)| (k, v.0.clone())) - .collect(), + external_paths: paths.iter().map(|(&k, v)| (k, v.0.clone())).collect(), paths: paths, implementors: HashMap::new(), stack: Vec::new(), @@ -504,16 +516,12 @@ pub fn run(mut krate: clean::Crate, extern_locations: HashMap::new(), primitive_locations: HashMap::new(), stripped_mod: false, - access_levels: access_levels, + access_levels: krate.access_levels.clone(), orphan_methods: Vec::new(), traits: mem::replace(&mut krate.external_traits, HashMap::new()), - deref_trait_did: analysis.as_ref().and_then(|a| a.deref_trait_did), - typarams: analysis.as_ref().map(|a| { - a.external_typarams.borrow_mut().take().unwrap() - }).unwrap_or(HashMap::new()), - inlined: analysis.as_ref().map(|a| { - a.inlined.borrow_mut().take().unwrap() - }).unwrap_or(HashSet::new()), + deref_trait_did: deref_trait_did, + typarams: external_typarams, + inlined: inlined, }; // Cache where all our extern crates are located diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bc7c7c5e0ca..0d80e702816 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -48,14 +48,11 @@ extern crate rustc_unicode; extern crate serialize as rustc_serialize; // used by deriving -use std::cell::RefCell; use std::collections::HashMap; use std::default::Default; use std::env; -use std::io::Read; use std::path::PathBuf; use std::process; -use std::rc::Rc; use std::sync::mpsc::channel; use externalfiles::ExternalHtml; @@ -113,12 +110,9 @@ const DEFAULT_PASSES: &'static [&'static str] = &[ "unindent-comments", ]; -thread_local!(pub static ANALYSISKEY: Rc>> = { - Rc::new(RefCell::new(None)) -}); - struct Output { krate: clean::Crate, + renderinfo: html::render::RenderInfo, passes: Vec, } @@ -302,14 +296,15 @@ pub fn main_args(args: &[String]) -> isize { return 1; } }; - let Output { krate, passes, } = out; + let Output { krate, passes, renderinfo } = out; info!("going to format"); match matches.opt_str("w").as_ref().map(|s| &**s) { Some("html") | None => { html::render::run(krate, &external_html, output.unwrap_or(PathBuf::from("doc")), passes.into_iter().collect(), - css_file_extension) + css_file_extension, + renderinfo) .expect("failed to generate documentation") } Some(s) => { @@ -380,12 +375,8 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche tx.send(core::run_core(paths, cfgs, externs, Input::File(cr), triple)).unwrap(); }); - let (mut krate, analysis) = rx.recv().unwrap(); + let (mut krate, renderinfo) = rx.recv().unwrap(); info!("finished with rustc"); - let mut analysis = Some(analysis); - ANALYSISKEY.with(|s| { - *s.borrow_mut() = analysis.take(); - }); if let Some(name) = matches.opt_str("crate-name") { krate.name = name @@ -443,5 +434,5 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche // Run everything! info!("Executing passes/plugins"); let krate = pm.run_plugins(krate); - Output { krate: krate, passes: passes } + Output { krate: krate, renderinfo: renderinfo, passes: passes } } diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index adc39b69986..b9a2acb02e8 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -88,10 +88,7 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult { pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult { // This stripper collects all *retained* nodes. let mut retained = DefIdSet(); - let analysis = super::ANALYSISKEY.with(|a| a.clone()); - let analysis = analysis.borrow(); - let analysis = analysis.as_ref().unwrap(); - let access_levels = analysis.access_levels.clone(); + let access_levels = krate.access_levels.clone(); // strip all private items { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 982f477fc4a..5a7050fb42f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -108,15 +108,14 @@ pub fn run(input: &str, map: &map, maybe_typed: core::NotTyped(&sess), input: input, - external_paths: RefCell::new(Some(HashMap::new())), - external_traits: RefCell::new(None), - external_typarams: RefCell::new(None), - inlined: RefCell::new(None), + external_traits: RefCell::new(HashMap::new()), all_crate_impls: RefCell::new(HashMap::new()), deref_trait_did: Cell::new(None), + access_levels: Default::default(), + renderinfo: Default::default(), }; - let mut v = RustdocVisitor::new(&ctx, None); + let mut v = RustdocVisitor::new(&ctx); v.visit(ctx.map.krate()); let mut krate = v.clean(&ctx); if let Some(name) = crate_name { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5c36c38abc5..a406c843b82 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -41,14 +41,12 @@ pub struct RustdocVisitor<'a, 'tcx: 'a> { pub module: Module, pub attrs: hir::HirVec, pub cx: &'a core::DocContext<'a, 'tcx>, - pub analysis: Option<&'a core::CrateAnalysis>, view_item_stack: HashSet, inlining_from_glob: bool, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { - pub fn new(cx: &'a core::DocContext<'a, 'tcx>, - analysis: Option<&'a core::CrateAnalysis>) -> RustdocVisitor<'a, 'tcx> { + pub fn new(cx: &'a core::DocContext<'a, 'tcx>) -> RustdocVisitor<'a, 'tcx> { // If the root is reexported, terminate all recursion. let mut stack = HashSet::new(); stack.insert(ast::CRATE_NODE_ID); @@ -56,7 +54,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { module: Module::new(None), attrs: hir::HirVec::new(), cx: cx, - analysis: analysis, view_item_stack: stack, inlining_from_glob: false, } @@ -247,13 +244,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let def_node_id = match tcx.map.as_local_node_id(def) { Some(n) => n, None => return false }; - let analysis = match self.analysis { - Some(analysis) => analysis, None => return false - }; let use_attrs = tcx.map.attrs(id).clean(self.cx); - let is_private = !analysis.access_levels.is_public(def); + let is_private = !self.cx.access_levels.borrow().is_public(def); let is_hidden = inherits_doc_hidden(self.cx, def_node_id); let is_no_inline = use_attrs.list("doc").has_word("no_inline");