Skip to content

Commit 3fcfc54

Browse files
committed
Auto merge of #161200 - mejrs:fake_item_queries, r=camelid
querify getting fake doc items
2 parents 809936e + 8123f4a commit 3fcfc54

11 files changed

Lines changed: 125 additions & 36 deletions

File tree

‎Cargo.lock‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4616,6 +4616,7 @@ dependencies = [
46164616
"rustc_abi",
46174617
"rustc_ast",
46184618
"rustc_ast_lowering",
4619+
"rustc_attr_ir",
46194620
"rustc_attr_parsing",
46204621
"rustc_crate_store",
46214622
"rustc_data_structures",

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,18 @@ impl CrateMetadata {
13081308
canonical_symbols
13091309
}
13101310

1311+
/// Iterates over the fake_doc_items in the given crate.
1312+
fn get_fake_doc_items(&self, tcx: TyCtxt<'_>) -> Vec<DefId> {
1313+
let mut fake_doc_items = Vec::new();
1314+
1315+
for def_index in self.root.fake_doc_items.decode((self, tcx)) {
1316+
let id = self.local_def_id(def_index);
1317+
fake_doc_items.push(id);
1318+
}
1319+
1320+
fake_doc_items
1321+
}
1322+
13111323
fn get_mod_child(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ModChild {
13121324
let ident = self.item_ident(tcx, id);
13131325
let res = Res::Def(self.def_kind(id), self.local_def_id(id));

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ provide! { tcx, def_id, other, cdata,
402402
defined_lang_items => { cdata.get_lang_items(tcx) }
403403
diagnostic_items => { cdata.get_diagnostic_items(tcx) }
404404
canonical_symbols => { cdata.get_canonical_symbols(tcx) }
405+
fake_doc_items => { cdata.get_fake_doc_items(tcx) }
405406
missing_lang_items => { cdata.get_missing_lang_items(tcx) }
406407

407408
missing_extern_crate_item => {

‎compiler/rustc_metadata/src/rmeta/encoder.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
644644

645645
let canonical_symbols = stat!("canonical-symbols", || self.encode_canonical_symbols());
646646

647+
let fake_doc_items = stat!("fake-doc-items", || self.encode_fake_doc_items());
648+
647649
let native_libraries = stat!("native-libs", || self.encode_native_libraries());
648650

649651
let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
@@ -763,6 +765,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
763765
lang_items,
764766
diagnostic_items,
765767
canonical_symbols,
768+
fake_doc_items,
766769
lang_items_missing,
767770
stripped_cfg_items,
768771
native_libraries,
@@ -2171,6 +2174,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
21712174
self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
21722175
}
21732176

2177+
fn encode_fake_doc_items(&mut self) -> LazyArray<DefIndex> {
2178+
empty_proc_macro!(self);
2179+
let tcx = self.tcx;
2180+
let fake_doc_items = &tcx.fake_doc_items(LOCAL_CRATE);
2181+
self.lazy_array(fake_doc_items.iter().map(|cs| cs.index))
2182+
}
2183+
21742184
fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, LangItem)> {
21752185
empty_proc_macro!(self);
21762186
let lang_items = self.tcx.lang_items().iter();

‎compiler/rustc_metadata/src/rmeta/mod.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ pub(crate) struct CrateRoot {
270270
stripped_cfg_items: LazyArray<StrippedCfgItem<DefIndex>>,
271271
diagnostic_items: LazyArray<(Symbol, DefIndex)>,
272272
canonical_symbols: LazyArray<(Symbol, DefIndex)>,
273+
fake_doc_items: LazyArray<DefIndex>,
273274
native_libraries: LazyArray<NativeLib>,
274275
foreign_modules: LazyArray<ForeignModule>,
275276
traits: LazyArray<DefIndex>,

‎compiler/rustc_middle/src/queries.rs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2846,6 +2846,20 @@ rustc_queries! {
28462846
separate_provide_extern
28472847
}
28482848

2849+
/// Returns the fake doc items defined in a crate's root.
2850+
query fake_doc_items(_: CrateNum) -> &'tcx Vec<DefId> {
2851+
arena_cache
2852+
desc { "calculating the fake doc items" }
2853+
separate_provide_extern
2854+
}
2855+
2856+
/// Returns all fake doc items defined in all crates' roots.
2857+
query all_fake_doc_items(_: ()) -> &'tcx Vec<DefId> {
2858+
arena_cache
2859+
eval_always
2860+
desc { "calculating all fake doc items" }
2861+
}
2862+
28492863
//-----------------------------------------------------------------------------
28502864
// "Non-queries" are special dep kinds that are not queries.
28512865
//-----------------------------------------------------------------------------

‎compiler/rustc_passes/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edition = "2024"
88
rustc_abi = { path = "../rustc_abi" }
99
rustc_ast = { path = "../rustc_ast" }
1010
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
11+
rustc_attr_ir = { path = "../rustc_attr_ir" }
1112
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
1213
rustc_crate_store = { path = "../rustc_crate_store" }
1314
rustc_data_structures = { path = "../rustc_data_structures" }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//! Collecting fake doc items. This query is used by rustdoc to document attributes, keywords and
2+
//! primitives.
3+
4+
use rustc_attr_ir::{DocAttribute, find_attr};
5+
use rustc_middle::query::{LocalCrate, Providers};
6+
use rustc_middle::ty::TyCtxt;
7+
use rustc_span::def_id::{DefId, LOCAL_CRATE};
8+
use rustc_span::sym;
9+
10+
/// Traverse and collect the fake doc items in the current crate
11+
fn fake_doc_items(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DefId> {
12+
let mut fake_doc_items = Vec::new();
13+
14+
// Optimization: can this crate even define fake doc items?
15+
let features = tcx.features().enabled_features();
16+
if features.contains(&sym::rustc_attrs) || features.contains(&sym::rustdoc_internals) {
17+
// Collect fake doc items in this crate.
18+
for id in tcx.hir_root_module().item_ids {
19+
let id = id.hir_id();
20+
if find_attr!(
21+
tcx,
22+
id,
23+
RustcDocPrimitive(..)
24+
| Doc(DocAttribute { keyword: Some(..), .. })
25+
| Doc(DocAttribute { attribute: Some(..), .. })
26+
) {
27+
fake_doc_items.push(id.expect_owner().to_def_id());
28+
}
29+
}
30+
}
31+
32+
fake_doc_items
33+
}
34+
35+
/// Traverse and collect all the fake doc items in all crates.
36+
fn all_fake_doc_items(tcx: TyCtxt<'_>, (): ()) -> Vec<DefId> {
37+
let mut fake_doc_items = Vec::new();
38+
39+
// Collect fake doc items in visible crates.
40+
for cnum in tcx
41+
.crates(())
42+
.iter()
43+
.copied()
44+
.filter(|cnum| tcx.is_user_visible_dep(*cnum))
45+
.chain(std::iter::once(LOCAL_CRATE))
46+
{
47+
fake_doc_items.extend_from_slice(tcx.fake_doc_items(cnum))
48+
}
49+
50+
fake_doc_items
51+
}
52+
53+
pub(crate) fn provide(providers: &mut Providers) {
54+
providers.fake_doc_items = fake_doc_items;
55+
providers.all_fake_doc_items = all_fake_doc_items;
56+
}

‎compiler/rustc_passes/src/lib.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! This API is completely unstable and subject to change.
66
77
// tidy-alphabetical-start
8+
#![feature(deref_patterns)]
89
#![feature(option_into_flat_iter)]
910
// tidy-alphabetical-end
1011

@@ -21,6 +22,7 @@ mod diagnostic_items;
2122
mod diagnostics;
2223
mod eii;
2324
pub mod entry;
25+
mod fake_doc_items;
2426
pub mod hir_id_validator;
2527
pub mod input_stats;
2628
mod lang_items;
@@ -44,5 +46,6 @@ pub fn provide(providers: &mut Providers) {
4446
stability::provide(providers);
4547
upvars::provide(providers);
4648
check_export::provide(providers);
49+
fake_doc_items::provide(providers);
4750
providers.check_externally_implementable_items = eii::check_externally_implementable_items;
4851
}

‎src/librustdoc/clean/types.rs‎

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -236,31 +236,12 @@ impl ExternalCrate {
236236
.unwrap_or(Unknown) // Well, at least we tried.
237237
}
238238

239-
fn mapped_root_anon_consts<T>(
239+
fn fake_doc_items<T>(
240240
&self,
241241
tcx: TyCtxt<'_>,
242242
f: impl Fn(DefId, TyCtxt<'_>) -> Option<(DefId, T)>,
243243
) -> impl Iterator<Item = (DefId, T)> {
244-
let root = self.def_id();
245-
246-
if root.is_local() {
247-
Either::Left(
248-
tcx.hir_root_module()
249-
.item_ids
250-
.iter()
251-
.filter(move |&&id| matches!(tcx.hir_item(id).kind, hir::ItemKind::Const(..)))
252-
.filter_map(move |&id| f(id.owner_id.into(), tcx)),
253-
)
254-
} else {
255-
Either::Right(
256-
tcx.module_children(root)
257-
.iter()
258-
.filter_map(|item| {
259-
if let Res::Def(DefKind::Const, did) = item.res { Some(did) } else { None }
260-
})
261-
.filter_map(move |did| f(did, tcx)),
262-
)
263-
}
244+
tcx.fake_doc_items(self.crate_num).into_iter().filter_map(move |did| f(*did, tcx))
264245
}
265246

266247
pub(crate) fn keywords(&self, tcx: TyCtxt<'_>) -> impl Iterator<Item = (DefId, Symbol)> {
@@ -281,7 +262,7 @@ impl ExternalCrate {
281262
let as_target = move |did: DefId, tcx: TyCtxt<'_>| -> Option<(DefId, Symbol)> {
282263
find_attr!(tcx, did, Doc(d) => callback(d)).flatten().map(|value| (did, value))
283264
};
284-
self.mapped_root_anon_consts(tcx, as_target)
265+
self.fake_doc_items(tcx, as_target)
285266
}
286267

287268
pub(crate) fn primitives(
@@ -316,7 +297,7 @@ impl ExternalCrate {
316297
Some((def_id, prim))
317298
}
318299

319-
self.mapped_root_anon_consts(tcx, as_primitive)
300+
self.fake_doc_items(tcx, as_primitive)
320301
}
321302
}
322303

@@ -1891,27 +1872,35 @@ impl PrimitiveType {
18911872
/// `rustc_doc_primitive`, then it's entirely random whether `std` or the other crate is picked.
18921873
/// (no_std crates are usually fine unless multiple dependencies define a primitive.)
18931874
pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap<PrimitiveType, DefId> {
1875+
fn as_primitive(def_id: DefId, tcx: TyCtxt<'_>) -> Option<PrimitiveType> {
1876+
let (attr_span, prim_sym) = find_attr!(
1877+
tcx, def_id,
1878+
RustcDocPrimitive(span, prim) => (*span, *prim)
1879+
)?;
1880+
let Some(prim) = PrimitiveType::from_symbol(prim_sym) else {
1881+
span_bug!(attr_span, "primitive `{prim_sym}` is not a member of `PrimitiveType`");
1882+
};
1883+
Some(prim)
1884+
}
1885+
18941886
static PRIMITIVE_LOCATIONS: OnceCell<FxIndexMap<PrimitiveType, DefId>> = OnceCell::new();
18951887
PRIMITIVE_LOCATIONS.get_or_init(|| {
18961888
let mut primitive_locations = FxIndexMap::default();
18971889
// NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
18981890
// This is a degenerate case that I don't plan to support.
1899-
for &crate_num in tcx.crates(()) {
1900-
let e = ExternalCrate { crate_num };
1901-
let crate_name = e.name(tcx);
1902-
debug!(?crate_num, ?crate_name);
1903-
for (def_id, prim) in e.primitives(tcx) {
1904-
// HACK: try to link to std instead where possible
1905-
if crate_name == sym::core && primitive_locations.contains_key(&prim) {
1906-
continue;
1907-
}
1891+
1892+
let mut ids = tcx.all_fake_doc_items(()).clone();
1893+
1894+
// HACK: Primitives are unhygienically duplicated by `include!`.
1895+
// Sort them with core first, so that if std is present in the crate graph,
1896+
// core's items are overridden and we link to std preferentially.
1897+
ids.iter_mut().partition_in_place(|id| tcx.crate_name(id.krate) == sym::core);
1898+
for def_id in ids {
1899+
if let Some(prim) = as_primitive(def_id, tcx) {
19081900
primitive_locations.insert(prim, def_id);
19091901
}
19101902
}
1911-
let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
1912-
for (def_id, prim) in local_primitives {
1913-
primitive_locations.insert(prim, def_id);
1914-
}
1903+
19151904
primitive_locations
19161905
})
19171906
}

0 commit comments

Comments
 (0)