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
This commit is contained in:
parent
f5ca02c334
commit
e2d3a4f631
@ -9,6 +9,7 @@ use crate::token::{self, CommentKind, Token};
|
||||
use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
|
||||
use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing};
|
||||
use crate::tokenstream::{LazyTokenStream, TokenStream};
|
||||
use crate::util::comments;
|
||||
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_span::source_map::BytePos;
|
||||
@ -262,6 +263,10 @@ impl Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn may_have_doc_links(&self) -> bool {
|
||||
self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
|
||||
}
|
||||
|
||||
pub fn get_normal_item(&self) -> &AttrItem {
|
||||
match self.kind {
|
||||
AttrKind::Normal(ref item, _) => item,
|
||||
|
@ -24,6 +24,14 @@ pub struct Comment {
|
||||
pub pos: BytePos,
|
||||
}
|
||||
|
||||
/// A fast conservative estimate on whether the string can contain documentation links.
|
||||
/// A pair of square brackets `[]` must exist in the string, but we only search for the
|
||||
/// opening bracket because brackets always go in pairs in practice.
|
||||
#[inline]
|
||||
pub fn may_have_doc_links(s: &str) -> bool {
|
||||
s.contains('[')
|
||||
}
|
||||
|
||||
/// Makes a doc string more presentable to users.
|
||||
/// Used by rustdoc and perhaps other tools, but not by rustc.
|
||||
pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
|
||||
|
@ -1744,6 +1744,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
adjustments: generator_data.adjustments,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_may_have_doc_links(self, index: DefIndex) -> bool {
|
||||
self.root.tables.may_have_doc_links.get(self, index).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl CrateMetadata {
|
||||
|
@ -531,6 +531,10 @@ impl CStore {
|
||||
) -> impl Iterator<Item = DefId> + '_ {
|
||||
self.get_crate_data(cnum).get_all_incoherent_impls()
|
||||
}
|
||||
|
||||
pub fn may_have_doc_links_untracked(&self, def_id: DefId) -> bool {
|
||||
self.get_crate_data(def_id.krate).get_may_have_doc_links(def_id.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl CrateStore for CStore {
|
||||
|
@ -977,6 +977,14 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
fn encode_attrs(&mut self, def_id: DefId) {
|
||||
let attrs = self.tcx.get_attrs(def_id);
|
||||
record!(self.tables.attributes[def_id] <- attrs);
|
||||
if attrs.iter().any(|attr| attr.may_have_doc_links()) {
|
||||
self.tables.may_have_doc_links.set(def_id.index, ());
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_def_ids(&mut self) {
|
||||
if self.is_proc_macro {
|
||||
return;
|
||||
@ -989,7 +997,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
let Some(def_kind) = def_kind else { continue };
|
||||
self.tables.opt_def_kind.set(def_id.index, def_kind);
|
||||
record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
|
||||
record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id));
|
||||
self.encode_attrs(def_id);
|
||||
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
|
||||
if should_encode_visibility(def_kind) {
|
||||
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
|
||||
@ -1651,7 +1659,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
|
||||
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
|
||||
record!(self.tables.attributes[LOCAL_CRATE.as_def_id()] <- tcx.get_attrs(LOCAL_CRATE.as_def_id()));
|
||||
self.encode_attrs(LOCAL_CRATE.as_def_id());
|
||||
record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id()));
|
||||
if let Some(stability) = stability {
|
||||
record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
|
||||
@ -1692,7 +1700,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
let def_id = id.to_def_id();
|
||||
self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
|
||||
record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
|
||||
record!(self.tables.attributes[def_id] <- attrs);
|
||||
self.encode_attrs(def_id);
|
||||
record!(self.tables.def_keys[def_id] <- def_key);
|
||||
record!(self.tables.def_ident_span[def_id] <- span);
|
||||
record!(self.tables.def_span[def_id] <- span);
|
||||
|
@ -360,6 +360,7 @@ define_tables! {
|
||||
def_path_hashes: Table<DefIndex, DefPathHash>,
|
||||
proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
|
||||
generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>,
|
||||
may_have_doc_links: Table<DefIndex, ()>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
|
||||
|
@ -186,6 +186,20 @@ impl FixedSizeEncoding for Option<RawDefId> {
|
||||
}
|
||||
}
|
||||
|
||||
impl FixedSizeEncoding for Option<()> {
|
||||
type ByteArray = [u8; 1];
|
||||
|
||||
#[inline]
|
||||
fn from_bytes(b: &[u8; 1]) -> Self {
|
||||
(b[0] != 0).then(|| ())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_to_bytes(self, b: &mut [u8; 1]) {
|
||||
b[0] = self.is_some() as u8
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
|
||||
// generic `Lazy<T>` impl, but in the general case we might not need / want to
|
||||
// fit every `usize` in `u32`.
|
||||
|
@ -1,7 +1,7 @@
|
||||
// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
|
||||
// check-pass
|
||||
#![deny(warnings)]
|
||||
|
||||
//! Email me at <hello@localhost>.
|
||||
//~^ ERROR unknown disambiguator `hello`
|
||||
|
||||
//! This should *not* warn: <hello@example.com>.
|
||||
|
@ -1,16 +0,0 @@
|
||||
error: unknown disambiguator `hello`
|
||||
--> $DIR/email-address-localhost.rs:4:18
|
||||
|
|
||||
LL | //! Email me at <hello@localhost>.
|
||||
| ^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/email-address-localhost.rs:2:9
|
||||
|
|
||||
LL | #![deny(warnings)]
|
||||
| ^^^^^^^^
|
||||
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
|
||||
= note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
x
Reference in New Issue
Block a user