diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2022-04-16 23:49:37 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2022-04-19 22:53:46 +0300 |
| commit | e2d3a4f63187ed6b092b5ec4a7d8b66f897ca308 (patch) | |
| tree | 474b8950b5cfe7321db50ce55523fc838d1ca2f3 | |
| parent | f5ca02c334b2eaa6817c15d6e2c88ab98d2a2054 (diff) | |
| download | rust-e2d3a4f63187ed6b092b5ec4a7d8b66f897ca308.tar.gz rust-e2d3a4f63187ed6b092b5ec4a7d8b66f897ca308.zip | |
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
| -rw-r--r-- | compiler/rustc_ast/src/attr/mod.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/util/comments.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/encoder.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/mod.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_metadata/src/rmeta/table.rs | 14 | ||||
| -rw-r--r-- | src/test/rustdoc-ui/intra-doc/email-address-localhost.rs | 2 | ||||
| -rw-r--r-- | src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr | 16 |
9 files changed, 48 insertions, 20 deletions
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 80caf37d709..9a6d12faa60 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -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, diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index 8730aeb0f3b..b4fff0022e2 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -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 { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c0f2319f003..77afa7b4a5c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -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 { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 6a8f1dec0c5..6b1f7d55026 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -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 { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 066bcb428f6..f485e09913e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e1a1589adb3..f1498665ff3 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -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)] diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 7a23cba536a..53fc2efe00b 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -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`. diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs index 9465e8e7ab9..7a5156e81c4 100644 --- a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs +++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs @@ -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>. diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr deleted file mode 100644 index 1b07828fc6e..00000000000 --- a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr +++ /dev/null @@ -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 - |
