summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-12-16 13:59:41 +0100
committerJosh Stone <jistone@redhat.com>2025-01-02 14:28:32 -0800
commit32ee5bc6a33092f4b642631e425ddbeeec96fb08 (patch)
tree89e18e5172aeffbd644f4ae8066448b820358afd
parente09de50ce0ded8b290098874f9d778f521b8b0cc (diff)
downloadrust-32ee5bc6a33092f4b642631e425ddbeeec96fb08.tar.gz
rust-32ee5bc6a33092f4b642631e425ddbeeec96fb08.zip
Also handle cases where attributes are unclosed
(cherry picked from commit 23839853425e8c0c80d0aadb32bf5b4ba1bdf64b)
-rw-r--r--src/librustdoc/doctest/make.rs56
-rw-r--r--tests/rustdoc-ui/doctest/comment-in-attr-134221.rs4
-rw-r--r--tests/rustdoc-ui/doctest/comment-in-attr-134221.stdout18
3 files changed, 60 insertions, 18 deletions
diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs
index f484c98a0d3..66549afe5a1 100644
--- a/src/librustdoc/doctest/make.rs
+++ b/src/librustdoc/doctest/make.rs
@@ -51,8 +51,17 @@ impl DocTestBuilder {
                 !lang_str.compile_fail && !lang_str.test_harness && !lang_str.standalone_crate
             });
 
-        let SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else } =
-            partition_source(source, edition);
+        let Some(SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else }) =
+            partition_source(source, edition)
+        else {
+            return Self::invalid(
+                String::new(),
+                String::new(),
+                String::new(),
+                source.to_string(),
+                test_id,
+            );
+        };
 
         // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
         // crate already is included.
@@ -77,18 +86,7 @@ impl DocTestBuilder {
         else {
             // If the parser panicked due to a fatal error, pass the test code through unchanged.
             // The error will be reported during compilation.
-            return Self {
-                supports_color: false,
-                has_main_fn: false,
-                crate_attrs,
-                maybe_crate_attrs,
-                crates,
-                everything_else,
-                already_has_extern_crate: false,
-                test_id,
-                failed_ast: true,
-                can_be_merged: false,
-            };
+            return Self::invalid(crate_attrs, maybe_crate_attrs, crates, everything_else, test_id);
         };
         // If the AST returned an error, we don't want this doctest to be merged with the
         // others. Same if it contains `#[feature]` or `#[no_std]`.
@@ -113,6 +111,27 @@ impl DocTestBuilder {
         }
     }
 
+    fn invalid(
+        crate_attrs: String,
+        maybe_crate_attrs: String,
+        crates: String,
+        everything_else: String,
+        test_id: Option<String>,
+    ) -> Self {
+        Self {
+            supports_color: false,
+            has_main_fn: false,
+            crate_attrs,
+            maybe_crate_attrs,
+            crates,
+            everything_else,
+            already_has_extern_crate: false,
+            test_id,
+            failed_ast: true,
+            can_be_merged: false,
+        }
+    }
+
     /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
     /// lines before the test code begins.
     pub(crate) fn generate_unique_doctest(
@@ -533,7 +552,7 @@ struct SourceInfo {
     everything_else: String,
 }
 
-fn partition_source(s: &str, edition: Edition) -> SourceInfo {
+fn partition_source(s: &str, edition: Edition) -> Option<SourceInfo> {
     #[derive(Copy, Clone, PartialEq)]
     enum PartitionState {
         Attrs,
@@ -608,11 +627,16 @@ fn partition_source(s: &str, edition: Edition) -> SourceInfo {
         }
     }
 
+    if !mod_attr_pending.is_empty() {
+        debug!("invalid doctest code: {s:?}");
+        return None;
+    }
+
     source_info.everything_else = source_info.everything_else.trim().to_string();
 
     debug!("crate_attrs:\n{}{}", source_info.crate_attrs, source_info.maybe_crate_attrs);
     debug!("crates:\n{}", source_info.crates);
     debug!("after:\n{}", source_info.everything_else);
 
-    source_info
+    Some(source_info)
 }
diff --git a/tests/rustdoc-ui/doctest/comment-in-attr-134221.rs b/tests/rustdoc-ui/doctest/comment-in-attr-134221.rs
index fa8cd106659..3689ebe166a 100644
--- a/tests/rustdoc-ui/doctest/comment-in-attr-134221.rs
+++ b/tests/rustdoc-ui/doctest/comment-in-attr-134221.rs
@@ -20,4 +20,8 @@
   foo,
 )]
 ```
+
+```rust
+#![
+```
 */
diff --git a/tests/rustdoc-ui/doctest/comment-in-attr-134221.stdout b/tests/rustdoc-ui/doctest/comment-in-attr-134221.stdout
index 728bfdb010f..aa1b27d1f0b 100644
--- a/tests/rustdoc-ui/doctest/comment-in-attr-134221.stdout
+++ b/tests/rustdoc-ui/doctest/comment-in-attr-134221.stdout
@@ -1,7 +1,8 @@
 
-running 2 tests
+running 3 tests
 test $DIR/comment-in-attr-134221.rs - (line 11) ... FAILED
 test $DIR/comment-in-attr-134221.rs - (line 17) ... FAILED
+test $DIR/comment-in-attr-134221.rs - (line 23) ... FAILED
 
 failures:
 
@@ -27,10 +28,23 @@ error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0635`.
 Couldn't compile the test.
+---- $DIR/comment-in-attr-134221.rs - (line 23) stdout ----
+error: this file contains an unclosed delimiter
+  --> $DIR/comment-in-attr-134221.rs:$LINE:$COL
+   |
+LL | #![
+   |   -^
+   |   |
+   |   unclosed delimiter
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
 
 failures:
     $DIR/comment-in-attr-134221.rs - (line 11)
     $DIR/comment-in-attr-134221.rs - (line 17)
+    $DIR/comment-in-attr-134221.rs - (line 23)
 
-test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+test result: FAILED. 0 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME