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 +