Rollup merge of #62213 - QuietMisdreavus:cfg-doctest, r=GuillaumeGomez
rustdoc: set cfg(doctest) when collecting doctests Note: This PR builds on top of https://github.com/rust-lang/rust/pull/61199; only the last commit is specific to this PR. As discussed in https://github.com/rust-lang/rust/pull/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 https://github.com/rust-lang/rust/pull/61351 lands.) Tracking issue: https://github.com/rust-lang/rust/issues/62210
This commit is contained in:
commit
fe807fcf3e
@ -212,6 +212,36 @@ pub struct BigX;
|
|||||||
Then, when looking for it through the `rustdoc` search, if you enter "x" or
|
Then, when looking for it through the `rustdoc` search, if you enter "x" or
|
||||||
"big", search will show the `BigX` struct first.
|
"big", search will show the `BigX` struct first.
|
||||||
|
|
||||||
|
### Include items only when collecting doctests
|
||||||
|
|
||||||
|
Rustdoc's [documentation tests] can do some things that regular unit tests can't, so it can
|
||||||
|
sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in
|
||||||
|
documentation. To this end, Rustdoc allows you to have certain items only appear when it's
|
||||||
|
collecting doctests, so you can utilize doctest functionality without forcing the test to appear in
|
||||||
|
docs, or to find an arbitrary private item to include it on.
|
||||||
|
|
||||||
|
If you add `#![feature(cfg_doctest)]` to your crate, Rustdoc will set `cfg(doctest)` when collecting
|
||||||
|
doctests. Note that they will still link against only the public items of your crate; if you need to
|
||||||
|
test private items, unit tests are still the way to go.
|
||||||
|
|
||||||
|
In this example, we're adding doctests that we know won't compile, to verify that our struct can
|
||||||
|
only take in valid data:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#![feature(cfg_doctest)]
|
||||||
|
|
||||||
|
/// We have a struct here. Remember it doesn't accept negative numbers!
|
||||||
|
pub struct MyStruct(usize);
|
||||||
|
|
||||||
|
/// ```compile_fail
|
||||||
|
/// let x = my_crate::MyStruct(-5);
|
||||||
|
/// ```
|
||||||
|
#[cfg(doctest)]
|
||||||
|
pub struct MyStructOnlyTakesUsize;
|
||||||
|
```
|
||||||
|
|
||||||
|
[documentation tests]: documentation-tests.html
|
||||||
|
|
||||||
## Unstable command-line arguments
|
## Unstable command-line arguments
|
||||||
|
|
||||||
These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
|
These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
|
||||||
|
@ -351,6 +351,9 @@ impl Options {
|
|||||||
.unwrap_or_else(|| PathBuf::from("doc"));
|
.unwrap_or_else(|| PathBuf::from("doc"));
|
||||||
let mut cfgs = matches.opt_strs("cfg");
|
let mut cfgs = matches.opt_strs("cfg");
|
||||||
cfgs.push("rustdoc".to_string());
|
cfgs.push("rustdoc".to_string());
|
||||||
|
if should_test {
|
||||||
|
cfgs.push("doctest".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
|
let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
|
||||||
|
|
||||||
|
@ -577,6 +577,9 @@ declare_features! (
|
|||||||
// Allows `async || body` closures.
|
// Allows `async || body` closures.
|
||||||
(active, async_closure, "1.37.0", Some(62290), None),
|
(active, async_closure, "1.37.0", Some(62290), None),
|
||||||
|
|
||||||
|
// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests
|
||||||
|
(active, cfg_doctest, "1.37.0", Some(62210), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: actual feature gates
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
@ -1592,6 +1595,7 @@ const GATED_CFGS: &[(Symbol, Symbol, fn(&Features) -> bool)] = &[
|
|||||||
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
|
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
|
||||||
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
|
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
|
||||||
(sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)),
|
(sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)),
|
||||||
|
(sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)),
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -171,6 +171,7 @@ symbols! {
|
|||||||
cfg,
|
cfg,
|
||||||
cfg_attr,
|
cfg_attr,
|
||||||
cfg_attr_multi,
|
cfg_attr_multi,
|
||||||
|
cfg_doctest,
|
||||||
cfg_target_feature,
|
cfg_target_feature,
|
||||||
cfg_target_has_atomic,
|
cfg_target_has_atomic,
|
||||||
cfg_target_thread_local,
|
cfg_target_thread_local,
|
||||||
@ -241,6 +242,7 @@ symbols! {
|
|||||||
doc_keyword,
|
doc_keyword,
|
||||||
doc_masked,
|
doc_masked,
|
||||||
doc_spotlight,
|
doc_spotlight,
|
||||||
|
doctest,
|
||||||
document_private_items,
|
document_private_items,
|
||||||
dotdoteq_in_patterns,
|
dotdoteq_in_patterns,
|
||||||
dotdot_in_tuple_patterns,
|
dotdot_in_tuple_patterns,
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// compile-flags:--test
|
// compile-flags:--test --test-args --test-threads=1
|
||||||
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
|
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
|
||||||
|
|
||||||
// Crates like core have doctests gated on `cfg(not(test))` so we need to make
|
// Crates like core have doctests gated on `cfg(not(test))` so we need to make
|
||||||
// sure `cfg(test)` is not active when running `rustdoc --test`.
|
// sure `cfg(test)` is not active when running `rustdoc --test`.
|
||||||
|
|
||||||
|
#![feature(cfg_doctest)]
|
||||||
|
|
||||||
/// this doctest will be ignored:
|
/// this doctest will be ignored:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -20,3 +22,11 @@ pub struct Foo;
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
|
/// this doctest will be tested, but will not appear in documentation:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// assert!(true)
|
||||||
|
/// ```
|
||||||
|
#[cfg(doctest)]
|
||||||
|
pub struct Bar;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
running 1 test
|
running 2 tests
|
||||||
test $DIR/cfg-test.rs - Foo (line 18) ... ok
|
test $DIR/cfg-test.rs - Bar (line 28) ... ok
|
||||||
|
test $DIR/cfg-test.rs - Foo (line 20) ... ok
|
||||||
|
|
||||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||||
|
|
||||||
|
8
src/test/rustdoc/cfg-doctest.rs
Normal file
8
src/test/rustdoc/cfg-doctest.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#![feature(cfg_doctest)]
|
||||||
|
|
||||||
|
// @!has cfg_doctest/struct.SomeStruct.html
|
||||||
|
// @!has cfg_doctest/index.html '//a/@href' 'struct.SomeStruct.html'
|
||||||
|
|
||||||
|
/// Sneaky, this isn't actually part of docs.
|
||||||
|
#[cfg(doctest)]
|
||||||
|
pub struct SomeStruct;
|
4
src/test/ui/feature-gate/feature-gate-cfg_doctest.rs
Normal file
4
src/test/ui/feature-gate/feature-gate-cfg_doctest.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#[cfg(doctest)] //~ ERROR
|
||||||
|
pub struct SomeStruct;
|
||||||
|
|
||||||
|
fn main() {}
|
12
src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr
Normal file
12
src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0658]: `cfg(doctest)` is experimental and subject to change
|
||||||
|
--> $DIR/feature-gate-cfg_doctest.rs:1:7
|
||||||
|
|
|
||||||
|
LL | #[cfg(doctest)]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62210
|
||||||
|
= help: add #![feature(cfg_doctest)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue
Block a user