Skip to content

Commit e32328b

Browse files
Rollup merge of rust-lang#89596 - GuillaumeGomez:implicit-doc-cfg, r=jyn514
Make cfg imply doc(cfg) This is a reopening of rust-lang#79341, rebased and modified a bit (we made a lot of refactoring in rustdoc's types so they needed to be reflected in this PR as well): * `hidden_cfg` is now in the `Cache` instead of `DocContext` because `cfg` information isn't stored anymore on `clean::Attributes` type but instead computed on-demand, so we need this information in later parts of rustdoc. * I removed the `bool_to_options` feature (which makes the code a bit simpler to read for `SingleExt` trait implementation. * I updated the version for the feature. There is only one thing I couldn't figure out: [this comment](rust-lang#79341 (comment)) > I think I'll likely scrap the whole `SingleExt` extension trait as the diagnostics for 0 and >1 items should be different. How/why should they differ? EDIT: this part has been solved, the current code was fine, just needed a little simplification. cc `@Nemo157` r? `@jyn514` Original PR description: This is only active when the `doc_cfg` feature is active. The implicit cfg can be overridden via `#[doc(cfg(...))]`, so e.g. to hide a `#[cfg]` you can use something like: ```rust #[cfg(unix)] #[doc(cfg(all()))] pub struct Unix; ``` By adding `#![doc(cfg_hide(foobar))]` to the crate attributes the cfg `#[cfg(foobar)]` (and _only_ that _exact_ cfg) will not be implicitly treated as a `doc(cfg)` to render a message in the documentation.
2 parents de0b4f9 + 09c7688 commit e32328b

File tree

23 files changed

+247
-10
lines changed

23 files changed

+247
-10
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
279279

280280
gate_doc!(
281281
cfg => doc_cfg
282+
cfg_hide => doc_cfg_hide
282283
masked => doc_masked
283284
notable_trait => doc_notable_trait
284285
keyword => doc_keyword

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,9 @@ declare_features! (
675675
/// Allows `#[track_caller]` on closures and generators.
676676
(active, closure_track_caller, "1.57.0", Some(87417), None),
677677

678+
/// Allows `#[doc(cfg_hide(...))]`.
679+
(active, doc_cfg_hide, "1.57.0", Some(43781), None),
680+
678681
// -------------------------------------------------------------------------
679682
// feature-group-end: actual feature gates
680683
// -------------------------------------------------------------------------

compiler/rustc_passes/src/check_attr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,7 @@ impl CheckAttrVisitor<'tcx> {
938938
// plugins: removed, but rustdoc warns about it itself
939939
sym::alias
940940
| sym::cfg
941+
| sym::cfg_hide
941942
| sym::hidden
942943
| sym::html_favicon_url
943944
| sym::html_logo_url

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ symbols! {
399399
cfg_attr_multi,
400400
cfg_doctest,
401401
cfg_eval,
402+
cfg_hide,
402403
cfg_panic,
403404
cfg_sanitize,
404405
cfg_target_abi,
@@ -547,6 +548,7 @@ symbols! {
547548
doc,
548549
doc_alias,
549550
doc_cfg,
551+
doc_cfg_hide,
550552
doc_keyword,
551553
doc_masked,
552554
doc_notable_trait,

library/alloc/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@
6767
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
6868
test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
6969
)]
70+
#![cfg_attr(
71+
not(bootstrap),
72+
doc(cfg_hide(not(test), not(any(test, bootstrap)), target_has_atomic = "ptr"))
73+
)]
7074
#![no_std]
7175
#![needs_allocator]
7276
#![warn(deprecated_in_future)]
@@ -146,6 +150,8 @@
146150
#![feature(associated_type_bounds)]
147151
#![feature(slice_group_by)]
148152
#![feature(decl_macro)]
153+
#![feature(doc_cfg)]
154+
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
149155
// Allow testing this library
150156

151157
#[cfg(test)]

