about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-04-25 01:57:10 +0000
committerbors <bors@rust-lang.org>2021-04-25 01:57:10 +0000
commitf7c468fe9a1448b1f6ceee6a4c831fe6122a54f0 (patch)
treec068cc9a2a5b1aa8b29d30d48fd551f813067a58
parentb56b175c6c3d77f66793b2062b6325f822c87136 (diff)
parentba361428509ddabfcee5b4274d4068d4d612f963 (diff)
downloadrust-f7c468fe9a1448b1f6ceee6a4c831fe6122a54f0.tar.gz
rust-f7c468fe9a1448b1f6ceee6a4c831fe6122a54f0.zip
Auto merge of #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 https://github.com/rust-lang/rust/issues/76382.
-rw-r--r--src/librustdoc/clean/auto_trait.rs2
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/inline.rs9
-rw-r--r--src/librustdoc/clean/mod.rs15
-rw-r--r--src/librustdoc/clean/types.rs46
-rw-r--r--src/librustdoc/fold.rs5
-rw-r--r--src/librustdoc/html/render/context.rs10
-rw-r--r--src/librustdoc/html/render/print_item.rs2
-rw-r--r--src/librustdoc/html/sources.rs8
-rw-r--r--src/librustdoc/json/conversions.rs4
-rw-r--r--src/librustdoc/passes/bare_urls.rs5
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs2
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs9
-rw-r--r--src/librustdoc/passes/doc_test_lints.rs6
-rw-r--r--src/librustdoc/passes/html_tags.rs4
16 files changed, 80 insertions, 55 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 9052e595420..010059a89c9 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 f7e08d10401..50c0fb85d5a 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 2f6a91641e4..e88a739d042 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,
@@ -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 2dc3f63a2d8..c0a8c88bdeb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -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());
@@ -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,
+        )
     }
 }
 
@@ -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(),
@@ -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 },
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0b55d276bad..607a634c1bc 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<Symbol>,
@@ -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,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> {
@@ -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),
         }
@@ -605,6 +623,7 @@ impl ItemKind {
 #[derive(Clone, Debug)]
 crate struct Module {
     crate items: Vec<Item>,
+    crate span: Span,
 }
 
 crate struct ListAttributesIter<'a> {
@@ -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>,
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index ed91a560575..37d11d4ed47 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 9cffcef9749..6d45ed69c12 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<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,
         };
@@ -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 5865da9440b..f1d79ab097b 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 5a2a165191a..3d4d8df0a71 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 80ef0073da8..42cd765c294 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(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),
@@ -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,
diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs
index ac0d74cbbb9..56ef15eb884 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<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")
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index fdac33fd60e..c8b82fb1563 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);
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index f98f524ca40..68a66806e04 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<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);
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 837cd034b65..dad6593248d 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 b3635848990..c8d2263d81d 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 881feb0d87a..f29d38e3e07 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()