diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 91d5758077c94..1a4786c9b0664 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -415,29 +415,28 @@ impl Item { .unwrap_or(false) } - pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Span { + pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { let kind = match &*self.kind { ItemKind::StrippedItem(k) => k, _ => &*self.kind, }; match kind { - ItemKind::ModuleItem(Module { span, .. }) => *span, - ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => Span::dummy(), + ItemKind::ModuleItem(Module { span, .. }) => Some(*span), + ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None, ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => { if let ItemId::Blanket { impl_id, .. } = self.item_id { - rustc_span(impl_id, tcx) + Some(rustc_span(impl_id, tcx)) } else { panic!("blanket impl item has non-blanket ID") } } - _ => { - self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy) - } + _ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)), } } pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span { - crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner()) + crate::passes::span_of_attrs(&self.attrs) + .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner())) } /// Finds the `doc` attribute as a NameValue and returns the corresponding @@ -2109,14 +2108,6 @@ impl Span { self.0 } - pub(crate) fn dummy() -> Self { - Self(rustc_span::DUMMY_SP) - } - - pub(crate) fn is_dummy(&self) -> bool { - self.0.is_dummy() - } - pub(crate) fn filename(&self, sess: &Session) -> FileName { sess.source_map().span_to_filename(self.0) } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 2ed7a6f1bb144..6f029c66c0b7d 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -301,13 +301,10 @@ 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 { - self.href_from_span(item.span(self.tcx()), true) + self.href_from_span(item.span(self.tcx())?, true) } pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option { - if span.is_dummy() { - return None; - } let mut root = self.root_path(); let mut path = String::new(); let cnum = span.cnum(self.sess()); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 09c54969ef122..5ed5299e09bc0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2677,7 +2677,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite let contents = match fs::read_to_string(&path) { Ok(contents) => contents, Err(err) => { - let span = item.span(tcx).inner(); + let span = item.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()); tcx.sess .span_err(span, &format!("failed to read file {}: {}", path.display(), err)); return false; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index f508808a8b6f5..f37c54e42983f 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -53,6 +53,7 @@ impl LocalSourcesCollector<'_, '_> { fn add_local_source(&mut self, item: &clean::Item) { let sess = self.tcx.sess; let span = item.span(self.tcx); + let Some(span) = span else { return }; // skip all synthetic "files" if !is_real_and_local(span, sess) { return; @@ -109,6 +110,7 @@ impl DocVisitor for SourceCollector<'_, '_> { let tcx = self.cx.tcx(); let span = item.span(tcx); + let Some(span) = span else { return }; let sess = tcx.sess; // If we're not rendering sources, there's nothing to do. diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4c21fd553289b..14d99f3410d43 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -59,7 +59,7 @@ impl JsonRenderer<'_> { id: from_item_id_with_name(item_id, self.tcx, name), crate_id: item_id.krate().as_u32(), name: name.map(|sym| sym.to_string()), - span: self.convert_span(span), + span: span.and_then(|span| self.convert_span(span)), visibility: self.convert_visibility(visibility), docs, attrs, diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 4c6e3eb040d27..48835abf9525b 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -215,7 +215,6 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { None, ); - let filename = i.span(self.ctx.tcx).filename(self.ctx.sess()); let has_doc_example = tests.found_tests != 0; // The `expect_def_id()` should be okay because `local_def_id_to_hir_id` // would presumably panic if a fake `DefIndex` were passed. @@ -261,13 +260,16 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { let should_have_docs = !should_be_ignored && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default)); - 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), - should_have_docs, - ); + if let Some(span) = i.span(self.ctx.tcx) { + let filename = span.filename(self.ctx.sess()); + 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), + should_have_docs, + ); + } } } diff --git a/src/test/rustdoc-json/impls/auto.rs b/src/test/rustdoc-json/impls/auto.rs new file mode 100644 index 0000000000000..fb32d7c31bc9b --- /dev/null +++ b/src/test/rustdoc-json/impls/auto.rs @@ -0,0 +1,18 @@ +#![feature(no_core, auto_traits, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +pub auto trait Bar {} + +/// has span +impl Foo { + pub fn baz(&self) {} +} + +// Testing spans, so all tests below code +// @is auto.json "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null +// @is - "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]" +// @is - "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]" +pub struct Foo;