Skip to content

Commit

Permalink
Auto merge of rust-lang#132105 - GuillaumeGomez:doctest-nested-main, …
Browse files Browse the repository at this point in the history
…r=notriddle

[rustdoc] Do not consider nested functions as main function even if named `main` in doctests

Fixes rust-lang#131893.

If a nested function is called `main`, it is not considered as the entry point of the program. Therefore, doctests should not consider such functions as such either.

r? `@notriddle`
  • Loading branch information
bors committed Oct 25, 2024
2 parents 788202a + aab2b67 commit 017ae1b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
15 changes: 11 additions & 4 deletions src/librustdoc/doctest/make.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,21 +289,28 @@ fn parse_source(
// Recurse through functions body. It is necessary because the doctest source code is
// wrapped in a function to limit the number of AST errors. If we don't recurse into
// functions, we would thing all top-level items (so basically nothing).
fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) {
fn check_item(
item: &ast::Item,
info: &mut ParseSourceInfo,
crate_name: &Option<&str>,
is_top_level: bool,
) {
if !info.has_global_allocator
&& item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
{
info.has_global_allocator = true;
}
match item.kind {
ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => {
if item.ident.name == sym::main {
if item.ident.name == sym::main && is_top_level {
info.has_main_fn = true;
}
if let Some(ref body) = fn_item.body {
for stmt in &body.stmts {
match stmt.kind {
ast::StmtKind::Item(ref item) => check_item(item, info, crate_name),
ast::StmtKind::Item(ref item) => {
check_item(item, info, crate_name, false)
}
ast::StmtKind::MacCall(..) => info.found_macro = true,
_ => {}
}
Expand All @@ -329,7 +336,7 @@ fn parse_source(
loop {
match parser.parse_item(ForceCollect::No) {
Ok(Some(item)) => {
check_item(&item, info, crate_name);
check_item(&item, info, crate_name, true);

if info.has_main_fn && info.found_extern_crate {
break;
Expand Down
24 changes: 24 additions & 0 deletions tests/rustdoc-ui/doctest/nested-main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//@ check-pass
//@ compile-flags:--test --test-args=--test-threads=1
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"

// Regression test for <https://github.com/rust-lang/rust/issues/131893>.
// It ensures that if a function called `main` is nested, it will not consider
// it as the `main` function.

/// ```
/// fn dox() {
/// fn main() {}
/// }
/// ```
pub fn foo() {}

// This one ensures that having a nested `main` doesn't prevent the
// actual `main` function to be detected.
/// ```
/// fn main() {
/// fn main() {}
/// }
/// ```
pub fn foo2() {}
7 changes: 7 additions & 0 deletions tests/rustdoc-ui/doctest/nested-main.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

running 2 tests
test $DIR/nested-main.rs - foo (line 10) ... ok
test $DIR/nested-main.rs - foo2 (line 19) ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

0 comments on commit 017ae1b

Please sign in to comment.