From a212960a4b47bb0879c75bc32de984d7626d5921 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 1 Aug 2019 23:18:37 +0200 Subject: [PATCH 1/3] stabilize cfg(doctest) --- src/doc/rustdoc/src/documentation-tests.md | 31 +++++++++++++++++++ src/doc/rustdoc/src/unstable-features.md | 30 ------------------ src/libsyntax/feature_gate/accepted.rs | 2 ++ src/libsyntax/feature_gate/active.rs | 3 -- src/libsyntax/feature_gate/builtin_attrs.rs | 1 - src/test/rustdoc-ui/cfg-test.rs | 2 -- src/test/rustdoc-ui/cfg-test.stdout | 4 +-- src/test/rustdoc/cfg-doctest.rs | 2 -- .../feature-gate/feature-gate-cfg_doctest.rs | 4 --- .../feature-gate-cfg_doctest.stderr | 12 ------- 10 files changed, 35 insertions(+), 56 deletions(-) delete mode 100644 src/test/ui/feature-gate/feature-gate-cfg_doctest.rs delete mode 100644 src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index c9acd3c307b54..68b9c0d241422 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -379,3 +379,34 @@ However, it's preferable to use fenced code blocks over indented code blocks. Not only are fenced code blocks considered more idiomatic for Rust code, but there is no way to use directives such as `ignore` or `should_panic` with indented code blocks. + +### 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. + +When compiling a crate for use in doctests (with `--test` option), rustdoc will set `cfg(doctest)`. +Note that they will still link against only the public items of your crate; if you need to +test private items, either make items conditionally public via `cfg(doctest)` or write a unit test. + +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 +/// 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; +``` + +Please note that the struct `MyStructOnlyTakesUsize` will not appear in documentation or in the +public API considering it only exists when running rustdoc with the `--test` option. + +[documentation tests]: documentation-tests.html diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 49d05b5038df7..3c3e72aa37959 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -211,36 +211,6 @@ pub struct BigX; Then, when looking for it through the `rustdoc` search, if you enter "x" or "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 These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are diff --git a/src/libsyntax/feature_gate/accepted.rs b/src/libsyntax/feature_gate/accepted.rs index d309a17298baa..a1cf2d421084e 100644 --- a/src/libsyntax/feature_gate/accepted.rs +++ b/src/libsyntax/feature_gate/accepted.rs @@ -251,6 +251,8 @@ declare_features! ( (accepted, non_exhaustive, "1.40.0", Some(44109), None), /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456), None), + /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. + (accepted, cfg_doctest, "1.40.0", Some(62210), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 22638a1376c72..736a363bbfc0a 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -506,9 +506,6 @@ declare_features! ( /// Allows `async || body` closures. (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), - /// Allows `[x; N]` where `x` is a constant (RFC 2203). (active, const_in_array_repeat_expressions, "1.37.0", Some(49147), None), diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index efe84238795a5..eb811c3e0ff9b 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -31,7 +31,6 @@ const GATED_CFGS: &[(Symbol, Symbol, GateFn)] = &[ (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), - (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), ]; #[derive(Debug)] diff --git a/src/test/rustdoc-ui/cfg-test.rs b/src/test/rustdoc-ui/cfg-test.rs index e88ddfb9e2ad2..587fe21f8fa73 100644 --- a/src/test/rustdoc-ui/cfg-test.rs +++ b/src/test/rustdoc-ui/cfg-test.rs @@ -5,8 +5,6 @@ // 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`. -#![feature(cfg_doctest)] - /// this doctest will be ignored: /// /// ``` diff --git a/src/test/rustdoc-ui/cfg-test.stdout b/src/test/rustdoc-ui/cfg-test.stdout index 86141aed5c3f2..474f13cfa9843 100644 --- a/src/test/rustdoc-ui/cfg-test.stdout +++ b/src/test/rustdoc-ui/cfg-test.stdout @@ -1,7 +1,7 @@ running 2 tests -test $DIR/cfg-test.rs - Bar (line 28) ... ok -test $DIR/cfg-test.rs - Foo (line 20) ... ok +test $DIR/cfg-test.rs - Bar (line 26) ... ok +test $DIR/cfg-test.rs - Foo (line 18) ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out diff --git a/src/test/rustdoc/cfg-doctest.rs b/src/test/rustdoc/cfg-doctest.rs index fca6d1029f981..6a9d26a4bb78c 100644 --- a/src/test/rustdoc/cfg-doctest.rs +++ b/src/test/rustdoc/cfg-doctest.rs @@ -1,5 +1,3 @@ -#![feature(cfg_doctest)] - // @!has cfg_doctest/struct.SomeStruct.html // @!has cfg_doctest/index.html '//a/@href' 'struct.SomeStruct.html' diff --git a/src/test/ui/feature-gate/feature-gate-cfg_doctest.rs b/src/test/ui/feature-gate/feature-gate-cfg_doctest.rs deleted file mode 100644 index 308f68bd52a79..0000000000000 --- a/src/test/ui/feature-gate/feature-gate-cfg_doctest.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[cfg(doctest)] //~ ERROR -pub struct SomeStruct; - -fn main() {} diff --git a/src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr b/src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr deleted file mode 100644 index 5ab45e01e50c5..0000000000000 --- a/src/test/ui/feature-gate/feature-gate-cfg_doctest.stderr +++ /dev/null @@ -1,12 +0,0 @@ -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`. From 3e3d919dabf1fc63642a41542eb68061ebfa894c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 1 Oct 2019 14:50:05 +0200 Subject: [PATCH 2/3] improve documentation of rustdoc doctest feature --- src/doc/rustdoc/src/documentation-tests.md | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 68b9c0d241422..45fbb4fbfc66b 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -382,22 +382,22 @@ indented code blocks. ### Include items only when collecting doctests -Rustdoc's [documentation tests] can do some things that regular unit tests can't, so it can +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. When compiling a crate for use in doctests (with `--test` option), rustdoc will set `cfg(doctest)`. -Note that they will still link against only the public items of your crate; if you need to -test private items, either make items conditionally public via `cfg(doctest)` or write a unit test. +Note that they will still link against only the public items of your crate; if you need to test +private items, you need to write a unit test. 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 /// We have a struct here. Remember it doesn't accept negative numbers! -pub struct MyStruct(usize); +pub struct MyStruct(pub usize); /// ```compile_fail /// let x = my_crate::MyStruct(-5); @@ -406,7 +406,22 @@ pub struct MyStruct(usize); pub struct MyStructOnlyTakesUsize; ``` -Please note that the struct `MyStructOnlyTakesUsize` will not appear in documentation or in the -public API considering it only exists when running rustdoc with the `--test` option. +Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate +API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while rustdoc is +collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc, +but is hidden from the public documentation. -[documentation tests]: documentation-tests.html +Another possible use of `cfg(doctest)` is to test doctests that are included in your README file +without including it in your main documentation. For example, you could write this into your +`lib.rs` to test your README as part of your doctests: + +```rust,no_run (includes-extra-file) +#![feature(extern_doc)] + +#[doc(include="../README.md")] +#[cfg(doctest)] +pub struct ReadmeDoctests; +``` + +This will include your README as documentation on the hidden struct `ReadmeDoctests`, which will +then be tested alongside the rest of your doctests. From 1595fdee1f9bff2901bcd3cd3fd7a22ea64cac24 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 1 Oct 2019 15:25:03 +0200 Subject: [PATCH 3/3] Update since version for doctest feature --- src/doc/rustdoc/src/documentation-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 45fbb4fbfc66b..bc1da5ff15a8c 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -415,7 +415,7 @@ Another possible use of `cfg(doctest)` is to test doctests that are included in without including it in your main documentation. For example, you could write this into your `lib.rs` to test your README as part of your doctests: -```rust,no_run (includes-extra-file) +```rust,ignore #![feature(extern_doc)] #[doc(include="../README.md")]