From 7c4150fce0510218304b726174029fbb2c33ee03 Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Thu, 8 Aug 2024 11:36:48 -0700
Subject: [PATCH 1/2] rustdoc: do not run doctests with invalid langstrings

---
 src/librustdoc/html/markdown.rs               | 20 +++++++++++++++----
 src/librustdoc/html/markdown/tests.rs         |  6 +++---
 ...octest-no-run-invalid-langstring-124577.rs | 11 ++++++++++
 3 files changed, 30 insertions(+), 7 deletions(-)
 create mode 100644 tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs

diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 97d97808b9314..bb8d39aaf1dcc 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -924,6 +924,7 @@ pub(crate) struct TagIterator<'a, 'tcx> {
     data: &'a str,
     is_in_attribute_block: bool,
     extra: Option<&'a ExtraInfo<'tcx>>,
+    is_error: bool,
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
@@ -950,13 +951,20 @@ struct Indices {
 
 impl<'a, 'tcx> TagIterator<'a, 'tcx> {
     pub(crate) fn new(data: &'a str, extra: Option<&'a ExtraInfo<'tcx>>) -> Self {
-        Self { inner: data.char_indices().peekable(), data, is_in_attribute_block: false, extra }
+        Self {
+            inner: data.char_indices().peekable(),
+            data,
+            is_in_attribute_block: false,
+            extra,
+            is_error: false,
+        }
     }
 
-    fn emit_error(&self, err: impl Into<DiagMessage>) {
+    fn emit_error(&mut self, err: impl Into<DiagMessage>) {
         if let Some(extra) = self.extra {
             extra.error_invalid_codeblock_attr(err);
         }
+        self.is_error = true;
     }
 
     fn skip_separators(&mut self) -> Option<usize> {
@@ -1154,6 +1162,9 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> {
     type Item = LangStringToken<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
+        if self.is_error {
+            return None;
+        }
         let Some(start) = self.skip_separators() else {
             if self.is_in_attribute_block {
                 self.emit_error("unclosed attribute block (`{}`): missing `}` at the end");
@@ -1342,14 +1353,15 @@ impl LangString {
             }
         };
 
-        call(&mut TagIterator::new(string, extra));
+        let mut tag_iter = TagIterator::new(string, extra);
+        call(&mut tag_iter);
 
         // ignore-foo overrides ignore
         if !ignores.is_empty() {
             data.ignore = Ignore::Some(ignores);
         }
 
-        data.rust &= !seen_custom_tag && (!seen_other_tags || seen_rust_tags);
+        data.rust &= !seen_custom_tag && (!seen_other_tags || seen_rust_tags) && !tag_iter.is_error;
 
         data
     }
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 971120d4991c1..e490099a92e14 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -61,7 +61,7 @@ fn test_lang_string_parse() {
         ..Default::default()
     });
     // error
-    t(LangString { original: "{rust}".into(), rust: true, ..Default::default() });
+    t(LangString { original: "{rust}".into(), rust: false, ..Default::default() });
     t(LangString {
         original: "{.rust}".into(),
         rust: true,
@@ -233,7 +233,7 @@ fn test_lang_string_parse() {
         ..Default::default()
     });
     // error
-    t(LangString { original: "{class=first=second}".into(), rust: true, ..Default::default() });
+    t(LangString { original: "{class=first=second}".into(), rust: false, ..Default::default() });
     // error
     t(LangString {
         original: "{class=first.second}".into(),
@@ -261,7 +261,7 @@ fn test_lang_string_parse() {
         ..Default::default()
     });
     // error
-    t(LangString { original: r#"{class=f"irst"}"#.into(), rust: true, ..Default::default() });
+    t(LangString { original: r#"{class=f"irst"}"#.into(), rust: false, ..Default::default() });
 }
 
 #[test]
diff --git a/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs
new file mode 100644
index 0000000000000..b3e993e8ee939
--- /dev/null
+++ b/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs
@@ -0,0 +1,11 @@
+//@ compile-flags:--test
+#![allow(rustdoc::invalid_codeblock_attributes)]
+
+// https://github.com/rust-lang/rust/pull/124577#issuecomment-2276034737
+
+// Test that invalid langstrings don't get run.
+
+/// ```{rust,ignore}
+/// panic!();
+/// ```
+pub struct Foo;

From 1d19c2c009529fff08a95cbe548bcb1a6e02651c Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Fri, 9 Aug 2024 07:57:46 -0700
Subject: [PATCH 2/2] rustdoc: move invalid langstring test to UI

---
 .../doctest/doctest-no-run-invalid-langstring-124577.rs      | 1 +
 .../doctest/doctest-no-run-invalid-langstring-124577.stdout  | 5 +++++
 2 files changed, 6 insertions(+)
 rename tests/{rustdoc => rustdoc-ui}/doctest/doctest-no-run-invalid-langstring-124577.rs (94%)
 create mode 100644 tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout

diff --git a/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
similarity index 94%
rename from tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs
rename to tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
index b3e993e8ee939..571bc94e30f98 100644
--- a/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs
+++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
@@ -1,4 +1,5 @@
 //@ compile-flags:--test
+//@ check-pass
 #![allow(rustdoc::invalid_codeblock_attributes)]
 
 // https://github.com/rust-lang/rust/pull/124577#issuecomment-2276034737
diff --git a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout
new file mode 100644
index 0000000000000..e5c27bebbdb23
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout
@@ -0,0 +1,5 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+