From bff1645bdbe82157b90907239ef651f4b8d41f84 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 22 Nov 2021 19:47:58 -0700 Subject: [PATCH] fix(doctest): detect extern crate items in statement doctests This partially reverts #91026, because rustdoc needs to detect the extern statements, even when they appear inside implicit `main()`. It does not entirely revert it, so the old bug is still fixed, by duplicating some of the logic from `parse_mod` instead of trying to use it directly. Fixes #91134 --- .../rustc_parse/src/parser/diagnostics.rs | 2 +- src/librustdoc/doctest.rs | 21 ++++++++++++------- src/test/rustdoc-ui/auxiliary/empty-fn.rs | 3 +++ src/test/rustdoc-ui/issue-91134.rs | 14 +++++++++++++ src/test/rustdoc-ui/issue-91134.stdout | 6 ++++++ 5 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 src/test/rustdoc-ui/auxiliary/empty-fn.rs create mode 100644 src/test/rustdoc-ui/issue-91134.rs create mode 100644 src/test/rustdoc-ui/issue-91134.stdout diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 81328e09156..17e79a02360 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1121,7 +1121,7 @@ pub(super) fn maybe_recover_from_bad_qpath_stage_2( Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path))) } - pub(super) fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { + pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { if self.eat(&token::Semi) { let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`"); err.span_suggestion_short( diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 37db20aaefa..de4a3732e73 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1,4 +1,4 @@ -use rustc_ast::{self as ast, token}; +use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_errors::{ColorConfig, ErrorReported, FatalError}; @@ -537,6 +537,7 @@ fn drop(&mut self) { use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::Handler; use rustc_parse::maybe_new_parser_from_source_str; + use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; @@ -572,9 +573,9 @@ fn drop(&mut self) { } }; - match parser.parse_mod(&token::Eof) { - Ok((_attrs, items, _span)) => { - for item in items { + loop { + match parser.parse_item(ForceCollect::No) { + Ok(Some(item)) => { if !found_main { if let ast::ItemKind::Fn(..) = item.kind { if item.ident.name == sym::main { @@ -606,10 +607,16 @@ fn drop(&mut self) { break; } } + Ok(None) => break, + Err(mut e) => { + e.cancel(); + break; + } } - Err(mut e) => { - e.cancel(); - } + + // The supplied slice is only used for diagnostics, + // which are swallowed here anyway. + parser.maybe_consume_incorrect_semicolon(&[]); } // Reset errors so that they won't be reported as compiler bugs when dropping the diff --git a/src/test/rustdoc-ui/auxiliary/empty-fn.rs b/src/test/rustdoc-ui/auxiliary/empty-fn.rs new file mode 100644 index 00000000000..877810f15d7 --- /dev/null +++ b/src/test/rustdoc-ui/auxiliary/empty-fn.rs @@ -0,0 +1,3 @@ +// no-prefer-dynamic +#![crate_type = "lib"] +pub fn empty() {} diff --git a/src/test/rustdoc-ui/issue-91134.rs b/src/test/rustdoc-ui/issue-91134.rs new file mode 100644 index 00000000000..d2ff3a25226 --- /dev/null +++ b/src/test/rustdoc-ui/issue-91134.rs @@ -0,0 +1,14 @@ +// compile-flags: --test --crate-name=empty_fn --extern=empty_fn --test-args=--test-threads=1 +// aux-build:empty-fn.rs +// check-pass +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// edition:2021 + +/// +/// +/// ``` +/// extern crate empty_fn; +/// empty_fn::empty(); +/// ``` +pub struct Something; diff --git a/src/test/rustdoc-ui/issue-91134.stdout b/src/test/rustdoc-ui/issue-91134.stdout new file mode 100644 index 00000000000..8e65c2f3cd1 --- /dev/null +++ b/src/test/rustdoc-ui/issue-91134.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/issue-91134.rs - something (line 10) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +