Skip to content

Commit e2d3a4f

Browse files
committed
rustc_metadata: Store a flag telling whether an item may have doc links in its attributes
This should be cheap on rustc side, but it's significant optimization for rustdoc that won't need to decode and process attributes unnecessarily
1 parent f5ca02c commit e2d3a4f

File tree

9 files changed

+48
-20
lines changed

9 files changed

+48
-20
lines changed

compiler/rustc_ast/src/attr/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::token::{self, CommentKind, Token};
99
use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
1010
use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing};
1111
use crate::tokenstream::{LazyTokenStream, TokenStream};
12+
use crate::util::comments;
1213

1314
use rustc_index::bit_set::GrowableBitSet;
1415
use rustc_span::source_map::BytePos;
@@ -262,6 +263,10 @@ impl Attribute {
262263
}
263264
}
264265

266+
pub fn may_have_doc_links(&self) -> bool {
267+
self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
268+
}
269+
265270
pub fn get_normal_item(&self) -> &AttrItem {
266271
match self.kind {
267272
AttrKind::Normal(ref item, _) => item,

compiler/rustc_ast/src/util/comments.rs

+8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ pub struct Comment {
2424
pub pos: BytePos,
2525
}
2626

27+
/// A fast conservative estimate on whether the string can contain documentation links.
28+
/// A pair of square brackets `[]` must exist in the string, but we only search for the
29+
/// opening bracket because brackets always go in pairs in practice.
30+
#[inline]
31+
pub fn may_have_doc_links(s: &str) -> bool {
32+
s.contains('[')
33+
}
34+
2735
/// Makes a doc string more presentable to users.
2836
/// Used by rustdoc and perhaps other tools, but not by rustc.
2937
pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {

compiler/rustc_metadata/src/rmeta/decoder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
17441744
adjustments: generator_data.adjustments,
17451745
})
17461746
}
1747+
1748+
fn get_may_have_doc_links(self, index: DefIndex) -> bool {
1749+
self.root.tables.may_have_doc_links.get(self, index).is_some()
1750+
}
17471751
}
17481752

17491753
impl CrateMetadata {

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+4
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,10 @@ impl CStore {
531531
) -> impl Iterator<Item = DefId> + '_ {
532532
self.get_crate_data(cnum).get_all_incoherent_impls()
533533
}
534+
535+
pub fn may_have_doc_links_untracked(&self, def_id: DefId) -> bool {
536+
self.get_crate_data(def_id.krate).get_may_have_doc_links(def_id.index)
537+
}
534538
}
535539

536540
impl CrateStore for CStore {

compiler/rustc_metadata/src/rmeta/encoder.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,14 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
977977
}
978978

979979
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
980+
fn encode_attrs(&mut self, def_id: DefId) {
981+
let attrs = self.tcx.get_attrs(def_id);
982+
record!(self.tables.attributes[def_id] <- attrs);
983+
if attrs.iter().any(|attr| attr.may_have_doc_links()) {
984+
self.tables.may_have_doc_links.set(def_id.index, ());
985+
}
986+
}
987+
980988
fn encode_def_ids(&mut self) {
981989
if self.is_proc_macro {
982990
return;
@@ -989,7 +997,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
989997
let Some(def_kind) = def_kind else { continue };
990998
self.tables.opt_def_kind.set(def_id.index, def_kind);
991999
record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
992-
record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id));
1000+
self.encode_attrs(def_id);
9931001
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
9941002
if should_encode_visibility(def_kind) {
9951003
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
@@ -1651,7 +1659,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16511659

16521660
self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
16531661
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
1654-
record!(self.tables.attributes[LOCAL_CRATE.as_def_id()] <- tcx.get_attrs(LOCAL_CRATE.as_def_id()));
1662+
self.encode_attrs(LOCAL_CRATE.as_def_id());
16551663
record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id()));
16561664
if let Some(stability) = stability {
16571665
record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
@@ -1692,7 +1700,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16921700
let def_id = id.to_def_id();
16931701
self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
16941702
record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
1695-
record!(self.tables.attributes[def_id] <- attrs);
1703+
self.encode_attrs(def_id);
16961704
record!(self.tables.def_keys[def_id] <- def_key);
16971705
record!(self.tables.def_ident_span[def_id] <- span);
16981706
record!(self.tables.def_span[def_id] <- span);

compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ define_tables! {
360360
def_path_hashes: Table<DefIndex, DefPathHash>,
361361
proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
362362
generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>,
363+
may_have_doc_links: Table<DefIndex, ()>,
363364
}
364365

365366
#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]

compiler/rustc_metadata/src/rmeta/table.rs

+14
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,20 @@ impl FixedSizeEncoding for Option<RawDefId> {
186186
}
187187
}
188188

189+
impl FixedSizeEncoding for Option<()> {
190+
type ByteArray = [u8; 1];
191+
192+
#[inline]
193+
fn from_bytes(b: &[u8; 1]) -> Self {
194+
(b[0] != 0).then(|| ())
195+
}
196+
197+
#[inline]
198+
fn write_to_bytes(self, b: &mut [u8; 1]) {
199+
b[0] = self.is_some() as u8
200+
}
201+
}
202+
189203
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
190204
// generic `Lazy<T>` impl, but in the general case we might not need / want to
191205
// fit every `usize` in `u32`.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
2+
// check-pass
23
#![deny(warnings)]
34

45
//! Email me at <hello@localhost>.
5-
//~^ ERROR unknown disambiguator `hello`
66
77
//! This should *not* warn: <[email protected]>.

src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr

-16
This file was deleted.

0 commit comments

Comments
 (0)