Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculate span info on-demand #80339

Merged
merged 4 commits into from
Apr 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustdoc/clean/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/blanket_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
9 changes: 5 additions & 4 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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 {
Expand Down
15 changes: 9 additions & 6 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl Clean<Item> 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());
Expand All @@ -111,11 +111,14 @@ impl Clean<Item> 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,
)
}
}

Expand Down Expand Up @@ -1942,6 +1945,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>
});
let mut make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| {
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(),
Expand Down Expand Up @@ -2001,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 },
Expand Down
46 changes: 33 additions & 13 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Symbol>,
Expand All @@ -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)
Expand All @@ -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) }
Expand All @@ -255,6 +263,26 @@ impl Item {
if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
}

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, .. }) =
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(tcx).inner())
}

/// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found.
crate fn doc_value(&self) -> Option<String> {
Expand Down Expand Up @@ -296,20 +324,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),
}
Expand Down Expand Up @@ -605,6 +623,7 @@ impl ItemKind {
#[derive(Clone, Debug)]
crate struct Module {
crate items: Vec<Item>,
crate span: Span,
}

crate struct ListAttributesIter<'a> {
Expand Down Expand Up @@ -2108,6 +2127,7 @@ impl Constant {

#[derive(Clone, Debug)]
crate struct Impl {
crate span: Span,
crate unsafety: hir::Unsafety,
crate generics: Generics,
crate provided_trait_methods: FxHashSet<Symbol>,
Expand Down
5 changes: 4 additions & 1 deletion src/librustdoc/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> {
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,
};
Expand Down Expand Up @@ -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!(
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/librustdoc/html/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(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),
Expand Down Expand Up @@ -462,6 +463,7 @@ impl FromWithTcx<clean::Impl> for Impl {
negative_polarity,
synthetic,
blanket_impl,
span: _span,
} = impl_;
Impl {
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
Expand Down
5 changes: 2 additions & 3 deletions src/librustdoc/passes/bare_urls.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{span_of_attrs, Pass};
use super::Pass;
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
Expand Down Expand Up @@ -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<usize>| {
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")
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/passes/calculate_doc_coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/librustdoc/passes/check_code_block_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
);

Expand All @@ -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<clean::Item> {
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);
Expand Down
9 changes: 3 additions & 6 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
Loading