From 5372e66884b7962acfce99d5dd8aef7e48d0257e Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Sun, 29 Jan 2023 15:20:03 +0100 Subject: [PATCH 01/10] Remove `GenFuture` from core The handling of async constructs in the compiler does not rely on `GenFuture` anymore since `1.67`, so this code can now be removed from `core`. --- library/core/src/future/mod.rs | 45 ---------------------------------- 1 file changed, 45 deletions(-) diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index c4fb3620946..46cbcd43530 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -56,51 +56,6 @@ unsafe impl Send for ResumeTy {} #[unstable(feature = "gen_future", issue = "50547")] unsafe impl Sync for ResumeTy {} -/// Wrap a generator in a future. -/// -/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give -/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). -// This is `const` to avoid extra errors after we recover from `const async fn` -#[doc(hidden)] -#[unstable(feature = "gen_future", issue = "50547")] -#[rustc_const_unstable(feature = "gen_future", issue = "50547")] -#[inline] -pub const fn from_generator(gen: T) -> impl Future -where - T: crate::ops::Generator, -{ - use crate::{ - ops::{Generator, GeneratorState}, - pin::Pin, - task::Poll, - }; - - #[rustc_diagnostic_item = "gen_future"] - struct GenFuture>(T); - - // We rely on the fact that async/await futures are immovable in order to create - // self-referential borrows in the underlying generator. - impl> !Unpin for GenFuture {} - - impl> Future for GenFuture { - type Output = T::Return; - #[track_caller] - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. - let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; - - // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The - // `.await` lowering will safely cast that back to a `&mut Context`. - match gen.resume(ResumeTy(NonNull::from(cx).cast::>())) { - GeneratorState::Yielded(()) => Poll::Pending, - GeneratorState::Complete(x) => Poll::Ready(x), - } - } - } - - GenFuture(gen) -} - #[lang = "get_context"] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] From 3e5e38731834246f09f596dec954f35d26bc5629 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 30 Jan 2023 12:01:05 -0500 Subject: [PATCH 02/10] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 2cd1b5593d2..f2a78f64b66 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 2cd1b5593d26dc6a03c20f8619187ad4b2485552 +Subproject commit f2a78f64b668f63f581203c6bac509903f7c00ee diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 19f798d4488..f1a4614aa41 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 19f798d448835a4888e3b3eae7fe69f1d61d8681 +Subproject commit f1a4614aa41cc544b91b79760a709e113f3451d7 diff --git a/src/doc/nomicon b/src/doc/nomicon index 960d610e7f3..bd1829d2352 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 960d610e7f33889a2577f5f17c26f0d5c82b30df +Subproject commit bd1829d235296952bf72ca55635e360584b8805e diff --git a/src/doc/reference b/src/doc/reference index 2cb0ed9ba56..22882fb3f7b 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 2cb0ed9ba56360949f492f9866afe8c293f9f9da +Subproject commit 22882fb3f7b4d69fdc0d1731e8b9cfcb6910537d diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index a9fb7d13ead..134376872e8 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit a9fb7d13eadfcc5f457962731f105b97f9a7474a +Subproject commit 134376872e8c387ef369507e0ee9b5a0e3272718 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 7352353ae91..e359ee27fc3 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 7352353ae91c48b136d2ca7d03822e1448165e1e +Subproject commit e359ee27fc3da3356d71a732128c0a1abe02e53a From 7080f80e8b64eb5f2037de50991edb9e82aee3a5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 30 Jan 2023 11:05:12 -0700 Subject: [PATCH 03/10] rustdoc: remove unnecessary wrapper div.item-decl from HTML --- src/librustdoc/html/highlight.rs | 8 +- src/librustdoc/html/render/print_item.rs | 590 ++++++++---------- src/librustdoc/html/static/css/rustdoc.css | 2 +- tests/rustdoc-gui/code-tags.goml | 10 +- tests/rustdoc-gui/font-weight.goml | 9 +- tests/rustdoc-gui/list_code_block.goml | 2 +- .../rustdoc-gui/type-declation-overflow.goml | 18 +- tests/rustdoc/array-links.rs | 8 +- tests/rustdoc/assoc-consts.rs | 2 +- tests/rustdoc/assoc-item-cast.rs | 2 +- tests/rustdoc/assoc-types.rs | 12 +- tests/rustdoc/async-fn.rs | 30 +- tests/rustdoc/attribute-rendering.rs | 2 +- tests/rustdoc/attributes.rs | 6 +- tests/rustdoc/auxiliary/issue-85454.rs | 2 +- tests/rustdoc/const-fn.rs | 2 +- tests/rustdoc/const-generics/add-impl.rs | 2 +- .../const-generics/const-generic-defaults.rs | 2 +- .../const-generics/const-generics-docs.rs | 36 +- tests/rustdoc/const-generics/const-impl.rs | 2 +- .../const-generics/generic_const_exprs.rs | 2 +- tests/rustdoc/const-generics/type-alias.rs | 2 +- tests/rustdoc/const-intrinsic.rs | 6 +- tests/rustdoc/const-value-display.rs | 4 +- tests/rustdoc/decl-trailing-whitespace.rs | 2 +- tests/rustdoc/fn-pointer-arg-name.rs | 2 +- ...ide-complex-unevaluated-const-arguments.rs | 2 +- tests/rustdoc/inline-default-methods.rs | 4 +- tests/rustdoc/inline_cross/dyn_trait.rs | 12 +- tests/rustdoc/inline_cross/impl_trait.rs | 32 +- tests/rustdoc/inline_cross/issue-24183.rs | 4 +- tests/rustdoc/issue-20646.rs | 4 +- tests/rustdoc/issue-20727-2.rs | 12 +- tests/rustdoc/issue-20727-3.rs | 12 +- tests/rustdoc/issue-20727-4.rs | 20 +- tests/rustdoc/issue-20727.rs | 12 +- tests/rustdoc/issue-22038.rs | 8 +- tests/rustdoc/issue-33302.rs | 6 +- tests/rustdoc/issue-85454.rs | 4 +- tests/rustdoc/issue-98697.rs | 4 +- tests/rustdoc/legacy-const-generic.rs | 4 +- tests/rustdoc/lifetime-name.rs | 2 +- tests/rustdoc/macro-higher-kinded-function.rs | 4 +- tests/rustdoc/mut-params.rs | 4 +- tests/rustdoc/normalize-assoc-item.rs | 16 +- tests/rustdoc/pub-method.rs | 2 +- tests/rustdoc/range-arg-pattern.rs | 2 +- tests/rustdoc/reexport-dep-foreign-fn.rs | 2 +- tests/rustdoc/reexports-priv.rs | 48 +- tests/rustdoc/reexports.rs | 24 +- tests/rustdoc/rfc-2632-const-trait-impl.rs | 16 +- tests/rustdoc/safe-intrinsic.rs | 6 +- tests/rustdoc/slice-links.rs | 8 +- tests/rustdoc/struct-arg-pattern.rs | 2 +- tests/rustdoc/test-parens.rs | 2 +- tests/rustdoc/toggle-item-contents.rs | 6 +- tests/rustdoc/trait_alias.rs | 6 +- tests/rustdoc/tuple-struct-fields-doc.rs | 2 +- tests/rustdoc/tuples.rs | 12 +- tests/rustdoc/unit-return.rs | 8 +- tests/rustdoc/where-sized.rs | 4 +- .../rustdoc/where.SWhere_Simd_item-decl.html | 2 +- .../where.SWhere_TraitWhere_item-decl.html | 4 +- tests/rustdoc/where.rs | 6 +- .../whitespace-after-where-clause.enum.html | 4 +- .../whitespace-after-where-clause.enum2.html | 4 +- .../rustdoc/whitespace-after-where-clause.rs | 16 +- .../whitespace-after-where-clause.struct.html | 4 +- ...whitespace-after-where-clause.struct2.html | 4 +- .../whitespace-after-where-clause.trait.html | 4 +- .../whitespace-after-where-clause.trait2.html | 4 +- .../whitespace-after-where-clause.union.html | 4 +- .../whitespace-after-where-clause.union2.html | 4 +- tests/rustdoc/wrapping.rs | 4 +- 74 files changed, 552 insertions(+), 593 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 8a9e6caf611..1644d1c5a29 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -58,11 +58,11 @@ pub(crate) fn render_example_with_highlighting( write_footer(out, playground_button); } -/// Highlights `src` as a macro, returning the HTML output. -pub(crate) fn render_macro_with_highlighting(src: &str, out: &mut Buffer) { - write_header(out, "macro", None, Tooltip::None); +/// Highlights `src` as an item-decl, returning the HTML output. +pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) { + write!(out, "
");
     write_code(out, src, None, None);