library/core/src/lib.rs

+25
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,30 @@
6060
test(no_crate_inject, attr(deny(warnings))),
6161
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
6262
)]
63+
#![cfg_attr(
64+
not(bootstrap),
65+
doc(cfg_hide(
66+
not(test),
67+
target_pointer_width = "16",
68+
target_pointer_width = "32",
69+
target_pointer_width = "64",
70+
target_has_atomic = "8",
71+
target_has_atomic = "16",
72+
target_has_atomic = "32",
73+
target_has_atomic = "64",
74+
target_has_atomic = "ptr",
75+
target_has_atomic_equal_alignment = "8",
76+
target_has_atomic_equal_alignment = "16",
77+
target_has_atomic_equal_alignment = "32",
78+
target_has_atomic_equal_alignment = "64",
79+
target_has_atomic_equal_alignment = "ptr",
80+
target_has_atomic_load_store = "8",
81+
target_has_atomic_load_store = "16",
82+
target_has_atomic_load_store = "32",
83+
target_has_atomic_load_store = "64",
84+
target_has_atomic_load_store = "ptr",
85+
))
86+
)]
6387
#![no_core]
6488
//
6589
// Lints:
@@ -133,6 +157,7 @@
133157
#![feature(doc_notable_trait)]
134158
#![feature(doc_primitive)]
135159
#![feature(exhaustive_patterns)]
160+
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
136161
#![feature(extern_types)]
137162
#![feature(fundamental)]
138163
#![feature(if_let_guard)]

library/std/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
test(no_crate_inject, attr(deny(warnings))),
196196
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
197197
)]
198+
#![cfg_attr(not(bootstrap), doc(cfg_hide(not(test), not(any(test, bootstrap)))))]
198199
// Don't link to std. We are std.
199200
#![no_std]
200201
#![warn(deprecated_in_future)]
@@ -263,6 +264,7 @@
263264
#![feature(custom_test_frameworks)]
264265
#![feature(decl_macro)]
265266
#![feature(doc_cfg)]
267+
#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))]
266268
#![feature(doc_keyword)]
267269
#![feature(doc_masked)]
268270
#![feature(doc_notable_trait)]

library/std/src/os/raw/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ macro_rules! type_alias {
4646
}
4747

4848
type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
49+
#[doc(cfg(all()))]
4950
#[cfg(any(
5051
all(
5152
target_os = "linux",
@@ -88,6 +89,7 @@ type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
8889
all(target_os = "fuchsia", target_arch = "aarch64")
8990
))]}
9091
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
92+
#[doc(cfg(all()))]
9193
#[cfg(not(any(
9294
all(
9395
target_os = "linux",
@@ -136,12 +138,16 @@ type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
136138
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
137139
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
138140
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
141+
#[doc(cfg(all()))]
139142
#[cfg(any(target_pointer_width = "32", windows))] }
140143
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
144+
#[doc(cfg(all()))]
141145
#[cfg(any(target_pointer_width = "32", windows))] }
142146
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
147+
#[doc(cfg(all()))]
143148
#[cfg(all(target_pointer_width = "64", not(windows)))] }
144149
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
150+
#[doc(cfg(all()))]
145151
#[cfg(all(target_pointer_width = "64", not(windows)))] }
146152
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
147153
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }

library/std/src/os/windows/raw.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ use crate::os::raw::c_void;
77
#[stable(feature = "raw_ext", since = "1.1.0")]
88
pub type HANDLE = *mut c_void;
99
#[cfg(target_pointer_width = "32")]
10+
#[doc(cfg(all()))]
1011
#[stable(feature = "raw_ext", since = "1.1.0")]
1112
pub type SOCKET = u32;
1213
#[cfg(target_pointer_width = "64")]
14+
#[doc(cfg(all()))]
1315
#[stable(feature = "raw_ext", since = "1.1.0")]
1416
pub type SOCKET = u64;

