Skip to content

Commit f7c468f

Browse files
committed
Auto merge of rust-lang#80339 - jyn514:no-span, r=GuillaumeGomez
Calculate `span` info on-demand - Add helper `attr_span` for common reused function - Stop storing `Span`s on `Item` directly; calculate them on demand instead - Special case modules, which have different spans depending on whether you use inner or outer attributes - Special case impls with fake IDs, which can have either dummy spans (for auto traits) or the DefId of the impl block (for blanket impls) - Use a fake ID for primitives instead of the ID of the crate; this lets `source()` know that it should use a dummy span instead of the span of the crate. This shrinks `Item` from 48 to 40 bytes. Helps with rust-lang#76382.
2 parents b56b175 + ba36142 commit f7c468f

16 files changed

+80
-55
lines changed

Diff for: src/librustdoc/clean/auto_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
110110
};
111111

112112
Some(Item {
113-
span: Span::dummy(),
114113
name: None,
115114
attrs: Default::default(),
116115
visibility: Inherited,
117116
def_id: self.cx.next_def_id(item_def_id.krate),
118117
kind: box ImplItem(Impl {
118+
span: Span::dummy(),
119119
unsafety: hir::Unsafety::Normal,
120120
generics: new_generics,
121121
provided_trait_methods: Default::default(),

Diff for: src/librustdoc/clean/blanket_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
100100
.collect();
101101

102102
impls.push(Item {
103-
span: self.cx.tcx.def_span(impl_def_id).clean(self.cx),
104103
name: None,
105104
attrs: Default::default(),
106105
visibility: Inherited,
107106
def_id: self.cx.next_def_id(impl_def_id.krate),
108107
kind: box ImplItem(Impl {
108+
span: self.cx.tcx.def_span(impl_def_id).clean(self.cx),
109109
unsafety: hir::Unsafety::Normal,
110110
generics: (
111111
self.cx.tcx.generics_of(impl_def_id),

Diff for: src/librustdoc/clean/inline.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_ast as ast;
66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_hir as hir;
88
use rustc_hir::def::{DefKind, Res};
9-
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
9+
use rustc_hir::def_id::DefId;
1010
use rustc_hir::Mutability;
1111
use rustc_metadata::creader::LoadedMacro;
1212
use rustc_middle::ty::{self, TyCtxt};
@@ -422,6 +422,7 @@ crate fn build_impl(
422422
did,
423423
None,
424424
clean::ImplItem(clean::Impl {
425+
span: clean::types::rustc_span(did, cx.tcx),
425426
unsafety: hir::Unsafety::Normal,
426427
generics,
427428
provided_trait_methods: provided,
@@ -459,8 +460,7 @@ fn build_module(
459460
items.push(clean::Item {
460461
name: None,
461462
attrs: box clean::Attributes::default(),
462-
span: clean::Span::dummy(),
463-
def_id: DefId::local(CRATE_DEF_INDEX),
463+
def_id: cx.next_def_id(did.krate),
464464
visibility: clean::Public,
465465
kind: box clean::ImportItem(clean::Import::new_simple(
466466
item.ident.name,
@@ -487,7 +487,8 @@ fn build_module(
487487
}
488488
}
489489

490-
clean::Module { items }
490+
let span = clean::Span::from_rustc_span(cx.tcx.def_span(did));
491+
clean::Module { items, span }
491492
}
492493

493494
crate fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {

Diff for: src/librustdoc/clean/mod.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl Clean<Item> for doctree::Module<'_> {
100100

101101
// determine if we should display the inner contents or
102102
// the outer `mod` item for the source code.
103-
let span = {
103+
let span = Span::from_rustc_span({
104104
let sm = cx.sess().source_map();
105105
let outer = sm.lookup_char_pos(self.where_outer.lo());
106106
let inner = sm.lookup_char_pos(self.where_inner.lo());
@@ -111,11 +111,14 @@ impl Clean<Item> for doctree::Module<'_> {
111111
// mod foo; (and a separate SourceFile for the contents)
112112
self.where_inner
113113
}
114-
};
114+
});
115115

116-
let what_rustc_thinks =
117-
Item::from_hir_id_and_parts(self.id, Some(self.name), ModuleItem(Module { items }), cx);
118-
Item { span: span.clean(cx), ..what_rustc_thinks }
116+
Item::from_hir_id_and_parts(
117+
self.id,
118+
Some(self.name),
119+
ModuleItem(Module { items, span }),
120+
cx,
121+
)
119122
}
120123
}
121124

@@ -1942,6 +1945,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>
19421945
});
19431946
let mut make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| {
19441947
let kind = ImplItem(Impl {
1948+
span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx),
19451949
unsafety: impl_.unsafety,
19461950
generics: impl_.generics.clean(cx),
19471951
provided_trait_methods: provided.clone(),
@@ -2001,7 +2005,6 @@ fn clean_extern_crate(
20012005
vec![Item {
20022006
name: Some(name),
20032007
attrs: box attrs.clean(cx),
2004-
span: krate.span.clean(cx),
20052008
def_id: crate_def_id,
20062009
visibility: krate.vis.clean(cx),
20072010
kind: box ExternCrateItem { src: orig_name },

Diff for: src/librustdoc/clean/types.rs

+33-13
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ impl ExternalCrate {
211211
/// directly to the AST's concept of an item; it's a strict superset.
212212
#[derive(Clone)]
213213
crate struct Item {
214-
crate span: Span,
215214
/// The name of this item.
216215
/// Optional because not every item has a name, e.g. impls.
217216
crate name: Option<Symbol>,
@@ -225,14 +224,13 @@ crate struct Item {
225224

226225
// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
227226
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
228-
rustc_data_structures::static_assert_size!(Item, 48);
227+
rustc_data_structures::static_assert_size!(Item, 40);
229228

230229
impl fmt::Debug for Item {
231230
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
232231
let def_id: &dyn fmt::Debug = if self.is_fake() { &"**FAKE**" } else { &self.def_id };
233232

234233
fmt.debug_struct("Item")
235-
.field("source", &self.span)
236234
.field("name", &self.name)
237235
.field("attrs", &self.attrs)
238236
.field("kind", &self.kind)
@@ -242,6 +240,16 @@ impl fmt::Debug for Item {
242240
}
243241
}
244242

243+
crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
244+
Span::from_rustc_span(def_id.as_local().map_or_else(
245+
|| tcx.def_span(def_id),
246+
|local| {
247+
let hir = tcx.hir();
248+
hir.span_with_body(hir.local_def_id_to_hir_id(local))
249+
},
250+
))
251+
}
252+
245253
impl Item {
246254
crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
247255
if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) }
@@ -255,6 +263,26 @@ impl Item {
255263
if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
256264
}
257265

266+
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
267+
let kind = match &*self.kind {
268+
ItemKind::StrippedItem(k) => k,
269+
_ => &*self.kind,
270+
};
271+
if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
272+
kind
273+
{
274+
*span
275+
} else if self.is_fake() {
276+
Span::dummy()
277+
} else {
278+
rustc_span(self.def_id, tcx)
279+
}
280+
}
281+
282+
crate fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
283+
crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
284+
}
285+
258286
/// Finds the `doc` attribute as a NameValue and returns the corresponding
259287
/// value found.
260288
crate fn doc_value(&self) -> Option<String> {
@@ -296,20 +324,10 @@ impl Item {
296324
) -> Item {
297325
debug!("name={:?}, def_id={:?}", name, def_id);
298326

299-
// `span_if_local()` lies about functions and only gives the span of the function signature
300-
let span = def_id.as_local().map_or_else(
301-
|| cx.tcx.def_span(def_id),
302-
|local| {
303-
let hir = cx.tcx.hir();
304-
hir.span_with_body(hir.local_def_id_to_hir_id(local))
305-
},
306-
);
307-
308327
Item {
309328
def_id,
310329
kind: box kind,
311330
name,
312-
span: span.clean(cx),
313331
attrs,
314332
visibility: cx.tcx.visibility(def_id).clean(cx),
315333
}
@@ -605,6 +623,7 @@ impl ItemKind {
605623
#[derive(Clone, Debug)]
606624
crate struct Module {
607625
crate items: Vec<Item>,
626+
crate span: Span,
608627
}
609628

610629
crate struct ListAttributesIter<'a> {
@@ -2108,6 +2127,7 @@ impl Constant {
21082127

21092128
#[derive(Clone, Debug)]
21102129
crate struct Impl {
2130+
crate span: Span,
21112131
crate unsafety: hir::Unsafety,
21122132
crate generics: Generics,
21132133
crate provided_trait_methods: FxHashSet<Symbol>,

Diff for: src/librustdoc/fold.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ crate trait DocFolder: Sized {
8080
}
8181

8282
fn fold_mod(&mut self, m: Module) -> Module {
83-
Module { items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect() }
83+
Module {
84+
span: m.span,
85+
items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect(),
86+
}
8487
}
8588

8689
fn fold_crate(&mut self, mut c: Crate) -> Crate {

Diff for: src/librustdoc/html/render/context.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -281,15 +281,15 @@ impl<'tcx> Context<'tcx> {
281281
/// may happen, for example, with externally inlined items where the source
282282
/// of their crate documentation isn't known.
283283
pub(super) fn src_href(&self, item: &clean::Item) -> Option<String> {
284-
if item.span.is_dummy() {
284+
if item.span(self.tcx()).is_dummy() {
285285
return None;
286286
}
287287
let mut root = self.root_path();
288288
let mut path = String::new();
289-
let cnum = item.span.cnum(self.sess());
289+
let cnum = item.span(self.tcx()).cnum(self.sess());
290290

291291
// We can safely ignore synthetic `SourceFile`s.
292-
let file = match item.span.filename(self.sess()) {
292+
let file = match item.span(self.tcx()).filename(self.sess()) {
293293
FileName::Real(ref path) => path.local_path().to_path_buf(),
294294
_ => return None,
295295
};
@@ -323,8 +323,8 @@ impl<'tcx> Context<'tcx> {
323323
(&*symbol, &path)
324324
};
325325

326-
let loline = item.span.lo(self.sess()).line;
327-
let hiline = item.span.hi(self.sess()).line;
326+
let loline = item.span(self.tcx()).lo(self.sess()).line;
327+
let hiline = item.span(self.tcx()).hi(self.sess()).line;
328328
let lines =
329329
if loline == hiline { loline.to_string() } else { format!("{}-{}", loline, hiline) };
330330
Some(format!(

Diff for: src/librustdoc/html/render/print_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac
10131013
Some("macro"),
10141014
None,
10151015
None,
1016-
it.span.inner().edition(),
1016+
it.span(cx.tcx()).inner().edition(),
10171017
);
10181018
});
10191019
document(w, cx, it, None)

Diff for: src/librustdoc/html/sources.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ impl DocFolder for SourceCollector<'_, '_> {
4141
// then we need to render it out to the filesystem.
4242
if self.scx.include_sources
4343
// skip all synthetic "files"
44-
&& item.span.filename(self.sess()).is_real()
44+
&& item.span(self.scx.tcx).filename(self.sess()).is_real()
4545
// skip non-local files
46-
&& item.span.cnum(self.sess()) == LOCAL_CRATE
46+
&& item.span(self.scx.tcx).cnum(self.sess()) == LOCAL_CRATE
4747
{
48-
let filename = item.span.filename(self.sess());
48+
let filename = item.span(self.scx.tcx).filename(self.sess());
4949
// If it turns out that we couldn't read this file, then we probably
5050
// can't read any of the files (generating html output from json or
5151
// something like that), so just don't include sources for the
@@ -55,7 +55,7 @@ impl DocFolder for SourceCollector<'_, '_> {
5555
Ok(()) => true,
5656
Err(e) => {
5757
self.scx.tcx.sess.span_err(
58-
item.span.inner(),
58+
item.span(self.scx.tcx).inner(),
5959
&format!("failed to render source code for `{}`: {}", filename, e),
6060
);
6161
false

Diff for: src/librustdoc/json/conversions.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ impl JsonRenderer<'_> {
4040
.iter()
4141
.map(rustc_ast_pretty::pprust::attribute_to_string)
4242
.collect();
43-
let clean::Item { span, name, attrs: _, kind: _, visibility, def_id } = item;
43+
let span = item.span(self.tcx);
44+
let clean::Item { name, attrs: _, kind: _, visibility, def_id } = item;
4445
let inner = match *item.kind {
4546
clean::StrippedItem(_) => return None,
4647
_ => from_clean_item(item, self.tcx),
@@ -462,6 +463,7 @@ impl FromWithTcx<clean::Impl> for Impl {
462463
negative_polarity,
463464
synthetic,
464465
blanket_impl,
466+
span: _span,
465467
} = impl_;
466468
Impl {
467469
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,

Diff for: src/librustdoc/passes/bare_urls.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{span_of_attrs, Pass};
1+
use super::Pass;
22
use crate::clean::*;
33
use crate::core::DocContext;
44
use crate::fold::DocFolder;
@@ -69,8 +69,7 @@ impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
6969
if !dox.is_empty() {
7070
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
7171
let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
72-
.or_else(|| span_of_attrs(&item.attrs))
73-
.unwrap_or(item.span.inner());
72+
.unwrap_or_else(|| item.attr_span(cx.tcx));
7473
cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| {
7574
lint.build(msg)
7675
.note("bare URLs are not automatically turned into clickable links")

Diff for: src/librustdoc/passes/calculate_doc_coverage.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
211211
None,
212212
);
213213

214-
let filename = i.span.filename(self.ctx.sess());
214+
let filename = i.span(self.ctx.tcx).filename(self.ctx.sess());
215215
let has_doc_example = tests.found_tests != 0;
216216
let hir_id = self.ctx.tcx.hir().local_def_id_to_hir_id(i.def_id.expect_local());
217217
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);

Diff for: src/librustdoc/passes/check_code_block_syntax.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::clean;
99
use crate::core::DocContext;
1010
use crate::fold::DocFolder;
1111
use crate::html::markdown::{self, RustCodeBlock};
12-
use crate::passes::{span_of_attrs, Pass};
12+
use crate::passes::Pass;
1313

1414
crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
1515
name: "check-code-block-syntax",
@@ -86,7 +86,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
8686
// We couldn't calculate the span of the markdown block that had the error, so our
8787
// diagnostics are going to be a bit lacking.
8888
let mut diag = self.cx.sess().struct_span_warn(
89-
super::span_of_attrs(&item.attrs).unwrap_or(item.span.inner()),
89+
item.attr_span(self.cx.tcx),
9090
"doc comment contains an invalid Rust code block",
9191
);
9292

@@ -110,7 +110,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
110110
impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
111111
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
112112
if let Some(dox) = &item.attrs.collapsed_doc_value() {
113-
let sp = span_of_attrs(&item.attrs).unwrap_or(item.span.inner());
113+
let sp = item.attr_span(self.cx.tcx);
114114
let extra = crate::html::markdown::ExtraInfo::new_did(self.cx.tcx, item.def_id, sp);
115115
for code_block in markdown::rust_code_blocks(&dox, &extra) {
116116
self.check_rust_syntax(&item, &dox, code_block);

Diff for: src/librustdoc/passes/collect_intra_doc_links.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ use crate::html::markdown::{markdown_links, MarkdownLink};
3737
use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
3838
use crate::passes::Pass;
3939

40-
use super::span_of_attrs;
41-
4240
mod early;
4341
crate use early::IntraLinkCrateLoader;
4442

@@ -1242,7 +1240,7 @@ impl LinkCollector<'_, '_> {
12421240
&ori_link.range,
12431241
&item.attrs,
12441242
)
1245-
.unwrap_or_else(|| span_of_attrs(&item.attrs).unwrap_or(item.span.inner()));
1243+
.unwrap_or_else(|| item.attr_span(self.cx.tcx));
12461244

12471245
rustc_session::parse::feature_err(
12481246
&self.cx.tcx.sess.parse_sess,
@@ -1695,13 +1693,12 @@ fn report_diagnostic(
16951693
}
16961694
};
16971695

1698-
let attrs = &item.attrs;
1699-
let sp = span_of_attrs(attrs).unwrap_or(item.span.inner());
1696+
let sp = item.attr_span(tcx);
17001697

17011698
tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
17021699
let mut diag = lint.build(msg);
17031700

1704-
let span = super::source_span_for_markdown_range(tcx, dox, link_range, attrs);
1701+
let span = super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs);
17051702

17061703
if let Some(sp) = span {
17071704
diag.set_span(sp);

0 commit comments

Comments
 (0)