From 1babece1e8888151b1b248367eb1017450dc107c Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Fri, 13 Jan 2023 14:14:26 +1300 Subject: [PATCH 1/9] suggest fix for attempted integer identifier in patterns --- .../locales/en-US/mir_build.ftl | 2 ++ compiler/rustc_mir_build/src/errors.rs | 15 ++++++++ .../src/thir/pattern/check_match.rs | 20 ++++++++--- .../ui/consts/const-match-check.eval1.stderr | 4 +++ .../ui/consts/const-match-check.eval2.stderr | 4 +++ .../consts/const-match-check.matchck.stderr | 16 +++++++++ tests/ui/pattern/issue-106552.rs | 7 ++++ tests/ui/pattern/issue-106552.stderr | 35 +++++++++++++++++++ 8 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 tests/ui/pattern/issue-106552.rs create mode 100644 tests/ui/pattern/issue-106552.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl index a082c0b61fa7e..224855fff8b56 100644 --- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -364,3 +364,5 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co [one] variant that isn't *[other] variants that aren't } matched + +mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 06523b0a1de84..7f81aef1c7321 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -770,6 +770,8 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { #[subdiagnostic] pub let_suggestion: Option, #[subdiagnostic] + pub misc_suggestion: Option, + #[subdiagnostic] pub res_defined_here: Option, } @@ -848,3 +850,16 @@ pub enum SuggestLet { count: usize, }, } + +#[derive(Subdiagnostic)] +pub enum MiscPatternSuggestion { + #[suggestion( + mir_build_suggest_attempted_int_lit, + code = "_", + applicability = "maybe-incorrect" + )] + AttemptedIntegerLiteral { + #[primary_span] + start_span: Span, + }, +} diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e13c0662ef85f..34e637f594842 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -6,8 +6,9 @@ use super::{PatCtxt, PatternError}; use crate::errors::*; +use hir::{ExprKind, PatKind}; use rustc_arena::TypedArena; -use rustc_ast::Mutability; +use rustc_ast::{LitKind, Mutability}; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; @@ -389,7 +390,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { return; } - let (inform, interpreted_as_const, res_defined_here,let_suggestion) = + let (inform, interpreted_as_const, res_defined_here,let_suggestion, misc_suggestion) = if let hir::PatKind::Path(hir::QPath::Resolved( None, hir::Path { @@ -413,6 +414,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } }, None, + None, ) } else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) { let mut bindings = vec![]; @@ -426,10 +428,19 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let end_span = semi_span.shrink_to_lo(); let count = witnesses.len(); + // If the pattern to match is an integer literal: + let int_suggestion = if + let PatKind::Lit(expr) = &pat.kind + && bindings.is_empty() + && let ExprKind::Lit(Spanned { node: LitKind::Int(_, _), span }) = expr.kind { + // Then give a suggestion, the user might've meant to create a binding instead. + Some(MiscPatternSuggestion::AttemptedIntegerLiteral { start_span: span.shrink_to_lo() }) + } else { None }; + let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }}; - (sp.map(|_|Inform), None, None, Some(let_suggestion)) + (sp.map(|_|Inform), None, None, Some(let_suggestion), int_suggestion) } else{ - (sp.map(|_|Inform), None, None, None) + (sp.map(|_|Inform), None, None, None, None) }; let adt_defined_here = try { @@ -453,6 +464,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { _p: (), pattern_ty, let_suggestion, + misc_suggestion, res_defined_here, adt_defined_here, }); diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr index 1caf1617e213c..08fcd1deab1d3 100644 --- a/tests/ui/consts/const-match-check.eval1.stderr +++ b/tests/ui/consts/const-match-check.eval1.stderr @@ -11,6 +11,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | A = { if let 0 = 0 { todo!() } 0 }, | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | A = { let _0 = 0; 0 }, + | + error: aborting due to previous error diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr index f038ba1c8ed85..5d86ca4bfd17b 100644 --- a/tests/ui/consts/const-match-check.eval2.stderr +++ b/tests/ui/consts/const-match-check.eval2.stderr @@ -11,6 +11,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = []; | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | let x: [i32; { let _0 = 0; 0 }] = []; + | + error: aborting due to previous error diff --git a/tests/ui/consts/const-match-check.matchck.stderr b/tests/ui/consts/const-match-check.matchck.stderr index b1921f8a41e48..c8f66bb0fc027 100644 --- a/tests/ui/consts/const-match-check.matchck.stderr +++ b/tests/ui/consts/const-match-check.matchck.stderr @@ -11,6 +11,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | const X: i32 = { let _0 = 0; 0 }; + | + error[E0005]: refutable pattern in local binding --> $DIR/const-match-check.rs:8:23 @@ -25,6 +29,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | static Y: i32 = { let _0 = 0; 0 }; + | + error[E0005]: refutable pattern in local binding --> $DIR/const-match-check.rs:13:26 @@ -39,6 +47,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | const X: i32 = { let _0 = 0; 0 }; + | + error[E0005]: refutable pattern in local binding --> $DIR/const-match-check.rs:19:26 @@ -53,6 +65,10 @@ help: you might want to use `if let` to ignore the variants that aren't matched | LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | const X: i32 = { let _0 = 0; 0 }; + | + error: aborting due to 4 previous errors diff --git a/tests/ui/pattern/issue-106552.rs b/tests/ui/pattern/issue-106552.rs new file mode 100644 index 0000000000000..aa2c141e05ef2 --- /dev/null +++ b/tests/ui/pattern/issue-106552.rs @@ -0,0 +1,7 @@ +fn main() { + let 5 = 6; + //~^ error refutable pattern in local binding [E0005] + + let x @ 5 = 6; + //~^ error refutable pattern in local binding [E0005] +} diff --git a/tests/ui/pattern/issue-106552.stderr b/tests/ui/pattern/issue-106552.stderr new file mode 100644 index 0000000000000..ed5d40c096850 --- /dev/null +++ b/tests/ui/pattern/issue-106552.stderr @@ -0,0 +1,35 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/issue-106552.rs:2:9 + | +LL | let 5 = 6; + | ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let 5 = 6 { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | let _5 = 6; + | + + +error[E0005]: refutable pattern in local binding + --> $DIR/issue-106552.rs:5:9 + | +LL | let x @ 5 = 6; + | ^^^^^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `let else` to handle the variants that aren't matched + | +LL | let x @ 5 = 6 else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0005`. From 1ea6862db3830c86355d9179a4cee9410711f68f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 13 Jan 2023 23:53:28 +0000 Subject: [PATCH 2/9] Unify Opaque/Projection handling in region outlives code --- .../src/type_check/free_region_relations.rs | 9 +--- .../rustc_hir_analysis/src/outlives/utils.rs | 20 +++----- .../src/infer/error_reporting/mod.rs | 9 ++-- .../src/infer/outlives/components.rs | 15 +++--- .../rustc_infer/src/infer/outlives/env.rs | 8 +--- .../src/infer/outlives/obligations.rs | 48 +++++-------------- .../rustc_infer/src/infer/outlives/verify.rs | 14 ++---- .../src/infer/region_constraints/mod.rs | 20 ++++---- compiler/rustc_infer/src/traits/util.rs | 13 +---- compiler/rustc_middle/src/traits/query.rs | 6 +-- .../rustc_middle/src/ty/structural_impls.rs | 1 + .../src/implied_outlives_bounds.rs | 5 +- 12 files changed, 54 insertions(+), 114 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 09cf870bcf35a..4976456afcb31 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -359,14 +359,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a)); } - OutlivesBound::RegionSubProjection(r_a, projection_b) => { + OutlivesBound::RegionSubAlias(r_a, kind, alias_b) => { self.region_bound_pairs - .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); - } - - OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => { - self.region_bound_pairs - .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a)); + .insert(ty::OutlivesPredicate(GenericKind::Alias(kind, alias_b), r_a)); } } } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index b51b740d08e2e..7d38a6e5f33c1 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -80,8 +80,8 @@ pub(crate) fn insert_outlives_predicate<'tcx>( .or_insert(span); } - Component::Projection(proj_ty) => { - // This would arise from something like: + Component::Alias(kind, alias) => { + // This would either arise from something like: // // ``` // struct Foo<'a, T: Iterator> { @@ -89,15 +89,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>( // } // ``` // - // Here we want to add an explicit `where ::Item: 'a`. - let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.def_id, proj_ty.substs); - required_predicates - .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) - .or_insert(span); - } - - Component::Opaque(def_id, substs) => { - // This would arise from something like: + // or: // // ```rust // type Opaque = impl Sized; @@ -105,9 +97,9 @@ pub(crate) fn insert_outlives_predicate<'tcx>( // struct Ss<'a, T>(&'a Opaque); // ``` // - // Here we want to have an implied bound `Opaque: 'a` - - let ty = tcx.mk_opaque(def_id, substs); + // Here we want to add an explicit `where ::Item: 'a` + // or `Opaque: 'a` depending on the alias kind. + let ty: Ty<'tcx> = tcx.mk_ty(ty::Alias(kind, alias)); required_predicates .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) .or_insert(span); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 533a3c768eb16..7fbe49ce92233 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2256,9 +2256,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{}`", p), - GenericKind::Projection(ref p) => format!("the associated type `{}`", p), - GenericKind::Opaque(def_id, substs) => { - format!("the opaque type `{}`", self.tcx.def_path_str_with_substs(def_id, substs)) + GenericKind::Alias(ty::Projection, ref p) => format!("the associated type `{}`", p), + GenericKind::Alias(ty::Opaque, ref p) => { + format!( + "the opaque type `{}`", + self.tcx.def_path_str_with_substs(p.def_id, p.substs) + ) } }; diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index aa2b5d067d266..31451192bc50e 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -3,9 +3,8 @@ // RFC for reference. use rustc_data_structures::sso::SsoHashSet; -use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use smallvec::{smallvec, SmallVec}; #[derive(Debug)] @@ -23,7 +22,7 @@ pub enum Component<'tcx> { // is not in a position to judge which is the best technique, so // we just product the projection as a component and leave it to // the consumer to decide (but see `EscapingProjection` below). - Projection(ty::AliasTy<'tcx>), + Alias(ty::AliasKind, ty::AliasTy<'tcx>), // In the case where a projection has escaping regions -- meaning // regions bound within the type itself -- we always use @@ -46,8 +45,6 @@ pub enum Component<'tcx> { // them. This gives us room to improve the regionck reasoning in // the future without breaking backwards compat. EscapingProjection(Vec>), - - Opaque(DefId, SubstsRef<'tcx>), } /// Push onto `out` all the things that must outlive `'a` for the condition @@ -130,8 +127,8 @@ fn compute_components<'tcx>( // outlives any other lifetime, which is unsound. // See https://github.com/rust-lang/rust/issues/84305 for // more details. - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { - out.push(Component::Opaque(def_id, substs)); + ty::Alias(ty::Opaque, data) => { + out.push(Component::Alias(ty::Opaque, data)); }, // For projections, we prefer to generate an obligation like @@ -142,7 +139,7 @@ fn compute_components<'tcx>( // trait-ref. Therefore, if we see any higher-ranked regions, // we simply fallback to the most restrictive rule, which // requires that `Pi: 'a` for all `i`. - ty::Alias(ty::Projection, ref data) => { + ty::Alias(ty::Projection, data) => { if !data.has_escaping_bound_vars() { // best case: no escaping regions, so push the // projection and skip the subtree (thus generating no @@ -150,7 +147,7 @@ fn compute_components<'tcx>( // the rules OutlivesProjectionEnv, // OutlivesProjectionTraitDef, and // OutlivesProjectionComponents to regionck. - out.push(Component::Projection(*data)); + out.push(Component::Alias(ty::Projection, data)); } else { // fallback case: hard code // OutlivesProjectionComponents. Continue walking diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 33543135ddb0e..52c3d97f24111 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -138,13 +138,9 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> { self.region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a)); } - OutlivesBound::RegionSubProjection(r_a, projection_b) => { + OutlivesBound::RegionSubAlias(r_a, kind, projection_b) => { self.region_bound_pairs - .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); - } - OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => { - self.region_bound_pairs - .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a)); + .insert(ty::OutlivesPredicate(GenericKind::Alias(kind, projection_b), r_a)); } OutlivesBound::RegionSubRegion(r_a, r_b) => { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index a85e6a19b11b6..4a93597a643f8 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -266,11 +266,8 @@ where Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); } - Component::Opaque(def_id, substs) => { - self.opaque_must_outlive(*def_id, substs, origin, region) - } - Component::Projection(projection_ty) => { - self.projection_must_outlive(origin, region, *projection_ty); + Component::Alias(kind, data) => { + self.alias_must_outlive(*kind, *data, origin, region) } Component::EscapingProjection(subcomponents) => { self.components_must_outlive(origin, &subcomponents, region, category); @@ -305,44 +302,25 @@ where } #[instrument(level = "debug", skip(self))] - fn opaque_must_outlive( + fn alias_must_outlive( &mut self, - def_id: DefId, - substs: SubstsRef<'tcx>, + kind: ty::AliasKind, + data: ty::AliasTy<'tcx>, origin: infer::SubregionOrigin<'tcx>, region: ty::Region<'tcx>, ) { self.generic_must_outlive( origin, region, - GenericKind::Opaque(def_id, substs), - def_id, - substs, - true, + GenericKind::Alias(kind, data), + data.def_id, + data.substs, + kind == ty::Opaque, |ty| match *ty.kind() { - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => (def_id, substs), - _ => bug!("expected only projection types from env, not {:?}", ty), - }, - ); - } - - #[instrument(level = "debug", skip(self))] - fn projection_must_outlive( - &mut self, - origin: infer::SubregionOrigin<'tcx>, - region: ty::Region<'tcx>, - projection_ty: ty::AliasTy<'tcx>, - ) { - self.generic_must_outlive( - origin, - region, - GenericKind::Projection(projection_ty), - projection_ty.def_id, - projection_ty.substs, - false, - |ty| match ty.kind() { - ty::Alias(ty::Projection, projection_ty) => { - (projection_ty.def_id, projection_ty.substs) + ty::Alias(filter_kind, ty::AliasTy { def_id, substs, .. }) + if kind == filter_kind => + { + (def_id, substs) } _ => bug!("expected only projection types from env, not {:?}", ty), }, diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 40bbec8ddd091..66bbf47c3b6e6 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -170,16 +170,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { match *component { Component::Region(lt) => VerifyBound::OutlivedBy(lt), Component::Param(param_ty) => self.param_bound(param_ty), - Component::Opaque(did, substs) => self.projection_opaque_bounds( - GenericKind::Opaque(did, substs), - did, - substs, - visited, - ), - Component::Projection(projection_ty) => self.projection_opaque_bounds( - GenericKind::Projection(projection_ty), - projection_ty.def_id, - projection_ty.substs, + Component::Alias(kind, data) => self.projection_opaque_bounds( + GenericKind::Alias(kind, data), + data.def_id, + data.substs, visited, ), Component::EscapingProjection(ref components) => { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 9a427ceacd0a7..fda5ffe784678 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -12,10 +12,8 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; -use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; -use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReLateBound, ReVar}; @@ -169,8 +167,7 @@ pub struct Verify<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub enum GenericKind<'tcx> { Param(ty::ParamTy), - Projection(ty::AliasTy<'tcx>), - Opaque(DefId, SubstsRef<'tcx>), + Alias(ty::AliasKind, ty::AliasTy<'tcx>), } /// Describes the things that some `GenericKind` value `G` is known to @@ -749,9 +746,9 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { GenericKind::Param(ref p) => write!(f, "{:?}", p), - GenericKind::Projection(ref p) => write!(f, "{:?}", p), - GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| { - write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap())) + GenericKind::Alias(ty::Projection, ref p) => write!(f, "{:?}", p), + GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| { + write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap())) }), } } @@ -761,9 +758,9 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { GenericKind::Param(ref p) => write!(f, "{}", p), - GenericKind::Projection(ref p) => write!(f, "{}", p), - GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| { - write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap())) + GenericKind::Alias(ty::Projection, ref p) => write!(f, "{}", p), + GenericKind::Alias(ty::Opaque, ref p) => ty::tls::with(|tcx| { + write!(f, "{}", tcx.def_path_str_with_substs(p.def_id, tcx.lift(p.substs).unwrap())) }), } } @@ -773,8 +770,7 @@ impl<'tcx> GenericKind<'tcx> { pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), - GenericKind::Projection(ref p) => tcx.mk_projection(p.def_id, p.substs), - GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs), + GenericKind::Alias(kind, data) => tcx.mk_ty(ty::Alias(kind, data)), } } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 8f0bd3a9abe5e..6fedb0ed8ac53 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -249,17 +249,8 @@ impl<'tcx> Elaborator<'tcx> { Component::UnresolvedInferenceVariable(_) => None, - Component::Opaque(def_id, substs) => { - let ty = tcx.mk_opaque(def_id, substs); - Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives( - ty::OutlivesPredicate(ty, r_min), - ))) - } - - Component::Projection(projection) => { - // We might end up here if we have `Foo<::Assoc>: 'a`. - // With this, we can deduce that `::Assoc: 'a`. - let ty = tcx.mk_projection(projection.def_id, projection.substs); + Component::Alias(kind, data) => { + let ty = tcx.mk_ty(ty::Alias(kind, data)); Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives( ty::OutlivesPredicate(ty, r_min), ))) diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 543f5b87e00bc..2a68315fefc56 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -8,9 +8,8 @@ use crate::error::DropCheckOverflow; use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; -use crate::ty::subst::{GenericArg, SubstsRef}; +use crate::ty::subst::GenericArg; use crate::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::DefId; use rustc_span::source_map::Span; pub mod type_op { @@ -214,6 +213,5 @@ pub struct NormalizationResult<'tcx> { pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), - RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>), - RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>), + RegionSubAlias(ty::Region<'tcx>, ty::AliasKind, ty::AliasTy<'tcx>), } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 30073b541ecbd..8f64eb3e4baf6 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -227,6 +227,7 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, + crate::ty::AliasKind, crate::ty::Placeholder, crate::ty::ClosureKind, crate::ty::FreeRegion, diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 010233d7718c2..d457a4a2beaf5 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -154,9 +154,8 @@ fn implied_bounds_from_components<'tcx>( match component { Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)), Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)), - Component::Projection(p) => Some(OutlivesBound::RegionSubProjection(sub_region, p)), - Component::Opaque(def_id, substs) => { - Some(OutlivesBound::RegionSubOpaque(sub_region, def_id, substs)) + Component::Alias(kind, p) => { + Some(OutlivesBound::RegionSubAlias(sub_region, kind, p)) } Component::EscapingProjection(_) => // If the projection has escaping regions, don't From 3a3f70c94e280cbd8354874438643d15ca6ef319 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 14 Jan 2023 10:58:55 -0700 Subject: [PATCH 3/9] rustdoc: remove redundant item kind class from `.item-decl > pre` This class originated in the very first commit of `rustdoc_ng`, and was used to add a color border around the item decl based on its kind. https://github.com/rust-lang/rust/blob/4fd061c426902b0904c65e64a3780b21f9ab3afb/src/rustdoc_ng/html/static/main.css#L102-L106 The item decl no longer has a border, and there aren't any kind-specific styles in modern rustdoc's rendering of this UI item. Most of this commit is updating test cases so that they use `item-decl` to find the `
` tag instead of relying on the fact that the class name
had `rust {kind}` in it while other `
` tags only had class `rust`.
---
 src/librustdoc/html/render/print_item.rs      | 32 ++++++++---------
 tests/rustdoc-gui/code-tags.goml              | 10 +++---
 tests/rustdoc-gui/font-weight.goml            |  6 ++--
 tests/rustdoc-gui/list_code_block.goml        |  2 +-
 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/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/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       |  4 +--
 tests/rustdoc/inline_cross/impl_trait.rs      | 32 ++++++++---------
 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/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/reexports-priv.rs               | 16 ++++-----
 tests/rustdoc/reexports.rs                    |  8 ++---
 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         |  4 +--
 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    |  2 +-
 tests/rustdoc/where.rs                        |  2 +-
 .../whitespace-after-where-clause.enum.html   |  2 +-
 .../whitespace-after-where-clause.enum2.html  |  2 +-
 .../whitespace-after-where-clause.struct.html |  2 +-
 ...whitespace-after-where-clause.struct2.html |  2 +-
 .../whitespace-after-where-clause.trait.html  |  2 +-
 .../whitespace-after-where-clause.trait2.html |  2 +-
 .../whitespace-after-where-clause.union.html  |  2 +-
 .../whitespace-after-where-clause.union2.html |  2 +-
 tests/rustdoc/wrapping.rs                     |  4 +--
 63 files changed, 218 insertions(+), 218 deletions(-)

diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index d6e57decdcf18..3b0c018694ad4 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -531,7 +531,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
         f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
 
     wrap_into_item_decl(w, |w| {
-        wrap_item(w, "fn", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             w.reserve(header_len);
             write!(
@@ -570,7 +570,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
     // Output the trait definition
     wrap_into_item_decl(w, |w| {
-        wrap_item(w, "trait", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             write!(
                 w,
@@ -1051,7 +1051,7 @@ 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, "trait-alias", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             write!(
                 w,
@@ -1075,7 +1075,7 @@ 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, "opaque", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             write!(
                 w,
@@ -1099,7 +1099,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl
 
 fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) {
     fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
-        wrap_item(w, "typedef", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             write!(w, "{}", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx));
             write!(
@@ -1128,7 +1128,7 @@ 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, "union", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             render_union(w, it, Some(&s.generics), &s.fields, "", cx);
         });
@@ -1193,7 +1193,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
     let tcx = cx.tcx();
     let count_variants = e.variants().count();
     wrap_into_item_decl(w, |w| {
-        wrap_item(w, "enum", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_pre(w, it, "");
             write!(
                 w,
@@ -1357,17 +1357,17 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c
         let name = it.name.expect("proc-macros always have names");
         match m.kind {
             MacroKind::Bang => {
-                wrap_item(w, "macro", |w| {
+                wrap_item(w, |w| {
                     write!(w, "{}!() {{ /* proc-macro */ }}", name);
                 });
             }
             MacroKind::Attr => {
-                wrap_item(w, "attr", |w| {
+                wrap_item(w, |w| {
                     write!(w, "#[{}]", name);
                 });
             }
             MacroKind::Derive => {
-                wrap_item(w, "derive", |w| {
+                wrap_item(w, |w| {
                     write!(w, "#[derive({})]", name);
                     if !m.helpers.is_empty() {
                         w.push_str("\n{\n");
@@ -1401,7 +1401,7 @@ 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, "const", |w| {
+        wrap_item(w, |w| {
             let tcx = cx.tcx();
             render_attributes_in_code(w, it);
 
@@ -1451,7 +1451,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
 
 fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
     wrap_into_item_decl(w, |w| {
-        wrap_item(w, "struct", |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);
         });
@@ -1504,7 +1504,7 @@ 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, "static", |w| {
+        wrap_item(w, |w| {
             render_attributes_in_code(w, it);
             write!(
                 w,
@@ -1521,7 +1521,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
 
 fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
     wrap_into_item_decl(w, |w| {
-        wrap_item(w, "foreigntype", |w| {
+        wrap_item(w, |w| {
             w.write_str("extern {\n");
             render_attributes_in_code(w, it);
             write!(
@@ -1618,11 +1618,11 @@ where
     w.write_str("")
 }
 
-fn wrap_item(w: &mut Buffer, item_name: &str, f: F)
+fn wrap_item(w: &mut Buffer, f: F)
 where
     F: FnOnce(&mut Buffer),
 {
-    w.write_fmt(format_args!("
", item_name));
+    w.write_str(r#"
"#);
     f(w);
     w.write_str("
"); } diff --git a/tests/rustdoc-gui/code-tags.goml b/tests/rustdoc-gui/code-tags.goml index 94c1a6525aaa5..8561f537f3d32 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: "pre.rust.fn > code"
+assert: ".item-decl pre.rust > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-assert: "pre.rust.struct > code"
+assert: ".item-decl pre.rust > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
-assert: "pre.rust.enum > code"
+assert: ".item-decl pre.rust > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
-assert: "pre.rust.trait > code"
+assert: ".item-decl pre.rust > code"
 
 goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
-assert: "pre.rust.typedef > code"
+assert: ".item-decl pre.rust > code"
diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml
index 8ba005b0c35a0..fafb156317866 100644
--- a/tests/rustdoc-gui/font-weight.goml
+++ b/tests/rustdoc-gui/font-weight.goml
@@ -20,7 +20,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 trait'] — selects immediate child with tag pre and classes rust and trait
+// * /pre[@class='rust'] — selects immediate child with tag pre and class rust
 // * /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 +29,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 trait']/code/a[@class='constant']//text()/parent::*",
+    "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
     1,
 )
 assert-css: (
-    "//*[@class='item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*",
+    "//*[@class='item-decl']/pre[@class='rust']/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 3423a449de478..c527cfbfcbc56 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: ("pre.rust.fn")
+assert: (".item-decl pre.rust")
diff --git a/tests/rustdoc/array-links.rs b/tests/rustdoc/array-links.rs
index 07f92ac51b9f5..e7c0ee2de1a7a 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 - '//pre[@class="rust fn"]/code'
+// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn alpha() -> &'static [u32; 1] {
     loop {}
 }
 
 // @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//pre[@class="rust fn"]/code'
+// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn beta() -> &'static [T; 1] {
     loop {}
 }
 
 // @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//pre[@class="rust fn"]/code'
+// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn gamma() -> MyBox<[u32; 1]> {
     loop {}
 }
 
 // @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//pre[@class="rust fn"]/code'
+// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn delta() -> MyBox<[T; 1]> {
     loop {}
 }
diff --git a/tests/rustdoc/assoc-consts.rs b/tests/rustdoc/assoc-consts.rs
index 3da19a13e5331..77b139b644f3a 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 '//*[@class="rust trait"]' \
+    // @has assoc_consts/trait.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
     //      '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 a409d64131afd..ab9702a24f469 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 - '//pre[@class="rust typedef"]' 'type AsExprOf = >::Expression;'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type AsExprOf = >::Expression;'
 pub type AsExprOf = >::Expression;
diff --git a/tests/rustdoc/assoc-types.rs b/tests/rustdoc/assoc-types.rs
index a9e5b8d001928..de36c8ffeff0f 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 - '//*[@class="rust fn"]' '-> &T::Output'
-// @has - '//*[@class="rust fn"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
+// @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'
 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 - '//*[@class="rust fn"]' 'T::Input'
-// @has - '//*[@class="rust fn"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @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'
 pub fn use_input(_feed: &T, _element: T::Input) { }
 
 // @has assoc_types/fn.cmp_input.html
-// @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq'
-// @has - '//*[@class="rust fn"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @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'
 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 af765c51ace39..fb7ebb5f82239 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 '//pre[@class="rust fn"]' 'pub async fn foo() -> Option'
+// @has async_fn/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn foo() -> Option'
 pub async fn foo() -> Option {
     None
 }
 
-// @has async_fn/fn.bar.html '//pre[@class="rust fn"]' 'pub async fn bar(a: i32, b: i32) -> i32'
+// @has async_fn/fn.bar.html '//div[@class="item-decl"]/pre[@class="rust"]' '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 '//pre[@class="rust fn"]' 'pub async fn baz(a: T) -> T'
+// @has async_fn/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn baz(a: T) -> T'
 pub async fn baz(a: T) -> T {
     a
 }
 
-// @has async_fn/fn.qux.html '//pre[@class="rust fn"]' 'pub async unsafe fn qux() -> char'
+// @has async_fn/fn.qux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async unsafe fn qux() -> char'
 pub async unsafe fn qux() -> char {
     '⚠'
 }
 
-// @has async_fn/fn.mut_args.html '//pre[@class="rust fn"]' 'pub async fn mut_args(a: usize)'
+// @has async_fn/fn.mut_args.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_args(a: usize)'
 pub async fn mut_args(mut a: usize) {}
 
-// @has async_fn/fn.mut_ref.html '//pre[@class="rust fn"]' 'pub async fn mut_ref(x: i32)'
+// @has async_fn/fn.mut_ref.html '//div[@class="item-decl"]/pre[@class="rust"]' '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 '//pre[@class="rust fn"]' 'pub async fn quux() -> impl Bar'
+// @has async_fn/fn.quux.html '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust fn"]' 'pub async fn const_generics(_: impl Trait)'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust fn"]' 'pub async fn elided(foo: &str) -> &str'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust fn"]' 'pub async fn user_elided(foo: &str) -> &str'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn user_elided(foo: &str) -> &str'
 pub async fn user_elided(foo: &'_ str) -> &str {}
 // @has async_fn/fn.static_trait.html
-// @has - '//pre[@class="rust fn"]' 'pub async fn static_trait(foo: &str) -> Box'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust fn"]' "pub async fn lifetime_for_trait(foo: &str) -> Box"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "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 - '//pre[@class="rust fn"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "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 - '//pre[@class="rust fn"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "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 - '//pre[@class="rust fn"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "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/attributes.rs b/tests/rustdoc/attributes.rs
index a36dadced87d7..70e2e5c29508c 100644
--- a/tests/rustdoc/attributes.rs
+++ b/tests/rustdoc/attributes.rs
@@ -1,13 +1,13 @@
 #![crate_name = "foo"]
 
-// @has foo/fn.f.html '//*[@class="rust fn"]' '#[no_mangle]'
+// @has foo/fn.f.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[no_mangle]'
 #[no_mangle]
 pub extern "C" fn f() {}
 
-// @has foo/fn.g.html '//*[@class="rust fn"]' '#[export_name = "bar"]'
+// @has foo/fn.g.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[export_name = "bar"]'
 #[export_name = "bar"]
 pub extern "C" fn g() {}
 
-// @has foo/struct.Repr.html '//*[@class="item-decl"]' '#[repr(C, align(8))]'
+// @has foo/struct.Repr.html '//div[@class="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 45664dfc3823d..5143968bbd439 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 - '//pre[@class="rust trait"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 28eba849ace07..4366ad4d0adac 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 - '//*[@class="rust fn"]' 'pub const fn bar() -> '
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 6cbae9abebb73..b5226ad3f78bd 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 '//pre[@class="rust struct"]' 'pub struct Simd'
+// @has foo/struct.Simd.html '//div[@class="item-decl"]/pre[@class="rust"]' '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 2693d9b596993..acc3b853e5679 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 '//pre[@class="rust struct"]' \
+// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 5bf76e3c46908..543332d2c320b 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 '//pre[@class="rust fn"]' \
+// @has foo/fn.extern_fn.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub fn extern_fn() -> impl Iterator'
 pub use extern_crate::extern_fn;
-// @has foo/struct.ExternTy.html '//pre[@class="rust struct"]' \
+// @has foo/struct.ExternTy.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub struct ExternTy {'
 pub use extern_crate::ExternTy;
-// @has foo/type.TyAlias.html '//pre[@class="rust typedef"]' \
+// @has foo/type.TyAlias.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'type TyAlias = ExternTy;'
 pub use extern_crate::TyAlias;
-// @has foo/trait.WTrait.html '//pre[@class="rust trait"]' \
+// @has foo/trait.WTrait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub trait WTrait'
-// @has - '//*[@class="rust trait"]' 'fn hey() -> usize'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn hey() -> usize'
 pub use extern_crate::WTrait;
 
-// @has foo/trait.Trait.html '//pre[@class="rust trait"]' \
+// @has foo/trait.Trait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 '//pre[@class="rust struct"]' \
+// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub struct Foowhere u8: Trait'
 pub struct Foo where u8: Trait;
-// @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar(_)'
+// @has foo/struct.Bar.html '//div[@class="item-decl"]/pre[@class="rust"]' '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 '//pre[@class="rust fn"]' \
+// @has foo/fn.test.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub fn test() -> impl Traitwhere u8: Trait'
 pub fn test() -> impl Trait where u8: Trait {
     2u8
 }
 
-// @has foo/fn.a_sink.html '//pre[@class="rust fn"]' \
+// @has foo/fn.a_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 '//pre[@class="rust fn"]' \
+// @has foo/fn.b_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub async fn b_sink(_: impl Trait)'
 pub async fn b_sink(_: impl Trait) {}
 
-// @has foo/fn.concrete.html '//pre[@class="rust fn"]' \
+// @has foo/fn.concrete.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'pub fn concrete() -> [u8; 22]'
 pub fn concrete() -> [u8; 3 + std::mem::size_of::() << 1] {
     Default::default()
 }
 
-// @has foo/type.Faz.html '//pre[@class="rust typedef"]' \
+// @has foo/type.Faz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      'type Faz = [u8; N];'
 pub type Faz = [u8; N];
-// @has foo/type.Fiz.html '//pre[@class="rust typedef"]' \
+// @has foo/type.Fiz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 '//pre[@class="rust struct"]' \
+// @has foo/struct.Foz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 '//pre[@class="rust fn"]' \
+// @has foo/fn.q_user.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 '//pre[@class="rust union"]' \
+// @has foo/union.Union.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 '//pre[@class="rust enum"]' \
+// @has foo/enum.Enum.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 75ee84279be3c..726fb8f0c3416 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 '//pre[@class="rust struct"]' 'pub struct VSet'
+// @has foo/struct.VSet.html '//div[@class="item-decl"]/pre[@class="rust"]' '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 215ee228eb857..c53cf6dcd0570 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 '//pre[@class="rust struct"]' \
+// @has foo/struct.Ice.html '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 ebda5b1940455..72473a112440c 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 '//pre[@class="rust typedef"]' 'type CellIndex = [i64; D];'
+// @has foo/type.CellIndex.html '//div[@class="item-decl"]/pre[@class="rust"]' 'type CellIndex = [i64; D];'
 pub type CellIndex = [i64; D];
diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs
index 2fc486d01dae0..42f6ac7923bf2 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 - '//pre[@class="rust fn"]' 'pub const unsafe extern "rust-intrinsic" fn transmute(_: T) -> U'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
     #[stable(since="1.0.0", feature="rust1")]
     pub fn needs_drop() -> !;
 }
diff --git a/tests/rustdoc/fn-pointer-arg-name.rs b/tests/rustdoc/fn-pointer-arg-name.rs
index 4293d849df52c..96c64ac4e0211 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 - '//*[@class="rust fn"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 644a6e1cf33c5..406157ce26c80 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 \
-//      '//*[@class="rust trait"]' \
+//      '//div[@class="item-decl"]/pre[@class="rust"]' \
 //      '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 c97644e7f8723..a4ca928f3331b 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 - '//*[@class="rust trait"]' 'fn bar(&self);'
-// @has - '//*[@class="rust trait"]' 'fn foo(&mut self) { ... }'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(&self);'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 fa760540e4365..0da8bfc3a9ae3 100644
--- a/tests/rustdoc/inline_cross/dyn_trait.rs
+++ b/tests/rustdoc/inline_cross/dyn_trait.rs
@@ -22,10 +22,10 @@ pub use dyn_trait::Ty2;
 pub use dyn_trait::Ty3;
 
 // @has user/fn.func0.html
-// @has - '//pre[@class="rust fn"]' "func0(_: &dyn Fn())"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func0(_: &dyn Fn())"
 // FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
 pub use dyn_trait::func0;
 
 // @has user/fn.func1.html
-// @has - '//pre[@class="rust fn"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "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 9c4f646592038..e8587209b6165 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 - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)"
-// @!has - '//pre[@class="rust fn"]' 'where'
+// @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'
 pub use impl_trait_aux::func;
 
 // @has impl_trait/fn.func2.html
-// @has - '//pre[@class="rust fn"]' "func2("
-// @has - '//pre[@class="rust fn"]' "_x: impl Deref> + Iterator,"
-// @has - '//pre[@class="rust fn"]' "_y: impl Iterator)"
-// @!has - '//pre[@class="rust fn"]' 'where'
+// @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'
 pub use impl_trait_aux::func2;
 
 // @has impl_trait/fn.func3.html
-// @has - '//pre[@class="rust fn"]' "func3("
-// @has - '//pre[@class="rust fn"]' "_x: impl Iterator> + Clone)"
-// @!has - '//pre[@class="rust fn"]' 'where'
+// @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'
 pub use impl_trait_aux::func3;
 
 // @has impl_trait/fn.func4.html
-// @has - '//pre[@class="rust fn"]' "func4("
-// @has - '//pre[@class="rust fn"]' "T: Iterator,"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func4("
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "T: Iterator,"
 pub use impl_trait_aux::func4;
 
 // @has impl_trait/fn.func5.html
-// @has - '//pre[@class="rust fn"]' "func5("
-// @has - '//pre[@class="rust fn"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>,"
-// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
-// @!has - '//pre[@class="rust fn"]' 'where'
+// @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'
 pub use impl_trait_aux::func5;
 
 // @has impl_trait/fn.async_fn.html
-// @has - '//pre[@class="rust fn"]' "pub async fn async_fn()"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn async_fn()"
 pub use impl_trait_aux::async_fn;
 
 // @has impl_trait/struct.Foo.html
diff --git a/tests/rustdoc/issue-20646.rs b/tests/rustdoc/issue-20646.rs
index 2589e27f21502..a774b0ca7cd7a 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 \
-//      '//*[@class="rust fn"]' 'where T: Trait'
+//      '//div[@class="item-decl"]/pre[@class="rust"]' '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 \
-    //      '//*[@class="rust fn"]' 'where T: Trait'
+    //      '//div[@class="item-decl"]/pre[@class="rust"]' '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 022ff290e1a71..026b4f5acc912 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 - '//*[@class="rust trait"]' 'trait Add {'
-    // @has - '//*[@class="rust trait"]' 'type Output;'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add {'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
     type Output;
 
-    // @has - '//*[@class="rust trait"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//*[@class="rust trait"]' 'trait Add {'
-    // @has - '//*[@class="rust trait"]' 'type Output;'
-    // @has - '//*[@class="rust trait"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+    // @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;'
     pub use issue_20727::Add;
 }
diff --git a/tests/rustdoc/issue-20727-3.rs b/tests/rustdoc/issue-20727-3.rs
index 52032b75aeaf5..741ce8023d7e7 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 - '//*[@class="rust trait"]' 'trait Deref2 {'
-    // @has - '//*[@class="rust trait"]' 'type Target: Bar;'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
     type Target: Bar;
 
-    // @has - '//*[@class="rust trait"]' 'fn deref(&self) -> Self::Target;'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
     fn deref(&self) -> Self::Target;
 }
 
 // @has issue_20727_3/reexport/trait.Deref2.html
 pub mod reexport {
-    // @has - '//*[@class="rust trait"]' 'trait Deref2 {'
-    // @has - '//*[@class="rust trait"]' 'type Target: Bar;'
-    // @has - '//*[@class="rust trait"]' 'fn deref(&self) -> Self::Target;'
+    // @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;'
     pub use issue_20727::Deref2;
 }
diff --git a/tests/rustdoc/issue-20727-4.rs b/tests/rustdoc/issue-20727-4.rs
index 643f938759093..b8fac4da6eadf 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 - '//*[@class="rust trait"]' 'trait Index {'
-    // @has - '//*[@class="rust trait"]' 'type Output: ?Sized'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index {'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
     type Output: ?Sized;
 
-    // @has - '//*[@class="rust trait"]' \
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
     //        '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 - '//*[@class="rust trait"]' \
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
     //        'trait IndexMut: Index {'
-    // @has - '//*[@class="rust trait"]' \
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
     //        '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 - '//*[@class="rust trait"]' 'trait Indexwhere Idx: ?Sized,{'
-    // @has - '//*[@class="rust trait"]' 'type Output: ?Sized'
-    // @has - '//*[@class="rust trait"]' \
+    // @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"]' \
     //        'fn index(&self, index: Idx) -> &Self::Output'
     pub use issue_20727::Index;
 
     // @has issue_20727_4/reexport/trait.IndexMut.html
-    // @has - '//*[@class="rust trait"]' \
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
     //        'trait IndexMut: Indexwhere Idx: ?Sized,{'
-    // @has - '//*[@class="rust trait"]' \
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
     //        '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 c1a98cd57daf8..df334821cccc9 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 - '//*[@class="rust trait"]' 'trait Deref {'
-    // @has - '//*[@class="rust trait"]' 'type Target: ?Sized;'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
     type Target: ?Sized;
 
-    // @has - '//*[@class="rust trait"]' \
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
     //        "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 - '//*[@class="rust trait"]' 'trait Deref {'
-    // @has - '//*[@class="rust trait"]' 'type Target: ?Sized;'
-    // @has - '//*[@class="rust trait"]' \
+    // @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"]' \
     //      "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 ff5813dac8099..19e626ba13235 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 \
-    //      '//*[@class="rust fn"]' 'pub unsafe extern "C" fn foo1()'
+    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn foo1()'
     pub fn foo1();
 }
 
 extern "system" {
     // @has issue_22038/fn.foo2.html \
-    //      '//*[@class="rust fn"]' 'pub unsafe extern "system" fn foo2()'
+    //      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "system" fn foo2()'
     pub fn foo2();
 }
 
 // @has issue_22038/fn.bar.html \
-//      '//*[@class="rust fn"]' 'pub extern "C" fn bar()'
+//      '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "C" fn bar()'
 pub extern "C" fn bar() {}
 
 // @has issue_22038/fn.baz.html \
-//      '//*[@class="rust fn"]' 'pub extern "system" fn baz()'
+//      '//div[@class="item-decl"]/pre[@class="rust"]' '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 1e4791e01253d..b4c52e2f17a6d 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 \
-        //        '//pre[@class="rust const"]' 'pub const CST: i32'
+        //        '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const CST: i32'
         pub const CST: i32 = ($n * $n);
         // @has issue_33302/static.ST.html \
-        //        '//pre[@class="rust static"]' 'pub static ST: i32'
+        //        '//div[@class="item-decl"]/pre[@class="rust"]' '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 \
-            //        '//*[@class="rust trait"]' 'const D: i32'
+            //        '//div[@class="item-decl"]/pre[@class="rust"]' '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 3351b5c8350fd..74fc22b31dc0c 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 - '//pre[@class="rust trait"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//pre[@class="rust trait"]' 'pub trait FromResidual::Residual> { fn from_residual(residual: R) -> Self; }'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 d50268509b2c1..884b63ac97ffc 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 '//pre[@class="rust fn"]/code' 'fn repro()where F: Fn(&str)'
-// @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<'
+// @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<'
 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 46a50e2fc30b4..14533624e448e 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 - '//*[@class="rust fn"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 - '//*[@class="rust fn"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 5d30a745a61a6..0fb6605910907 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 - '//*[@class="rust typedef"]' "pub type Resolutions<'tcx> = &'tcx u8;"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub type Resolutions<'tcx> = &'tcx u8;"
 pub type Resolutions<'tcx> = &'tcx u8;
diff --git a/tests/rustdoc/mut-params.rs b/tests/rustdoc/mut-params.rs
index f3ea699583917..3b862e651c909 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 '//*[@class="rust fn"]' 1
-// @!has - '//*[@class="rust fn"]' 'mut'
+// @count foo/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 1
+// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'mut'
 pub fn baz(mut foo: Foo) {}
diff --git a/tests/rustdoc/normalize-assoc-item.rs b/tests/rustdoc/normalize-assoc-item.rs
index db56f68526b3f..659480479fd13 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' '//pre[@class="rust fn"]' 'pub fn f() -> isize'
+// @has 'normalize_assoc_item/fn.f.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f() -> isize'
 pub fn f() -> ::X {
     0
 }
 
-// @has 'normalize_assoc_item/fn.f2.html' '//pre[@class="rust fn"]' 'pub fn f2() -> fn() -> i32'
+// @has 'normalize_assoc_item/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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' '//pre[@class="rust struct"]' 'pub struct Unknown(pub ::X);'
+// @has 'normalize_assoc_item/struct.Unknown.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown(pub ::X);'
 pub struct Unknown(pub ::X);
 
-// @has 'normalize_assoc_item/struct.Unknown2.html' '//pre[@class="rust struct"]' 'pub struct Unknown2(pub Inner::X);'
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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' '//pre[@class="rust fn"]' "pub fn g() -> &isize"
+// @has 'normalize_assoc_item/fn.g.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn g() -> &isize"
 pub fn g() -> >::Y {
     &0
 }
 
-// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust const"]' "pub const A: &isize"
+// @has 'normalize_assoc_item/constant.A.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub const A: &isize"
 pub const A: >::Y = &0;
 
 // test cross-crate re-exports
 extern crate inner;
-// @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust fn"]' "pub fn foo() -> i32"
+// @has 'normalize_assoc_item/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn foo() -> i32"
 pub use inner::foo;
 
-// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust fn"]' "pub fn h() -> IntoIter"
+// @has 'normalize_assoc_item/fn.h.html' '//div[@class="item-decl"]/pre[@class="rust"]' "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 fa7de0aff6a22..0dca3f672cd3c 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 - '//*[@class="rust fn"]' 'pub fn bar() -> '
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 756939ae3773c..bdbcc47c9f28d 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 - '//*[@class="rust fn"]' 'pub fn f(_: u8)'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(_: u8)'
 pub fn f(0u8..=255: u8) {}
diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexports-priv.rs
index 11364e7f707ef..35c90ba5d7b89 100644
--- a/tests/rustdoc/reexports-priv.rs
+++ b/tests/rustdoc/reexports-priv.rs
@@ -32,7 +32,7 @@ pub(self) use reexports::BarSelf;
 // @!has 'foo/enum.BarLocal.html'
 use reexports::BarLocal;
 
-// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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' '//*[@class="rust typedef"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
 pub use reexports::Type;
 // @!has 'foo/type.TypeCrate.html'
 pub(crate) use reexports::TypeCrate;
@@ -94,22 +94,22 @@ pub mod outer {
         // @!has 'foo/outer/inner/enum.BarLocal.html'
         use reexports::BarLocal;
 
-        // @has 'foo/outer/inner/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+        // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
         pub use reexports::foo;
-        // @has 'foo/outer/inner/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()'
+        // @has 'foo/outer/inner/fn.foo_crate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) fn foo_crate()'
         pub(crate) use reexports::foo_crate;
-        // @has 'foo/outer/inner/fn.foo_super.html' '//*[@class="rust fn"]' 'pub(in outer) fn foo_super()'
+        // @has 'foo/outer/inner/fn.foo_super.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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' '//*[@class="rust typedef"]' 'pub type Type ='
+        // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
         pub use reexports::Type;
-        // @has 'foo/outer/inner/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate ='
+        // @has 'foo/outer/inner/type.TypeCrate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) type TypeCrate ='
         pub(crate) use reexports::TypeCrate;
-        // @has 'foo/outer/inner/type.TypeSuper.html' '//*[@class="rust typedef"]' 'pub(in outer) type TypeSuper ='
+        // @has 'foo/outer/inner/type.TypeSuper.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) type TypeSuper ='
         pub(super) use reexports::TypeSuper;
         // @!has 'foo/outer/inner/type.TypeSelf.html'
         pub(self) use reexports::TypeSelf;
diff --git a/tests/rustdoc/reexports.rs b/tests/rustdoc/reexports.rs
index 9aa6d7224baca..65d305c6d2c42 100644
--- a/tests/rustdoc/reexports.rs
+++ b/tests/rustdoc/reexports.rs
@@ -31,7 +31,7 @@ pub(self) use reexports::BarSelf;
 // @!has 'foo/enum.BarLocal.html'
 use reexports::BarLocal;
 
-// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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' '//*[@class="rust typedef"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
 pub use reexports::Type;
 // @!has 'foo/type.TypeCrate.html'
 pub(crate) use reexports::TypeCrate;
@@ -93,7 +93,7 @@ pub mod outer {
         // @!has 'foo/outer/inner/enum.BarLocal.html'
         use reexports::BarLocal;
 
-        // @has 'foo/outer/inner/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+        // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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' '//*[@class="rust typedef"]' 'pub type Type ='
+        // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
         pub use reexports::Type;
         // @!has 'foo/outer/inner/type.TypeCrate.html'
         pub(crate) use reexports::TypeCrate;
diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs
index 7ed9d6729b647..a229a4e29fefb 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 '//pre[@class="rust trait"]/code/a[@class="trait"]' '~const'
-// @has - '//pre[@class="rust trait"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//pre[@class="rust trait"]/code/span[@class="where"]' '~const'
-// @has - '//pre[@class="rust trait"]/code/span[@class="where"]' ': Clone'
+// @!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'
 #[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 '//pre[@class="rust fn"]/code/a[@class="trait"]' '~const'
-// @has - '//pre[@class="rust fn"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' '~const'
-// @has - '//pre[@class="rust fn"]/code/span[@class="where fmt-newline"]' ': Clone'
+// @!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'
 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 d08abdaeb1411..0b65bf1dfed0f 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 - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "rust-intrinsic" fn abort() -> !'
     #[rustc_safe_intrinsic]
     pub fn abort() -> !;
     // @has 'foo/fn.unreachable.html'
-    // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
     pub fn unreachable() -> !;
 }
 
 extern "C" {
     // @has 'foo/fn.needs_drop.html'
-    // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+    // @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 9a78e963e3036..67137fdcab274 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 - '//pre[@class="rust fn"]/code'
+// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn alpha() -> &'static [u32] {
     loop {}
 }
 
 // @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//pre[@class="rust fn"]/code'
+// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn beta() -> &'static [T] {
     loop {}
 }
 
 // @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//pre[@class="rust fn"]/code'
+// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn gamma() -> MyBox<[u32]> {
     loop {}
 }
 
 // @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//pre[@class="rust fn"]/code'
+// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn delta() -> MyBox<[T]> {
     loop {}
 }
diff --git a/tests/rustdoc/struct-arg-pattern.rs b/tests/rustdoc/struct-arg-pattern.rs
index 3c0369e3d3413..3bfb43a0bef2c 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' '//*[@class="rust fn"]' 'pub fn body_owner(_: BodyId)'
+// @has 'foo/fn.body_owner.html' '//div[@class="item-decl"]/pre[@class="rust"]' '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 d9b9c7957d9a1..f5fdb1f52bf8e 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 - '//*[@class="rust fn"]' "_: &(dyn ToString + 'static)"
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_: &(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 87240f233ff2a..5d34ec09b66dc 100644
--- a/tests/rustdoc/toggle-item-contents.rs
+++ b/tests/rustdoc/toggle-item-contents.rs
@@ -81,8 +81,8 @@ pub enum EnumStructVariant {
 }
 
 // @has 'toggle_item_contents/enum.LargeEnum.html'
-// @count - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 1
-// @has - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
+// @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'
 pub enum LargeEnum {
     A, B, C, D, E, F(u8), G, H, I, J, K, L, M
 }
diff --git a/tests/rustdoc/tuple-struct-fields-doc.rs b/tests/rustdoc/tuple-struct-fields-doc.rs
index 8ab1143d1f70e..d72c10f2b2542 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 - '//pre[@class="rust enum"]' 'BarVariant(String),'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 62e2f9e7ef244..e716de8b55c8f 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 - '//pre[@class="rust fn"]/code'
+// @snapshot link_unit - '//div[@class="item-decl"]/pre[@class="rust"]/code'
 pub fn tuple0(x: ()) -> () { x }
 // @has foo/fn.tuple1.html //pre 'pub fn tuple1(x: (i32,)) -> (i32,)'
-// @snapshot link1_i32 - '//pre[@class="rust fn"]/code'
+// @snapshot link1_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/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 - '//pre[@class="rust fn"]/code'
+// @snapshot link2_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/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 - '//pre[@class="rust fn"]/code'
+// @snapshot link1_t - '//div[@class="item-decl"]/pre[@class="rust"]/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 - '//pre[@class="rust fn"]/code'
+// @snapshot link2_t - '//div[@class="item-decl"]/pre[@class="rust"]/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 - '//pre[@class="rust fn"]/code'
+// @snapshot link2_tu - '//div[@class="item-decl"]/pre[@class="rust"]/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 ae3a6031519fb..353cd1c477249 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' '//*[@class="rust fn"]' 'F: FnMut(u8) + Clone'
+// @has 'foo/fn.f0.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u8) + Clone'
 pub fn f0(f: F) {}
 
-// @has 'foo/fn.f1.html' '//*[@class="rust fn"]' 'F: FnMut(u16) + Clone'
+// @has 'foo/fn.f1.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u16) + Clone'
 pub fn f1 () + Clone>(f: F) {}
 
-// @has 'foo/fn.f2.html' '//*[@class="rust fn"]' 'F: FnMut(u32) + Clone'
+// @has 'foo/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u32) + Clone'
 pub use unit_return::f2;
 
-// @has 'foo/fn.f3.html' '//*[@class="rust fn"]' 'F: FnMut(u64) + Clone'
+// @has 'foo/fn.f3.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u64) + Clone'
 pub use unit_return::f3;
diff --git a/tests/rustdoc/where-sized.rs b/tests/rustdoc/where-sized.rs
index fe7cad8c3ef84..c0c085e6ac725 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 - '//*[@class="rust fn"]' 'pub fn foo(_: &X)'
-// @has - '//*[@class="rust fn"]' 'where X: ?Sized,'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo(_: &X)'
+// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '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 6c1b5d3151352..f84cb3753cb93 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 d5d6c556d8001..85b626674274c 100644 --- a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html +++ b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html @@ -1,4 +1,4 @@ -
pub trait TraitWhere {
+
pub trait TraitWhere {
     type Item<'a>
    where
        Self: 'a
; fn func(self)
    where
        Self: Sized
, diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs index 8b5bce28f5a2a..3ac0c6872a821 100644 --- a/tests/rustdoc/where.rs +++ b/tests/rustdoc/where.rs @@ -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 '//pre[@class="rust typedef"]' \ +// @has foo/type.Golf.html '//div[@class="item-decl"]/pre[@class="rust"]' \ // "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 f7663e4616ae6..20bde549a0378 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 diff --git a/tests/rustdoc/whitespace-after-where-clause.enum2.html b/tests/rustdoc/whitespace-after-where-clause.enum2.html index ac7d775982110..d9fc0c22309db 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 diff --git a/tests/rustdoc/whitespace-after-where-clause.struct.html b/tests/rustdoc/whitespace-after-where-clause.struct.html index fa3f224e7ad0f..f375265d7c183 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 diff --git a/tests/rustdoc/whitespace-after-where-clause.struct2.html b/tests/rustdoc/whitespace-after-where-clause.struct2.html index fb06b0f77c5ce..1c59962eb1c58 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 diff --git a/tests/rustdoc/whitespace-after-where-clause.trait.html b/tests/rustdoc/whitespace-after-where-clause.trait.html index 50cfe362328b6..a2df06e7736af 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait.html @@ -1,4 +1,4 @@ -
pub trait ToOwned<T>where
    T: Clone,
{ +
pub trait ToOwned<T>where
    T: Clone,
{ type Owned; fn to_owned(&self) -> Self::Owned; diff --git a/tests/rustdoc/whitespace-after-where-clause.trait2.html b/tests/rustdoc/whitespace-after-where-clause.trait2.html index 21eb89b75011b..2bfd6f7685a67 100644 --- a/tests/rustdoc/whitespace-after-where-clause.trait2.html +++ b/tests/rustdoc/whitespace-after-where-clause.trait2.html @@ -1,4 +1,4 @@ -
pub trait ToOwned2<T: Clone> {
+
pub trait ToOwned2<T: Clone> {
     type Owned;
 
     fn to_owned(&self) -> Self::Owned;
diff --git a/tests/rustdoc/whitespace-after-where-clause.union.html b/tests/rustdoc/whitespace-after-where-clause.union.html
index 7bb177debc3a8..066f8f87b160b 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 diff --git a/tests/rustdoc/whitespace-after-where-clause.union2.html b/tests/rustdoc/whitespace-after-where-clause.union2.html index 0d237df53c7f4..6b48c5dbd3e28 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 diff --git a/tests/rustdoc/wrapping.rs b/tests/rustdoc/wrapping.rs index 8d8221bcdf293..178b8adc3f04a 100644 --- a/tests/rustdoc/wrapping.rs +++ b/tests/rustdoc/wrapping.rs @@ -1,5 +1,5 @@ use std::fmt::Debug; -// @has 'wrapping/fn.foo.html' '//pre[@class="rust fn"]' 'pub fn foo() -> impl Debug' -// @count - '//pre[@class="rust fn"]/br' 0 +// @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 pub fn foo() -> impl Debug {} From e590b934998c85175b85cb13842163a27a221dc7 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sat, 14 Jan 2023 21:20:20 +1300 Subject: [PATCH 4/9] make error emitted on `impl &Trait` nicer --- compiler/rustc_ast/src/ast.rs | 3 +- compiler/rustc_parse/src/parser/ty.rs | 39 +++++++++-- tests/ui/generics/issue-106694.rs | 24 +++++++ tests/ui/generics/issue-106694.stderr | 93 +++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 tests/ui/generics/issue-106694.rs create mode 100644 tests/ui/generics/issue-106694.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7de594719ddc4..9317579f70dd5 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2032,7 +2032,8 @@ impl Clone for Ty { impl Ty { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, MutTy { ty, .. }) | TyKind::Ptr(MutTy { ty, .. }) = &final_ty.kind + { final_ty = ty; } final_ty diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a6f702e542869..aedebd0fb7062 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -727,11 +727,13 @@ impl<'a> Parser<'a> { let mut bounds = Vec::new(); let mut negative_bounds = Vec::new(); + // In addition to looping while we find generic bounds: + // We continue even if we find a keyword. This is necessary for error recovery on, + // for example, `impl fn()`. The only keyword that can go after generic bounds is + // `where`, so stop if it's it. + // We also continue if we find types (not traits), again for error recovery. while self.can_begin_bound() - // Continue even if we find a keyword. - // This is necessary for error recover on, for example, `impl fn()`. - // - // The only keyword that can go after generic bounds is `where`, so stop if it's it. + || self.token.can_begin_type() || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)) { if self.token.is_keyword(kw::Dyn) { @@ -938,6 +940,35 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) && let Some(path) = self.recover_path_from_fn() { + path + } else if !self.token.is_path_start() && self.token.can_begin_type() && let Ok(ty) = self.parse_ty_no_plus() { + // Instead of finding a path (a trait), we found a type. + let mut err = self.struct_span_err(ty.span, "expected a trait, found type"); + + // If we can recover, try to extract a path from the type. Note + // that we do not use the try operator when parsing the type because + // if it fails then we get a parser error which we don't want (we're trying + // to recover from errors, not make more). + let path = if self.may_recover() + && matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..)) + && let TyKind::Path(_, path) = &ty.peel_refs().kind { + // Just get the indirection part of the type. + let span = ty.span.until(path.span); + + err.span_suggestion_verbose( + span, + "consider removing the indirection", + "", + Applicability::MaybeIncorrect, + ); + + path.clone() + } else { + return Err(err); + }; + + err.emit(); + path } else { self.parse_path(PathStyle::Type)? diff --git a/tests/ui/generics/issue-106694.rs b/tests/ui/generics/issue-106694.rs new file mode 100644 index 0000000000000..c4b02ee81ec8f --- /dev/null +++ b/tests/ui/generics/issue-106694.rs @@ -0,0 +1,24 @@ +trait Trait {} + +fn foo(_: impl &Trait) {} +//~^ ERROR expected a trait, found type + +fn bar(_: T) {} +//~^ ERROR expected a trait, found type + +fn partially_correct_impl(_: impl &*const &Trait + Copy) {} +//~^ ERROR expected a trait, found type + +fn foo_bad(_: impl &BadTrait) {} +//~^ ERROR expected a trait, found type +//~^^ ERROR cannot find trait `BadTrait` in this scope + +fn bar_bad(_: T) {} +//~^ ERROR expected a trait, found type +//~^^ ERROR cannot find trait `BadTrait` in this scope + +fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} +//~^ ERROR expected a trait, found type +//~^^ ERROR cannot find trait `BadTrait` in this scope + +fn main() {} diff --git a/tests/ui/generics/issue-106694.stderr b/tests/ui/generics/issue-106694.stderr new file mode 100644 index 0000000000000..235b8982a99c6 --- /dev/null +++ b/tests/ui/generics/issue-106694.stderr @@ -0,0 +1,93 @@ +error: expected a trait, found type + --> $DIR/issue-106694.rs:3:16 + | +LL | fn foo(_: impl &Trait) {} + | ^^^^^^ + | +help: consider removing the indirection + | +LL - fn foo(_: impl &Trait) {} +LL + fn foo(_: impl Trait) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:6:11 + | +LL | fn bar(_: T) {} + | ^^^^^^ + | +help: consider removing the indirection + | +LL - fn bar(_: T) {} +LL + fn bar(_: T) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:9:35 + | +LL | fn partially_correct_impl(_: impl &*const &Trait + Copy) {} + | ^^^^^^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn partially_correct_impl(_: impl &*const &Trait + Copy) {} +LL + fn partially_correct_impl(_: impl Trait + Copy) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:12:20 + | +LL | fn foo_bad(_: impl &BadTrait) {} + | ^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn foo_bad(_: impl &BadTrait) {} +LL + fn foo_bad(_: impl BadTrait) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:16:15 + | +LL | fn bar_bad(_: T) {} + | ^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn bar_bad(_: T) {} +LL + fn bar_bad(_: T) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:20:39 + | +LL | fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} + | ^^^^^^^^^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} +LL + fn partially_correct_impl_bad(_: impl BadTrait + Copy) {} + | + +error[E0405]: cannot find trait `BadTrait` in this scope + --> $DIR/issue-106694.rs:12:21 + | +LL | fn foo_bad(_: impl &BadTrait) {} + | ^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `BadTrait` in this scope + --> $DIR/issue-106694.rs:16:16 + | +LL | fn bar_bad(_: T) {} + | ^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `BadTrait` in this scope + --> $DIR/issue-106694.rs:20:48 + | +LL | fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} + | ^^^^^^^^ not found in this scope + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0405`. From fcd5ed21b77dd1d72696e43dd70e60b1ad458f55 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 16 Jan 2023 16:18:56 +1300 Subject: [PATCH 5/9] fix dropping diagnostic without emit --- compiler/rustc_parse/src/parser/ty.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index aedebd0fb7062..1766b0293de52 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -941,7 +941,8 @@ impl<'a> Parser<'a> { && let Some(path) = self.recover_path_from_fn() { path - } else if !self.token.is_path_start() && self.token.can_begin_type() && let Ok(ty) = self.parse_ty_no_plus() { + } else if !self.token.is_path_start() && self.token.can_begin_type() { + let ty = self.parse_ty_no_plus()?; // Instead of finding a path (a trait), we found a type. let mut err = self.struct_span_err(ty.span, "expected a trait, found type"); From fdaac4e48ea276a595a7cdd08f4801763dfbb6cf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 16 Jan 2023 19:55:20 +0000 Subject: [PATCH 6/9] ConstBlocks are poly if their substs are poly --- compiler/rustc_ty_utils/src/consts.rs | 44 ++++++++++++++++++- .../const-block-is-poly.rs | 11 +++++ .../const-block-is-poly.stderr | 20 +++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index a9b4e1420ea0d..a9fbad55dac55 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -302,13 +302,53 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { } match expr.kind { - thir::ExprKind::NamedConst { substs, .. } => substs.has_non_region_param(), + thir::ExprKind::NamedConst { substs, .. } + | thir::ExprKind::ConstBlock { substs, .. } => substs.has_non_region_param(), thir::ExprKind::ConstParam { .. } => true, thir::ExprKind::Repeat { value, count } => { self.visit_expr(&self.thir()[value]); count.has_non_region_param() } - _ => false, + thir::ExprKind::Scope { .. } + | thir::ExprKind::Box { .. } + | thir::ExprKind::If { .. } + | thir::ExprKind::Call { .. } + | thir::ExprKind::Deref { .. } + | thir::ExprKind::Binary { .. } + | thir::ExprKind::LogicalOp { .. } + | thir::ExprKind::Unary { .. } + | thir::ExprKind::Cast { .. } + | thir::ExprKind::Use { .. } + | thir::ExprKind::NeverToAny { .. } + | thir::ExprKind::Pointer { .. } + | thir::ExprKind::Loop { .. } + | thir::ExprKind::Let { .. } + | thir::ExprKind::Match { .. } + | thir::ExprKind::Block { .. } + | thir::ExprKind::Assign { .. } + | thir::ExprKind::AssignOp { .. } + | thir::ExprKind::Field { .. } + | thir::ExprKind::Index { .. } + | thir::ExprKind::VarRef { .. } + | thir::ExprKind::UpvarRef { .. } + | thir::ExprKind::Borrow { .. } + | thir::ExprKind::AddressOf { .. } + | thir::ExprKind::Break { .. } + | thir::ExprKind::Continue { .. } + | thir::ExprKind::Return { .. } + | thir::ExprKind::Array { .. } + | thir::ExprKind::Tuple { .. } + | thir::ExprKind::Adt(_) + | thir::ExprKind::PlaceTypeAscription { .. } + | thir::ExprKind::ValueTypeAscription { .. } + | thir::ExprKind::Closure(_) + | thir::ExprKind::Literal { .. } + | thir::ExprKind::NonHirLiteral { .. } + | thir::ExprKind::ZstLiteral { .. } + | thir::ExprKind::StaticRef { .. } + | thir::ExprKind::InlineAsm(_) + | thir::ExprKind::ThreadLocalRef(_) + | thir::ExprKind::Yield { .. } => false, } } fn pat_is_poly(&mut self, pat: &thir::Pat<'tcx>) -> bool { diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs new file mode 100644 index 0000000000000..7332a8f03c05f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs @@ -0,0 +1,11 @@ +#![feature(inline_const, generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +fn foo() { + let _ = [0u8; const { std::mem::size_of::() }]; + //~^ ERROR: overly complex generic constant +} + +fn main() { + foo::(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr new file mode 100644 index 0000000000000..1513e491b9b99 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -0,0 +1,20 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-block-is-poly.rs:1:26 + | +LL | #![feature(inline_const, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: overly complex generic constant + --> $DIR/const-block-is-poly.rs:5:19 + | +LL | let _ = [0u8; const { std::mem::size_of::() }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const blocks are not supported in generic constant + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error; 1 warning emitted + From 9f6fef96571f52b3e4320cfcb906dfdc66eac1c3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 16 Jan 2023 20:21:29 +0000 Subject: [PATCH 7/9] Properly pluralize 'generic constants' --- .../rustc_error_messages/locales/en-US/ty_utils.ftl | 12 ++++++------ .../array-size-in-generic-struct-param.full.stderr | 2 +- .../generic_const_exprs/const-block-is-poly.stderr | 2 +- .../generic_const_exprs/let-bindings.stderr | 4 ++-- .../generic_const_exprs/unused_expr.stderr | 6 +++--- .../const-generics/issues/issue-67945-2.full.stderr | 2 +- .../const-generics/issues/issue-67945-3.full.stderr | 2 +- .../const-generics/issues/issue-67945-4.full.stderr | 2 +- tests/ui/const-generics/issues/issue-77357.stderr | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/ty_utils.ftl b/compiler/rustc_error_messages/locales/en-US/ty_utils.ftl index 1040ee1c97d81..abe65a0e3fef0 100644 --- a/compiler/rustc_error_messages/locales/en-US/ty_utils.ftl +++ b/compiler/rustc_error_messages/locales/en-US/ty_utils.ftl @@ -10,17 +10,17 @@ ty_utils_address_and_deref_not_supported = dereferencing or taking the address i ty_utils_array_not_supported = array construction is not supported in generic constants -ty_utils_block_not_supported = blocks are not supported in generic constant +ty_utils_block_not_supported = blocks are not supported in generic constants -ty_utils_never_to_any_not_supported = converting nevers to any is not supported in generic constant +ty_utils_never_to_any_not_supported = converting nevers to any is not supported in generic constants ty_utils_tuple_not_supported = tuple construction is not supported in generic constants -ty_utils_index_not_supported = indexing is not supported in generic constant +ty_utils_index_not_supported = indexing is not supported in generic constants -ty_utils_field_not_supported = field access is not supported in generic constant +ty_utils_field_not_supported = field access is not supported in generic constants -ty_utils_const_block_not_supported = const blocks are not supported in generic constant +ty_utils_const_block_not_supported = const blocks are not supported in generic constants ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants @@ -44,4 +44,4 @@ ty_utils_control_flow_not_supported = control flow is not supported in generic c ty_utils_inline_asm_not_supported = assembly is not supported in generic constants -ty_utils_operation_not_supported = unsupported operation in generic constant +ty_utils_operation_not_supported = unsupported operation in generic constants diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr index 041232e869079..1d10dfdf10c6e 100644 --- a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -10,7 +10,7 @@ error: overly complex generic constant --> $DIR/array-size-in-generic-struct-param.rs:19:15 | LL | arr: [u8; CFG.arr_size], - | ^^^^^^^^^^^^ field access is not supported in generic constant + | ^^^^^^^^^^^^ field access is not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr index 1513e491b9b99..f262599084015 100644 --- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -11,7 +11,7 @@ error: overly complex generic constant --> $DIR/const-block-is-poly.rs:5:19 | LL | let _ = [0u8; const { std::mem::size_of::() }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const blocks are not supported in generic constant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr index 5ebb4c3999c36..823a4f8a185bb 100644 --- a/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -2,7 +2,7 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:68 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future @@ -11,7 +11,7 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:35 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr index df73acf53de65..265a3b9d23341 100644 --- a/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -2,7 +2,7 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:4:34 | LL | fn add() -> [u8; { N + 1; 5 }] { - | ^^^^^^^^^^^^ blocks are not supported in generic constant + | ^^^^^^^^^^^^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future @@ -11,7 +11,7 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:9:34 | LL | fn div() -> [u8; { N / 1; 5 }] { - | ^^^^^^^^^^^^ blocks are not supported in generic constant + | ^^^^^^^^^^^^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future @@ -20,7 +20,7 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:16:38 | LL | fn fn_call() -> [u8; { foo(N); 5 }] { - | ^^^^^^^^^^^^^ blocks are not supported in generic constant + | ^^^^^^^^^^^^^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/issues/issue-67945-2.full.stderr b/tests/ui/const-generics/issues/issue-67945-2.full.stderr index cce85772aa4da..47429b7612f94 100644 --- a/tests/ui/const-generics/issues/issue-67945-2.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-2.full.stderr @@ -8,7 +8,7 @@ LL | | let x: Option> = None; LL | | LL | | 0 LL | | }], - | |_____^ blocks are not supported in generic constant + | |_____^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/issues/issue-67945-3.full.stderr b/tests/ui/const-generics/issues/issue-67945-3.full.stderr index d3d9452d316ea..98f9f83976aa7 100644 --- a/tests/ui/const-generics/issues/issue-67945-3.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-3.full.stderr @@ -7,7 +7,7 @@ LL | | let x: Option = None; LL | | LL | | 0 LL | | }], - | |_____^ blocks are not supported in generic constant + | |_____^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/issues/issue-67945-4.full.stderr b/tests/ui/const-generics/issues/issue-67945-4.full.stderr index 9604eb35d02b2..c03d40a7bb832 100644 --- a/tests/ui/const-generics/issues/issue-67945-4.full.stderr +++ b/tests/ui/const-generics/issues/issue-67945-4.full.stderr @@ -7,7 +7,7 @@ LL | | let x: Option> = None; LL | | LL | | 0 LL | | }], - | |_____^ blocks are not supported in generic constant + | |_____^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future diff --git a/tests/ui/const-generics/issues/issue-77357.stderr b/tests/ui/const-generics/issues/issue-77357.stderr index 804c0ae5175a8..68b35a38b0f8a 100644 --- a/tests/ui/const-generics/issues/issue-77357.stderr +++ b/tests/ui/const-generics/issues/issue-77357.stderr @@ -2,7 +2,7 @@ error: overly complex generic constant --> $DIR/issue-77357.rs:6:46 | LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant + | ^^^^^^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants | = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future From 1ae1c49c501f8c6baf662e0a8081280bb7a9e79c Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 16 Jan 2023 11:55:27 -0700 Subject: [PATCH 8/9] document EarlyBinder::subst_identity and skip_binder --- compiler/rustc_middle/src/ty/subst.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 5dc9e311bf6b1..3008c64199a11 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -538,6 +538,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List { /// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo(T)` /// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call /// `subst`. +/// +/// If you don't have anything to `subst`, you may be looking for +/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] pub struct EarlyBinder(pub T); @@ -578,6 +581,14 @@ impl EarlyBinder { EarlyBinder(value) } + /// Skips the binder and returns the "bound" value. + /// This can be used to extract data that does not depend on generic parameters + /// (e.g., getting the `DefId` of the inner value or getting the number of + /// arguments of an `FnSig`). Otherwise, consider using + /// [`subst_identity`](EarlyBinder::subst_identity). + /// + /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is + /// the analogous operation on [`super::Binder`]. pub fn skip_binder(self) -> T { self.0 } @@ -729,6 +740,14 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder { self.0.fold_with(&mut folder) } + /// Makes the identity substitution `T0 => T0, ..., TN => TN`. + /// Conceptually, this converts universally bound variables into placeholders + /// when inside of a given item. + /// + /// For example, consider `for fn foo(){ .. }`: + /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). + /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling + /// `subst_identity` to discharge the `EarlyBinder`. pub fn subst_identity(self) -> T { self.0 } From 6c763821ba80fa54fcf237b0d422aa16d2a4e6f9 Mon Sep 17 00:00:00 2001 From: jyn Date: Mon, 16 Jan 2023 18:14:44 -0600 Subject: [PATCH 9/9] Don't add A-bootstrap to PRs modifying Cargo.lock Changing Cargo.lock is common even when adding dependencies between existing rustc crates. --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 22f09396efc6a..94eb25e90cb41 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -185,7 +185,6 @@ trigger_files = [ "src/tools/x", "configure", "Cargo.toml", - "Cargo.lock", "config.toml.example", "src/stage0.json" ]