diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 8feef9c259c13..d01677acdd62b 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { }; Some(Item { - source: Span::empty(), + source: Span::dummy(), name: None, attrs: Default::default(), visibility: Inherited, @@ -126,7 +126,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { stability: None, const_stability: None, deprecation: None, - kind: ImplItem(Impl { + kind: ImplItem(box Impl { unsafety: hir::Unsafety::Normal, generics: new_generics, provided_trait_methods: Default::default(), diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 33b5e84c5e074..e41ed79a0cf87 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -115,7 +115,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { stability: None, const_stability: None, deprecation: None, - kind: ImplItem(Impl { + kind: ImplItem(box Impl { unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index f3067360f0680..debc440581912 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -62,7 +62,7 @@ crate fn try_inline( } Res::Def(DefKind::Fn, did) => { record_extern_fqn(cx, did, clean::TypeKind::Function); - clean::FunctionItem(build_external_function(cx, did)) + clean::FunctionItem(box build_external_function(cx, did)) } Res::Def(DefKind::Struct, did) => { record_extern_fqn(cx, did, clean::TypeKind::Struct); @@ -77,7 +77,7 @@ crate fn try_inline( Res::Def(DefKind::TyAlias, did) => { record_extern_fqn(cx, did, clean::TypeKind::Typedef); ret.extend(build_impls(cx, Some(parent_module), did, attrs)); - clean::TypedefItem(build_type_alias(cx, did), false) + clean::TypedefItem(box build_type_alias(cx, did), false) } Res::Def(DefKind::Enum, did) => { record_extern_fqn(cx, did, clean::TypeKind::Enum); @@ -438,7 +438,7 @@ crate fn build_impl( ret.push(clean::Item::from_def_id_and_parts( did, None, - clean::ImplItem(clean::Impl { + clean::ImplItem(box clean::Impl { unsafety: hir::Unsafety::Normal, generics, provided_trait_methods: provided, @@ -479,7 +479,7 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet) items.push(clean::Item { name: None, attrs: clean::Attributes::default(), - source: clean::Span::empty(), + source: clean::Span::dummy(), def_id: DefId::local(CRATE_DEF_INDEX), visibility: clean::Public, stability: None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 16274430902e4..f49ae9030141e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -25,7 +25,7 @@ use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt}; use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{self, ExpnKind, Pos}; +use rustc_span::{self, ExpnKind}; use rustc_typeck::hir_ty_to_ty; use std::collections::hash_map::Entry; @@ -919,7 +919,7 @@ fn clean_fn_or_proc_macro( } else { hir::Constness::NotConst }; - FunctionItem(func) + FunctionItem(box func) } } } @@ -1076,7 +1076,7 @@ impl Clean for hir::TraitItem<'_> { { m.header.constness = hir::Constness::NotConst; } - MethodItem(m, None) + MethodItem(box m, None) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => { let (generics, decl) = enter_impl_trait(cx, || { @@ -1090,7 +1090,7 @@ impl Clean for hir::TraitItem<'_> { { t.header.constness = hir::Constness::NotConst; } - TyMethodItem(t) + TyMethodItem(box t) } hir::TraitItemKind::Type(ref bounds, ref default) => { AssocTypeItem(bounds.clean(cx), default.clean(cx)) @@ -1116,12 +1116,12 @@ impl Clean for hir::ImplItem<'_> { { m.header.constness = hir::Constness::NotConst; } - MethodItem(m, Some(self.defaultness)) + MethodItem(box m, Some(self.defaultness)) } hir::ImplItemKind::TyAlias(ref ty) => { let type_ = ty.clean(cx); let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); - TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true) + TypedefItem(box Typedef { type_, generics: Generics::default(), item_type }, true) } }; Item::from_def_id_and_parts(local_did, Some(self.ident.name.clean(cx)), inner, cx) @@ -1185,7 +1185,7 @@ impl Clean for ty::AssocItem { ty::TraitContainer(_) => None, }; MethodItem( - Function { + box Function { generics, decl, header: hir::FnHeader { @@ -1200,7 +1200,7 @@ impl Clean for ty::AssocItem { defaultness, ) } else { - TyMethodItem(Function { + TyMethodItem(box Function { generics, decl, header: hir::FnHeader { @@ -1270,7 +1270,7 @@ impl Clean for ty::AssocItem { let type_ = cx.tcx.type_of(self.def_id).clean(cx); let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); TypedefItem( - Typedef { + box Typedef { type_, generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, item_type, @@ -1881,29 +1881,8 @@ impl Clean for hir::VariantData<'_> { } impl Clean for rustc_span::Span { - fn clean(&self, cx: &DocContext<'_>) -> Span { - if self.is_dummy() { - return Span::empty(); - } - - // Get the macro invocation instead of the definition, - // in case the span is result of a macro expansion. - // (See rust-lang/rust#39726) - let span = self.source_callsite(); - - let sm = cx.sess().source_map(); - let filename = sm.span_to_filename(span); - let lo = sm.lookup_char_pos(span.lo()); - let hi = sm.lookup_char_pos(span.hi()); - Span { - filename, - cnum: lo.file.cnum, - loline: lo.line, - locol: lo.col.to_usize(), - hiline: hi.line, - hicol: hi.col.to_usize(), - original: span, - } + fn clean(&self, _cx: &DocContext<'_>) -> Span { + Span::from_rustc_span(*self) } } @@ -2002,7 +1981,7 @@ impl Clean> for (&hir::Item<'_>, Option) { let rustdoc_ty = ty.clean(cx); let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did)); TypedefItem( - Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type }, + box Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type }, false, ) } @@ -2109,7 +2088,7 @@ fn clean_impl(impl_: &hir::Item<'_>, cx: &DocContext<'_>) -> Vec { _ => None, }); let make_item = |trait_: Option, for_: Type, items: Vec| { - let kind = ImplItem(Impl { + let kind = ImplItem(box Impl { unsafety, generics: generics.clean(cx), provided_trait_methods: provided.clone(), @@ -2284,7 +2263,7 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { (generics.clean(cx), (&**decl, &names[..]).clean(cx)) }); let (all_types, ret_types) = get_all_types(&generics, &decl, cx); - ForeignFunctionItem(Function { + ForeignFunctionItem(box Function { decl, generics, header: hir::FnHeader { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d4796b7ed66ca..cbb4d5dfd6c8d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -17,15 +17,16 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_feature::UnstableFeatures; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::Mutability; use rustc_index::vec::IndexVec; use rustc_middle::ty::{AssocKind, TyCtxt}; +use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr}; -use rustc_span::{self, FileName}; +use rustc_span::{self, FileName, Loc}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; use smallvec::{smallvec, SmallVec}; @@ -304,24 +305,26 @@ crate enum ItemKind { StructItem(Struct), UnionItem(Union), EnumItem(Enum), - FunctionItem(Function), + FunctionItem(Box), ModuleItem(Module), - TypedefItem(Typedef, bool /* is associated type */), + TypedefItem(Box, bool /* is associated type */), OpaqueTyItem(OpaqueTy), StaticItem(Static), ConstantItem(Constant), TraitItem(Trait), TraitAliasItem(TraitAlias), - ImplItem(Impl), + // Impl is 400 bytes (!!), so box it to avoid penalizing other items + // FIXME(jyn514): calculate this information on demand instead + ImplItem(Box), /// A method signature only. Used for required methods in traits (ie, /// non-default-methods). - TyMethodItem(Function), + TyMethodItem(Box), /// A method with a body. - MethodItem(Function, Option), + MethodItem(Box, Option), StructFieldItem(Type), VariantItem(Variant), /// `fn`s from an extern block - ForeignFunctionItem(Function), + ForeignFunctionItem(Box), /// `static`s from an extern block ForeignStaticItem(Static), /// `type`s from an extern block @@ -1609,32 +1612,41 @@ crate enum VariantKind { Struct(VariantStruct), } +/// Small wrapper around `rustc_span::Span` that adds helper methods and enforces calling `source_callsite`. #[derive(Clone, Debug)] -crate struct Span { - crate filename: FileName, - crate cnum: CrateNum, - crate loline: usize, - crate locol: usize, - crate hiline: usize, - crate hicol: usize, - crate original: rustc_span::Span, -} +crate struct Span(rustc_span::Span); impl Span { - crate fn empty() -> Span { - Span { - filename: FileName::Anon(0), - cnum: LOCAL_CRATE, - loline: 0, - locol: 0, - hiline: 0, - hicol: 0, - original: rustc_span::DUMMY_SP, - } + crate fn from_rustc_span(sp: rustc_span::Span) -> Self { + // Get the macro invocation instead of the definition, + // in case the span is result of a macro expansion. + // (See rust-lang/rust#39726) + Self(sp.source_callsite()) + } + + crate fn dummy() -> Self { + Self(rustc_span::DUMMY_SP) } crate fn span(&self) -> rustc_span::Span { - self.original + self.0 + } + + crate fn filename(&self, sess: &Session) -> FileName { + sess.source_map().span_to_filename(self.0) + } + + crate fn lo(&self, sess: &Session) -> Loc { + sess.source_map().lookup_char_pos(self.0.lo()) + } + + crate fn hi(&self, sess: &Session) -> Loc { + sess.source_map().lookup_char_pos(self.0.hi()) + } + + crate fn cnum(&self, sess: &Session) -> CrateNum { + // FIXME: is there a time when the lo and hi crate would be different? + self.lo(sess).file.cnum } } diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index d0fdc69cc1932..6334524eb1ca3 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use rustc_data_structures::sync::Lrc; +use rustc_session::Session; use rustc_span::edition::Edition; use crate::clean; @@ -19,6 +21,7 @@ crate trait FormatRenderer: Clone { render_info: RenderInfo, edition: Edition, cache: &mut Cache, + sess: Lrc, ) -> Result<(Self, clean::Crate), Error>; /// Renders a single non-module item. This means no recursive sub-item rendering is required. @@ -49,6 +52,7 @@ crate fn run_format( render_info: RenderInfo, diag: &rustc_errors::Handler, edition: Edition, + sess: Lrc, ) -> Result<(), Error> { let (krate, mut cache) = Cache::from_krate( render_info.clone(), @@ -59,7 +63,7 @@ crate fn run_format( ); let (mut format_renderer, mut krate) = - T::init(krate, options, render_info, edition, &mut cache)?; + T::init(krate, options, render_info, edition, &mut cache, sess)?; let cache = Arc::new(cache); // Freeze the cache now that the index has been built. Put an Arc into TLS for future diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 901f00b21da9d..5375451248644 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -52,10 +52,12 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Mutability; use rustc_middle::middle::stability; +use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::FileName; @@ -121,6 +123,7 @@ crate struct Context { } crate struct SharedContext { + crate sess: Lrc, /// The path to the crate root source minus the file name. /// Used for simplifying paths to the highlighted source code files. crate src_root: PathBuf, @@ -173,6 +176,10 @@ impl Context { let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext,); self.dst.join(&filename) } + + fn sess(&self) -> &Session { + &self.shared.sess + } } impl SharedContext { @@ -383,6 +390,7 @@ impl FormatRenderer for Context { _render_info: RenderInfo, edition: Edition, cache: &mut Cache, + sess: Lrc, ) -> Result<(Context, clean::Crate), Error> { // need to save a copy of the options for rendering the index page let md_opts = options.clone(); @@ -455,6 +463,7 @@ impl FormatRenderer for Context { } let (sender, receiver) = channel(); let mut scx = SharedContext { + sess, collapsed: krate.collapsed, src_root, include_sources, @@ -1631,24 +1640,24 @@ impl Context { /// of their crate documentation isn't known. fn src_href(&self, item: &clean::Item, cache: &Cache) -> Option { let mut root = self.root_path(); - let mut path = String::new(); + let cnum = item.source.cnum(self.sess()); // We can safely ignore synthetic `SourceFile`s. - let file = match item.source.filename { + let file = match item.source.filename(self.sess()) { FileName::Real(ref path) => path.local_path().to_path_buf(), _ => return None, }; let file = &file; - let (krate, path) = if item.source.cnum == LOCAL_CRATE { + let (krate, path) = if cnum == LOCAL_CRATE { if let Some(path) = self.shared.local_sources.get(file) { (&self.shared.layout.krate, path) } else { return None; } } else { - let (krate, src_root) = match *cache.extern_locations.get(&item.source.cnum)? { + let (krate, src_root) = match *cache.extern_locations.get(&cnum)? { (ref name, ref src, ExternalLocation::Local) => (name, src), (ref name, ref src, ExternalLocation::Remote(ref s)) => { root = s.to_string(); @@ -1667,11 +1676,10 @@ impl Context { (krate, &path) }; - let lines = if item.source.loline == item.source.hiline { - item.source.loline.to_string() - } else { - format!("{}-{}", item.source.loline, item.source.hiline) - }; + let loline = item.source.lo(self.sess()).line; + let hiline = item.source.hi(self.sess()).line; + let lines = + if loline == hiline { loline.to_string() } else { format!("{}-{}", loline, hiline) }; Some(format!( "{root}src/{krate}/{path}#{lines}", root = Escape(&root), @@ -3553,7 +3561,7 @@ fn render_deref_methods( .items .iter() .find_map(|item| match item.kind { - clean::TypedefItem(ref t, true) => Some(match *t { + clean::TypedefItem(ref t, true) => Some(match **t { clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), }), @@ -4231,7 +4239,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { { if let Some((target, real_target)) = impl_.inner_impl().items.iter().find_map(|item| match item.kind { - clean::TypedefItem(ref t, true) => Some(match *t { + clean::TypedefItem(ref t, true) => Some(match **t { clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), }), diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index e7b5a90d84df0..ef9e9f350fb84 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -7,6 +7,7 @@ use crate::html::highlight; use crate::html::layout; use crate::html::render::{SharedContext, BASIC_KEYWORDS}; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_session::Session; use rustc_span::source_map::FileName; use std::ffi::OsStr; use std::fs; @@ -34,37 +35,45 @@ struct SourceCollector<'a> { impl<'a> DocFolder for SourceCollector<'a> { fn fold_item(&mut self, item: clean::Item) -> Option { + // If we're not rendering sources, there's nothing to do. // If we're including source files, and we haven't seen this file yet, // then we need to render it out to the filesystem. if self.scx.include_sources // skip all synthetic "files" - && item.source.filename.is_real() + && item.source.filename(self.sess()).is_real() // skip non-local files - && item.source.cnum == LOCAL_CRATE + && item.source.cnum(self.sess()) == LOCAL_CRATE { + let filename = item.source.filename(self.sess()); // If it turns out that we couldn't read this file, then we probably // can't read any of the files (generating html output from json or // something like that), so just don't include sources for the // entire crate. The other option is maintaining this mapping on a // per-file basis, but that's probably not worth it... - self.scx.include_sources = match self.emit_source(&item.source.filename) { + self.scx.include_sources = match self.emit_source(&filename) { Ok(()) => true, Err(e) => { println!( "warning: source code was requested to be rendered, \ but processing `{}` had an error: {}", - item.source.filename, e + filename, e ); println!(" skipping rendering of source code"); false } }; } + // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value, + // we could return None here without having to walk the rest of the crate. Some(self.fold_item_recur(item)) } } impl<'a> SourceCollector<'a> { + fn sess(&self) -> &Session { + &self.scx.sess + } + /// Renders the given filename into its corresponding HTML source file. fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> { let p = match *filename { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index afb8dfa676657..1a4bd0b6916de 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -6,14 +6,16 @@ use std::convert::From; use rustc_ast::ast; use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_span::Pos; use crate::clean; use crate::doctree; use crate::formats::item_type::ItemType; use crate::json::types::*; +use crate::json::JsonRenderer; -impl From for Option { - fn from(item: clean::Item) -> Self { +impl JsonRenderer { + pub(super) fn convert_item(&self, item: clean::Item) -> Option { let item_type = ItemType::from(&item); let clean::Item { source, @@ -32,7 +34,7 @@ impl From for Option { id: def_id.into(), crate_id: def_id.krate.as_u32(), name, - source: source.into(), + source: self.convert_span(source), visibility: visibility.into(), docs: attrs.collapsed_doc_value().unwrap_or_default(), links: attrs @@ -53,22 +55,23 @@ impl From for Option { }), } } -} -impl From for Option { - fn from(span: clean::Span) -> Self { - let clean::Span { loline, locol, hiline, hicol, .. } = span; - match span.filename { - rustc_span::FileName::Real(name) => Some(Span { - filename: match name { - rustc_span::RealFileName::Named(path) => path, - rustc_span::RealFileName::Devirtualized { local_path, virtual_name: _ } => { - local_path - } - }, - begin: (loline, locol), - end: (hiline, hicol), - }), + fn convert_span(&self, span: clean::Span) -> Option { + match span.filename(&self.sess) { + rustc_span::FileName::Real(name) => { + let hi = span.hi(&self.sess); + let lo = span.lo(&self.sess); + Some(Span { + filename: match name { + rustc_span::RealFileName::Named(path) => path, + rustc_span::RealFileName::Devirtualized { local_path, virtual_name: _ } => { + local_path + } + }, + begin: (lo.line, lo.col.to_usize()), + end: (hi.line, hi.col.to_usize()), + }) + } _ => None, } } @@ -166,17 +169,17 @@ impl From for ItemEnum { StructFieldItem(f) => ItemEnum::StructFieldItem(f.into()), EnumItem(e) => ItemEnum::EnumItem(e.into()), VariantItem(v) => ItemEnum::VariantItem(v.into()), - FunctionItem(f) => ItemEnum::FunctionItem(f.into()), - ForeignFunctionItem(f) => ItemEnum::FunctionItem(f.into()), + FunctionItem(box f) => ItemEnum::FunctionItem(f.into()), + ForeignFunctionItem(box f) => ItemEnum::FunctionItem(f.into()), TraitItem(t) => ItemEnum::TraitItem(t.into()), TraitAliasItem(t) => ItemEnum::TraitAliasItem(t.into()), - MethodItem(m, _) => ItemEnum::MethodItem(m.into()), - TyMethodItem(m) => ItemEnum::MethodItem(m.into()), - ImplItem(i) => ItemEnum::ImplItem(i.into()), + MethodItem(box m, _) => ItemEnum::MethodItem(m.into()), + TyMethodItem(box m) => ItemEnum::MethodItem(m.into()), + ImplItem(box i) => ItemEnum::ImplItem(i.into()), StaticItem(s) => ItemEnum::StaticItem(s.into()), ForeignStaticItem(s) => ItemEnum::StaticItem(s.into()), ForeignTypeItem => ItemEnum::ForeignTypeItem, - TypedefItem(t, _) => ItemEnum::TypedefItem(t.into()), + TypedefItem(box t, _) => ItemEnum::TypedefItem(t.into()), OpaqueTyItem(t) => ItemEnum::OpaqueTyItem(t.into()), ConstantItem(c) => ItemEnum::ConstantItem(c.into()), MacroItem(m) => ItemEnum::MacroItem(m.source), diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 5f640bfddf10b..5c5239d1b6a26 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -13,6 +13,8 @@ use std::path::PathBuf; use std::rc::Rc; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Lrc; +use rustc_session::Session; use rustc_span::edition::Edition; use crate::clean; @@ -24,6 +26,7 @@ use crate::html::render::cache::ExternalLocation; #[derive(Clone)] crate struct JsonRenderer { + sess: Lrc, /// A mapping of IDs that contains all local items for this crate which gets output as a top /// level field of the JSON blob. index: Rc>>, @@ -124,10 +127,12 @@ impl FormatRenderer for JsonRenderer { _render_info: RenderInfo, _edition: Edition, _cache: &mut Cache, + sess: Lrc, ) -> Result<(Self, clean::Crate), Error> { debug!("Initializing json renderer"); Ok(( JsonRenderer { + sess, index: Rc::new(RefCell::new(FxHashMap::default())), out_path: options.output, }, @@ -143,7 +148,7 @@ impl FormatRenderer for JsonRenderer { item.kind.inner_items().for_each(|i| self.item(i.clone(), cache).unwrap()); let id = item.def_id; - if let Some(mut new_item) = item.into(): Option { + if let Some(mut new_item) = self.convert_item(item) { if let types::ItemEnum::TraitItem(ref mut t) = new_item.inner { t.implementors = self.get_trait_implementors(id, cache) } else if let types::ItemEnum::StructItem(ref mut s) = new_item.inner { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 26bf4b569ff4b..e094ead12bd0f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -61,9 +61,11 @@ use std::default::Default; use std::env; use std::process; +use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; use rustc_session::getopts; +use rustc_session::Session; use rustc_session::{early_error, early_warn}; #[macro_use] @@ -483,8 +485,9 @@ fn run_renderer( render_info: config::RenderInfo, diag: &rustc_errors::Handler, edition: rustc_span::edition::Edition, + sess: Lrc, ) -> MainResult { - match formats::run_format::(krate, renderopts, render_info, &diag, edition) { + match formats::run_format::(krate, renderopts, render_info, &diag, edition, sess) { Ok(_) => Ok(()), Err(e) => { let mut msg = diag.struct_err(&format!("couldn't generate documentation: {}", e.error)); @@ -552,12 +555,15 @@ fn main_options(options: config::Options) -> MainResult { info!("going to format"); let (error_format, edition, debugging_options) = diag_opts; let diag = core::new_handler(error_format, None, &debugging_options); + let sess_time = sess.clone(); match output_format { - None | Some(config::OutputFormat::Html) => sess.time("render_html", || { - run_renderer::(krate, renderopts, renderinfo, &diag, edition) + None | Some(config::OutputFormat::Html) => sess_time.time("render_html", || { + run_renderer::( + krate, renderopts, renderinfo, &diag, edition, sess, + ) }), - Some(config::OutputFormat::Json) => sess.time("render_json", || { - run_renderer::(krate, renderopts, renderinfo, &diag, edition) + Some(config::OutputFormat::Json) => sess_time.time("render_json", || { + run_renderer::(krate, renderopts, renderinfo, &diag, edition, sess) }), } } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 3f9978c8fca84..52f6a97089bde 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -216,13 +216,9 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { return Some(i); } clean::ImplItem(ref impl_) => { + let filename = i.source.filename(self.ctx.sess()); if let Some(ref tr) = impl_.trait_ { - debug!( - "impl {:#} for {:#} in {}", - tr.print(), - impl_.for_.print(), - i.source.filename - ); + debug!("impl {:#} for {:#} in {}", tr.print(), impl_.for_.print(), filename,); // don't count trait impls, the missing-docs lint doesn't so we shouldn't // either @@ -231,7 +227,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { // inherent impls *can* be documented, and those docs show up, but in most // cases it doesn't make sense, as all methods on a type are in one single // impl block - debug!("impl {:#} in {}", impl_.for_.print(), i.source.filename); + debug!("impl {:#} in {}", impl_.for_.print(), filename); } } _ => { @@ -251,6 +247,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { None, ); + let filename = i.source.filename(self.ctx.sess()); let has_doc_example = tests.found_tests != 0; let hir_id = self.ctx.tcx.hir().local_def_id_to_hir_id(i.def_id.expect_local()); let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); @@ -258,8 +255,8 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { // unless the user had an explicit `allow` let should_have_docs = level != lint::Level::Allow || matches!(source, LintSource::Default); - debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename); - self.items.entry(i.source.filename.clone()).or_default().count_item( + debug!("counting {:?} {:?} in {}", i.type_(), i.name, filename); + self.items.entry(filename).or_default().count_item( has_docs, has_doc_example, should_have_doc_example(self.ctx, &i), diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 4c3defabc3294..492be3ddcddd8 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -55,7 +55,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in &new_items { - if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = it.kind { + if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = it.kind { if cleaner.keep_item(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() { let target = items .iter() @@ -75,7 +75,7 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { } new_items.retain(|it| { - if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = it.kind { + if let ImplItem(box Impl { ref for_, ref trait_, ref blanket_impl, .. }) = it.kind { cleaner.keep_item(for_) || trait_.as_ref().map_or(false, |t| cleaner.keep_item(t)) || blanket_impl.is_some()