about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-10-25 05:11:05 +0000
committerbors <bors@rust-lang.org>2024-10-25 05:11:05 +0000
commit017ae1b21f7be6dcdcfc95631e54bde806653a8a (patch)
treec08d3b710ded87c4f93ef67802ef54b1f249fdc8
parent788202a2cef5dde0743490fd51515f373d4207a6 (diff)
parentaab2b6747db09b8572f879bd74dbee701287536d (diff)
downloadrust-017ae1b21f7be6dcdcfc95631e54bde806653a8a.tar.gz
rust-017ae1b21f7be6dcdcfc95631e54bde806653a8a.zip
Auto merge of #132105 - GuillaumeGomez:doctest-nested-main, r=notriddle
[rustdoc] Do not consider nested functions as main function even if named `main` in doctests

Fixes #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`
-rw-r--r--src/librustdoc/doctest/make.rs15
-rw-r--r--tests/rustdoc-ui/doctest/nested-main.rs24
-rw-r--r--tests/rustdoc-ui/doctest/nested-main.stdout7
3 files changed, 42 insertions, 4 deletions
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index efbb332d12d..3ae60938749 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -289,7 +289,12 @@ 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)
         {
@@ -297,13 +302,15 @@ fn parse_source(
         }
         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,
                             _ => {}
                         }
@@ -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;
diff --git a/tests/rustdoc-ui/doctest/nested-main.rs b/tests/rustdoc-ui/doctest/nested-main.rs
new file mode 100644
index 00000000000..e939ba81214
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nested-main.rs
@@ -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() {}
diff --git a/tests/rustdoc-ui/doctest/nested-main.stdout b/tests/rustdoc-ui/doctest/nested-main.stdout
new file mode 100644
index 00000000000..af9a8f5e1d7
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/nested-main.stdout
@@ -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
+