diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index d5c965f7053e0..4194abc8d5742 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -407,17 +407,27 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { is_extern_crate = check_item(&item, &mut info, crate_name); } - StmtKind::Expr(ref expr) if matches!(expr.kind, ast::ExprKind::Err(_)) => { - reset_error_count(&psess); - return Err(()); + StmtKind::Expr(ref expr) => { + if matches!(expr.kind, ast::ExprKind::Err(_)) { + reset_error_count(&psess); + return Err(()); + } + has_non_items = true; } - StmtKind::MacCall(ref mac_call) if !info.has_main_fn => { + // We assume that the macro calls will expand to item(s) even though they could + // expand to statements and expressions. And the simple fact that we're trying + // to retrieve a `main` function inside it is a terrible idea. + StmtKind::MacCall(ref mac_call) => { + if info.has_main_fn { + continue; + } let mut iter = mac_call.mac.args.tokens.iter(); while let Some(token) = iter.next() { @@ -437,7 +447,9 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result {} + _ => { + has_non_items = true; + } } // Weirdly enough, the `Stmt` span doesn't include its attributes, so we need to @@ -462,6 +474,11 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { diff --git a/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs new file mode 100644 index 0000000000000..ed7584b742533 --- /dev/null +++ b/tests/rustdoc-ui/doctest/auxiliary/macro-after-main.rs @@ -0,0 +1 @@ +use std::string::String; diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs index 508faadcf6729..ca5dd78746789 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs @@ -4,12 +4,12 @@ //@ compile-flags:--test //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ failure-status: 101 +//@ check-pass /// /// /// ```rust -/// struct S {}; // unexpected semicolon after struct def +/// struct S {}; /// /// fn main() { /// assert_eq!(0, 1); diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout index 9eb8b391e7809..1068b98cb0fbb 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stdout @@ -1,29 +1,6 @@ running 1 test -test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... FAILED +test $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) ... ok -failures: - ----- $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) stdout ---- -error: expected item, found `;` - --> $DIR/failed-doctest-extra-semicolon-on-item.rs:12:12 - | -LL | struct S {}; // unexpected semicolon after struct def - | ^ - | - = help: braced struct declarations are not followed by a semicolon -help: remove this semicolon - | -LL - struct S {}; // unexpected semicolon after struct def -LL + struct S {} // unexpected semicolon after struct def - | - -error: aborting due to 1 previous error - -Couldn't compile the test. - -failures: - $DIR/failed-doctest-extra-semicolon-on-item.rs - m (line 11) - -test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/macro-after-main.rs b/tests/rustdoc-ui/doctest/macro-after-main.rs new file mode 100644 index 0000000000000..0a42343f1c272 --- /dev/null +++ b/tests/rustdoc-ui/doctest/macro-after-main.rs @@ -0,0 +1,16 @@ +// This test checks a corner case where the macro calls used to be skipped, +// making them considered as statement, and therefore some cases where +// `include!` macro was then put into a function body, making the doctest +// compilation fail. + +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +//! ``` +//! include!("./auxiliary/macro-after-main.rs"); +//! +//! fn main() {} +//! eprintln!(); +//! ``` diff --git a/tests/rustdoc-ui/doctest/macro-after-main.stdout b/tests/rustdoc-ui/doctest/macro-after-main.stdout new file mode 100644 index 0000000000000..72ffe2b5a27c5 --- /dev/null +++ b/tests/rustdoc-ui/doctest/macro-after-main.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/macro-after-main.rs - (line 11) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs new file mode 100644 index 0000000000000..ee2299c0fd87e --- /dev/null +++ b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.rs @@ -0,0 +1,22 @@ +// This test ensures that if there is an expression alongside a `main` +// function, it will not consider the entire code to be part of the `main` +// function and will generate its own function to wrap everything. +// +// This is a regression test for: +// * +// * +//@ compile-flags:--test +//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ check-pass + +#![crate_name = "foo"] + +//! ``` +//! # if cfg!(miri) { return; } +//! use std::ops::Deref; +//! +//! fn main() { +//! println!("Hi!"); +//! } +//! ``` diff --git a/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout new file mode 100644 index 0000000000000..90d7c3546bf10 --- /dev/null +++ b/tests/rustdoc-ui/doctest/test-main-alongside-exprs.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/test-main-alongside-exprs.rs - (line 15) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +