diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index c971e231463cd..fda2512a05036 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1316,8 +1316,7 @@ crate struct RustCodeBlock {
/// The range in the markdown that the code within the code block occupies.
crate code: Range,
crate is_fenced: bool,
- crate syntax: Option,
- crate is_ignore: bool,
+ crate lang_string: LangString,
}
/// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
@@ -1333,7 +1332,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec {
let syntax = syntax.as_ref();
let lang_string = if syntax.is_empty() {
@@ -1344,8 +1343,6 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec (offset.start, offset.end),
Some((_, sub_offset)) => {
@@ -1354,8 +1351,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec) -> Vec) -> Vec {
// The ending of the offset goes too far sometime so we reduce it by one in
// these cases.
if offset.end > offset.start && md.get(offset.end..=offset.end) == Some(&"\n") {
(
- None,
+ LangString::default(),
offset.start,
offset.end,
Range { start: offset.start, end: offset.end - 1 },
false,
- false,
)
} else {
- (None, offset.start, offset.end, offset, false, false)
+ (LangString::default(), offset.start, offset.end, offset, false)
}
}
};
@@ -1398,8 +1392,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec SyntaxChecker<'a, 'tcx> {
let source = dox[code_block.code].to_owned();
let sess = ParseSess::with_span_handler(handler, sm);
+ let edition = code_block.lang_string.edition.unwrap_or(self.cx.tcx.sess.edition());
+ let expn_data = ExpnData::default(
+ ExpnKind::AstPass(AstPass::TestHarness),
+ DUMMY_SP,
+ edition,
+ None,
+ None,
+ );
+ let span = DUMMY_SP.fresh_expansion(expn_data, self.cx.tcx.create_stable_hashing_context());
+
let is_empty = rustc_driver::catch_fatal_errors(|| {
parse_stream_from_source_str(
FileName::Custom(String::from("doctest")),
source,
&sess,
- None,
+ Some(span),
)
.is_empty()
})
@@ -61,8 +71,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
};
let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_id);
- let empty_block = code_block.syntax.is_none() && code_block.is_fenced;
- let is_ignore = code_block.is_ignore;
+ let empty_block = code_block.lang_string == Default::default() && code_block.is_fenced;
+ let is_ignore = code_block.lang_string.ignore != markdown::Ignore::None;
// The span and whether it is precise or not.
let (sp, precise_span) = match super::source_span_for_markdown_range(
diff --git a/src/test/rustdoc-ui/doctest-edition.rs b/src/test/rustdoc-ui/doctest-edition.rs
new file mode 100644
index 0000000000000..b0787be972f2f
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-edition.rs
@@ -0,0 +1,16 @@
+// edition:2021
+
+#![deny(rustdoc::invalid_rust_codeblocks)]
+//~^ NOTE lint level is defined here
+
+// By default, rustdoc should use the edition of the crate.
+//! ```
+//! foo'b'
+//! ```
+//~^^^ ERROR could not parse
+//~| NOTE prefix `foo` is unknown
+
+// Rustdoc should respect `edition2018` when highlighting syntax.
+//! ```edition2018
+//! foo'b'
+//! ```
diff --git a/src/test/rustdoc-ui/doctest-edition.stderr b/src/test/rustdoc-ui/doctest-edition.stderr
new file mode 100644
index 0000000000000..1643d605375a1
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-edition.stderr
@@ -0,0 +1,22 @@
+error: could not parse code block as Rust code
+ --> $DIR/doctest-edition.rs:7:5
+ |
+LL | //! ```
+ | _____^
+LL | | //! foo'b'
+LL | | //! ```
+ | |_______^
+ |
+note: the lint level is defined here
+ --> $DIR/doctest-edition.rs:3:9
+ |
+LL | #![deny(rustdoc::invalid_rust_codeblocks)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: error from rustc: prefix `foo` is unknown
+help: mark blocks that do not contain Rust code as text
+ |
+LL | //! ```text
+ | ++++
+
+error: aborting due to previous error
+