]> git.lizzy.rs Git - rust.git/commitdiff
Modify doctest's auto-`fn main()` to allow `Result`s
authorAndre Bogus <bogusandre@gmail.com>
Mon, 3 Dec 2018 17:16:20 +0000 (18:16 +0100)
committerAndre Bogus <bogusandre@gmail.com>
Sun, 17 Feb 2019 15:42:49 +0000 (16:42 +0100)
This lets the default `fn main()` unwrap any `Result`s, which
allows the use of `?` in most tests without adding it manually.

src/doc/rustdoc/src/documentation-tests.md
src/librustdoc/test.rs
src/test/rustdoc/process-termination.rs [new file with mode: 0644]

index dd8dcb7ff9bd23e886b3071c60b69af31cf3e17f..020ffe4e1df87a281842b5740554a978d746338e 100644 (file)
@@ -236,6 +236,23 @@ appears to the reader as the initial idea but works with doc tests:
 /// ```
 ```
 
+As of version 1.34.0, one can also omit the `fn main()`, but you will have to
+disambiguate the error type:
+
+```ignore
+/// ```
+/// use std::io;
+/// let mut input = String::new();
+/// io::stdin().read_line(&mut input)?;
+/// # Ok::<(), io:Error>(())
+/// ```
+```
+
+This is an unfortunate consequence of the `?` operator adding an implicit
+conversion, so type inference fails because the type is not unique. Please note
+that you must write the `(())` in one sequence without intermediate whitespace
+so that rustdoc understands you want an implicit `Result`-returning function.
+
 ## Documenting macros
 
 Here’s an example of documenting a macro:
index 4d870daac4d039c338a4a5a55f7c08966d5f5584..133edb77051a6536b528ed6e9bb86c9d3aef0e78 100644 (file)
@@ -470,13 +470,19 @@ pub fn make_test(s: &str,
         }
     }
 
-    if dont_insert_main || already_has_main {
+    // FIXME: This code cannot yet handle no_std test cases yet
+    if dont_insert_main || already_has_main || prog.contains("![no_std]") {
         prog.push_str(everything_else);
     } else {
-        prog.push_str("fn main() {\n");
+        let returns_result = everything_else.trim_end().ends_with("(())");
+        let (main_pre, main_post) = if returns_result {
+            ("fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {",
+             "}\n_inner().unwrap() }")
+        } else {
+            ("fn main() {\n", "\n}")
+        };
+        prog.extend([main_pre, everything_else, main_post].iter().cloned());
         line_offset += 1;
-        prog.push_str(everything_else);
-        prog.push_str("\n}");
     }
 
     debug!("final doctest:\n{}", prog);
diff --git a/src/test/rustdoc/process-termination.rs b/src/test/rustdoc/process-termination.rs
new file mode 100644 (file)
index 0000000..3225879
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags:--test
+
+/// A check of using various process termination strategies
+///
+/// # Examples
+///
+/// ```rust
+/// assert!(true); // this returns `()`, all is well
+/// ```
+///
+/// You can also simply return `Ok(())`, but you'll need to disambiguate the
+/// type using turbofish, because we cannot infer the type:
+///
+/// ```rust
+/// Ok::<(), &'static str>(())
+/// ```
+///
+/// You can err with anything that implements `Debug`:
+///
+/// ```rust,should_panic
+/// Err("This is returned from `main`, leading to panic")?;
+/// Ok::<(), &'static str>(())
+/// ```
+pub fn check_process_termination() {}