From a4b62142799095a6426db6d873d1de173d20c445 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 24 Mar 2021 01:49:12 -0400 Subject: [PATCH 1/4] Add attr_span helper function --- src/librustdoc/clean/types.rs | 4 ++++ src/librustdoc/passes/bare_urls.rs | 5 ++--- src/librustdoc/passes/check_code_block_syntax.rs | 6 +++--- src/librustdoc/passes/collect_intra_doc_links.rs | 9 +++------ src/librustdoc/passes/doc_test_lints.rs | 6 +++--- src/librustdoc/passes/html_tags.rs | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 0b55d276bad0e..e2eeacdb567a3 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -255,6 +255,10 @@ impl Item { if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) } } + crate fn attr_span(&self, _tcx: TyCtxt<'_>) -> rustc_span::Span { + crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span.inner()) + } + /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. crate fn doc_value(&self) -> Option { diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs index ac0d74cbbb9d0..56ef15eb88420 100644 --- a/src/librustdoc/passes/bare_urls.rs +++ b/src/librustdoc/passes/bare_urls.rs @@ -1,4 +1,4 @@ -use super::{span_of_attrs, Pass}; +use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; @@ -69,8 +69,7 @@ impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> { if !dox.is_empty() { let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range| { let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs) - .or_else(|| span_of_attrs(&item.attrs)) - .unwrap_or(item.span.inner()); + .unwrap_or_else(|| item.attr_span(cx.tcx)); cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| { lint.build(msg) .note("bare URLs are not automatically turned into clickable links") diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index f98f524ca4072..68a66806e0476 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -9,7 +9,7 @@ use crate::clean; use crate::core::DocContext; use crate::fold::DocFolder; use crate::html::markdown::{self, RustCodeBlock}; -use crate::passes::{span_of_attrs, Pass}; +use crate::passes::Pass; crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass { name: "check-code-block-syntax", @@ -86,7 +86,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { // We couldn't calculate the span of the markdown block that had the error, so our // diagnostics are going to be a bit lacking. let mut diag = self.cx.sess().struct_span_warn( - super::span_of_attrs(&item.attrs).unwrap_or(item.span.inner()), + item.attr_span(self.cx.tcx), "doc comment contains an invalid Rust code block", ); @@ -110,7 +110,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> { fn fold_item(&mut self, item: clean::Item) -> Option { if let Some(dox) = &item.attrs.collapsed_doc_value() { - let sp = span_of_attrs(&item.attrs).unwrap_or(item.span.inner()); + let sp = item.attr_span(self.cx.tcx); let extra = crate::html::markdown::ExtraInfo::new_did(self.cx.tcx, item.def_id, sp); for code_block in markdown::rust_code_blocks(&dox, &extra) { self.check_rust_syntax(&item, &dox, code_block); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 837cd034b655c..dad6593248dae 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -37,8 +37,6 @@ use crate::html::markdown::{markdown_links, MarkdownLink}; use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS}; use crate::passes::Pass; -use super::span_of_attrs; - mod early; crate use early::IntraLinkCrateLoader; @@ -1242,7 +1240,7 @@ impl LinkCollector<'_, '_> { &ori_link.range, &item.attrs, ) - .unwrap_or_else(|| span_of_attrs(&item.attrs).unwrap_or(item.span.inner())); + .unwrap_or_else(|| item.attr_span(self.cx.tcx)); rustc_session::parse::feature_err( &self.cx.tcx.sess.parse_sess, @@ -1695,13 +1693,12 @@ fn report_diagnostic( } }; - let attrs = &item.attrs; - let sp = span_of_attrs(attrs).unwrap_or(item.span.inner()); + let sp = item.attr_span(tcx); tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| { let mut diag = lint.build(msg); - let span = super::source_span_for_markdown_range(tcx, dox, link_range, attrs); + let span = super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs); if let Some(sp) = span { diag.set_span(sp); diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index b36358489900e..c8d2263d81d54 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -3,7 +3,7 @@ //! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. -use super::{span_of_attrs, Pass}; +use super::Pass; use crate::clean; use crate::clean::*; use crate::core::DocContext; @@ -97,7 +97,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() { if should_have_doc_example(cx, &item) { debug!("reporting error for {:?} (hir_id={:?})", item, hir_id); - let sp = span_of_attrs(&item.attrs).unwrap_or(item.span.inner()); + let sp = item.attr_span(cx.tcx); cx.tcx.struct_span_lint_hir( crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id, @@ -109,7 +109,7 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { cx.tcx.struct_span_lint_hir( crate::lint::PRIVATE_DOC_TESTS, hir_id, - span_of_attrs(&item.attrs).unwrap_or(item.span.inner()), + item.attr_span(cx.tcx), |lint| lint.build("documentation test in private item").emit(), ); } diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 881feb0d87a47..f29d38e3e078a 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -1,4 +1,4 @@ -use super::{span_of_attrs, Pass}; +use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; @@ -181,7 +181,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { let sp = match super::source_span_for_markdown_range(tcx, &dox, range, &item.attrs) { Some(sp) => sp, - None => span_of_attrs(&item.attrs).unwrap_or(item.span.inner()), + None => item.attr_span(tcx), }; tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { lint.build(msg).emit() From b412b46cf70de4e08cda3ac120ebfa349c1bc268 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 24 Mar 2021 00:52:52 -0400 Subject: [PATCH 2/4] Do the hard part first The only bit failing was the module, so change that before removing the `span` field. --- src/librustdoc/clean/inline.rs | 3 ++- src/librustdoc/clean/mod.rs | 13 ++++++++----- src/librustdoc/clean/types.rs | 9 +++++++-- src/librustdoc/fold.rs | 5 ++++- src/librustdoc/html/render/context.rs | 10 +++++----- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/sources.rs | 6 +++--- src/librustdoc/json/conversions.rs | 3 ++- src/librustdoc/passes/calculate_doc_coverage.rs | 2 +- 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2f6a91641e48e..91073ddfd943c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -487,7 +487,8 @@ fn build_module( } } - clean::Module { items } + let span = clean::Span::from_rustc_span(cx.tcx.def_span(did)); + clean::Module { items, span } } crate fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2dc3f63a2d8e4..93d227e507fff 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -100,7 +100,7 @@ impl Clean for doctree::Module<'_> { // determine if we should display the inner contents or // the outer `mod` item for the source code. - let span = { + let span = Span::from_rustc_span({ let sm = cx.sess().source_map(); let outer = sm.lookup_char_pos(self.where_outer.lo()); let inner = sm.lookup_char_pos(self.where_inner.lo()); @@ -111,11 +111,14 @@ impl Clean for doctree::Module<'_> { // mod foo; (and a separate SourceFile for the contents) self.where_inner } - }; + }); - let what_rustc_thinks = - Item::from_hir_id_and_parts(self.id, Some(self.name), ModuleItem(Module { items }), cx); - Item { span: span.clean(cx), ..what_rustc_thinks } + Item::from_hir_id_and_parts( + self.id, + Some(self.name), + ModuleItem(Module { items, span }), + cx, + ) } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index e2eeacdb567a3..8d07a64360dc4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -232,7 +232,7 @@ impl fmt::Debug for Item { let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id }; fmt.debug_struct("Item") - .field("source", &self.span) + .field("source", &self.span()) .field("name", &self.name) .field("attrs", &self.attrs) .field("kind", &self.kind) @@ -255,8 +255,12 @@ impl Item { if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) } } + crate fn span(&self) -> Span { + if let ItemKind::ModuleItem(Module { span, .. }) = &*self.kind { *span } else { self.span } + } + crate fn attr_span(&self, _tcx: TyCtxt<'_>) -> rustc_span::Span { - crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span.inner()) + crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span().inner()) } /// Finds the `doc` attribute as a NameValue and returns the corresponding @@ -609,6 +613,7 @@ impl ItemKind { #[derive(Clone, Debug)] crate struct Module { crate items: Vec, + crate span: Span, } crate struct ListAttributesIter<'a> { diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index ed91a56057574..37d11d4ed47c4 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -80,7 +80,10 @@ crate trait DocFolder: Sized { } fn fold_mod(&mut self, m: Module) -> Module { - Module { items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect() } + Module { + span: m.span, + items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect(), + } } fn fold_crate(&mut self, mut c: Crate) -> Crate { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 9cffcef9749f8..089167a66730c 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -281,15 +281,15 @@ impl<'tcx> Context<'tcx> { /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. pub(super) fn src_href(&self, item: &clean::Item) -> Option { - if item.span.is_dummy() { + if item.span().is_dummy() { return None; } let mut root = self.root_path(); let mut path = String::new(); - let cnum = item.span.cnum(self.sess()); + let cnum = item.span().cnum(self.sess()); // We can safely ignore synthetic `SourceFile`s. - let file = match item.span.filename(self.sess()) { + let file = match item.span().filename(self.sess()) { FileName::Real(ref path) => path.local_path().to_path_buf(), _ => return None, }; @@ -323,8 +323,8 @@ impl<'tcx> Context<'tcx> { (&*symbol, &path) }; - let loline = item.span.lo(self.sess()).line; - let hiline = item.span.hi(self.sess()).line; + let loline = item.span().lo(self.sess()).line; + let hiline = item.span().hi(self.sess()).line; let lines = if loline == hiline { loline.to_string() } else { format!("{}-{}", loline, hiline) }; Some(format!( diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 5865da9440b16..0fc1c7d60e7e2 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1013,7 +1013,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac Some("macro"), None, None, - it.span.inner().edition(), + it.span().inner().edition(), ); }); document(w, cx, it, None) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 5a2a165191a60..a22ff11b41601 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -41,11 +41,11 @@ impl DocFolder for SourceCollector<'_, '_> { // then we need to render it out to the filesystem. if self.scx.include_sources // skip all synthetic "files" - && item.span.filename(self.sess()).is_real() + && item.span().filename(self.sess()).is_real() // skip non-local files - && item.span.cnum(self.sess()) == LOCAL_CRATE + && item.span().cnum(self.sess()) == LOCAL_CRATE { - let filename = item.span.filename(self.sess()); + let filename = item.span().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 diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 80ef0073da8a4..6e773f7605930 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -40,7 +40,8 @@ impl JsonRenderer<'_> { .iter() .map(rustc_ast_pretty::pprust::attribute_to_string) .collect(); - let clean::Item { span, name, attrs: _, kind: _, visibility, def_id } = item; + let span = item.span(); + let clean::Item { name, attrs: _, kind: _, span: _, visibility, def_id } = item; let inner = match *item.kind { clean::StrippedItem(_) => return None, _ => from_clean_item(item, self.tcx), diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index fdac33fd60e2a..559bf7d83038f 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -211,7 +211,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { None, ); - let filename = i.span.filename(self.ctx.sess()); + let filename = i.span().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); From c44c64df711e407ef10f8ae62100e46f0323065f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 24 Mar 2021 01:20:13 -0400 Subject: [PATCH 3/4] Get rid of `item.span` - Remove `span` field, adding `Item::span()` instead - Special-case `Impl` and `Module` items - Use dummy spans for primitive items --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 6 +-- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 41 +++++++++++-------- src/librustdoc/html/render/context.rs | 10 ++--- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/sources.rs | 8 ++-- src/librustdoc/json/conversions.rs | 5 ++- .../passes/calculate_doc_coverage.rs | 2 +- 10 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 9052e5954200f..010059a89c9b1 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -110,12 +110,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { }; Some(Item { - span: Span::dummy(), name: None, attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(item_def_id.krate), kind: box ImplItem(Impl { + span: Span::dummy(), 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 f7e08d1040188..50c0fb85d5aa0 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -100,12 +100,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .collect(); impls.push(Item { - span: self.cx.tcx.def_span(impl_def_id).clean(self.cx), name: None, attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(impl_def_id.krate), kind: box ImplItem(Impl { + span: self.cx.tcx.def_span(impl_def_id).clean(self.cx), 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 91073ddfd943c..e88a739d04296 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -6,7 +6,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::DefId; use rustc_hir::Mutability; use rustc_metadata::creader::LoadedMacro; use rustc_middle::ty::{self, TyCtxt}; @@ -422,6 +422,7 @@ crate fn build_impl( did, None, clean::ImplItem(clean::Impl { + span: clean::types::rustc_span(did, cx.tcx), unsafety: hir::Unsafety::Normal, generics, provided_trait_methods: provided, @@ -459,8 +460,7 @@ fn build_module( items.push(clean::Item { name: None, attrs: box clean::Attributes::default(), - span: clean::Span::dummy(), - def_id: DefId::local(CRATE_DEF_INDEX), + def_id: cx.next_def_id(did.krate), visibility: clean::Public, kind: box clean::ImportItem(clean::Import::new_simple( item.ident.name, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 93d227e507fff..c0a8c88bdeba0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1945,6 +1945,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> }); let mut make_item = |trait_: Option, for_: Type, items: Vec| { let kind = ImplItem(Impl { + span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx), unsafety: impl_.unsafety, generics: impl_.generics.clean(cx), provided_trait_methods: provided.clone(), @@ -2004,7 +2005,6 @@ fn clean_extern_crate( vec![Item { name: Some(name), attrs: box attrs.clean(cx), - span: krate.span.clean(cx), def_id: crate_def_id, visibility: krate.vis.clean(cx), kind: box ExternCrateItem { src: orig_name }, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 8d07a64360dc4..f310dc3e1b6d9 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -211,7 +211,6 @@ impl ExternalCrate { /// directly to the AST's concept of an item; it's a strict superset. #[derive(Clone)] crate struct Item { - crate span: Span, /// The name of this item. /// Optional because not every item has a name, e.g. impls. crate name: Option, @@ -225,14 +224,13 @@ crate struct Item { // `Item` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Item, 48); +rustc_data_structures::static_assert_size!(Item, 40); impl fmt::Debug for Item { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id }; fmt.debug_struct("Item") - .field("source", &self.span()) .field("name", &self.name) .field("attrs", &self.attrs) .field("kind", &self.kind) @@ -242,6 +240,16 @@ impl fmt::Debug for Item { } } +crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span { + Span::from_rustc_span(def_id.as_local().map_or_else( + || tcx.def_span(def_id), + |local| { + let hir = tcx.hir(); + hir.span_with_body(hir.local_def_id_to_hir_id(local)) + }, + )) +} + impl Item { crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> { if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) } @@ -255,12 +263,20 @@ impl Item { if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) } } - crate fn span(&self) -> Span { - if let ItemKind::ModuleItem(Module { span, .. }) = &*self.kind { *span } else { self.span } + crate fn span(&self, tcx: TyCtxt<'_>) -> Span { + if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) = + &*self.kind + { + *span + } else if self.is_fake() { + Span::dummy() + } else { + rustc_span(self.def_id, tcx) + } } - crate fn attr_span(&self, _tcx: TyCtxt<'_>) -> rustc_span::Span { - crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span().inner()) + crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span { + crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner()) } /// Finds the `doc` attribute as a NameValue and returns the corresponding @@ -304,20 +320,10 @@ impl Item { ) -> Item { debug!("name={:?}, def_id={:?}", name, def_id); - // `span_if_local()` lies about functions and only gives the span of the function signature - let span = def_id.as_local().map_or_else( - || cx.tcx.def_span(def_id), - |local| { - let hir = cx.tcx.hir(); - hir.span_with_body(hir.local_def_id_to_hir_id(local)) - }, - ); - Item { def_id, kind: box kind, name, - span: span.clean(cx), attrs, visibility: cx.tcx.visibility(def_id).clean(cx), } @@ -2117,6 +2123,7 @@ impl Constant { #[derive(Clone, Debug)] crate struct Impl { + crate span: Span, crate unsafety: hir::Unsafety, crate generics: Generics, crate provided_trait_methods: FxHashSet, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 089167a66730c..6d45ed69c1232 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -281,15 +281,15 @@ impl<'tcx> Context<'tcx> { /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. pub(super) fn src_href(&self, item: &clean::Item) -> Option { - if item.span().is_dummy() { + if item.span(self.tcx()).is_dummy() { return None; } let mut root = self.root_path(); let mut path = String::new(); - let cnum = item.span().cnum(self.sess()); + let cnum = item.span(self.tcx()).cnum(self.sess()); // We can safely ignore synthetic `SourceFile`s. - let file = match item.span().filename(self.sess()) { + let file = match item.span(self.tcx()).filename(self.sess()) { FileName::Real(ref path) => path.local_path().to_path_buf(), _ => return None, }; @@ -323,8 +323,8 @@ impl<'tcx> Context<'tcx> { (&*symbol, &path) }; - let loline = item.span().lo(self.sess()).line; - let hiline = item.span().hi(self.sess()).line; + let loline = item.span(self.tcx()).lo(self.sess()).line; + let hiline = item.span(self.tcx()).hi(self.sess()).line; let lines = if loline == hiline { loline.to_string() } else { format!("{}-{}", loline, hiline) }; Some(format!( diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0fc1c7d60e7e2..f1d79ab097b9f 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1013,7 +1013,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac Some("macro"), None, None, - it.span().inner().edition(), + it.span(cx.tcx()).inner().edition(), ); }); document(w, cx, it, None) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index a22ff11b41601..3d4d8df0a7198 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -41,11 +41,11 @@ impl DocFolder for SourceCollector<'_, '_> { // then we need to render it out to the filesystem. if self.scx.include_sources // skip all synthetic "files" - && item.span().filename(self.sess()).is_real() + && item.span(self.scx.tcx).filename(self.sess()).is_real() // skip non-local files - && item.span().cnum(self.sess()) == LOCAL_CRATE + && item.span(self.scx.tcx).cnum(self.sess()) == LOCAL_CRATE { - let filename = item.span().filename(self.sess()); + let filename = item.span(self.scx.tcx).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 @@ -55,7 +55,7 @@ impl DocFolder for SourceCollector<'_, '_> { Ok(()) => true, Err(e) => { self.scx.tcx.sess.span_err( - item.span.inner(), + item.span(self.scx.tcx).inner(), &format!("failed to render source code for `{}`: {}", filename, e), ); false diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 6e773f7605930..42cd765c294b1 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -40,8 +40,8 @@ impl JsonRenderer<'_> { .iter() .map(rustc_ast_pretty::pprust::attribute_to_string) .collect(); - let span = item.span(); - let clean::Item { name, attrs: _, kind: _, span: _, visibility, def_id } = item; + let span = item.span(self.tcx); + let clean::Item { name, attrs: _, kind: _, visibility, def_id } = item; let inner = match *item.kind { clean::StrippedItem(_) => return None, _ => from_clean_item(item, self.tcx), @@ -463,6 +463,7 @@ impl FromWithTcx for Impl { negative_polarity, synthetic, blanket_impl, + span: _span, } = impl_; Impl { is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 559bf7d83038f..c8b82fb1563df 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -211,7 +211,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { None, ); - let filename = i.span().filename(self.ctx.sess()); + let filename = i.span(self.ctx.tcx).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); From ba361428509ddabfcee5b4274d4068d4d612f963 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 23 Apr 2021 00:26:29 -0400 Subject: [PATCH 4/4] Finally (finally) ((finally!!!!)) fix spans for the standard library --- src/librustdoc/clean/types.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f310dc3e1b6d9..607a634c1bced 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -264,8 +264,12 @@ impl Item { } crate fn span(&self, tcx: TyCtxt<'_>) -> Span { + let kind = match &*self.kind { + ItemKind::StrippedItem(k) => k, + _ => &*self.kind, + }; if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) = - &*self.kind + kind { *span } else if self.is_fake() {