diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index c37736f137df9..c8dbc8d321002 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -428,6 +428,27 @@ impl<'a, F: Write> TokenHandler<'a, '_, F> {
}
}
}
+
+ /// Used when we're done with the current expansion "original code" (ie code before expansion).
+ /// We close all tags inside `Class::Original` and only keep the ones that were not closed yet.
+ fn close_original_tag(&mut self) {
+ let mut classes_to_reopen = Vec::new();
+ while let Some(mut class_info) = self.class_stack.open_classes.pop() {
+ if class_info.class == Class::Original {
+ while let Some(class_info) = classes_to_reopen.pop() {
+ self.class_stack.open_classes.push(class_info);
+ }
+ class_info.close_tag(self.out);
+ return;
+ }
+ class_info.close_tag(self.out);
+ if !class_info.pending_exit {
+ class_info.closing_tag = None;
+ classes_to_reopen.push(class_info);
+ }
+ }
+ panic!("Didn't find `Class::Original` to close");
+ }
}
impl Drop for TokenHandler<'_, '_, F> {
@@ -476,7 +497,9 @@ fn end_expansion<'a, W: Write>(
expanded_codes: &'a [ExpandedCode],
span: Span,
) -> Option<&'a ExpandedCode> {
- token_handler.class_stack.exit_elem();
+ // We close `Class::Original` and everything open inside it.
+ token_handler.close_original_tag();
+ // Then we check if we have another macro expansion on the same line.
let expansion = get_next_expansion(expanded_codes, token_handler.line, span);
if expansion.is_none() {
token_handler.close_expansion();
diff --git a/tests/rustdoc/macro/auxiliary/one-line-expand.rs b/tests/rustdoc/macro/auxiliary/one-line-expand.rs
new file mode 100644
index 0000000000000..14df0f2d4f20e
--- /dev/null
+++ b/tests/rustdoc/macro/auxiliary/one-line-expand.rs
@@ -0,0 +1,15 @@
+//@ force-host
+//@ no-prefer-dynamic
+//@ compile-flags: --crate-type proc-macro
+
+#![crate_type = "proc-macro"]
+#![crate_name = "just_some_proc"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn repro(_args: TokenStream, _input: TokenStream) -> TokenStream {
+ "struct Repro;".parse().unwrap()
+}
diff --git a/tests/rustdoc/macro/one-line-expand.rs b/tests/rustdoc/macro/one-line-expand.rs
new file mode 100644
index 0000000000000..ceb9521820d61
--- /dev/null
+++ b/tests/rustdoc/macro/one-line-expand.rs
@@ -0,0 +1,19 @@
+// Regression test for .
+// It ensures that the macro expansion correctly handles its "class stack".
+
+//@ compile-flags: -Zunstable-options --generate-macro-expansion
+//@ aux-build:one-line-expand.rs
+
+#![crate_name = "foo"]
+
+extern crate just_some_proc;
+
+//@ has 'src/foo/one-line-expand.rs.html'
+//@ has - '//*[@class="comment"]' '//'
+//@ has - '//*[@class="original"]' '#[just_some_proc::repro]'
+//@ has - '//*[@class="original"]/*[@class="attr"]' '#[just_some_proc::repro]'
+//@ has - '//code/*[@class="kw"]' 'struct '
+
+//
+#[just_some_proc::repro]
+struct Repro;