src/librustdoc/clean/inline.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,10 @@ fn merge_attrs(
318318
} else {
319319
Attributes::from_ast(&both, None)
320320
},
321-
both.cfg(cx.sess()),
321+
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
322322
)
323323
} else {
324-
(old_attrs.clean(cx), old_attrs.cfg(cx.sess()))
324+
(old_attrs.clean(cx), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
325325
}
326326
}
327327

src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1973,7 +1973,7 @@ fn clean_extern_crate(
19731973
def_id: crate_def_id.into(),
19741974
visibility: krate.vis.clean(cx),
19751975
kind: box ExternCrateItem { src: orig_name },
1976-
cfg: attrs.cfg(cx.sess()),
1976+
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
19771977
}]
19781978
}
19791979

src/librustdoc/clean/types.rs

+39-4
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ impl Item {
421421
kind,
422422
box ast_attrs.clean(cx),
423423
cx,
424-
ast_attrs.cfg(cx.sess()),
424+
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
425425
)
426426
}
427427

@@ -747,7 +747,7 @@ crate trait AttributesExt {
747747

748748
fn other_attrs(&self) -> Vec<ast::Attribute>;
749749

750-
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>>;
750+
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
751751
}
752752

753753
impl AttributesExt for [ast::Attribute] {
@@ -772,8 +772,41 @@ impl AttributesExt for [ast::Attribute] {
772772
self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
773773
}
774774

775-
fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
776-
let mut cfg = Cfg::True;
775+
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
776+
let sess = tcx.sess;
777+
let doc_cfg_active = tcx.features().doc_cfg;
778+
779+
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
780+
let mut iter = it.into_iter();
781+
let item = iter.next()?;
782+
if iter.next().is_some() {
783+
return None;
784+
}
785+
Some(item)
786+
}
787+
788+
let mut cfg = if doc_cfg_active {
789+
let mut doc_cfg = self
790+
.iter()
791+
.filter(|attr| attr.has_name(sym::doc))
792+
.flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
793+
.filter(|attr| attr.has_name(sym::cfg))
794+
.peekable();
795+
if doc_cfg.peek().is_some() {
796+
doc_cfg
797+
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
798+
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
799+
} else {
800+
self.iter()
801+
.filter(|attr| attr.has_name(sym::cfg))
802+
.filter_map(|attr| single(attr.meta_item_list()?))
803+
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
804+
.filter(|cfg| !hidden_cfg.contains(cfg))
805+
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
806+
}
807+
} else {
808+
Cfg::True
809+
};
777810

778811
for attr in self.iter() {
779812
// #[doc]
@@ -800,6 +833,8 @@ impl AttributesExt for [ast::Attribute] {
800833
}
801834
}
802835

