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) {
+ fn emit_error(&mut self, err: impl Into) {
if let Some(extra) = self.extra {
extra.error_invalid_codeblock_attr(err);
}
+ self.is_error = true;
}
fn skip_separators(&mut self) -> Option {
@@ -1154,6 +1162,9 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> {
type Item = LangStringToken<'a>;
fn next(&mut self) -> Option {
+ 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-ui/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
new file mode 100644
index 0000000000000..571bc94e30f98
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
@@ -0,0 +1,12 @@
+//@ compile-flags:--test
+//@ check-pass
+#![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;
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
+