-    write_footer(out, None);
+    write!(out, "
"); } /// Highlights `src` as a source code page, returning the HTML output. diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index b0288d55c25..71cde1f964c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -530,26 +530,24 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle let notable_traits = f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx)); - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - w.reserve(header_len); - write!( - w, - "{vis}{constness}{asyncness}{unsafety}{abi}fn \ - {name}{generics}{decl}{notable_traits}{where_clause}", - vis = visibility, - constness = constness, - asyncness = asyncness, - unsafety = unsafety, - abi = abi, - name = name, - generics = f.generics.print(cx), - where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline), - decl = f.decl.full_print(header_len, 0, cx), - notable_traits = notable_traits.unwrap_or_default(), - ); - }); + wrap_item(w, |w| { + render_attributes_in_pre(w, it, ""); + w.reserve(header_len); + write!( + w, + "{vis}{constness}{asyncness}{unsafety}{abi}fn \ + {name}{generics}{decl}{notable_traits}{where_clause}", + vis = visibility, + constness = constness, + asyncness = asyncness, + unsafety = unsafety, + abi = abi, + name = name, + generics = f.generics.print(cx), + where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline), + decl = f.decl.full_print(header_len, 0, cx), + notable_traits = notable_traits.unwrap_or_default(), + ); }); document(w, cx, it, None, HeadingOffset::H2); } @@ -569,145 +567,140 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone(); // Output the trait definition - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - write!( - w, - "{}{}{}trait {}{}{}", - visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - t.unsafety(tcx).print_with_space(), - if t.is_auto(tcx) { "auto " } else { "" }, - it.name.unwrap(), - t.generics.print(cx), - bounds - ); + wrap_item(w, |w| { + render_attributes_in_pre(w, it, ""); + write!( + w, + "{}{}{}trait {}{}{}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + t.unsafety(tcx).print_with_space(), + if t.is_auto(tcx) { "auto " } else { "" }, + it.name.unwrap(), + t.generics.print(cx), + bounds + ); - if !t.generics.where_predicates.is_empty() { - write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline)); - } else { - w.write_str(" "); + if !t.generics.where_predicates.is_empty() { + write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline)); + } else { + w.write_str(" "); + } + + if t.items.is_empty() { + w.write_str("{ }"); + } else { + // FIXME: we should be using a derived_id for the Anchors here + w.write_str("{\n"); + let mut toggle = false; + + // If there are too many associated types, hide _everything_ + if should_hide_fields(count_types) { + toggle = true; + toggle_open( + w, + format_args!("{} associated items", count_types + count_consts + count_methods), + ); } - - if t.items.is_empty() { - w.write_str("{ }"); - } else { - // FIXME: we should be using a derived_id for the Anchors here - w.write_str("{\n"); - let mut toggle = false; - - // If there are too many associated types, hide _everything_ - if should_hide_fields(count_types) { - toggle = true; - toggle_open( - w, - format_args!( - "{} associated items", - count_types + count_consts + count_methods - ), - ); - } - for types in [&required_types, &provided_types] { - for t in types { - render_assoc_item( - w, - t, - AssocItemLink::Anchor(None), - ItemType::Trait, - cx, - RenderMode::Normal, - ); - w.write_str(";\n"); - } - } - // If there are too many associated constants, hide everything after them - // We also do this if the types + consts is large because otherwise we could - // render a bunch of types and _then_ a bunch of consts just because both were - // _just_ under the limit - if !toggle && should_hide_fields(count_types + count_consts) { - toggle = true; - toggle_open( - w, - format_args!( - "{} associated constant{} and {} method{}", - count_consts, - pluralize(count_consts), - count_methods, - pluralize(count_methods), - ), - ); - } - if count_types != 0 && (count_consts != 0 || count_methods != 0) { - w.write_str("\n"); - } - for consts in [&required_consts, &provided_consts] { - for c in consts { - render_assoc_item( - w, - c, - AssocItemLink::Anchor(None), - ItemType::Trait, - cx, - RenderMode::Normal, - ); - w.write_str(";\n"); - } - } - if !toggle && should_hide_fields(count_methods) { - toggle = true; - toggle_open(w, format_args!("{} methods", count_methods)); - } - if count_consts != 0 && count_methods != 0 { - w.write_str("\n"); - } - for (pos, m) in required_methods.iter().enumerate() { + for types in [&required_types, &provided_types] { + for t in types { render_assoc_item( w, - m, + t, AssocItemLink::Anchor(None), ItemType::Trait, cx, RenderMode::Normal, ); w.write_str(";\n"); - - if pos < required_methods.len() - 1 { - w.write_str(""); - } } - if !required_methods.is_empty() && !provided_methods.is_empty() { - w.write_str("\n"); - } - for (pos, m) in provided_methods.iter().enumerate() { + } + // If there are too many associated constants, hide everything after them + // We also do this if the types + consts is large because otherwise we could + // render a bunch of types and _then_ a bunch of consts just because both were + // _just_ under the limit + if !toggle && should_hide_fields(count_types + count_consts) { + toggle = true; + toggle_open( + w, + format_args!( + "{} associated constant{} and {} method{}", + count_consts, + pluralize(count_consts), + count_methods, + pluralize(count_methods), + ), + ); + } + if count_types != 0 && (count_consts != 0 || count_methods != 0) { + w.write_str("\n"); + } + for consts in [&required_consts, &provided_consts] { + for c in consts { render_assoc_item( w, - m, + c, AssocItemLink::Anchor(None), ItemType::Trait, cx, RenderMode::Normal, ); - match *m.kind { - clean::MethodItem(ref inner, _) - if !inner.generics.where_predicates.is_empty() => - { - w.write_str(",\n { ... }\n"); - } - _ => { - w.write_str(" { ... }\n"); - } - } - - if pos < provided_methods.len() - 1 { - w.write_str(""); - } + w.write_str(";\n"); } - if toggle { - toggle_close(w); - } - w.write_str("}"); } - }); + if !toggle && should_hide_fields(count_methods) { + toggle = true; + toggle_open(w, format_args!("{} methods", count_methods)); + } + if count_consts != 0 && count_methods != 0 { + w.write_str("\n"); + } + for (pos, m) in required_methods.iter().enumerate() { + render_assoc_item( + w, + m, + AssocItemLink::Anchor(None), + ItemType::Trait, + cx, + RenderMode::Normal, + ); + w.write_str(";\n"); + + if pos < required_methods.len() - 1 { + w.write_str(""); + } + } + if !required_methods.is_empty() && !provided_methods.is_empty() { + w.write_str("\n"); + } + for (pos, m) in provided_methods.iter().enumerate() { + render_assoc_item( + w, + m, + AssocItemLink::Anchor(None), + ItemType::Trait, + cx, + RenderMode::Normal, + ); + match *m.kind { + clean::MethodItem(ref inner, _) + if !inner.generics.where_predicates.is_empty() => + { + w.write_str(",\n { ... }\n"); + } + _ => { + w.write_str(" { ... }\n"); + } + } + + if pos < provided_methods.len() - 1 { + w.write_str(""); + } + } + if toggle { + toggle_close(w); + } + w.write_str("}"); + } }); // Trait documentation @@ -1050,18 +1043,16 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - write!( - w, - "trait {}{}{} = {};", - it.name.unwrap(), - t.generics.print(cx), - print_where_clause(&t.generics, cx, 0, Ending::Newline), - bounds(&t.bounds, true, cx) - ); - }); + wrap_item(w, |w| { + render_attributes_in_pre(w, it, ""); + write!( + w, + "trait {}{}{} = {};", + it.name.unwrap(), + t.generics.print(cx), + print_where_clause(&t.generics, cx, 0, Ending::Newline), + bounds(&t.bounds, true, cx) + ); }); document(w, cx, it, None, HeadingOffset::H2); @@ -1074,18 +1065,16 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: & } fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - write!( - w, - "type {}{}{where_clause} = impl {bounds};", - it.name.unwrap(), - t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), - bounds = bounds(&t.bounds, false, cx), - ); - }); + wrap_item(w, |w| { + render_attributes_in_pre(w, it, ""); + write!( + w, + "type {}{}{where_clause} = impl {bounds};", + it.name.unwrap(), + t.generics.print(cx), + where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), + bounds = bounds(&t.bounds, false, cx), + ); }); document(w, cx, it, None, HeadingOffset::H2); @@ -1113,7 +1102,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea }); } - wrap_into_item_decl(w, |w| write_content(w, cx, it, t)); + write_content(w, cx, it, t); document(w, cx, it, None, HeadingOffset::H2); @@ -1127,11 +1116,9 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea } fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - render_union(w, it, Some(&s.generics), &s.fields, "", cx); - }); + wrap_item(w, |w| { + render_attributes_in_pre(w, it, ""); + render_union(w, it, Some(&s.generics), &s.fields, "", cx); }); document(w, cx, it, None, HeadingOffset::H2); @@ -1192,60 +1179,58 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item] fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { let tcx = cx.tcx(); let count_variants = e.variants().count(); - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - write!( - w, - "{}enum {}{}", - visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - it.name.unwrap(), - e.generics.print(cx), - ); - if !print_where_clause_and_check(w, &e.generics, cx) { - // If there wasn't a `where` clause, we add a whitespace. - w.write_str(" "); + wrap_item(w, |w| { + render_attributes_in_pre(w, it, ""); + write!( + w, + "{}enum {}{}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + it.name.unwrap(), + e.generics.print(cx), + ); + if !print_where_clause_and_check(w, &e.generics, cx) { + // If there wasn't a `where` clause, we add a whitespace. + w.write_str(" "); + } + + let variants_stripped = e.has_stripped_entries(); + if count_variants == 0 && !variants_stripped { + w.write_str("{}"); + } else { + w.write_str("{\n"); + let toggle = should_hide_fields(count_variants); + if toggle { + toggle_open(w, format_args!("{} variants", count_variants)); + } + for v in e.variants() { + w.write_str(" "); + let name = v.name.unwrap(); + match *v.kind { + // FIXME(#101337): Show discriminant + clean::VariantItem(ref var) => match var.kind { + clean::VariantKind::CLike => write!(w, "{}", name), + clean::VariantKind::Tuple(ref s) => { + write!(w, "{}(", name); + print_tuple_struct_fields(w, cx, s); + w.write_str(")"); + } + clean::VariantKind::Struct(ref s) => { + render_struct(w, v, None, None, &s.fields, " ", false, cx); + } + }, + _ => unreachable!(), + } + w.write_str(",\n"); } - let variants_stripped = e.has_stripped_entries(); - if count_variants == 0 && !variants_stripped { - w.write_str("{}"); - } else { - w.write_str("{\n"); - let toggle = should_hide_fields(count_variants); - if toggle { - toggle_open(w, format_args!("{} variants", count_variants)); - } - for v in e.variants() { - w.write_str(" "); - let name = v.name.unwrap(); - match *v.kind { - // FIXME(#101337): Show discriminant - clean::VariantItem(ref var) => match var.kind { - clean::VariantKind::CLike => write!(w, "{}", name), - clean::VariantKind::Tuple(ref s) => { - write!(w, "{}(", name); - print_tuple_struct_fields(w, cx, s); - w.write_str(")"); - } - clean::VariantKind::Struct(ref s) => { - render_struct(w, v, None, None, &s.fields, " ", false, cx); - } - }, - _ => unreachable!(), - } - w.write_str(",\n"); - } - - if variants_stripped { - w.write_str(" // some variants omitted\n"); - } - if toggle { - toggle_close(w); - } - w.write_str("}"); + if variants_stripped { + w.write_str(" // some variants omitted\n"); } - }); + if toggle { + toggle_close(w); + } + w.write_str("}"); + } }); document(w, cx, it, None, HeadingOffset::H2); @@ -1346,38 +1331,30 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: } fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { - wrap_into_item_decl(w, |w| { - highlight::render_macro_with_highlighting(&t.source, w); - }); + highlight::render_item_decl_with_highlighting(&t.source, w); document(w, cx, it, None, HeadingOffset::H2) } fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) { - wrap_into_item_decl(w, |w| { + wrap_item(w, |w| { let name = it.name.expect("proc-macros always have names"); match m.kind { MacroKind::Bang => { - wrap_item(w, |w| { - write!(w, "{}!() {{ /* proc-macro */ }}", name); - }); + write!(w, "{}!() {{ /* proc-macro */ }}", name); } MacroKind::Attr => { - wrap_item(w, |w| { - write!(w, "#[{}]", name); - }); + write!(w, "#[{}]", name); } MacroKind::Derive => { - wrap_item(w, |w| { - write!(w, "#[derive({})]", name); - if !m.helpers.is_empty() { - w.push_str("\n{\n"); - w.push_str(" // Attributes available to this derive:\n"); - for attr in &m.helpers { - writeln!(w, " #[{}]", attr); - } - w.push_str("}\n"); + write!(w, "#[derive({})]", name); + if !m.helpers.is_empty() { + w.push_str("\n{\n"); + w.push_str(" // Attributes available to this derive:\n"); + for attr in &m.helpers { + writeln!(w, " #[{}]", attr); } - }); + w.push_str("}\n"); + } } } }); @@ -1400,61 +1377,57 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { } fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - let tcx = cx.tcx(); - render_attributes_in_code(w, it); + wrap_item(w, |w| { + let tcx = cx.tcx(); + render_attributes_in_code(w, it); - write!( - w, - "{vis}const {name}: {typ}", - vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - name = it.name.unwrap(), - typ = c.type_.print(cx), - ); + write!( + w, + "{vis}const {name}: {typ}", + vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + name = it.name.unwrap(), + typ = c.type_.print(cx), + ); - // FIXME: The code below now prints - // ` = _; // 100i32` - // if the expression is - // `50 + 50` - // which looks just wrong. - // Should we print - // ` = 100i32;` - // instead? + // FIXME: The code below now prints + // ` = _; // 100i32` + // if the expression is + // `50 + 50` + // which looks just wrong. + // Should we print + // ` = 100i32;` + // instead? - let value = c.value(tcx); - let is_literal = c.is_literal(tcx); - let expr = c.expr(tcx); - if value.is_some() || is_literal { - write!(w, " = {expr};", expr = Escape(&expr)); - } else { - w.write_str(";"); - } + let value = c.value(tcx); + let is_literal = c.is_literal(tcx); + let expr = c.expr(tcx); + if value.is_some() || is_literal { + write!(w, " = {expr};", expr = Escape(&expr)); + } else { + w.write_str(";"); + } - if !is_literal { - if let Some(value) = &value { - let value_lowercase = value.to_lowercase(); - let expr_lowercase = expr.to_lowercase(); + if !is_literal { + if let Some(value) = &value { + let value_lowercase = value.to_lowercase(); + let expr_lowercase = expr.to_lowercase(); - if value_lowercase != expr_lowercase - && value_lowercase.trim_end_matches("i32") != expr_lowercase - { - write!(w, " // {value}", value = Escape(value)); - } + if value_lowercase != expr_lowercase + && value_lowercase.trim_end_matches("i32") != expr_lowercase + { + write!(w, " // {value}", value = Escape(value)); } } - }); + } }); document(w, cx, it, None, HeadingOffset::H2) } fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_code(w, it); - render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); - }); + wrap_item(w, |w| { + render_attributes_in_code(w, it); + render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); }); document(w, cx, it, None, HeadingOffset::H2); @@ -1503,34 +1476,30 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - render_attributes_in_code(w, it); - write!( - w, - "{vis}static {mutability}{name}: {typ}", - vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), - mutability = s.mutability.print_with_space(), - name = it.name.unwrap(), - typ = s.type_.print(cx) - ); - }); + wrap_item(w, |w| { + render_attributes_in_code(w, it); + write!( + w, + "{vis}static {mutability}{name}: {typ}", + vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), + mutability = s.mutability.print_with_space(), + name = it.name.unwrap(), + typ = s.type_.print(cx) + ); }); document(w, cx, it, None, HeadingOffset::H2) } fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { - wrap_into_item_decl(w, |w| { - wrap_item(w, |w| { - w.write_str("extern {\n"); - render_attributes_in_code(w, it); - write!( - w, - " {}type {};\n}}", - visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), - it.name.unwrap(), - ); - }); + wrap_item(w, |w| { + w.write_str("extern {\n"); + render_attributes_in_code(w, it); + write!( + w, + " {}type {};\n}}", + visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), + it.name.unwrap(), + ); }); document(w, cx, it, None, HeadingOffset::H2); @@ -1609,20 +1578,11 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) bounds } -fn wrap_into_item_decl(w: &mut Buffer, f: F) -where - F: FnOnce(&mut Buffer), -{ - w.write_str("
"); - f(w); - w.write_str("
") -} - fn wrap_item(w: &mut Buffer, f: F) where F: FnOnce(&mut Buffer), { - w.write_str(r#"
"#);
+    w.write_str(r#"
"#);
     f(w);
     w.write_str("
"); } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 8699508e439..e9f0ae39f3e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -335,7 +335,7 @@ pre { padding: 14px; line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */ } -.item-decl pre { +pre.item-decl { overflow-x: auto; } /* This rule allows to have scrolling on the X axis. */ diff --git a/tests/rustdoc-gui/code-tags.goml b/tests/rustdoc-gui/code-tags.goml index 8561f537f3d..ca337cbc323 100644 --- a/tests/rustdoc-gui/code-tags.goml +++ b/tests/rustdoc-gui/code-tags.goml @@ -9,16 +9,16 @@ size: (1080, 600) // Check that their content is inside

 assert-count: (".example-wrap pre > code", 4)
 // Check that function signature is inside 

-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml
index fafb1563178..aad334d2bd2 100644
--- a/tests/rustdoc-gui/font-weight.goml
+++ b/tests/rustdoc-gui/font-weight.goml
@@ -1,6 +1,6 @@
 // This test checks that the font weight is correctly applied.
 goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
-assert-css: ("//*[@class='item-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"})
 assert-css: (
     "//*[@class='structfield small-section-header']//a[text()='Alias']",
     {"font-weight": "400"},
@@ -19,8 +19,7 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 
 // This is a complex selector, so here's how it works:
 //
-// * //*[@class='item-decl'] — selects element of any tag with classes docblock and item-decl
-// * /pre[@class='rust'] — selects immediate child with tag pre and class rust
+// * //pre[@class='rust item-decl'] — selects item-decl code block
 // * /code — selects immediate child with tag code
 // * /a[@class='constant'] — selects immediate child with tag a and class constant
 // * //text() — selects child that is text node
@@ -29,11 +28,11 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 // This uses '/parent::*' as a proxy for the style of the text node.
 // We can't just select the '' because intermediate tags could be added.
 assert-count: (
-    "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+    "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
     1,
 )
 assert-css: (
-    "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+    "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
     {"font-weight": "400"},
 )
 
diff --git a/tests/rustdoc-gui/list_code_block.goml b/tests/rustdoc-gui/list_code_block.goml
index c527cfbfcbc..4c477d70c89 100644
--- a/tests/rustdoc-gui/list_code_block.goml
+++ b/tests/rustdoc-gui/list_code_block.goml
@@ -1,4 +1,4 @@
 // This test checks that code blocks in list are supported.
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 goto: "./fn.check_list_code_block.html"
-assert: (".item-decl pre.rust")
+assert: ("pre.rust.item-decl")
diff --git a/tests/rustdoc-gui/type-declation-overflow.goml b/tests/rustdoc-gui/type-declation-overflow.goml
index 644429c014c..708e9dca0ee 100644
--- a/tests/rustdoc-gui/type-declation-overflow.goml
+++ b/tests/rustdoc-gui/type-declation-overflow.goml
@@ -12,7 +12,7 @@ size: (1100, 800)
 // Logically, the  scroll width should be the width of the window.
 assert-property: ("body", {"scrollWidth": "1100"})
 // However, since there is overflow in the type declaration, its scroll width is bigger.
-assert-property: (".item-decl pre", {"scrollWidth": "1324"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1324"})
 
 // In the table-ish view on the module index, the name should not be wrapped more than necessary.
 goto: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
@@ -24,7 +24,7 @@ assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
 assert-property: ("#main-content", {"scrollWidth": "840"})
 // And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "1103"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1103"})
 
 // ... and constant.
 // On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
@@ -33,7 +33,7 @@ assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
 assert-property: ("#main-content", {"scrollWidth": "840"})
 // And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "950"})
+assert-property: ("pre.item-decl", {"scrollWidth": "950"})
 
 // On mobile:
 size: (600, 600)
@@ -65,12 +65,12 @@ compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-ban
 goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
 
 click: ".item-decl .type-contents-toggle"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//details/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//details/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
 
 // Then on an item without "hidden methods".
 goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//code/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//code/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
diff --git a/tests/rustdoc/array-links.rs b/tests/rustdoc/array-links.rs
index e7c0ee2de1a..8ee294daa96 100644
--- a/tests/rustdoc/array-links.rs
+++ b/tests/rustdoc/array-links.rs
@@ -4,25 +4,25 @@
 pub struct MyBox(*const T);
 
 // @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn alpha() -> &'static [u32; 1] {
     loop {}
 }
 
 // @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
 pub fn beta() -> &'static [T; 1] {
     loop {}
 }
 
 // @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn gamma() -> MyBox<[u32; 1]> {
     loop {}
 }
 
 // @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
 pub fn delta() -> MyBox<[T; 1]> {
     loop {}
 }
diff --git a/tests/rustdoc/assoc-consts.rs b/tests/rustdoc/assoc-consts.rs
index 77b139b644f..68a11c57b52 100644
--- a/tests/rustdoc/assoc-consts.rs
+++ b/tests/rustdoc/assoc-consts.rs
@@ -1,5 +1,5 @@
 pub trait Foo {
-    // @has assoc_consts/trait.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \
     //      'const FOO: usize = 13usize;'
     // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
     const FOO: usize = 12 + 1;
diff --git a/tests/rustdoc/assoc-item-cast.rs b/tests/rustdoc/assoc-item-cast.rs
index ab9702a24f4..ad8235985bc 100644
--- a/tests/rustdoc/assoc-item-cast.rs
+++ b/tests/rustdoc/assoc-item-cast.rs
@@ -10,5 +10,5 @@ pub trait AsExpression {
 }
 
 // @has foo/type.AsExprOf.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type AsExprOf = >::Expression;'
+// @has - '//pre[@class="rust item-decl"]' 'type AsExprOf = >::Expression;'
 pub type AsExprOf = >::Expression;
diff --git a/tests/rustdoc/assoc-types.rs b/tests/rustdoc/assoc-types.rs
index de36c8ffeff..e74db7578d1 100644
--- a/tests/rustdoc/assoc-types.rs
+++ b/tests/rustdoc/assoc-types.rs
@@ -12,8 +12,8 @@ pub trait Index {
 }
 
 // @has assoc_types/fn.use_output.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '-> &T::Output'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
+// @has - '//pre[@class="rust item-decl"]' '-> &T::Output'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
 pub fn use_output>(obj: &T, index: usize) -> &T::Output {
     obj.index(index)
 }
@@ -23,13 +23,13 @@ pub trait Feed {
 }
 
 // @has assoc_types/fn.use_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'T::Input'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'T::Input'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
 pub fn use_input(_feed: &T, _element: T::Input) { }
 
 // @has assoc_types/fn.cmp_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where T::Input: PartialEq'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'where T::Input: PartialEq'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
 pub fn cmp_input(a: &T::Input, b: &U::Input) -> bool
     where T::Input: PartialEq
 {
diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs
index 8cafb5a2497..3db344af674 100644
--- a/tests/rustdoc/async-fn.rs
+++ b/tests/rustdoc/async-fn.rs
@@ -1,35 +1,35 @@
 // edition:2018
-// @has async_fn/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn foo() -> Option'
+// @has async_fn/fn.foo.html '//pre[@class="rust item-decl"]' 'pub async fn foo() -> Option'
 pub async fn foo() -> Option {
     None
 }
 
-// @has async_fn/fn.bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn bar(a: i32, b: i32) -> i32'
+// @has async_fn/fn.bar.html '//pre[@class="rust item-decl"]' 'pub async fn bar(a: i32, b: i32) -> i32'
 pub async fn bar(a: i32, b: i32) -> i32 {
     0
 }
 
-// @has async_fn/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn baz(a: T) -> T'
+// @has async_fn/fn.baz.html '//pre[@class="rust item-decl"]' 'pub async fn baz(a: T) -> T'
 pub async fn baz(a: T) -> T {
     a
 }
 
-// @has async_fn/fn.qux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async unsafe fn qux() -> char'
+// @has async_fn/fn.qux.html '//pre[@class="rust item-decl"]' 'pub async unsafe fn qux() -> char'
 pub async unsafe fn qux() -> char {
     '⚠'
 }
 
-// @has async_fn/fn.mut_args.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_args(a: usize)'
+// @has async_fn/fn.mut_args.html '//pre[@class="rust item-decl"]' 'pub async fn mut_args(a: usize)'
 pub async fn mut_args(mut a: usize) {}
 
-// @has async_fn/fn.mut_ref.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_ref(x: i32)'
+// @has async_fn/fn.mut_ref.html '//pre[@class="rust item-decl"]' 'pub async fn mut_ref(x: i32)'
 pub async fn mut_ref(ref mut x: i32) {}
 
 trait Bar {}
 
 impl Bar for () {}
 
-// @has async_fn/fn.quux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn quux() -> impl Bar'
+// @has async_fn/fn.quux.html '//pre[@class="rust item-decl"]' 'pub async fn quux() -> impl Bar'
 pub async fn quux() -> impl Bar {
     ()
 }
@@ -50,27 +50,27 @@ pub trait Pattern<'a> {}
 
 pub trait Trait {}
 // @has async_fn/fn.const_generics.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn const_generics(_: impl Trait)'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics(_: impl Trait)'
 pub async fn const_generics(_: impl Trait) {}
 
 // test that elided lifetimes are properly elided and not displayed as `'_`
 // regression test for #63037
 // @has async_fn/fn.elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str'
 pub async fn elided(foo: &str) -> &str {}
 // This should really be shown as written, but for implementation reasons it's difficult.
 // See `impl Clean for TyKind::Ref`.
 // @has async_fn/fn.user_elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn user_elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str'
 pub async fn user_elided(foo: &'_ str) -> &str {}
 // @has async_fn/fn.static_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn static_trait(foo: &str) -> Box'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box'
 pub async fn static_trait(foo: &str) -> Box {}
 // @has async_fn/fn.lifetime_for_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn lifetime_for_trait(foo: &str) -> Box"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box"
 pub async fn lifetime_for_trait(foo: &str) -> Box {}
 // @has async_fn/fn.elided_in_input_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
 pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
 
 struct AsyncFdReadyGuard<'a, T> { x: &'a T }
@@ -88,8 +88,8 @@ impl Foo {
 
 // test named lifetimes, just in case
 // @has async_fn/fn.named.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
 pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
 // @has async_fn/fn.named_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
 pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs
index 36e10923c85..a652fda1604 100644
--- a/tests/rustdoc/attribute-rendering.rs
+++ b/tests/rustdoc/attribute-rendering.rs
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 // @has 'foo/fn.f.html'
-// @has - //*[@'class="item-decl"]' '#[export_name = "f"] pub fn f()'
+// @has - //*[@'class="rust item-decl"]' '#[export_name = "f"] pub fn f()'
 #[export_name = "\
 f"]
 pub fn f() {}
diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs
index 70e2e5c2950..86333c7534a 100644
--- a/tests/rustdoc/attributes.rs
+++ b/tests/rustdoc/attributes.rs
@@ -1,13 +1,13 @@
 #![crate_name = "foo"]
 
-// @has foo/fn.f.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[no_mangle]'
+// @has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[no_mangle]'
 #[no_mangle]
 pub extern "C" fn f() {}
 
-// @has foo/fn.g.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[export_name = "bar"]'
+// @has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[export_name = "bar"]'
 #[export_name = "bar"]
 pub extern "C" fn g() {}
 
-// @has foo/struct.Repr.html '//div[@class="item-decl"]' '#[repr(C, align(8))]'
+// @has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
 #[repr(C, align(8))]
 pub struct Repr;
diff --git a/tests/rustdoc/auxiliary/issue-85454.rs b/tests/rustdoc/auxiliary/issue-85454.rs
index 5143968bbd4..5db4fe053af 100644
--- a/tests/rustdoc/auxiliary/issue-85454.rs
+++ b/tests/rustdoc/auxiliary/issue-85454.rs
@@ -1,5 +1,5 @@
 // @has issue_85454/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
 pub trait FromResidual::Residual> {
     fn from_residual(residual: R) -> Self;
 }
diff --git a/tests/rustdoc/const-fn.rs b/tests/rustdoc/const-fn.rs
index 18863abaeac..f6616185681 100644
--- a/tests/rustdoc/const-fn.rs
+++ b/tests/rustdoc/const-fn.rs
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub const fn bar() -> '
 /// foo
 pub const fn bar() -> usize {
     2
diff --git a/tests/rustdoc/const-generics/add-impl.rs b/tests/rustdoc/const-generics/add-impl.rs
index b5226ad3f78..195e47bc8ba 100644
--- a/tests/rustdoc/const-generics/add-impl.rs
+++ b/tests/rustdoc/const-generics/add-impl.rs
@@ -2,7 +2,7 @@
 
 use std::ops::Add;
 
-// @has foo/struct.Simd.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Simd'
+// @has foo/struct.Simd.html '//pre[@class="rust item-decl"]' 'pub struct Simd'
 pub struct Simd {
     inner: T,
 }
diff --git a/tests/rustdoc/const-generics/const-generic-defaults.rs b/tests/rustdoc/const-generics/const-generic-defaults.rs
index acc3b853e56..f781c6a62f2 100644
--- a/tests/rustdoc/const-generics/const-generic-defaults.rs
+++ b/tests/rustdoc/const-generics/const-generic-defaults.rs
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Foo(_);'
 pub struct Foo(T);
diff --git a/tests/rustdoc/const-generics/const-generics-docs.rs b/tests/rustdoc/const-generics/const-generics-docs.rs
index 543332d2c32..ade70bbe80d 100644
--- a/tests/rustdoc/const-generics/const-generics-docs.rs
+++ b/tests/rustdoc/const-generics/const-generics-docs.rs
@@ -3,21 +3,21 @@
 #![crate_name = "foo"]
 
 extern crate extern_crate;
-// @has foo/fn.extern_fn.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.extern_fn.html '//pre[@class="rust item-decl"]' \
 //      'pub fn extern_fn() -> impl Iterator'
 pub use extern_crate::extern_fn;
-// @has foo/struct.ExternTy.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.ExternTy.html '//pre[@class="rust item-decl"]' \
 //      'pub struct ExternTy {'
 pub use extern_crate::ExternTy;
-// @has foo/type.TyAlias.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.TyAlias.html '//pre[@class="rust item-decl"]' \
 //      'type TyAlias = ExternTy;'
 pub use extern_crate::TyAlias;
-// @has foo/trait.WTrait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.WTrait.html '//pre[@class="rust item-decl"]' \
 //      'pub trait WTrait'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn hey() -> usize'
+// @has - '//pre[@class="rust item-decl"]' 'fn hey() -> usize'
 pub use extern_crate::WTrait;
 
-// @has foo/trait.Trait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.Trait.html '//pre[@class="rust item-decl"]' \
 //      'pub trait Trait'
 // @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8'
 // @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8'
@@ -30,10 +30,10 @@ impl Trait<2> for u8 {}
 impl Trait<{1 + 2}> for u8 {}
 impl Trait for [u8; N] {}
 
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Foowhere u8: Trait'
 pub struct Foo where u8: Trait;
-// @has foo/struct.Bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Bar(_)'
+// @has foo/struct.Bar.html '//pre[@class="rust item-decl"]' 'pub struct Bar(_)'
 pub struct Bar([T; N]);
 
 // @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl Foowhere u8: Trait'
@@ -56,32 +56,32 @@ impl Bar {
     }
 }
 
-// @has foo/fn.test.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.test.html '//pre[@class="rust item-decl"]' \
 //      'pub fn test() -> impl Traitwhere u8: Trait'
 pub fn test() -> impl Trait where u8: Trait {
     2u8
 }
 
-// @has foo/fn.a_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.a_sink.html '//pre[@class="rust item-decl"]' \
 //      'pub async fn a_sink(v: [u8; N]) -> impl Trait'
 pub async fn a_sink(v: [u8; N]) -> impl Trait {
     v
 }
 
-// @has foo/fn.b_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.b_sink.html '//pre[@class="rust item-decl"]' \
 //      'pub async fn b_sink(_: impl Trait)'
 pub async fn b_sink(_: impl Trait) {}
 
-// @has foo/fn.concrete.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.concrete.html '//pre[@class="rust item-decl"]' \
 //      'pub fn concrete() -> [u8; 22]'
 pub fn concrete() -> [u8; 3 + std::mem::size_of::() << 1] {
     Default::default()
 }
 
-// @has foo/type.Faz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Faz.html '//pre[@class="rust item-decl"]' \
 //      'type Faz = [u8; N];'
 pub type Faz = [u8; N];
-// @has foo/type.Fiz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Fiz.html '//pre[@class="rust item-decl"]' \
 //      'type Fiz = [[u8; N]; 48];'
 pub type Fiz = [[u8; N]; 3 << 4];
 
@@ -91,7 +91,7 @@ macro_rules! define_me {
     }
 }
 
-// @has foo/struct.Foz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foz.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Foz(_);'
 define_me!(Foz);
 
@@ -103,13 +103,13 @@ impl Q for [u8; N] {
     const ASSOC: usize = N;
 }
 
-// @has foo/fn.q_user.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.q_user.html '//pre[@class="rust item-decl"]' \
 //      'pub fn q_user() -> [u8; 13]'
 pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {
     [0; <[u8; 13] as Q>::ASSOC]
 }
 
-// @has foo/union.Union.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/union.Union.html '//pre[@class="rust item-decl"]' \
 //      'pub union Union'
 pub union Union {
     // @has - //pre "pub arr: [u8; N]"
@@ -118,7 +118,7 @@ pub union Union {
     pub another_arr: [(); N],
 }
 
-// @has foo/enum.Enum.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/enum.Enum.html '//pre[@class="rust item-decl"]' \
 //      'pub enum Enum'
 pub enum Enum {
     // @has - //pre "Variant([u8; N])"
diff --git a/tests/rustdoc/const-generics/const-impl.rs b/tests/rustdoc/const-generics/const-impl.rs
index 726fb8f0c34..91866b7d890 100644
--- a/tests/rustdoc/const-generics/const-impl.rs
+++ b/tests/rustdoc/const-generics/const-impl.rs
@@ -8,7 +8,7 @@ pub enum Order {
     Unsorted,
 }
 
-// @has foo/struct.VSet.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct VSet'
+// @has foo/struct.VSet.html '//pre[@class="rust item-decl"]' 'pub struct VSet'
 // @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl Send for VSet'
 // @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl Sync for VSet'
 pub struct VSet {
diff --git a/tests/rustdoc/const-generics/generic_const_exprs.rs b/tests/rustdoc/const-generics/generic_const_exprs.rs
index c53cf6dcd05..e23b3006da6 100644
--- a/tests/rustdoc/const-generics/generic_const_exprs.rs
+++ b/tests/rustdoc/const-generics/generic_const_exprs.rs
@@ -2,6 +2,6 @@
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 // make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
-// @has foo/struct.Ice.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Ice.html '//pre[@class="rust item-decl"]' \
 //      'pub struct Ice;'
 pub struct Ice where [(); N + 1]:;
diff --git a/tests/rustdoc/const-generics/type-alias.rs b/tests/rustdoc/const-generics/type-alias.rs
index 72473a11244..4b93e72d273 100644
--- a/tests/rustdoc/const-generics/type-alias.rs
+++ b/tests/rustdoc/const-generics/type-alias.rs
@@ -1,4 +1,4 @@
 #![crate_name = "foo"]
 
-// @has foo/type.CellIndex.html '//div[@class="item-decl"]/pre[@class="rust"]' 'type CellIndex = [i64; D];'
+// @has foo/type.CellIndex.html '//pre[@class="rust item-decl"]' 'type CellIndex = [i64; D];'
 pub type CellIndex = [i64; D];
diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs
index 42f6ac7923b..6d2c6cce29c 100644
--- a/tests/rustdoc/const-intrinsic.rs
+++ b/tests/rustdoc/const-intrinsic.rs
@@ -6,20 +6,20 @@
 
 extern "rust-intrinsic" {
     // @has 'foo/fn.transmute.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const unsafe extern "rust-intrinsic" fn transmute(_: T) -> U'
+    // @has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute(_: T) -> U'
     #[stable(since="1.0.0", feature="rust1")]
     #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
     pub fn transmute(_: T) -> U;
 
     // @has 'foo/fn.unreachable.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
     #[stable(since="1.0.0", feature="rust1")]
     pub fn unreachable() -> !;
 }
 
 extern "C" {
     // @has 'foo/fn.needs_drop.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
     #[stable(since="1.0.0", feature="rust1")]
     pub fn needs_drop() -> !;
 }
diff --git a/tests/rustdoc/const-value-display.rs b/tests/rustdoc/const-value-display.rs
index 8d95f0de9d0..a7548ad2cc4 100644
--- a/tests/rustdoc/const-value-display.rs
+++ b/tests/rustdoc/const-value-display.rs
@@ -1,9 +1,9 @@
 #![crate_name = "foo"]
 
 // @has 'foo/constant.HOUR_IN_SECONDS.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
 pub const HOUR_IN_SECONDS: u64 = 60 * 60;
 
 // @has 'foo/constant.NEGATIVE.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
 pub const NEGATIVE: i64 = -60 * 60;
diff --git a/tests/rustdoc/decl-trailing-whitespace.rs b/tests/rustdoc/decl-trailing-whitespace.rs
index e47edc13218..d2a12435d8f 100644
--- a/tests/rustdoc/decl-trailing-whitespace.rs
+++ b/tests/rustdoc/decl-trailing-whitespace.rs
@@ -7,7 +7,7 @@ pub struct Error;
 // @has 'foo/trait.Write.html'
 
 pub trait Write {
-    // @snapshot 'declaration' - '//*[@class="item-decl"]//code'
+    // @snapshot 'declaration' - '//*[@class="rust item-decl"]//code'
     fn poll_write(
         self: Option,
         cx: &mut Option,
diff --git a/tests/rustdoc/fn-pointer-arg-name.rs b/tests/rustdoc/fn-pointer-arg-name.rs
index 96c64ac4e02..359ca64ee8d 100644
--- a/tests/rustdoc/fn-pointer-arg-name.rs
+++ b/tests/rustdoc/fn-pointer-arg-name.rs
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
 pub fn f(callback: fn(len: usize, foo: u32)) {}
diff --git a/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs b/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
index 406157ce26c..d368db909fa 100644
--- a/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
+++ b/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
@@ -63,7 +63,7 @@ impl Helper for St {
 // this test as long as one can ensure that private fields are not leaked!
 //
 // @has hide_complex_unevaluated_const_arguments/trait.Sub.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' \
+//      '//pre[@class="rust item-decl"]' \
 //      'pub trait Sub: Sup<{ _ }, { _ }> { }'
 pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {}
 
diff --git a/tests/rustdoc/inline-default-methods.rs b/tests/rustdoc/inline-default-methods.rs
index a4ca928f333..e6468316f58 100644
--- a/tests/rustdoc/inline-default-methods.rs
+++ b/tests/rustdoc/inline-default-methods.rs
@@ -4,6 +4,6 @@
 extern crate inline_default_methods;
 
 // @has inline_default_methods/trait.Foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(&self);'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(&mut self) { ... }'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo(&mut self) { ... }'
 pub use inline_default_methods::Foo;
diff --git a/tests/rustdoc/inline_cross/dyn_trait.rs b/tests/rustdoc/inline_cross/dyn_trait.rs
index 0da8bfc3a9a..649d98f7139 100644
--- a/tests/rustdoc/inline_cross/dyn_trait.rs
+++ b/tests/rustdoc/inline_cross/dyn_trait.rs
@@ -4,28 +4,28 @@
 // edition:2021
 
 // @has user/type.Ty0.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
 // FIXME(fmease): Hide default lifetime bound `'static`
 pub use dyn_trait::Ty0;
 
 // @has user/type.Ty1.html
-// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj"
+// @has - '//*[@class="rust item-decl"]//code' "dyn Display + 'obj"
 pub use dyn_trait::Ty1;
 
 // @has user/type.Ty2.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
 pub use dyn_trait::Ty2;
 
 // @has user/type.Ty3.html
-// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)"
+// @has - '//*[@class="rust item-decl"]//code' "&'s (dyn ToString + 's)"
 // FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString"
 pub use dyn_trait::Ty3;
 
 // @has user/fn.func0.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func0(_: &dyn Fn())"
+// @has - '//pre[@class="rust item-decl"]' "func0(_: &dyn Fn())"
 // FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
 pub use dyn_trait::func0;
 
 // @has user/fn.func1.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+// @has - '//pre[@class="rust item-decl"]' "func1<'func>(_: &(dyn Fn() + 'func))"
 pub use dyn_trait::func1;
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index e8587209b61..7d810ab4813 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -4,37 +4,37 @@
 extern crate impl_trait_aux;
 
 // @has impl_trait/fn.func.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func;
 
 // @has impl_trait/fn.func2.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func2("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Deref> + Iterator,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_y: impl Iterator)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func2("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Deref> + Iterator,"
+// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func2;
 
 // @has impl_trait/fn.func3.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func3("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Iterator> + Clone)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func3("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Iterator> + Clone)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func3;
 
 // @has impl_trait/fn.func4.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func4("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "T: Iterator,"
+// @has - '//pre[@class="rust item-decl"]' "func4("
+// @has - '//pre[@class="rust item-decl"]' "T: Iterator,"
 pub use impl_trait_aux::func4;
 
 // @has impl_trait/fn.func5.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func5("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func5("
+// @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>,"
+// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
 pub use impl_trait_aux::func5;
 
 // @has impl_trait/fn.async_fn.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn async_fn()"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()"
 pub use impl_trait_aux::async_fn;
 
 // @has impl_trait/struct.Foo.html
diff --git a/tests/rustdoc/inline_cross/issue-24183.rs b/tests/rustdoc/inline_cross/issue-24183.rs
index d11b6955f3c..751a32385e8 100644
--- a/tests/rustdoc/inline_cross/issue-24183.rs
+++ b/tests/rustdoc/inline_cross/issue-24183.rs
@@ -5,7 +5,7 @@
 // edition: 2021
 
 // @has usr/trait.U.html
-// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@class="rust item-decl"]' "pub trait U {"
 // @has - '//*[@id="method.modified"]' \
 // "fn modified(self) -> Self\
 // where \
@@ -14,5 +14,5 @@
 pub use issue_24183::U;
 
 // @has usr/trait.S.html
-// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+// @has - '//*[@class="rust item-decl"]' 'pub trait S: Sized {'
 pub use issue_24183::S;
diff --git a/tests/rustdoc/issue-20646.rs b/tests/rustdoc/issue-20646.rs
index a774b0ca7cd..b2ee9c26014 100644
--- a/tests/rustdoc/issue-20646.rs
+++ b/tests/rustdoc/issue-20646.rs
@@ -13,7 +13,7 @@ pub trait Trait {
 }
 
 // @has issue_20646/fn.fun.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait'
+//      '//pre[@class="rust item-decl"]' 'where T: Trait'
 pub fn fun(_: T) where T: Trait {}
 
 pub mod reexport {
@@ -21,6 +21,6 @@ pub mod reexport {
     //      '//*[@id="associatedtype.Output"]' \
     //      'type Output'
     // @has issue_20646/reexport/fn.fun.html \
-    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait'
+    //      '//pre[@class="rust item-decl"]' 'where T: Trait'
     pub use issue_20646::{Trait, fun};
 }
diff --git a/tests/rustdoc/issue-20727-2.rs b/tests/rustdoc/issue-20727-2.rs
index 026b4f5acc9..c1aa9617b2e 100644
--- a/tests/rustdoc/issue-20727-2.rs
+++ b/tests/rustdoc/issue-20727-2.rs
@@ -5,18 +5,18 @@ extern crate issue_20727;
 
 // @has issue_20727_2/trait.Add.html
 pub trait Add {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Add {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output;'
     type Output;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
     fn add(self, rhs: RHS) -> Self::Output;
 }
 
 // @has issue_20727_2/reexport/trait.Add.html
 pub mod reexport {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Add {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
     pub use issue_20727::Add;
 }
diff --git a/tests/rustdoc/issue-20727-3.rs b/tests/rustdoc/issue-20727-3.rs
index 741ce8023d7..2f9d91fc5f7 100644
--- a/tests/rustdoc/issue-20727-3.rs
+++ b/tests/rustdoc/issue-20727-3.rs
@@ -7,18 +7,18 @@ pub trait Bar {}
 
 // @has issue_20727_3/trait.Deref2.html
 pub trait Deref2 {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
     type Target: Bar;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
     fn deref(&self) -> Self::Target;
 }
 
 // @has issue_20727_3/reexport/trait.Deref2.html
 pub mod reexport {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
+    // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
     pub use issue_20727::Deref2;
 }
diff --git a/tests/rustdoc/issue-20727-4.rs b/tests/rustdoc/issue-20727-4.rs
index b8fac4da6ea..ec9f18fc3fe 100644
--- a/tests/rustdoc/issue-20727-4.rs
+++ b/tests/rustdoc/issue-20727-4.rs
@@ -5,36 +5,36 @@ extern crate issue_20727;
 
 // @has issue_20727_4/trait.Index.html
 pub trait Index {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Index {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
     type Output: ?Sized;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index(&self, index: Idx) -> &Self::Output'
     fn index(&self, index: Idx) -> &Self::Output;
 }
 
 // @has issue_20727_4/trait.IndexMut.html
 pub trait IndexMut: Index {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'trait IndexMut: Index {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
     fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
 }
 
 pub mod reexport {
     // @has issue_20727_4/reexport/trait.Index.html
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Indexwhere Idx: ?Sized,{'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' 'trait Indexwhere Idx: ?Sized,{'
+    // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index(&self, index: Idx) -> &Self::Output'
     pub use issue_20727::Index;
 
     // @has issue_20727_4/reexport/trait.IndexMut.html
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'trait IndexMut: Indexwhere Idx: ?Sized,{'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
     pub use issue_20727::IndexMut;
 }
diff --git a/tests/rustdoc/issue-20727.rs b/tests/rustdoc/issue-20727.rs
index df334821ccc..266848beef9 100644
--- a/tests/rustdoc/issue-20727.rs
+++ b/tests/rustdoc/issue-20727.rs
@@ -5,20 +5,20 @@ extern crate issue_20727;
 
 // @has issue_20727/trait.Deref.html
 pub trait Deref {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
     type Target: ?Sized;
 
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' \
     //        "fn deref<'a>(&'a self) -> &'a Self::Target;"
     fn deref<'a>(&'a self) -> &'a Self::Target;
 }
 
 // @has issue_20727/reexport/trait.Deref.html
 pub mod reexport {
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+    // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+    // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
+    // @has - '//pre[@class="rust item-decl"]' \
     //      "fn deref<'a>(&'a self) -> &'a Self::Target;"
     pub use issue_20727::Deref;
 }
diff --git a/tests/rustdoc/issue-22038.rs b/tests/rustdoc/issue-22038.rs
index 19e626ba132..de6cc78707c 100644
--- a/tests/rustdoc/issue-22038.rs
+++ b/tests/rustdoc/issue-22038.rs
@@ -1,19 +1,19 @@
 extern "C" {
     // @has issue_22038/fn.foo1.html \
-    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn foo1()'
+    //      '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()'
     pub fn foo1();
 }
 
 extern "system" {
     // @has issue_22038/fn.foo2.html \
-    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "system" fn foo2()'
+    //      '//pre[@class="rust item-decl"]' 'pub unsafe extern "system" fn foo2()'
     pub fn foo2();
 }
 
 // @has issue_22038/fn.bar.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "C" fn bar()'
+//      '//pre[@class="rust item-decl"]' 'pub extern "C" fn bar()'
 pub extern "C" fn bar() {}
 
 // @has issue_22038/fn.baz.html \
-//      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "system" fn baz()'
+//      '//pre[@class="rust item-decl"]' 'pub extern "system" fn baz()'
 pub extern "system" fn baz() {}
diff --git a/tests/rustdoc/issue-33302.rs b/tests/rustdoc/issue-33302.rs
index 7af00c77836..a316f3ad99b 100644
--- a/tests/rustdoc/issue-33302.rs
+++ b/tests/rustdoc/issue-33302.rs
@@ -6,17 +6,17 @@ macro_rules! make {
         pub struct S;
 
         // @has issue_33302/constant.CST.html \
-        //        '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const CST: i32'
+        //        '//pre[@class="rust item-decl"]' 'pub const CST: i32'
         pub const CST: i32 = ($n * $n);
         // @has issue_33302/static.ST.html \
-        //        '//div[@class="item-decl"]/pre[@class="rust"]' 'pub static ST: i32'
+        //        '//pre[@class="rust item-decl"]' 'pub static ST: i32'
         pub static ST: i32 = ($n * $n);
 
         pub trait T {
             fn ignore(_: &X) {}
             const C: X;
             // @has issue_33302/trait.T.html \
-            //        '//div[@class="item-decl"]/pre[@class="rust"]' 'const D: i32'
+            //        '//pre[@class="rust item-decl"]' 'const D: i32'
             // @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
             const D: i32 = ($n * $n);
         }
diff --git a/tests/rustdoc/issue-85454.rs b/tests/rustdoc/issue-85454.rs
index 74fc22b31dc..2d410a5974a 100644
--- a/tests/rustdoc/issue-85454.rs
+++ b/tests/rustdoc/issue-85454.rs
@@ -5,7 +5,7 @@
 extern crate issue_85454;
 
 // @has foo/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
 pub trait FromResidual::Residual> {
     fn from_residual(residual: R) -> Self;
 }
@@ -24,6 +24,6 @@ pub enum ControlFlow {
 
 pub mod reexport {
     // @has foo/reexport/trait.FromResidual.html
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
+    // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
     pub use issue_85454::*;
 }
diff --git a/tests/rustdoc/issue-98697.rs b/tests/rustdoc/issue-98697.rs
index 884b63ac97f..5d5aee1fe1d 100644
--- a/tests/rustdoc/issue-98697.rs
+++ b/tests/rustdoc/issue-98697.rs
@@ -8,8 +8,8 @@
 
 extern crate issue_98697_reexport_with_anonymous_lifetime;
 
-// @has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'fn repro()where F: Fn(&str)'
-// @!has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'for<'
+// @has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'fn repro()where F: Fn(&str)'
+// @!has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'for<'
 pub use issue_98697_reexport_with_anonymous_lifetime::repro;
 
 // @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra'
diff --git a/tests/rustdoc/legacy-const-generic.rs b/tests/rustdoc/legacy-const-generic.rs
index 14533624e44..3a488bdd208 100644
--- a/tests/rustdoc/legacy-const-generic.rs
+++ b/tests/rustdoc/legacy-const-generic.rs
@@ -2,14 +2,14 @@
 #![feature(rustc_attrs)]
 
 // @has 'foo/fn.foo.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
 #[rustc_legacy_const_generics(1)]
 pub fn foo(x: usize, z: usize) -> [usize; 3] {
     [x, Y, z]
 }
 
 // @has 'foo/fn.bar.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
 #[rustc_legacy_const_generics(1, 2)]
 pub fn bar(x: usize) -> [usize; 3] {
     [x, Y, z]
diff --git a/tests/rustdoc/lifetime-name.rs b/tests/rustdoc/lifetime-name.rs
index 0fb66059109..15e09f5165a 100644
--- a/tests/rustdoc/lifetime-name.rs
+++ b/tests/rustdoc/lifetime-name.rs
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has 'foo/type.Resolutions.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub type Resolutions<'tcx> = &'tcx u8;"
+// @has - '//pre[@class="rust item-decl"]' "pub type Resolutions<'tcx> = &'tcx u8;"
 pub type Resolutions<'tcx> = &'tcx u8;
diff --git a/tests/rustdoc/macro-higher-kinded-function.rs b/tests/rustdoc/macro-higher-kinded-function.rs
index b8c52b7b791..a45ef37a7fc 100644
--- a/tests/rustdoc/macro-higher-kinded-function.rs
+++ b/tests/rustdoc/macro-higher-kinded-function.rs
@@ -11,8 +11,8 @@ macro_rules! gen {
 }
 
 // @has 'foo/struct.Providers.html'
-// @has - '//*[@class="item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
-// @has - '//*[@class="item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @has - '//*[@class="rust item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
+// @has - '//*[@class="rust item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
 // @has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
 // @has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
 gen! {
diff --git a/tests/rustdoc/mut-params.rs b/tests/rustdoc/mut-params.rs
index 431db51d95f..e403b7b78c9 100644
--- a/tests/rustdoc/mut-params.rs
+++ b/tests/rustdoc/mut-params.rs
@@ -13,6 +13,6 @@ impl Foo {
     pub fn bar(mut bar: ()) {}
 }
 
-// @count foo/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 1
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'mut'
+// @count foo/fn.baz.html '//pre[@class="rust item-decl"]' 1
+// @!has - '//pre[@class="rust item-decl"]' 'mut'
 pub fn baz(mut foo: Foo) {}
diff --git a/tests/rustdoc/normalize-assoc-item.rs b/tests/rustdoc/normalize-assoc-item.rs
index 659480479fd..af7b2f955fd 100644
--- a/tests/rustdoc/normalize-assoc-item.rs
+++ b/tests/rustdoc/normalize-assoc-item.rs
@@ -19,12 +19,12 @@ impl Trait for isize {
     type X = <() as Trait>::X;
 }
 
-// @has 'normalize_assoc_item/fn.f.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f() -> isize'
+// @has 'normalize_assoc_item/fn.f.html' '//pre[@class="rust item-decl"]' 'pub fn f() -> isize'
 pub fn f() -> ::X {
     0
 }
 
-// @has 'normalize_assoc_item/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f2() -> fn() -> i32'
+// @has 'normalize_assoc_item/fn.f2.html' '//pre[@class="rust item-decl"]' 'pub fn f2() -> fn() -> i32'
 pub fn f2() -> ::X {
     todo!()
 }
@@ -49,10 +49,10 @@ impl Trait for Generic {
 // These can't be normalized because they depend on a generic parameter.
 // However the user can choose whether the text should be displayed as `Inner::X` or `::X`.
 
-// @has 'normalize_assoc_item/struct.Unknown.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown(pub ::X);'
+// @has 'normalize_assoc_item/struct.Unknown.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown(pub ::X);'
 pub struct Unknown(pub ::X);
 
-// @has 'normalize_assoc_item/struct.Unknown2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown2(pub Inner::X);'
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown2(pub Inner::X);'
 pub struct Unknown2(pub Inner::X);
 
 trait Lifetimes<'a> {
@@ -63,20 +63,20 @@ impl<'a> Lifetimes<'a> for usize {
     type Y = &'a isize;
 }
 
-// @has 'normalize_assoc_item/fn.g.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn g() -> &isize"
+// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust item-decl"]' "pub fn g() -> &isize"
 pub fn g() -> >::Y {
     &0
 }
 
-// @has 'normalize_assoc_item/constant.A.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub const A: &isize"
+// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust item-decl"]' "pub const A: &isize"
 pub const A: >::Y = &0;
 
 // test cross-crate re-exports
 extern crate inner;
-// @has 'normalize_assoc_item/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn foo() -> i32"
+// @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust item-decl"]' "pub fn foo() -> i32"
 pub use inner::foo;
 
-// @has 'normalize_assoc_item/fn.h.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn h() -> IntoIter"
+// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust item-decl"]' "pub fn h() -> IntoIter"
 pub fn h() ->  as IntoIterator>::IntoIter {
     vec![].into_iter()
 }
diff --git a/tests/rustdoc/pub-method.rs b/tests/rustdoc/pub-method.rs
index 7115a01d079..ea4791579cd 100644
--- a/tests/rustdoc/pub-method.rs
+++ b/tests/rustdoc/pub-method.rs
@@ -3,7 +3,7 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub fn bar() -> '
 /// foo
 pub fn bar() -> usize {
     2
diff --git a/tests/rustdoc/range-arg-pattern.rs b/tests/rustdoc/range-arg-pattern.rs
index bdbcc47c9f2..d0d9111bb40 100644
--- a/tests/rustdoc/range-arg-pattern.rs
+++ b/tests/rustdoc/range-arg-pattern.rs
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(_: u8)'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(_: u8)'
 pub fn f(0u8..=255: u8) {}
diff --git a/tests/rustdoc/reexport-dep-foreign-fn.rs b/tests/rustdoc/reexport-dep-foreign-fn.rs
index 6694c91d104..e7f5720d583 100644
--- a/tests/rustdoc/reexport-dep-foreign-fn.rs
+++ b/tests/rustdoc/reexport-dep-foreign-fn.rs
@@ -8,5 +8,5 @@
 extern crate all_item_types;
 
 // @has 'foo/fn.foo_ffn.html'
-// @has - '//*[@class="item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+// @has - '//*[@class="rust item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
 pub use all_item_types::foo_ffn;
diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexports-priv.rs
index 35c90ba5d7b..84ea4ad2c9e 100644
--- a/tests/rustdoc/reexports-priv.rs
+++ b/tests/rustdoc/reexports-priv.rs
@@ -5,7 +5,7 @@
 
 extern crate reexports;
 
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
 pub use reexports::addr_of;
 // @!has 'foo/macro.addr_of_crate.html'
 pub(crate) use reexports::addr_of_crate;
@@ -14,7 +14,7 @@ pub(self) use reexports::addr_of_self;
 // @!has 'foo/macro.addr_of_local.html'
 use reexports::addr_of_local;
 
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
 pub use reexports::Foo;
 // @!has 'foo/struct.FooCrate.html'
 pub(crate) use reexports::FooCrate;
@@ -23,7 +23,7 @@ pub(self) use reexports::FooSelf;
 // @!has 'foo/struct.FooLocal.html'
 use reexports::FooLocal;
 
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
 pub use reexports::Bar;
 // @!has 'foo/enum.BarCrate.html'
 pub(crate) use reexports::BarCrate;
@@ -32,7 +32,7 @@ pub(self) use reexports::BarSelf;
 // @!has 'foo/enum.BarLocal.html'
 use reexports::BarLocal;
 
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
 pub use reexports::foo;
 // @!has 'foo/fn.foo_crate.html'
 pub(crate) use reexports::foo_crate;
@@ -41,7 +41,7 @@ pub(self) use reexports::foo_self;
 // @!has 'foo/fn.foo_local.html'
 use reexports::foo_local;
 
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
 pub use reexports::Type;
 // @!has 'foo/type.TypeCrate.html'
 pub(crate) use reexports::TypeCrate;
@@ -50,7 +50,7 @@ pub(self) use reexports::TypeSelf;
 // @!has 'foo/type.TypeLocal.html'
 use reexports::TypeLocal;
 
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
 pub use reexports::Union;
 // @!has 'foo/union.UnionCrate.html'
 pub(crate) use reexports::UnionCrate;
@@ -61,66 +61,66 @@ use reexports::UnionLocal;
 
 pub mod outer {
     pub mod inner {
-        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
         pub use reexports::addr_of;
-        // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="rust item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
         pub(crate) use reexports::addr_of_crate;
-        // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="rust item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
         pub(super) use reexports::addr_of_super;
         // @!has 'foo/outer/inner/macro.addr_of_self.html'
         pub(self) use reexports::addr_of_self;
         // @!has 'foo/outer/inner/macro.addr_of_local.html'
         use reexports::addr_of_local;
 
-        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
         pub use reexports::Foo;
-        // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="item-decl"]' 'pub(crate) struct FooCrate;'
+        // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) struct FooCrate;'
         pub(crate) use reexports::FooCrate;
-        // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="item-decl"]' 'pub(in outer) struct FooSuper;'
+        // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) struct FooSuper;'
         pub(super) use reexports::FooSuper;
         // @!has 'foo/outer/inner/struct.FooSelf.html'
         pub(self) use reexports::FooSelf;
         // @!has 'foo/outer/inner/struct.FooLocal.html'
         use reexports::FooLocal;
 
-        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
         pub use reexports::Bar;
-        // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="item-decl"]' 'pub(crate) enum BarCrate {'
+        // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) enum BarCrate {'
         pub(crate) use reexports::BarCrate;
-        // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="item-decl"]' 'pub(in outer) enum BarSuper {'
+        // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) enum BarSuper {'
         pub(super) use reexports::BarSuper;
         // @!has 'foo/outer/inner/enum.BarSelf.html'
         pub(self) use reexports::BarSelf;
         // @!has 'foo/outer/inner/enum.BarLocal.html'
         use reexports::BarLocal;
 
-        // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+        // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
         pub use reexports::foo;
-        // @has 'foo/outer/inner/fn.foo_crate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) fn foo_crate()'
+        // @has 'foo/outer/inner/fn.foo_crate.html' '//pre[@class="rust item-decl"]' 'pub(crate) fn foo_crate()'
         pub(crate) use reexports::foo_crate;
-        // @has 'foo/outer/inner/fn.foo_super.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) fn foo_super()'
+        // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super()'
         pub(super) use::reexports::foo_super;
         // @!has 'foo/outer/inner/fn.foo_self.html'
         pub(self) use reexports::foo_self;
         // @!has 'foo/outer/inner/fn.foo_local.html'
         use reexports::foo_local;
 
-        // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+        // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
         pub use reexports::Type;
-        // @has 'foo/outer/inner/type.TypeCrate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) type TypeCrate ='
+        // @has 'foo/outer/inner/type.TypeCrate.html' '//pre[@class="rust item-decl"]' 'pub(crate) type TypeCrate ='
         pub(crate) use reexports::TypeCrate;
-        // @has 'foo/outer/inner/type.TypeSuper.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) type TypeSuper ='
+        // @has 'foo/outer/inner/type.TypeSuper.html' '//pre[@class="rust item-decl"]' 'pub(in outer) type TypeSuper ='
         pub(super) use reexports::TypeSuper;
         // @!has 'foo/outer/inner/type.TypeSelf.html'
         pub(self) use reexports::TypeSelf;
         // @!has 'foo/outer/inner/type.TypeLocal.html'
         use reexports::TypeLocal;
 
-        // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+        // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
         pub use reexports::Union;
-        // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="item-decl"]' 'pub(crate) union UnionCrate {'
+        // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) union UnionCrate {'
         pub(crate) use reexports::UnionCrate;
-        // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="item-decl"]' 'pub(in outer) union UnionSuper {'
+        // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) union UnionSuper {'
         pub(super) use reexports::UnionSuper;
         // @!has 'foo/outer/inner/union.UnionSelf.html'
         pub(self) use reexports::UnionSelf;
diff --git a/tests/rustdoc/reexports.rs b/tests/rustdoc/reexports.rs
index 65d305c6d2c..3c51ac395af 100644
--- a/tests/rustdoc/reexports.rs
+++ b/tests/rustdoc/reexports.rs
@@ -4,7 +4,7 @@
 
 extern crate reexports;
 
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
 pub use reexports::addr_of;
 // @!has 'foo/macro.addr_of_crate.html'
 pub(crate) use reexports::addr_of_crate;
@@ -13,7 +13,7 @@ pub(self) use reexports::addr_of_self;
 // @!has 'foo/macro.addr_of_local.html'
 use reexports::addr_of_local;
 
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
 pub use reexports::Foo;
 // @!has 'foo/struct.FooCrate.html'
 pub(crate) use reexports::FooCrate;
@@ -22,7 +22,7 @@ pub(self) use reexports::FooSelf;
 // @!has 'foo/struct.FooLocal.html'
 use reexports::FooLocal;
 
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
 pub use reexports::Bar;
 // @!has 'foo/enum.BarCrate.html'
 pub(crate) use reexports::BarCrate;
@@ -31,7 +31,7 @@ pub(self) use reexports::BarSelf;
 // @!has 'foo/enum.BarLocal.html'
 use reexports::BarLocal;
 
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
 pub use reexports::foo;
 // @!has 'foo/fn.foo_crate.html'
 pub(crate) use reexports::foo_crate;
@@ -40,7 +40,7 @@ pub(self) use reexports::foo_self;
 // @!has 'foo/fn.foo_local.html'
 use reexports::foo_local;
 
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
 pub use reexports::Type;
 // @!has 'foo/type.TypeCrate.html'
 pub(crate) use reexports::TypeCrate;
@@ -49,7 +49,7 @@ pub(self) use reexports::TypeSelf;
 // @!has 'foo/type.TypeLocal.html'
 use reexports::TypeLocal;
 
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
 pub use reexports::Union;
 // @!has 'foo/union.UnionCrate.html'
 pub(crate) use reexports::UnionCrate;
@@ -60,7 +60,7 @@ use reexports::UnionLocal;
 
 pub mod outer {
     pub mod inner {
-        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+        // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
         pub use reexports::addr_of;
         // @!has 'foo/outer/inner/macro.addr_of_crate.html'
         pub(crate) use reexports::addr_of_crate;
@@ -71,7 +71,7 @@ pub mod outer {
         // @!has 'foo/outer/inner/macro.addr_of_local.html'
         use reexports::addr_of_local;
 
-        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+        // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
         pub use reexports::Foo;
         // @!has 'foo/outer/inner/struct.FooCrate.html'
         pub(crate) use reexports::FooCrate;
@@ -82,7 +82,7 @@ pub mod outer {
         // @!has 'foo/outer/inner/struct.FooLocal.html'
         use reexports::FooLocal;
 
-        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+        // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
         pub use reexports::Bar;
         // @!has 'foo/outer/inner/enum.BarCrate.html'
         pub(crate) use reexports::BarCrate;
@@ -93,7 +93,7 @@ pub mod outer {
         // @!has 'foo/outer/inner/enum.BarLocal.html'
         use reexports::BarLocal;
 
-        // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+        // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
         pub use reexports::foo;
         // @!has 'foo/outer/inner/fn.foo_crate.html'
         pub(crate) use reexports::foo_crate;
@@ -104,7 +104,7 @@ pub mod outer {
         // @!has 'foo/outer/inner/fn.foo_local.html'
         use reexports::foo_local;
 
-        // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+        // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
         pub use reexports::Type;
         // @!has 'foo/outer/inner/type.TypeCrate.html'
         pub(crate) use reexports::TypeCrate;
@@ -115,7 +115,7 @@ pub mod outer {
         // @!has 'foo/outer/inner/type.TypeLocal.html'
         use reexports::TypeLocal;
 
-        // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+        // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
         pub use reexports::Union;
         // @!has 'foo/outer/inner/union.UnionCrate.html'
         pub(crate) use reexports::UnionCrate;
diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs
index a229a4e29fe..1120302ac7e 100644
--- a/tests/rustdoc/rfc-2632-const-trait-impl.rs
+++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs
@@ -12,10 +12,10 @@ use std::marker::Destruct;
 
 pub struct S(T);
 
-// @!has foo/trait.Tr.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' ': Clone'
+// @!has foo/trait.Tr.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Clone'
 #[const_trait]
 pub trait Tr {
     // @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
@@ -45,10 +45,10 @@ where
     }
 }
 
-// @!has foo/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' ': Clone'
+// @!has foo/fn.foo.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Clone'
 pub const fn foo()
 where
     Option: ~const Clone + ~const Destruct,
diff --git a/tests/rustdoc/safe-intrinsic.rs b/tests/rustdoc/safe-intrinsic.rs
index 0b65bf1dfed..c508909f9aa 100644
--- a/tests/rustdoc/safe-intrinsic.rs
+++ b/tests/rustdoc/safe-intrinsic.rs
@@ -7,16 +7,16 @@
 
 extern "rust-intrinsic" {
     // @has 'foo/fn.abort.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !'
     #[rustc_safe_intrinsic]
     pub fn abort() -> !;
     // @has 'foo/fn.unreachable.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
     pub fn unreachable() -> !;
 }
 
 extern "C" {
     // @has 'foo/fn.needs_drop.html'
-    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
     pub fn needs_drop() -> !;
 }
diff --git a/tests/rustdoc/slice-links.rs b/tests/rustdoc/slice-links.rs
index 67137fdcab2..6dea3b74ea3 100644
--- a/tests/rustdoc/slice-links.rs
+++ b/tests/rustdoc/slice-links.rs
@@ -4,25 +4,25 @@
 pub struct MyBox(*const T);
 
 // @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn alpha() -> &'static [u32] {
     loop {}
 }
 
 // @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
 pub fn beta() -> &'static [T] {
     loop {}
 }
 
 // @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
 pub fn gamma() -> MyBox<[u32]> {
     loop {}
 }
 
 // @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
 pub fn delta() -> MyBox<[T]> {
     loop {}
 }
diff --git a/tests/rustdoc/struct-arg-pattern.rs b/tests/rustdoc/struct-arg-pattern.rs
index 3bfb43a0bef..6f06c8c9c49 100644
--- a/tests/rustdoc/struct-arg-pattern.rs
+++ b/tests/rustdoc/struct-arg-pattern.rs
@@ -4,7 +4,7 @@ struct BodyId {
     hir_id: usize,
 }
 
-// @has 'foo/fn.body_owner.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn body_owner(_: BodyId)'
+// @has 'foo/fn.body_owner.html' '//pre[@class="rust item-decl"]' 'pub fn body_owner(_: BodyId)'
 pub fn body_owner(BodyId { hir_id }: BodyId) {
     // ...
 }
diff --git a/tests/rustdoc/test-parens.rs b/tests/rustdoc/test-parens.rs
index f5fdb1f52bf..9640b96b6b5 100644
--- a/tests/rustdoc/test-parens.rs
+++ b/tests/rustdoc/test-parens.rs
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_: &(dyn ToString + 'static)"
+// @has - '//pre[@class="rust item-decl"]' "_: &(dyn ToString + 'static)"
 pub fn foo(_: &(ToString + 'static)) {}
diff --git a/tests/rustdoc/toggle-item-contents.rs b/tests/rustdoc/toggle-item-contents.rs
index 5d34ec09b66..1f745043894 100644
--- a/tests/rustdoc/toggle-item-contents.rs
+++ b/tests/rustdoc/toggle-item-contents.rs
@@ -55,7 +55,7 @@ pub union Union {
 
 // @has 'toggle_item_contents/struct.PrivStruct.html'
 // @count - '//details[@class="toggle type-contents-toggle"]' 0
-// @has - '//div[@class="item-decl"]' '/* private fields */'
+// @has - '//pre[@class="rust item-decl"]' '/* private fields */'
 pub struct PrivStruct {
     a: usize,
     b: usize,
@@ -81,8 +81,8 @@ pub enum EnumStructVariant {
 }
 
 // @has 'toggle_item_contents/enum.LargeEnum.html'
-// @count - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 1
-// @has - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
+// @count - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
 pub enum LargeEnum {
     A, B, C, D, E, F(u8), G, H, I, J, K, L, M
 }
diff --git a/tests/rustdoc/trait_alias.rs b/tests/rustdoc/trait_alias.rs
index 791c099cc52..5c3f82c6b3c 100644
--- a/tests/rustdoc/trait_alias.rs
+++ b/tests/rustdoc/trait_alias.rs
@@ -14,13 +14,13 @@ use std::fmt::Debug;
 // @has foo/index.html '//a[@class="traitalias"]' 'Foo'
 
 // @has foo/traitalias.CopyAlias.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait CopyAlias = Copy;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;'
 pub trait CopyAlias = Copy;
 // @has foo/traitalias.Alias2.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;'
 pub trait Alias2 = Copy + Debug;
 // @has foo/traitalias.Foo.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Foo = Into + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo = Into + Debug;'
 pub trait Foo = Into + Debug;
 // @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
 pub fn bar() where T: Alias2 {}
diff --git a/tests/rustdoc/tuple-struct-fields-doc.rs b/tests/rustdoc/tuple-struct-fields-doc.rs
index d72c10f2b25..2836ddedc2b 100644
--- a/tests/rustdoc/tuple-struct-fields-doc.rs
+++ b/tests/rustdoc/tuple-struct-fields-doc.rs
@@ -19,7 +19,7 @@ pub struct Foo(
 );
 
 // @has foo/enum.Bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'BarVariant(String),'
+// @has - '//pre[@class="rust item-decl"]' 'BarVariant(String),'
 // @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$'
 // @has - '//*[@id="variant.BarVariant.field.0"]' '0: String'
 // @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs'
diff --git a/tests/rustdoc/tuples.rs b/tests/rustdoc/tuples.rs
index e716de8b55c..0ea5b5bfac9 100644
--- a/tests/rustdoc/tuples.rs
+++ b/tests/rustdoc/tuples.rs
@@ -1,20 +1,20 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.tuple0.html //pre 'pub fn tuple0(x: ())'
-// @snapshot link_unit - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_unit - '//pre[@class="rust item-decl"]/code'
 pub fn tuple0(x: ()) -> () { x }
 // @has foo/fn.tuple1.html //pre 'pub fn tuple1(x: (i32,)) -> (i32,)'
-// @snapshot link1_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_i32 - '//pre[@class="rust item-decl"]/code'
 pub fn tuple1(x: (i32,)) -> (i32,) { x }
 // @has foo/fn.tuple2.html //pre 'pub fn tuple2(x: (i32, i32)) -> (i32, i32)'
-// @snapshot link2_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_i32 - '//pre[@class="rust item-decl"]/code'
 pub fn tuple2(x: (i32, i32)) -> (i32, i32) { x }
 // @has foo/fn.tuple1_t.html //pre 'pub fn tuple1_t(x: (T,)) -> (T,)'
-// @snapshot link1_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_t - '//pre[@class="rust item-decl"]/code'
 pub fn tuple1_t(x: (T,)) -> (T,) { x }
 // @has foo/fn.tuple2_t.html //pre 'pub fn tuple2_t(x: (T, T)) -> (T, T)'
-// @snapshot link2_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_t - '//pre[@class="rust item-decl"]/code'
 pub fn tuple2_t(x: (T, T)) -> (T, T) { x }
 // @has foo/fn.tuple2_tu.html //pre 'pub fn tuple2_tu(x: (T, U)) -> (T, U)'
-// @snapshot link2_tu - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_tu - '//pre[@class="rust item-decl"]/code'
 pub fn tuple2_tu(x: (T, U)) -> (T, U) { x }
diff --git a/tests/rustdoc/unit-return.rs b/tests/rustdoc/unit-return.rs
index 353cd1c4772..6ddfa0c4d5c 100644
--- a/tests/rustdoc/unit-return.rs
+++ b/tests/rustdoc/unit-return.rs
@@ -4,14 +4,14 @@
 
 extern crate unit_return;
 
-// @has 'foo/fn.f0.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u8) + Clone'
+// @has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u8) + Clone'
 pub fn f0(f: F) {}
 
-// @has 'foo/fn.f1.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u16) + Clone'
+// @has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u16) + Clone'
 pub fn f1 () + Clone>(f: F) {}
 
-// @has 'foo/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u32) + Clone'
+// @has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u32) + Clone'
 pub use unit_return::f2;
 
-// @has 'foo/fn.f3.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u64) + Clone'
+// @has 'foo/fn.f3.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u64) + Clone'
 pub use unit_return::f3;
diff --git a/tests/rustdoc/where-sized.rs b/tests/rustdoc/where-sized.rs
index c0c085e6ac7..c1ac834b2fc 100644
--- a/tests/rustdoc/where-sized.rs
+++ b/tests/rustdoc/where-sized.rs
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo(_: &X)'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where X: ?Sized,'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn foo(_: &X)'
+// @has - '//pre[@class="rust item-decl"]' 'where X: ?Sized,'
 pub fn foo(_: &X) where X: ?Sized {}
diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html
index f84cb3753cb..6f151f2328e 100644
--- a/tests/rustdoc/where.SWhere_Simd_item-decl.html
+++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html
@@ -1 +1 @@
-
\ No newline at end of file
+
pub struct Simd<T>(_)
where
    T: MyTrait
;
\ No newline at end of file diff --git a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html index 85b62667427..11df902f372 100644 --- a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html +++ b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html @@ -1,8 +1,8 @@ -
pub trait TraitWhere {
+
pub trait TraitWhere {
     type Item<'a>
    where
        Self: 'a
; fn func(self)
    where
        Self: Sized
, { ... } fn lines(self) -> Lines<Self>
    where
        Self: Sized
, { ... } -}
\ No newline at end of file +}
\ No newline at end of file diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs index 644a0058244..4c34c7e51d9 100644 --- a/tests/rustdoc/where.rs +++ b/tests/rustdoc/where.rs @@ -22,13 +22,13 @@ impl Delta where D: MyTrait { pub struct Echo(E); // @has 'foo/struct.Simd.html' -// @snapshot SWhere_Simd_item-decl - '//div[@class="item-decl"]' +// @snapshot SWhere_Simd_item-decl - '//pre[@class="rust item-decl"]' pub struct Simd([T; 1]) where T: MyTrait; // @has 'foo/trait.TraitWhere.html' -// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="item-decl"]' +// @snapshot SWhere_TraitWhere_item-decl - '//pre[@class="rust item-decl"]' pub trait TraitWhere { type Item<'a> where Self: 'a; @@ -57,6 +57,6 @@ pub enum Foxtrot { Foxtrot1(F) } // "impl MyTrait for Foxtrotwhere F: MyTrait" impl MyTrait for Foxtrotwhere F: MyTrait {} -// @has foo/type.Golf.html '//div[@class="item-decl"]/pre[@class="rust"]' \ +// @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \ // "type Golfwhere T: Clone, = (T, T)" pub type Golf where T: Clone = (T, T); diff --git a/tests/rustdoc/whitespace-after-where-clause.enum.html b/tests/rustdoc/whitespace-after-where-clause.enum.html index eeb22878f3c..904d4611036 100644 --- a/tests/rustdoc/whitespace-after-where-clause.enum.html +++ b/tests/rustdoc/whitespace-after-where-clause.enum.html @@ -1,4 +1,4 @@ -
pub enum Cow<'a, B>where
    B: ToOwned<dyn Clone> + ?Sized + 'a,
{ +
pub enum Cow<'a, B>where
    B: ToOwned<dyn Clone> + ?Sized + 'a,
{ Borrowed(&'a B), Whatever(u32), -}
\ No newline at end of file +}
\ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.enum2.html b/tests/rustdoc/whitespace-after-where-clause.enum2.html index c8037c2a8df..7bc9b780197 100644 --- a/tests/rustdoc/whitespace-after-where-clause.enum2.html +++ b/tests/rustdoc/whitespace-after-where-clause.enum2.html @@ -1,4 +1,4 @@ -
pub enum Cow2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+
pub enum Cow2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
     Borrowed(&'a B),
     Whatever(u32),
-}
\ No newline at end of file +}
\ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.rs b/tests/rustdoc/whitespace-after-where-clause.rs index 4b740b970fc..b540c7c97c1 100644 --- a/tests/rustdoc/whitespace-after-where-clause.rs +++ b/tests/rustdoc/whitespace-after-where-clause.rs @@ -4,7 +4,7 @@ #![crate_name = "foo"] // @has 'foo/trait.ToOwned.html' -// @snapshot trait - '//*[@class="item-decl"]' +// @snapshot trait - '//*[@class="rust item-decl"]' pub trait ToOwned where T: Clone { @@ -14,7 +14,7 @@ where T: Clone } // @has 'foo/trait.ToOwned2.html' -// @snapshot trait2 - '//*[@class="item-decl"]' +// @snapshot trait2 - '//*[@class="rust item-decl"]' // There should be a whitespace before `{` in this case! pub trait ToOwned2 { type Owned; @@ -23,7 +23,7 @@ pub trait ToOwned2 { } // @has 'foo/enum.Cow.html' -// @snapshot enum - '//*[@class="item-decl"]' +// @snapshot enum - '//*[@class="rust item-decl"]' pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned, @@ -33,7 +33,7 @@ where } // @has 'foo/enum.Cow2.html' -// @snapshot enum2 - '//*[@class="item-decl"]' +// @snapshot enum2 - '//*[@class="rust item-decl"]' // There should be a whitespace before `{` in this case! pub enum Cow2<'a, B: ?Sized + ToOwned + 'a> { Borrowed(&'a B), @@ -41,7 +41,7 @@ pub enum Cow2<'a, B: ?Sized + ToOwned + 'a> { } // @has 'foo/struct.Struct.html' -// @snapshot struct - '//*[@class="item-decl"]' +// @snapshot struct - '//*[@class="rust item-decl"]' pub struct Struct<'a, B: ?Sized + 'a> where B: ToOwned, @@ -51,7 +51,7 @@ where } // @has 'foo/struct.Struct2.html' -// @snapshot struct2 - '//*[@class="item-decl"]' +// @snapshot struct2 - '//*[@class="rust item-decl"]' // There should be a whitespace before `{` in this case! pub struct Struct2<'a, B: ?Sized + ToOwned + 'a> { pub a: &'a B, @@ -59,7 +59,7 @@ pub struct Struct2<'a, B: ?Sized + ToOwned + 'a> { } // @has 'foo/union.Union.html' -// @snapshot union - '//*[@class="item-decl"]' +// @snapshot union - '//*[@class="rust item-decl"]' pub union Union<'a, B: ?Sized + 'a> where B: ToOwned, @@ -69,7 +69,7 @@ where } // @has 'foo/union.Union2.html' -// @snapshot union2 - '//*[@class="item-decl"]' +// @snapshot union2 - '//*[@class="rust item-decl"]' // There should be a whitespace before `{` in this case! pub union Union2<'a, B: ?Sized + ToOwned + 'a> { a: &'a B, diff --git a/tests/rustdoc/whitespace-after-where-clause.struct.html b/tests/rustdoc/whitespace-after-where-clause.struct.html index 5892270b2f9..54faee9e405 100644 --- a/tests/rustdoc/whitespace-after-where-clause.struct.html +++ b/tests/rustdoc/whitespace-after-where-clause.struct.html @@ -1,4 +1,4 @@ -
pub struct Struct<'a, B>where
    B: ToOwned<dyn Clone> + ?Sized + 'a,
{ +
pub struct Struct<'a, B>where
    B: ToOwned<dyn Clone> + ?Sized + 'a,
{ pub a: &'a B, pub b: u32, -}
\ No newline at end of file +} \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.struct2.html b/tests/rustdoc/whitespace-after-where-clause.struct2.html index d3952b0c566..d872d516c09 100644 --- a/tests/rustdoc/whitespace-after-where-clause.struct2.html +++ b/tests/rustdoc/whitespace-after-where-clause.struct2.html @@ -1,4 +1,4 @@ -
pub struct Struct2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+
pub struct Struct2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
     pub a: &'a B,
     pub b: u32,
-}
\ No newline at end of file +} \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.trait.html b/tests/rustdoc/whitespace-after-where-clause.trait.html index a2df06e7736..bc3653de52d 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait.html @@ -1,6 +1,6 @@ -
pub trait ToOwned<T>where
    T: Clone,
{ +
pub trait ToOwned<T>where
    T: Clone,
{ type Owned; fn to_owned(&self) -> Self::Owned; fn whatever(&self) -> T; -}
\ No newline at end of file +} \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.trait2.html b/tests/rustdoc/whitespace-after-where-clause.trait2.html index 2bfd6f7685a..eda4ca72acc 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait2.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait2.html @@ -1,6 +1,6 @@ -
pub trait ToOwned2<T: Clone> {
+
pub trait ToOwned2<T: Clone> {
     type Owned;
 
     fn to_owned(&self) -> Self::Owned;
     fn whatever(&self) -> T;
-}
\ No newline at end of file +} \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.union.html b/tests/rustdoc/whitespace-after-where-clause.union.html index 066f8f87b16..03a26280ba2 100644 --- a/tests/rustdoc/whitespace-after-where-clause.union.html +++ b/tests/rustdoc/whitespace-after-where-clause.union.html @@ -1,3 +1,3 @@ -
pub union Union<'a, B>where
    B: ToOwned<dyn Clone> + ?Sized + 'a,
{ +
pub union Union<'a, B>where
    B: ToOwned<dyn Clone> + ?Sized + 'a,
{ /* private fields */ -}
\ No newline at end of file +} \ No newline at end of file diff --git a/tests/rustdoc/whitespace-after-where-clause.union2.html b/tests/rustdoc/whitespace-after-where-clause.union2.html index 6b48c5dbd3e..fc78e9b6039 100644 --- a/tests/rustdoc/whitespace-after-where-clause.union2.html +++ b/tests/rustdoc/whitespace-after-where-clause.union2.html @@ -1,3 +1,3 @@ -
pub union Union2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
+
pub union Union2<'a, B: ?Sized + ToOwned<dyn Clone> + 'a> {
     /* private fields */
-}
\ No newline at end of file +} \ No newline at end of file diff --git a/tests/rustdoc/wrapping.rs b/tests/rustdoc/wrapping.rs index 178b8adc3f0..dd5c700329f 100644 --- a/tests/rustdoc/wrapping.rs +++ b/tests/rustdoc/wrapping.rs @@ -1,5 +1,5 @@ use std::fmt::Debug; -// @has 'wrapping/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo() -> impl Debug' -// @count - '//div[@class="item-decl"]/pre[@class="rust"]/br' 0 +// @has 'wrapping/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo() -> impl Debug' +// @count - '//pre[@class="rust item-decl"]/br' 0 pub fn foo() -> impl Debug {} From e9f56300676fd94639283ad86b93c048b6837ed6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 30 Jan 2023 19:28:47 +0100 Subject: [PATCH 04/10] Migrate last part of CSS themes to CSS variables --- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++++ src/librustdoc/html/static/css/themes/ayu.css | 17 +++++------------ src/librustdoc/html/static/css/themes/dark.css | 14 ++++---------- src/librustdoc/html/static/css/themes/light.css | 14 ++++---------- 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 8699508e439..81d8d3f7c32 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1262,6 +1262,14 @@ a.test-arrow:hover { line-height: 1.5; color: inherit; } +#search-tabs button:not(.selected) { + background-color: var(--search-tab-button-not-selected-background); + border-top-color: var(--search-tab-button-not-selected-border-top-color); +} +#search-tabs button:hover, #search-tabs button.selected { + background-color: var(--search-tab-button-selected-background); + border-top-color: var(--search-tab-button-selected-border-top-color); +} #search-tabs .count { font-size: 1rem; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index ed779bf6166..d20d13ab36d 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -46,6 +46,10 @@ Original by Dempfi (https://github.com/dempfi/ayu) --search-results-alias-color: #c5c5c5; --search-results-grey-color: #999; --search-tab-title-count-color: #888; + --search-tab-button-not-selected-border-top-color: none; + --search-tab-button-not-selected-background: transparent !important; + --search-tab-button-selected-border-top-color: none; + --search-tab-button-selected-background: #141920 !important; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ff7733; @@ -171,28 +175,17 @@ pre, .rustdoc.source .example-wrap { } #search-tabs > button.selected { - background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; border-top: none; } - #search-tabs > button:not(.selected) { - background-color: transparent !important; border: none; + background-color: transparent !important; } - #search-tabs > button:hover { border-bottom: 1px solid rgba(242, 151, 24, 0.3); } -/* rules that this theme does not need to set, here to satisfy the rule checker */ -/* note that a lot of these are partially set in some way (meaning they are set -individually rather than as a group) */ -/* FIXME: these rules should be at the bottom of the file but currently must be -above the `@media (max-width: 700px)` rules due to a bug in the css checker */ -/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */ -#search-tabs > button:hover, #search-tabs > button.selected {} - #settings-menu > a img { filter: invert(100); } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 3766f0daa42..b84d87c4a54 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -41,6 +41,10 @@ --search-results-alias-color: #fff; --search-results-grey-color: #ccc; --search-tab-title-count-color: #888; + --search-tab-button-not-selected-border-top-color: #252525; + --search-tab-button-not-selected-background: #252525; + --search-tab-button-selected-border-top-color: #0089ff; + --search-tab-button-selected-background: #353535; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ab8ac1; @@ -95,13 +99,3 @@ --scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1); --scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0); } - -#search-tabs > button:not(.selected) { - background-color: #252525; - border-top-color: #252525; -} - -#search-tabs > button:hover, #search-tabs > button.selected { - border-top-color: #0089ff; - background-color: #353535; -} diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 8a7f6abcf8d..342274e6767 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -41,6 +41,10 @@ --search-results-alias-color: #000; --search-results-grey-color: #999; --search-tab-title-count-color: #888; + --search-tab-button-not-selected-border-top-color: #e6e6e6; + --search-tab-button-not-selected-background: #e6e6e6; + --search-tab-button-selected-border-top-color: #0089ff; + --search-tab-button-selected-background: #ffffff; --stab-background-color: #fff5d6; --stab-code-color: #000; --code-highlight-kw-color: #8959a8; @@ -92,13 +96,3 @@ --scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1); --scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0); } - -#search-tabs > button:not(.selected) { - background-color: #e6e6e6; - border-top-color: #e6e6e6; -} - -#search-tabs > button:hover, #search-tabs > button.selected { - background-color: #ffffff; - border-top-color: #0089ff; -} From 343a359109a48f4ece657831bf0331e22d108800 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 30 Jan 2023 19:04:55 +0000 Subject: [PATCH 05/10] Use ObligationCtxt::new_in_snapshot in satisfied_from_param_env --- .../src/traits/const_evaluatable.rs | 2 +- ...m-with-associated-const-in-where-clause.rs | 17 ++++++++ ...gle-satisfied-ConstEvaluatable-in-probe.rs | 39 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc/document-item-with-associated-const-in-where-clause.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index f779d9dd8d9..786473457ae 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -219,7 +219,7 @@ fn satisfied_from_param_env<'tcx>( } if let Some(Ok(c)) = single_match { - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok()); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok()); assert!(ocx.select_all_or_error().is_empty()); diff --git a/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs b/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs new file mode 100644 index 00000000000..c9408ef3360 --- /dev/null +++ b/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Enumerable { + const N: usize; +} + +#[derive(Clone)] +pub struct SymmetricGroup +where + S: Enumerable, + [(); S::N]: Sized, +{ + _phantom: std::marker::PhantomData, +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs b/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs new file mode 100644 index 00000000000..0ba0c5a72ef --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs @@ -0,0 +1,39 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::marker::PhantomData; + +pub trait Bytes { + const BYTES: usize; +} + +#[derive(Clone, Debug)] +pub struct Conster +where + OT: Bytes, + [(); OT::BYTES]: Sized, +{ + _offset_type: PhantomData OT>, +} + +impl Conster +where + OT: Bytes, + [(); OT::BYTES]: Sized, +{ + pub fn new() -> Self { + Conster { _offset_type: PhantomData } + } +} + +pub fn make_conster() -> Conster +where + COT: Bytes, + [(); COT::BYTES]: Sized, +{ + Conster::new() +} + +fn main() {} From 085a48e7983d2b3b1f6d6fbeb127dd90b2a1377c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 23 Jan 2023 22:33:59 +0000 Subject: [PATCH 06/10] Implement unsizing in the new trait solver --- .../src/solve/assembly.rs | 10 + .../src/solve/project_goals.rs | 7 + .../src/solve/trait_goals.rs | 175 ++++++++++++++++++ tests/ui/traits/new-solver/unsize-good.rs | 25 +++ 4 files changed, 217 insertions(+) create mode 100644 tests/ui/traits/new-solver/unsize-good.rs diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index e44fd82ba22..e6c36d37ffb 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -173,6 +173,14 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; + + // Implement unsizing. The most common forms of unsizing are array to slice, + // and concrete (Sized) type into a `dyn Trait`. ADTs and Tuples can also + // have their final field unsized if it's generic. + fn consider_builtin_unsize_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -303,6 +311,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_future_candidate(self, goal) } else if lang_items.gen_trait() == Some(trait_def_id) { G::consider_builtin_generator_candidate(self, goal) + } else if lang_items.unsize_trait() == Some(trait_def_id) { + G::consider_builtin_unsize_candidate(self, goal) } else { Err(NoSolution) }; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index b175a6dde17..00b4fa67d68 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -554,6 +554,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { .to_predicate(tcx), ) } + + fn consider_builtin_unsize_candidate( + _ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + bug!("`Unsize` does not have an associated type: {:?}", goal); + } } /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 1ea8fb8fd3d..28144da1b1e 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -8,6 +8,7 @@ use super::{Certainty, EvalCtxt, Goal, QueryResult}; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; +use rustc_infer::traits::util::supertraits; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitable}; @@ -238,6 +239,180 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { .to_predicate(tcx), ) } + + fn consider_builtin_unsize_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let tcx = ecx.tcx(); + let a_ty = goal.predicate.self_ty(); + let b_ty = goal.predicate.trait_ref.substs.type_at(1); + if b_ty.is_ty_var() { + return ecx.make_canonical_response(Certainty::AMBIGUOUS); + } + ecx.infcx.probe(|_| { + match (a_ty.kind(), b_ty.kind()) { + // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b` + ( + &ty::Dynamic(a_data, a_region, ty::Dyn), + &ty::Dynamic(b_data, b_region, ty::Dyn), + ) => { + // All of a's auto traits need to be in b's auto traits. + let auto_traits_compatible = b_data + .auto_traits() + .all(|b| a_data.auto_traits().any(|a| a == b)); + if !auto_traits_compatible { + return Err(NoSolution); + } + + // If the principal def ids match (or are both none), then we're not doing + // trait upcasting. We're just removing auto traits (or shortening the lifetime). + if a_data.principal_def_id() == b_data.principal_def_id() { + // Require that all of the trait predicates from A match B, except for + // the auto traits. We do this by constructing a new A type with B's + // auto traits, and equating these types. + let new_a_data = a_data + .iter() + .filter(|a| { + matches!( + a.skip_binder(), + ty::ExistentialPredicate::Trait(_) | ty::ExistentialPredicate::Projection(_) + ) + }) + .chain( + b_data + .auto_traits() + .map(ty::ExistentialPredicate::AutoTrait) + .map(ty::Binder::dummy), + ); + let new_a_data = tcx.mk_poly_existential_predicates(new_a_data); + let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn); + + // We also require that A's lifetime outlives B's lifetime. + let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?; + nested_obligations.push(goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)))); + + ecx.evaluate_all_and_make_canonical_response(nested_obligations) + } else if let Some(a_principal) = a_data.principal() + && let Some(b_principal) = b_data.principal() + && supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) + .any(|trait_ref| trait_ref.def_id() == b_principal.def_id()) + { + // FIXME: Intentionally ignoring `need_migrate_deref_output_trait_object` here for now. + // Confirm upcasting candidate + todo!() + } else { + Err(NoSolution) + } + } + // `T` -> `dyn Trait` unsizing + (_, &ty::Dynamic(data, region, ty::Dyn)) => { + // Can only unsize to an object-safe type + // FIXME: Can auto traits be *not* object safe? + if data + .auto_traits() + .chain(data.principal_def_id()) + .any(|def_id| !tcx.is_object_safe(def_id)) + { + return Err(NoSolution); + } + + let Some(sized_def_id) = tcx.lang_items().sized_trait() else { + return Err(NoSolution); + }; + let nested_goals: Vec<_> = data + .iter() + // Check that the type implements all of the predicates of the def-id. + // (i.e. the principal, all of the associated types match, and any auto traits) + .map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))) + .chain([ + // The type must be Sized to be unsized. + goal.with( + tcx, + ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [a_ty])), + ), + // The type must outlive the lifetime of the `dyn` we're unsizing into. + goal.with( + tcx, + ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region)), + ), + ]) + .collect(); + + ecx.evaluate_all_and_make_canonical_response(nested_goals) + } + // `[T; n]` -> `[T]` unsizing + (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { + // We just require that the element type stays the same + let nested_goals = ecx.infcx.eq(goal.param_env, a_elem_ty, b_elem_ty)?; + ecx.evaluate_all_and_make_canonical_response(nested_goals) + } + // Struct unsizing `Struct` -> `Struct` where `T: Unsize` + (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) + if a_def.is_struct() && a_def.did() == b_def.did() => + { + let unsizing_params = tcx.unsizing_params_for_adt(a_def.did()); + // We must be unsizing some type parameters. This also implies + // that the struct has a tail field. + if unsizing_params.is_empty() { + return Err(NoSolution); + } + + let tail_field = a_def + .non_enum_variant() + .fields + .last() + .expect("expected unsized ADT to have a tail field"); + let tail_field_ty = tcx.bound_type_of(tail_field.did); + + let a_tail_ty = tail_field_ty.subst(tcx, a_substs); + let b_tail_ty = tail_field_ty.subst(tcx, b_substs); + + // Substitute just the unsizing params from B into A. The type after + // this substitution must be equal to B. This is so we don't unsize + // unrelated type parameters. + let new_a_substs = tcx.mk_substs(a_substs.iter().enumerate().map(|(i, a)| { + if unsizing_params.contains(i as u32) { b_substs[i] } else { a } + })); + let unsized_a_ty = tcx.mk_adt(a_def, new_a_substs); + + // Finally, we require that `TailA: Unsize` for the tail field + // types. + let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?; + nested_goals.push(goal.with( + tcx, + ty::Binder::dummy( + tcx.mk_trait_ref(goal.predicate.def_id(), [a_tail_ty, b_tail_ty]), + ), + )); + + ecx.evaluate_all_and_make_canonical_response(nested_goals) + } + // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize` + (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) + if a_tys.len() == b_tys.len() && !a_tys.is_empty() => + { + let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); + let b_last_ty = b_tys.last().unwrap(); + + // Substitute just the tail field of B., and require that they're equal. + let unsized_a_ty = tcx.mk_tup(a_rest_tys.iter().chain([b_last_ty])); + let mut nested_goals = ecx.infcx.eq(goal.param_env, unsized_a_ty, b_ty)?; + + // Similar to ADTs, require that the rest of the fields are equal. + nested_goals.push(goal.with( + tcx, + ty::Binder::dummy( + tcx.mk_trait_ref(goal.predicate.def_id(), [*a_last_ty, *b_last_ty]), + ), + )); + + ecx.evaluate_all_and_make_canonical_response(nested_goals) + } + _ => Err(NoSolution), + } + }) + } } impl<'tcx> EvalCtxt<'_, 'tcx> { diff --git a/tests/ui/traits/new-solver/unsize-good.rs b/tests/ui/traits/new-solver/unsize-good.rs new file mode 100644 index 00000000000..87ed9cfd10a --- /dev/null +++ b/tests/ui/traits/new-solver/unsize-good.rs @@ -0,0 +1,25 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(unsized_tuple_coercion)] + +trait Foo {} + +impl Foo for i32 {} + +fn main() { + // Unsizing via struct + let _: Box = Box::new(1i32); + + // Slice unsizing + let y = [1, 2, 3]; + let _: &[i32] = &y; + + // Tuple unsizing + let hi = (1i32,); + let _: &(dyn Foo,) = &hi; + + // Dropping auto traits + let a: &(dyn Foo + Send) = &1; + let _: &dyn Foo = a; +} From c24844048ff023aeaf47080634507677ffbe7001 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 23 Jan 2023 23:56:54 +0000 Subject: [PATCH 07/10] Trait upcasting support in new solver --- .../src/solve/assembly.rs | 21 ++- .../src/solve/project_goals.rs | 7 + .../src/solve/trait_goals.rs | 138 +++++++++++------- .../traits/new-solver/upcast-right-substs.rs | 14 ++ .../traits/new-solver/upcast-wrong-substs.rs | 13 ++ .../new-solver/upcast-wrong-substs.stderr | 14 ++ 6 files changed, 148 insertions(+), 59 deletions(-) create mode 100644 tests/ui/traits/new-solver/upcast-right-substs.rs create mode 100644 tests/ui/traits/new-solver/upcast-wrong-substs.rs create mode 100644 tests/ui/traits/new-solver/upcast-wrong-substs.stderr diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index e6c36d37ffb..1c4e498c57e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -174,13 +174,20 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - // Implement unsizing. The most common forms of unsizing are array to slice, - // and concrete (Sized) type into a `dyn Trait`. ADTs and Tuples can also - // have their final field unsized if it's generic. + // The most common forms of unsizing are array to slice, and concrete (Sized) + // type into a `dyn Trait`. ADTs and Tuples can also have their final field + // unsized if it's generic. fn consider_builtin_unsize_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; + + // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or + // if `Trait2` is a (transitive) supertrait of `Trait2`. + fn consider_builtin_dyn_unsize_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> Vec>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -323,6 +330,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } Err(NoSolution) => (), } + + // There may be multiple unsize candidates for a trait with several supertraits: + // `trait Foo: Bar + Bar` and `dyn Foo: Unsize>` + if lang_items.unsize_trait() == Some(trait_def_id) { + for result in G::consider_builtin_dyn_unsize_candidates(self, goal) { + candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }); + } + } } fn assemble_param_env_candidates>( diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 00b4fa67d68..f9506446aba 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -561,6 +561,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ) -> QueryResult<'tcx> { bug!("`Unsize` does not have an associated type: {:?}", goal); } + + fn consider_builtin_dyn_unsize_candidates( + _ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> Vec> { + bug!("`Unsize` does not have an associated type: {:?}", goal); + } } /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 28144da1b1e..c79f1f05512 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -4,7 +4,7 @@ use std::iter; use super::assembly::{self, Candidate, CandidateSource}; use super::infcx_ext::InferCtxtExt; -use super::{Certainty, EvalCtxt, Goal, QueryResult}; +use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult}; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; @@ -253,57 +253,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.infcx.probe(|_| { match (a_ty.kind(), b_ty.kind()) { // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b` - ( - &ty::Dynamic(a_data, a_region, ty::Dyn), - &ty::Dynamic(b_data, b_region, ty::Dyn), - ) => { - // All of a's auto traits need to be in b's auto traits. - let auto_traits_compatible = b_data - .auto_traits() - .all(|b| a_data.auto_traits().any(|a| a == b)); - if !auto_traits_compatible { - return Err(NoSolution); - } - - // If the principal def ids match (or are both none), then we're not doing - // trait upcasting. We're just removing auto traits (or shortening the lifetime). - if a_data.principal_def_id() == b_data.principal_def_id() { - // Require that all of the trait predicates from A match B, except for - // the auto traits. We do this by constructing a new A type with B's - // auto traits, and equating these types. - let new_a_data = a_data - .iter() - .filter(|a| { - matches!( - a.skip_binder(), - ty::ExistentialPredicate::Trait(_) | ty::ExistentialPredicate::Projection(_) - ) - }) - .chain( - b_data - .auto_traits() - .map(ty::ExistentialPredicate::AutoTrait) - .map(ty::Binder::dummy), - ); - let new_a_data = tcx.mk_poly_existential_predicates(new_a_data); - let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn); - - // We also require that A's lifetime outlives B's lifetime. - let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?; - nested_obligations.push(goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)))); - - ecx.evaluate_all_and_make_canonical_response(nested_obligations) - } else if let Some(a_principal) = a_data.principal() - && let Some(b_principal) = b_data.principal() - && supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) - .any(|trait_ref| trait_ref.def_id() == b_principal.def_id()) - { - // FIXME: Intentionally ignoring `need_migrate_deref_output_trait_object` here for now. - // Confirm upcasting candidate - todo!() - } else { - Err(NoSolution) - } + (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => { + // Dyn upcasting is handled separately, since due to upcasting, + // when there are two supertraits that differ by substs, we + // may return more than one query response. + return Err(NoSolution); } // `T` -> `dyn Trait` unsizing (_, &ty::Dynamic(data, region, ty::Dyn)) => { @@ -332,10 +286,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [a_ty])), ), // The type must outlive the lifetime of the `dyn` we're unsizing into. - goal.with( - tcx, - ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region)), - ), + goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))), ]) .collect(); @@ -413,6 +364,81 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } }) } + + fn consider_builtin_dyn_unsize_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> Vec> { + let tcx = ecx.tcx(); + + let a_ty = goal.predicate.self_ty(); + let b_ty = goal.predicate.trait_ref.substs.type_at(1); + let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { + return vec![]; + }; + let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { + return vec![]; + }; + + // All of a's auto traits need to be in b's auto traits. + let auto_traits_compatible = + b_data.auto_traits().all(|b| a_data.auto_traits().any(|a| a == b)); + if !auto_traits_compatible { + return vec![]; + } + + let mut responses = vec![]; + let mut unsize_dyn_to_principal = |principal: Option>| { + let _ = ecx.infcx.probe(|_| -> Result<(), NoSolution> { + // Require that all of the trait predicates from A match B, except for + // the auto traits. We do this by constructing a new A type with B's + // auto traits, and equating these types. + let new_a_data = principal + .into_iter() + .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)) + .chain(a_data.iter().filter(|a| { + matches!(a.skip_binder(), ty::ExistentialPredicate::Projection(_)) + })) + .chain( + b_data + .auto_traits() + .map(ty::ExistentialPredicate::AutoTrait) + .map(ty::Binder::dummy), + ); + let new_a_data = tcx.mk_poly_existential_predicates(new_a_data); + let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn); + + // We also require that A's lifetime outlives B's lifetime. + let mut nested_obligations = ecx.infcx.eq(goal.param_env, new_a_ty, b_ty)?; + nested_obligations.push( + goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))), + ); + + responses.push(ecx.evaluate_all_and_make_canonical_response(nested_obligations)?); + + Ok(()) + }); + }; + + // If the principal def ids match (or are both none), then we're not doing + // trait upcasting. We're just removing auto traits (or shortening the lifetime). + if a_data.principal_def_id() == b_data.principal_def_id() { + unsize_dyn_to_principal(a_data.principal()); + } else if let Some(a_principal) = a_data.principal() + && let Some(b_principal) = b_data.principal() + { + for super_trait_ref in supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) { + if super_trait_ref.def_id() != b_principal.def_id() { + continue; + } + let erased_trait_ref = super_trait_ref + .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + unsize_dyn_to_principal(Some(erased_trait_ref)); + } + } + + responses + } } impl<'tcx> EvalCtxt<'_, 'tcx> { diff --git a/tests/ui/traits/new-solver/upcast-right-substs.rs b/tests/ui/traits/new-solver/upcast-right-substs.rs new file mode 100644 index 00000000000..c19c82acf24 --- /dev/null +++ b/tests/ui/traits/new-solver/upcast-right-substs.rs @@ -0,0 +1,14 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(trait_upcasting)] + +trait Foo: Bar + Bar {} + +trait Bar {} + +fn main() { + let x: &dyn Foo = todo!(); + let y: &dyn Bar = x; + let z: &dyn Bar = x; +} diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.rs b/tests/ui/traits/new-solver/upcast-wrong-substs.rs new file mode 100644 index 00000000000..f2d04d932bb --- /dev/null +++ b/tests/ui/traits/new-solver/upcast-wrong-substs.rs @@ -0,0 +1,13 @@ +// compile-flags: -Ztrait-solver=next + +#![feature(trait_upcasting)] + +trait Foo: Bar + Bar {} + +trait Bar {} + +fn main() { + let x: &dyn Foo = todo!(); + let y: &dyn Bar = x; + //~^ ERROR mismatched types +} diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.stderr b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr new file mode 100644 index 00000000000..8623f395f59 --- /dev/null +++ b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/upcast-wrong-substs.rs:11:30 + | +LL | let y: &dyn Bar = x; + | --------------- ^ expected trait `Bar`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Bar` + found reference `&dyn Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From f7fc0b712103d8832b305efa72e4c9851161bbdf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 25 Jan 2023 17:02:16 +0000 Subject: [PATCH 08/10] nits --- .../src/solve/assembly.rs | 4 +-- .../src/solve/project_goals.rs | 2 +- .../src/solve/trait_goals.rs | 26 +++++++++---------- compiler/rustc_ty_utils/src/ty.rs | 4 --- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 1c4e498c57e..5690b6536bb 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -184,7 +184,7 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq { // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or // if `Trait2` is a (transitive) supertrait of `Trait2`. - fn consider_builtin_dyn_unsize_candidates( + fn consider_builtin_dyn_upcast_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec>; @@ -334,7 +334,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // There may be multiple unsize candidates for a trait with several supertraits: // `trait Foo: Bar + Bar` and `dyn Foo: Unsize>` if lang_items.unsize_trait() == Some(trait_def_id) { - for result in G::consider_builtin_dyn_unsize_candidates(self, goal) { + for result in G::consider_builtin_dyn_upcast_candidates(self, goal) { candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }); } } diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index f9506446aba..879f18843c9 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -562,7 +562,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { bug!("`Unsize` does not have an associated type: {:?}", goal); } - fn consider_builtin_dyn_unsize_candidates( + fn consider_builtin_dyn_upcast_candidates( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec> { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index c79f1f05512..29ee9da38e0 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -262,11 +262,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { // `T` -> `dyn Trait` unsizing (_, &ty::Dynamic(data, region, ty::Dyn)) => { // Can only unsize to an object-safe type - // FIXME: Can auto traits be *not* object safe? if data - .auto_traits() - .chain(data.principal_def_id()) - .any(|def_id| !tcx.is_object_safe(def_id)) + .principal_def_id() + .map_or(false, |def_id| !tcx.check_is_object_safe(def_id)) { return Err(NoSolution); } @@ -365,7 +363,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { }) } - fn consider_builtin_dyn_unsize_candidates( + fn consider_builtin_dyn_upcast_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec> { @@ -387,9 +385,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return vec![]; } - let mut responses = vec![]; let mut unsize_dyn_to_principal = |principal: Option>| { - let _ = ecx.infcx.probe(|_| -> Result<(), NoSolution> { + ecx.infcx.probe(|_| -> Result<_, NoSolution> { // Require that all of the trait predicates from A match B, except for // the auto traits. We do this by constructing a new A type with B's // auto traits, and equating these types. @@ -414,16 +411,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))), ); - responses.push(ecx.evaluate_all_and_make_canonical_response(nested_obligations)?); - - Ok(()) - }); + ecx.evaluate_all_and_make_canonical_response(nested_obligations) + }) }; + let mut responses = vec![]; // If the principal def ids match (or are both none), then we're not doing // trait upcasting. We're just removing auto traits (or shortening the lifetime). if a_data.principal_def_id() == b_data.principal_def_id() { - unsize_dyn_to_principal(a_data.principal()); + if let Ok(response) = unsize_dyn_to_principal(a_data.principal()) { + responses.push(response); + } } else if let Some(a_principal) = a_data.principal() && let Some(b_principal) = b_data.principal() { @@ -433,7 +431,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } let erased_trait_ref = super_trait_ref .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); - unsize_dyn_to_principal(Some(erased_trait_ref)); + if let Ok(response) = unsize_dyn_to_principal(Some(erased_trait_ref)) { + responses.push(response); + } } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index b5005c1d8d8..41e837e8b75 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -426,10 +426,6 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet Date: Mon, 30 Jan 2023 12:20:06 -0700 Subject: [PATCH 09/10] rustdoc: remove meta keywords from HTML Discussed in --- src/librustdoc/html/layout.rs | 1 - src/librustdoc/html/render/context.rs | 9 +-------- src/librustdoc/html/render/mod.rs | 2 -- src/librustdoc/html/render/write_shared.rs | 3 +-- src/librustdoc/html/sources.rs | 3 +-- src/librustdoc/html/templates/page.html | 1 - 6 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index a60e7cb10fa..6ab849c92a0 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -30,7 +30,6 @@ pub(crate) struct Page<'a> { pub(crate) root_path: &'a str, pub(crate) static_root_path: Option<&'a str>, pub(crate) description: &'a str, - pub(crate) keywords: &'a str, pub(crate) resource_suffix: &'a str, } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 15258a467a2..b59645ec2e2 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -18,7 +18,7 @@ use super::search_index::build_index; use super::write_shared::write_shared; use super::{ collect_spans_and_sources, print_sidebar, scrape_examples_help, sidebar_module_like, AllTypes, - LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS, + LinkFromSrc, NameDoc, StylePath, }; use crate::clean::{self, types::ExternalLocation, ExternalCrate}; @@ -195,7 +195,6 @@ impl<'tcx> Context<'tcx> { self.shared.layout.krate ) }; - let keywords = make_item_keywords(it); let name; let tyname_s = if it.is_crate() { name = format!("{} crate", tyname); @@ -212,7 +211,6 @@ impl<'tcx> Context<'tcx> { static_root_path: clone_shared.static_root_path.as_deref(), title: &title, description: &desc, - keywords: &keywords, resource_suffix: &clone_shared.resource_suffix, }; let mut page_buffer = Buffer::html(); @@ -598,7 +596,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { root_path: "../", static_root_path: shared.static_root_path.as_deref(), description: "List of all items in this crate", - keywords: BASIC_KEYWORDS, resource_suffix: &shared.resource_suffix, }; let all = shared.all.replace(AllTypes::new()); @@ -828,7 +825,3 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { &self.shared.cache } } - -fn make_item_keywords(it: &clean::Item) -> String { - format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) -} diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index be6de231854..816a8f4e274 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2743,8 +2743,6 @@ fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { } } -pub(crate) const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang"; - /// Returns a list of all paths used in the type. /// This is used to help deduplicate imported impls /// for reexported types. If any of the contained diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index bc8badad38e..6b71ecc24bd 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; -use super::{collect_paths_for_type, ensure_trailing_slash, Context, BASIC_KEYWORDS}; +use super::{collect_paths_for_type, ensure_trailing_slash, Context}; use crate::clean::Crate; use crate::config::{EmitType, RenderOptions}; use crate::docfs::PathError; @@ -340,7 +340,6 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; root_path: "./", static_root_path: shared.static_root_path.as_deref(), description: "List of crates", - keywords: BASIC_KEYWORDS, resource_suffix: &shared.resource_suffix, }; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 799c497d137..2c90bf4fadc 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -4,7 +4,7 @@ use crate::error::Error; use crate::html::format::Buffer; use crate::html::highlight; use crate::html::layout; -use crate::html::render::{Context, BASIC_KEYWORDS}; +use crate::html::render::Context; use crate::visit::DocVisitor; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -228,7 +228,6 @@ impl SourceCollector<'_, '_> { root_path: &root_path, static_root_path: shared.static_root_path.as_deref(), description: &desc, - keywords: BASIC_KEYWORDS, resource_suffix: &shared.resource_suffix, }; let v = layout::render( diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index fddda293b9a..8540ee66319 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -5,7 +5,6 @@ {#- -#} {#- -#} {#- -#} - {#- -#} {{page.title}} {#- -#} {#- -#} {#- -#} From 3c408d82a38e729fd2befea442633d726a02c56f Mon Sep 17 00:00:00 2001 From: Lucius Hu <1222865+lebensterben@users.noreply.github.com> Date: Tue, 31 Jan 2023 00:20:27 +0000 Subject: [PATCH 10/10] fix link in std::path::Path::display() The link `Debug` points to should be the trait `Debug`, not the macro `Debug`. --- library/std/src/path.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 2f53cf83936..e36e088896d 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2688,6 +2688,7 @@ impl Path { /// escapes the path please use [`Debug`] instead. /// /// [`Display`]: fmt::Display + /// [`Debug`]: fmt::Debug /// /// # Examples ///