836+
// treat #[target_feature(enable = "feat")] attributes as if they were
837+
// #[doc(cfg(target_feature = "feat"))] attributes as well
803838
for attr in self.lists(sym::target_feature) {
804839
if attr.has_name(sym::enable) {
805840
if let Some(feat) = attr.value_str() {

src/librustdoc/doctest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
11231123
let ast_attrs = self.tcx.hir().attrs(hir_id);
11241124
let mut attrs = Attributes::from_ast(ast_attrs, None);
11251125

1126-
if let Some(ref cfg) = ast_attrs.cfg(self.sess) {
1126+
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
11271127
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
11281128
return;
11291129
}

src/librustdoc/formats/cache.rs

+2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ crate struct Cache {
119119
///
120120
/// Links are indexed by the DefId of the item they document.
121121
crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
122+
/// Cfg that have been hidden via #![doc(cfg_hide(...))]
123+
crate hidden_cfg: FxHashSet<clean::cfg::Cfg>,
122124
}
123125

124126
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.

src/librustdoc/html/render/print_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
323323
let import_item = clean::Item {
324324
def_id: import_def_id.into(),
325325
attrs: import_attrs,
326-
cfg: ast_attrs.cfg(cx.sess()),
326+
cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
327327
..myitem.clone()
328328
};
329329

src/librustdoc/visit_ast.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_hir as hir;
66
use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::def_id::DefId;
88
use rustc_hir::Node;
9+
use rustc_hir::CRATE_HIR_ID;
910
use rustc_middle::middle::privacy::AccessLevel;
1011
use rustc_middle::ty::TyCtxt;
1112
use rustc_span;
@@ -15,7 +16,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
1516

1617
use std::mem;
1718

18-
use crate::clean::{self, AttributesExt, NestedAttributesExt};
19+
use crate::clean::{self, cfg::Cfg, AttributesExt, NestedAttributesExt};
1920
use crate::core;
2021
use crate::doctree::*;
2122

@@ -97,6 +98,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9798
}
9899
}
99100
}
101+
102+
self.cx.cache.hidden_cfg = self
103+
.cx
104+
.tcx
105+
.hir()
106+
.attrs(CRATE_HIR_ID)
107+
.iter()
108+
.filter(|attr| attr.has_name(sym::doc))
109+
.flat_map(|attr| attr.meta_item_list().into_iter().flatten())
110+
.filter(|attr| attr.has_name(sym::cfg_hide))
111+
.flat_map(|attr| {
112+
attr.meta_item_list()
113+
.unwrap_or(&[])
114+
.iter()
115+
.filter_map(|attr| {
116+
Some(
117+
Cfg::parse(attr.meta_item()?)
118+
.map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg))
119+
.ok()?,
120+
)
121+
})
122+
.collect::<Vec<_>>()
123+
})
124+
.collect();
125+
100126
self.cx.cache.exact_paths = self.exact_paths;
101127
top_level_module
102128
}

src/test/rustdoc-ui/doc-cfg.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(doc_cfg)]
2+
3+
#[doc(cfg(), cfg(foo, bar))]
4+
//~^ ERROR
5+
//~^^ ERROR
6+
#[doc(cfg(foo), cfg(bar))] // ok!
7+
#[doc(cfg())] //~ ERROR
8+
#[doc(cfg(foo, bar))] //~ ERROR
9+
pub fn foo() {}

src/test/rustdoc-ui/doc-cfg.stderr

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `cfg` predicate is not specified
2+
--> $DIR/doc-cfg.rs:3:7
3+
|
4+
LL | #[doc(cfg(), cfg(foo, bar))]
5+
| ^^^^^
6+
7+
error: multiple `cfg` predicates are specified
8+
--> $DIR/doc-cfg.rs:3:23
9+
|
10+
LL | #[doc(cfg(), cfg(foo, bar))]
11+
| ^^^
12+
13+
error: `cfg` predicate is not specified
14+
--> $DIR/doc-cfg.rs:7:7
15+
|
16+
LL | #[doc(cfg())]
17+
| ^^^^^
18+
19+
error: multiple `cfg` predicates are specified
20+
--> $DIR/doc-cfg.rs:8:16
21+
|
22+
LL | #[doc(cfg(foo, bar))]
23+
| ^^^
24+
25+
error: aborting due to 4 previous errors
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![doc(cfg_hide(test))]
2+
//~^ ERROR `#[doc(cfg_hide)]` is experimental
3+
4+
#[cfg(not(test))]
5+
pub fn public_fn() {}
6+
#[cfg(test)]
7+
pub fn internal_use_only() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0658]: `#[doc(cfg_hide)]` is experimental
2+
--> $DIR/feature-gate-doc_cfg_hide.rs:1:1
3+
|
4+
LL | #![doc(cfg_hide(test))]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #43781 <https://github.com/rust-lang/rust/issues/43781> for more information
8+
= help: add `#![feature(doc_cfg_hide)]` to the crate attributes to enable
9+
10+
error: Compilation failed, aborting rustdoc
11+
12+
error: aborting due to 2 previous errors
13+
14+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)