Skip to content

Commit e91ec2b

Browse files
Rollup merge of rust-lang#56470 - llogiq:process-termination-doctest, r=GuillaumeGomez
Modify doctest's auto-`fn main()` to allow `Result`s This lets the default `fn main()` ~~return `impl Termination`~~ unwrap Results, which allows the use of `?` in most tests without adding it manually. This fixes rust-lang#56260 ~~Blocked on `std::process::Termination` stabilization.~~ Using `Termination` would have been cleaner, but this should work OK.
2 parents 9a3392e + dad211e commit e91ec2b

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

src/doc/rustdoc/src/documentation-tests.md

+17
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,23 @@ appears to the reader as the initial idea but works with doc tests:
236236
/// ```
237237
```
238238

239+
As of version 1.34.0, one can also omit the `fn main()`, but you will have to
240+
disambiguate the error type:
241+
242+
```ignore
243+
/// ```
244+
/// use std::io;
245+
/// let mut input = String::new();
246+
/// io::stdin().read_line(&mut input)?;
247+
/// # Ok::<(), io:Error>(())
248+
/// ```
249+
```
250+
251+
This is an unfortunate consequence of the `?` operator adding an implicit
252+
conversion, so type inference fails because the type is not unique. Please note
253+
that you must write the `(())` in one sequence without intermediate whitespace
254+
so that rustdoc understands you want an implicit `Result`-returning function.
255+
239256
## Documenting macros
240257

241258
Here’s an example of documenting a macro:

src/librustdoc/test.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -534,13 +534,19 @@ pub fn make_test(s: &str,
534534
}
535535
}
536536

537-
if dont_insert_main || already_has_main {
537+
// FIXME: This code cannot yet handle no_std test cases yet
538+
if dont_insert_main || already_has_main || prog.contains("![no_std]") {
538539
prog.push_str(everything_else);
539540
} else {
540-
prog.push_str("fn main() {\n");
541+
let returns_result = everything_else.trim_end().ends_with("(())");
542+
let (main_pre, main_post) = if returns_result {
543+
("fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {",
544+
"}\n_inner().unwrap() }")
545+
} else {
546+
("fn main() {\n", "\n}")
547+
};
548+
prog.extend([main_pre, everything_else, main_post].iter().cloned());
541549
line_offset += 1;
542-
prog.push_str(everything_else);
543-
prog.push_str("\n}");
544550
}
545551

546552
debug!("final doctest:\n{}", prog);
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// compile-flags:--test
2+
3+
/// A check of using various process termination strategies
4+
///
5+
/// # Examples
6+
///
7+
/// ```rust
8+
/// assert!(true); // this returns `()`, all is well
9+
/// ```
10+
///
11+
/// You can also simply return `Ok(())`, but you'll need to disambiguate the
12+
/// type using turbofish, because we cannot infer the type:
13+
///
14+
/// ```rust
15+
/// Ok::<(), &'static str>(())
16+
/// ```
17+
///
18+
/// You can err with anything that implements `Debug`:
19+
///
20+
/// ```rust,should_panic
21+
/// Err("This is returned from `main`, leading to panic")?;
22+
/// Ok::<(), &'static str>(())
23+
/// ```
24+
pub fn check_process_termination() {}

0 commit comments

Comments
 (0)