Skip to content

Commit 9a00f3c

Browse files
committed
Auto merge of #44026 - QuietMisdreavus:trimmed-std, r=steveklabnik
hide internal types/traits from std docs via new #[doc(masked)] attribute Fixes #43701 (hopefully for good this time) This PR introduces a new parameter to the `#[doc]` attribute that rustdoc looks for on `extern crate` statements. When it sees `#[doc(masked)]` on such a statement, it hides traits and types from that crate from appearing in either the "Trait Implementations" section of many type pages, or the "Implementors" section of trait pages. This is then applied to the `libc`/`rand`/`compiler_builtins` imports in libstd to prevent those crates from creating broken links in the std docs. Like in #43348, this also introduces a feature gate, `doc_masked`, that controls the use of this parameter. To view the std docs generated with this change, head to https://tonberry.quietmisdreavus.net/std-43701/std/index.html.
2 parents 06bb0e0 + 64f6111 commit 9a00f3c

File tree

6 files changed

+111
-18
lines changed

6 files changed

+111
-18
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# `doc_masked`
2+
3+
The tracking issue for this feature is: [#44027]
4+
5+
-----
6+
7+
The `doc_masked` feature allows a crate to exclude types from a given crate from appearing in lists
8+
of trait implementations. The specifics of the feature are as follows:
9+
10+
1. When rustdoc encounters an `extern crate` statement annotated with a `#[doc(masked)]` attribute,
11+
it marks the crate as being masked.
12+
13+
2. When listing traits a given type implements, rustdoc ensures that traits from masked crates are
14+
not emitted into the documentation.
15+
16+
3. When listing types that implement a given trait, rustdoc ensures that types from masked crates
17+
are not emitted into the documentation.
18+
19+
This feature was introduced in PR [#44026] to ensure that compiler-internal and
20+
implementation-specific types and traits were not included in the standard library's documentation.
21+
Such types would introduce broken links into the documentation.
22+
23+
[#44026]: https://github.com/rust-lang/rust/pull/44026
24+
[#44027]: https://github.com/rust-lang/rust/pull/44027

src/librustdoc/clean/mod.rs

+31
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ pub struct Crate {
120120
// These are later on moved into `CACHEKEY`, leaving the map empty.
121121
// Only here so that they can be filtered through the rustdoc passes.
122122
pub external_traits: FxHashMap<DefId, Trait>,
123+
pub masked_crates: FxHashSet<CrateNum>,
123124
}
124125

125126
impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
@@ -144,6 +145,18 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
144145
// Clean the crate, translating the entire libsyntax AST to one that is
145146
// understood by rustdoc.
146147
let mut module = self.module.clean(cx);
148+
let mut masked_crates = FxHashSet();
149+
150+
match module.inner {
151+
ModuleItem(ref module) => {
152+
for it in &module.items {
153+
if it.is_extern_crate() && it.attrs.has_doc_masked() {
154+
masked_crates.insert(it.def_id.krate);
155+
}
156+
}
157+
}
158+
_ => unreachable!(),
159+
}
147160

148161
let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx);
149162
{
@@ -176,6 +189,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
176189
primitives,
177190
access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
178191
external_traits: mem::replace(&mut external_traits, Default::default()),
192+
masked_crates,
179193
}
180194
}
181195
}
@@ -329,6 +343,9 @@ impl Item {
329343
pub fn is_import(&self) -> bool {
330344
self.type_() == ItemType::Import
331345
}
346+
pub fn is_extern_crate(&self) -> bool {
347+
self.type_() == ItemType::ExternCrate
348+
}
332349

333350
pub fn is_stripped(&self) -> bool {
334351
match self.inner { StrippedItem(..) => true, _ => false }
@@ -574,6 +591,20 @@ impl Attributes {
574591
None
575592
}
576593

594+
pub fn has_doc_masked(&self) -> bool {
595+
for attr in &self.other_attrs {
596+
if !attr.check_name("doc") { continue; }
597+
598+
if let Some(items) = attr.meta_item_list() {
599+
if items.iter().filter_map(|i| i.meta_item()).any(|it| it.check_name("masked")) {
600+
return true;
601+
}
602+
}
603+
}
604+
605+
false
606+
}
607+
577608
pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes {
578609
let mut doc_strings = vec![];
579610
let mut sp = None;

src/librustdoc/html/render.rs

+29-17
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ pub struct Cache {
266266
deref_trait_did: Option<DefId>,
267267
deref_mut_trait_did: Option<DefId>,
268268
owned_box_did: Option<DefId>,
269+
masked_crates: FxHashSet<CrateNum>,
269270

270271
// In rare case where a structure is defined in one module but implemented
271272
// in another, if the implementing module is parsed before defining module,
@@ -538,6 +539,7 @@ pub fn run(mut krate: clean::Crate,
538539
deref_trait_did,
539540
deref_mut_trait_did,
540541
owned_box_did,
542+
masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()),
541543
typarams: external_typarams,
542544
};
543545

@@ -1114,12 +1116,16 @@ impl DocFolder for Cache {
11141116

11151117
// Collect all the implementors of traits.
11161118
if let clean::ImplItem(ref i) = item.inner {
1117-
if let Some(did) = i.trait_.def_id() {
1118-
self.implementors.entry(did).or_insert(vec![]).push(Implementor {
1119-
def_id: item.def_id,
1120-
stability: item.stability.clone(),
1121-
impl_: i.clone(),
1122-
});
1119+
if !self.masked_crates.contains(&item.def_id.krate) {
1120+
if let Some(did) = i.trait_.def_id() {
1121+
if i.for_.def_id().map_or(true, |d| !self.masked_crates.contains(&d.krate)) {
1122+
self.implementors.entry(did).or_insert(vec![]).push(Implementor {
1123+
def_id: item.def_id,
1124+
stability: item.stability.clone(),
1125+
impl_: i.clone(),
1126+
});
1127+
}
1128+
}
11231129
}
11241130
}
11251131

@@ -1281,18 +1287,24 @@ impl DocFolder for Cache {
12811287
// primitive rather than always to a struct/enum.
12821288
// Note: matching twice to restrict the lifetime of the `i` borrow.
12831289
let did = if let clean::Item { inner: clean::ImplItem(ref i), .. } = item {
1284-
match i.for_ {
1285-
clean::ResolvedPath { did, .. } |
1286-
clean::BorrowedRef {
1287-
type_: box clean::ResolvedPath { did, .. }, ..
1288-
} => {
1289-
Some(did)
1290-
}
1291-
ref t => {
1292-
t.primitive_type().and_then(|t| {
1293-
self.primitive_locations.get(&t).cloned()
1294-
})
1290+
let masked_trait = i.trait_.def_id().map_or(false,
1291+
|d| self.masked_crates.contains(&d.krate));
1292+
if !masked_trait {
1293+
match i.for_ {
1294+
clean::ResolvedPath { did, .. } |
1295+
clean::BorrowedRef {
1296+
type_: box clean::ResolvedPath { did, .. }, ..
1297+
} => {
1298+
Some(did)
1299+
}
1300+
ref t => {
1301+
t.primitive_type().and_then(|t| {
1302+
self.primitive_locations.get(&t).cloned()
1303+
})
1304+
}
12951305
}
1306+
} else {
1307+
None
12961308
}
12971309
} else {
12981310
unreachable!()

src/libstd/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@
314314
#![feature(unwind_attributes)]
315315
#![feature(vec_push_all)]
316316
#![feature(doc_cfg)]
317+
#![feature(doc_masked)]
317318
#![cfg_attr(test, feature(update_panic_count))]
318319

319320
#![cfg_attr(not(stage0), feature(const_max_value))]
@@ -359,19 +360,24 @@ use prelude::v1::*;
359360
debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
360361
extern crate core as __core;
361362

362-
#[allow(deprecated)] extern crate rand as core_rand;
363+
#[doc(masked)]
364+
#[allow(deprecated)]
365+
extern crate rand as core_rand;
363366
#[macro_use]
364367
#[macro_reexport(vec, format)]
365368
extern crate alloc;
366369
extern crate alloc_system;
367370
extern crate std_unicode;
371+
#[doc(masked)]
368372
extern crate libc;
369373

370374
// We always need an unwinder currently for backtraces
375+
#[doc(masked)]
371376
#[allow(unused_extern_crates)]
372377
extern crate unwind;
373378

374379
// compiler-rt intrinsics
380+
#[doc(masked)]
375381
extern crate compiler_builtins;
376382

377383
// During testing, this crate is not actually the "real" std library, but rather

src/libsyntax/feature_gate.rs

+6
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ declare_features! (
377377

378378
// #[doc(cfg(...))]
379379
(active, doc_cfg, "1.21.0", Some(43781)),
380+
// #[doc(masked)]
381+
(active, doc_masked, "1.21.0", None),
380382

381383
// allow `#[must_use]` on functions (RFC 1940)
382384
(active, fn_must_use, "1.21.0", Some(43302)),
@@ -1237,6 +1239,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
12371239
gate_feature_post!(&self, doc_cfg, attr.span,
12381240
"#[doc(cfg(...))] is experimental"
12391241
);
1242+
} else if content.iter().any(|c| c.check_name("masked")) {
1243+
gate_feature_post!(&self, doc_masked, attr.span,
1244+
"#[doc(masked)] is experimental"
1245+
);
12401246
}
12411247
}
12421248
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[doc(masked)] //~ ERROR: #[doc(masked)] is experimental
12+
extern crate std as realstd;
13+
14+
fn main() {}

0 commit comments

Comments
 (0)