Skip to content

Commit fe807fc

Browse files
authored
Rollup merge of #62213 - QuietMisdreavus:cfg-doctest, r=GuillaumeGomez
rustdoc: set cfg(doctest) when collecting doctests Note: This PR builds on top of #61199; only the last commit is specific to this PR. As discussed in #61199, we want the ability to isolate items to only when rustdoc is collecting doctests, but we can't use `cfg(test)` because of libcore's `#![cfg(not(test))]`. This PR proposes a new cfg flag, `cfg(doctest)`, specific to this situation, rather than reusing an existing flag. I've isolated it behind a feature gate so that we can contain the effects to nightly only. (A stable workaround that can be used in lieu of `#[cfg(doctest)]` is `#[cfg(rustdoc)] #[doc(hidden)]`, at least once #61351 lands.) Tracking issue: #62210
2 parents 3250b8e + cff6ce6 commit fe807fc

File tree

9 files changed

+78
-4
lines changed

9 files changed

+78
-4
lines changed

src/doc/rustdoc/src/unstable-features.md

+30
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,36 @@ pub struct BigX;
212212
Then, when looking for it through the `rustdoc` search, if you enter "x" or
213213
"big", search will show the `BigX` struct first.
214214

215+
### Include items only when collecting doctests
216+
217+
Rustdoc's [documentation tests] can do some things that regular unit tests can't, so it can
218+
sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in
219+
documentation. To this end, Rustdoc allows you to have certain items only appear when it's
220+
collecting doctests, so you can utilize doctest functionality without forcing the test to appear in
221+
docs, or to find an arbitrary private item to include it on.
222+
223+
If you add `#![feature(cfg_doctest)]` to your crate, Rustdoc will set `cfg(doctest)` when collecting
224+
doctests. Note that they will still link against only the public items of your crate; if you need to
225+
test private items, unit tests are still the way to go.
226+
227+
In this example, we're adding doctests that we know won't compile, to verify that our struct can
228+
only take in valid data:
229+
230+
```rust
231+
#![feature(cfg_doctest)]
232+
233+
/// We have a struct here. Remember it doesn't accept negative numbers!
234+
pub struct MyStruct(usize);
235+
236+
/// ```compile_fail
237+
/// let x = my_crate::MyStruct(-5);
238+
/// ```
239+
#[cfg(doctest)]
240+
pub struct MyStructOnlyTakesUsize;
241+
```
242+
243+
[documentation tests]: documentation-tests.html
244+
215245
## Unstable command-line arguments
216246

217247
These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are

src/librustdoc/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ impl Options {
351351
.unwrap_or_else(|| PathBuf::from("doc"));
352352
let mut cfgs = matches.opt_strs("cfg");
353353
cfgs.push("rustdoc".to_string());
354+
if should_test {
355+
cfgs.push("doctest".to_string());
356+
}
354357

355358
let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
356359

src/libsyntax/feature_gate.rs

+4
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ declare_features! (
577577
// Allows `async || body` closures.
578578
(active, async_closure, "1.37.0", Some(62290), None),
579579

580+
// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests
581+
(active, cfg_doctest, "1.37.0", Some(62210), None),
582+
580583
// -------------------------------------------------------------------------
581584
// feature-group-end: actual feature gates
582585
// -------------------------------------------------------------------------
@@ -1592,6 +1595,7 @@ const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[
15921595
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
15931596
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
15941597
(sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)),
1598+
(sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)),
15951599
];
15961600

15971601
#[derive(Debug)]

src/libsyntax_pos/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ symbols! {
171171
cfg,
172172
cfg_attr,
173173
cfg_attr_multi,
174+
cfg_doctest,
174175
cfg_target_feature,
175176
cfg_target_has_atomic,
176177
cfg_target_thread_local,
@@ -241,6 +242,7 @@ symbols! {
241242
doc_keyword,
242243
doc_masked,
243244
doc_spotlight,
245+
doctest,
244246
document_private_items,
245247
dotdoteq_in_patterns,
246248
dotdot_in_tuple_patterns,

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// build-pass (FIXME(62277): could be check-pass?)
2-
// compile-flags:--test
2+
// compile-flags:--test --test-args --test-threads=1
33
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
44

55
// Crates like core have doctests gated on `cfg(not(test))` so we need to make
66
// sure `cfg(test)` is not active when running `rustdoc --test`.
77

8+
#![feature(cfg_doctest)]
9+
810
/// this doctest will be ignored:
911
///
1012
/// ```
@@ -20,3 +22,11 @@ pub struct Foo;
2022
/// ```
2123
#[cfg(not(test))]
2224
pub struct Foo;
25+
26+
/// this doctest will be tested, but will not appear in documentation:
27+
///
28+
/// ```
29+
/// assert!(true)
30+
/// ```
31+
#[cfg(doctest)]
32+
pub struct Bar;

src/test/rustdoc-ui/cfg-test.stdout

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

2-
running 1 test
3-
test $DIR/cfg-test.rs - Foo (line 18) ... ok
2+
running 2 tests
3+
test $DIR/cfg-test.rs - Bar (line 28) ... ok
4+
test $DIR/cfg-test.rs - Foo (line 20) ... ok
45

5-
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
6+
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
67

src/test/rustdoc/cfg-doctest.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(cfg_doctest)]
2+
3+
// @!has cfg_doctest/struct.SomeStruct.html
4+
// @!has cfg_doctest/index.html '//a/@href' 'struct.SomeStruct.html'
5+
6+
/// Sneaky, this isn't actually part of docs.
7+
#[cfg(doctest)]
8+
pub struct SomeStruct;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[cfg(doctest)] //~ ERROR
2+
pub struct SomeStruct;
3+
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: `cfg(doctest)` is experimental and subject to change
2+
--> $DIR/feature-gate-cfg_doctest.rs:1:7
3+
|
4+
LL | #[cfg(doctest)]
5+
| ^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/62210
8+
= help: add #![feature(cfg_doctest)] to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)