about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-01-03 22:42:57 +0000
committerbors <bors@rust-lang.org>2025-01-03 22:42:57 +0000
commit8d2c06d151972fefa3f0bbf04ace3beede737145 (patch)
treee1fe1c24240be9c85eddd25167a7ac6c4fd1ef14
parent3f43b1a636738f41c48df073c5bcb97a97bf8459 (diff)
parentc02499feb11c960e79d72c2fdfb3e42053b563ec (diff)
downloadrust-8d2c06d151972fefa3f0bbf04ace3beede737145.tar.gz
rust-8d2c06d151972fefa3f0bbf04ace3beede737145.zip
Auto merge of #135086 - matthiaskrgr:rollup-3sfnc1w, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #133420 (Switch rtems target to panic unwind)
 - #134965 (Make Boxy UwU)
 - #135007 (Some type-outlives computation tweaks)
 - #135036 (run-make-support: adjust assertion printing, add some basic sanity checks)
 - #135043 (rustdoc: treat `allowed_through_unstable_modules` as deprecation)
 - #135044 (Improve infer (`_`) suggestions in `const`s and `static`s)
 - #135058 (refactor bootstrap path resolution)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--.mailmap3
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs9
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs64
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs45
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs28
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs55
-rw-r--r--compiler/rustc_middle/src/query/mod.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs2
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs2
-rw-r--r--library/panic_unwind/src/lib.rs2
-rw-r--r--library/std/src/sys/personality/mod.rs2
-rw-r--r--library/unwind/src/lib.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs5
-rw-r--r--src/bootstrap/src/core/builder/mod.rs64
-rw-r--r--src/bootstrap/src/core/builder/tests.rs32
-rw-r--r--src/librustdoc/clean/types.rs22
-rw-r--r--src/librustdoc/passes/propagate_stability.rs8
-rw-r--r--src/tools/run-make-support/src/assertion_helpers.rs107
-rw-r--r--src/tools/run-make-support/src/assertion_helpers/mod.rs135
-rw-r--r--src/tools/run-make-support/src/assertion_helpers/tests.rs100
-rw-r--r--tests/rustdoc-js-std/core-transmute.js11
-rw-r--r--tests/rustdoc-js-std/transmute-fail.js3
-rw-r--r--tests/rustdoc-js-std/transmute.js3
-rw-r--r--tests/ui/array-slice-vec/suggest-array-length.fixed25
-rw-r--r--tests/ui/array-slice-vec/suggest-array-length.rs25
-rw-r--r--tests/ui/array-slice-vec/suggest-array-length.stderr89
-rw-r--r--tests/ui/async-await/issues/issue-95307.rs4
-rw-r--r--tests/ui/async-await/issues/issue-95307.stderr7
-rw-r--r--tests/ui/const-generics/generic_arg_infer/in-signature.stderr70
-rw-r--r--tests/ui/consts/issue-104768.rs1
-rw-r--r--tests/ui/consts/issue-104768.stderr30
-rw-r--r--tests/ui/error-codes/E0121.stderr10
-rw-r--r--tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr18
-rw-r--r--tests/ui/feature-gates/feature-gate-generic_arg_infer.rs2
-rw-r--r--tests/ui/generic-const-items/assoc-const-missing-type.rs1
-rw-r--r--tests/ui/generic-const-items/assoc-const-missing-type.stderr18
-rw-r--r--tests/ui/macros/issue-69396-const-no-type-in-macro.rs2
-rw-r--r--tests/ui/macros/issue-69396-const-no-type-in-macro.stderr7
-rw-r--r--tests/ui/parser/issues/issue-89574.rs1
-rw-r--r--tests/ui/parser/issues/issue-89574.stderr10
-rw-r--r--tests/ui/suggestions/unnamable-types.rs2
-rw-r--r--tests/ui/suggestions/unnamable-types.stderr10
-rw-r--r--tests/ui/typeck/issue-79040.rs6
-rw-r--r--tests/ui/typeck/issue-79040.stderr12
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.rs1
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.stderr129
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item_help.stderr40
52 files changed, 780 insertions, 509 deletions
diff --git a/.mailmap b/.mailmap
index 87f32d28f58..eb6a9fcabca 100644
--- a/.mailmap
+++ b/.mailmap
@@ -88,7 +88,8 @@ boolean_coercion <booleancoercion@gmail.com>
 Boris Egorov <jightuse@gmail.com> <egorov@linux.com>
 bors <bors@rust-lang.org> bors[bot] <26634292+bors[bot]@users.noreply.github.com>
 bors <bors@rust-lang.org> bors[bot] <bors[bot]@users.noreply.github.com>
-Boxy <rust@boxyuwu.dev> <supbscripter@gmail.com>
+BoxyUwU <rust@boxyuwu.dev>
+BoxyUwU <rust@boxyuwu.dev> <supbscripter@gmail.com>
 Braden Nelson <moonheart08@users.noreply.github.com>
 Brandon Sanderson <singingboyo@gmail.com> Brandon Sanderson <singingboyo@hotmail.com>
 Brett Cannon <brett@python.org> Brett Cannon <brettcannon@users.noreply.github.com>
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 46e91636cfb..fe2d5a594f3 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -2031,11 +2031,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> {
         match c.value.kind {
             ExprKind::Underscore => {
-                if self.tcx.features().generic_arg_infer() {
-                    let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span));
-                    self.arena
-                        .alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind })
-                } else {
+                if !self.tcx.features().generic_arg_infer() {
                     feature_err(
                         &self.tcx.sess,
                         sym::generic_arg_infer,
@@ -2043,8 +2039,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         fluent_generated::ast_lowering_underscore_array_length_unstable,
                     )
                     .stash(c.value.span, StashKey::UnderscoreForArrayLengths);
-                    self.lower_anon_const_to_const_arg(c)
                 }
+                let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span));
+                self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind })
             }
             _ => self.lower_anon_const_to_const_arg(c),
         }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7a3cde4bc2f..44762299ee8 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3387,7 +3387,7 @@ impl<'hir> FnRetTy<'hir> {
         }
     }
 
-    pub fn get_infer_ret_ty(&self) -> Option<&'hir Ty<'hir>> {
+    pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> {
         if let Self::Return(ty) = self {
             if ty.is_suggestable_infer_ty() {
                 return Some(*ty);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ada70117b62..888605b2345 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -131,19 +131,25 @@ pub struct ItemCtxt<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 
 #[derive(Default)]
-pub(crate) struct HirPlaceholderCollector(pub(crate) Vec<Span>);
+pub(crate) struct HirPlaceholderCollector {
+    pub spans: Vec<Span>,
+    // If any of the spans points to a const infer var, then suppress any messages
+    // that may try to turn that const infer into a type parameter.
+    pub may_contain_const_infer: bool,
+}
 
 impl<'v> Visitor<'v> for HirPlaceholderCollector {
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
         if let hir::TyKind::Infer = t.kind {
-            self.0.push(t.span);
+            self.spans.push(t.span);
         }
         intravisit::walk_ty(self, t)
     }
     fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) {
         match generic_arg {
             hir::GenericArg::Infer(inf) => {
-                self.0.push(inf.span);
+                self.spans.push(inf.span);
+                self.may_contain_const_infer = true;
                 intravisit::walk_inf(self, inf);
             }
             hir::GenericArg::Type(t) => self.visit_ty(t),
@@ -152,7 +158,8 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
     }
     fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) {
         if let hir::ConstArgKind::Infer(span) = const_arg.kind {
-            self.0.push(span);
+            self.may_contain_const_infer = true;
+            self.spans.push(span);
         }
         intravisit::walk_const_arg(self, const_arg)
     }
@@ -277,8 +284,8 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
     placeholder_type_error(
         icx.lowerer(),
         Some(generics),
-        visitor.0,
-        suggest,
+        visitor.spans,
+        suggest && !visitor.may_contain_const_infer,
         None,
         item.kind.descr(),
     );
@@ -607,16 +614,16 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
             hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
         };
 
-        if !(visitor.0.is_empty() && infer_replacements.is_empty()) {
+        if !(visitor.spans.is_empty() && infer_replacements.is_empty()) {
             // We check for the presence of
             // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
 
             let mut diag = crate::collect::placeholder_type_error_diag(
                 self,
                 generics,
-                visitor.0,
+                visitor.spans,
                 infer_replacements.iter().map(|(s, _)| *s).collect(),
-                true,
+                !visitor.may_contain_const_infer,
                 hir_ty,
                 "function",
             );
@@ -712,7 +719,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
                         placeholder_type_error(
                             icx.lowerer(),
                             None,
-                            visitor.0,
+                            visitor.spans,
                             false,
                             None,
                             "static variable",
@@ -780,7 +787,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
                 placeholder_type_error(
                     icx.lowerer(),
                     None,
-                    visitor.0,
+                    visitor.spans,
                     false,
                     None,
                     it.kind.descr(),
@@ -822,7 +829,7 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
                 placeholder_type_error(
                     icx.lowerer(),
                     None,
-                    visitor.0,
+                    visitor.spans,
                     false,
                     None,
                     "associated constant",
@@ -837,7 +844,14 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
             // Account for `type T = _;`.
             let mut visitor = HirPlaceholderCollector::default();
             visitor.visit_trait_item(trait_item);
-            placeholder_type_error(icx.lowerer(), None, visitor.0, false, None, "associated type");
+            placeholder_type_error(
+                icx.lowerer(),
+                None,
+                visitor.spans,
+                false,
+                None,
+                "associated type",
+            );
         }
 
         hir::TraitItemKind::Type(_, None) => {
@@ -848,7 +862,14 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
             let mut visitor = HirPlaceholderCollector::default();
             visitor.visit_trait_item(trait_item);
 
-            placeholder_type_error(icx.lowerer(), None, visitor.0, false, None, "associated type");
+            placeholder_type_error(
+                icx.lowerer(),
+                None,
+                visitor.spans,
+                false,
+                None,
+                "associated type",
+            );
         }
     };
 
@@ -872,7 +893,14 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
             let mut visitor = HirPlaceholderCollector::default();
             visitor.visit_impl_item(impl_item);
 
-            placeholder_type_error(icx.lowerer(), None, visitor.0, false, None, "associated type");
+            placeholder_type_error(
+                icx.lowerer(),
+                None,
+                visitor.spans,
+                false,
+                None,
+                "associated type",
+            );
         }
         hir::ImplItemKind::Const(ty, _) => {
             // Account for `const T: _ = ..;`
@@ -882,7 +910,7 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
                 placeholder_type_error(
                     icx.lowerer(),
                     None,
-                    visitor.0,
+                    visitor.spans,
                     false,
                     None,
                     "associated constant",
@@ -1371,7 +1399,7 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
     generics: &'tcx hir::Generics<'tcx>,
     def_id: LocalDefId,
 ) -> ty::PolyFnSig<'tcx> {
-    if let Some(infer_ret_ty) = sig.decl.output.get_infer_ret_ty() {
+    if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
         return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
     }
 
@@ -1422,7 +1450,7 @@ fn recover_infer_ret_ty<'tcx>(
     let mut visitor = HirPlaceholderCollector::default();
     visitor.visit_ty(infer_ret_ty);
 
-    let mut diag = bad_placeholder(icx.lowerer(), visitor.0, "return type");
+    let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
     let ret_ty = fn_sig.output();
 
     // Don't leak types into signatures unless they're nameable!
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c0526903e88..87a04820f7e 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -4,6 +4,7 @@ use rustc_errors::{Applicability, StashKey, Suggestions};
 use rustc_hir as hir;
 use rustc_hir::HirId;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::Visitor;
 use rustc_middle::query::plumbing::CyclePlaceholder;
 use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
@@ -12,7 +13,7 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx
 use rustc_middle::{bug, span_bug};
 use rustc_span::{DUMMY_SP, Ident, Span};
 
-use super::{ItemCtxt, bad_placeholder};
+use super::{HirPlaceholderCollector, ItemCtxt, bad_placeholder};
 use crate::errors::TypeofReservedKeywordUsed;
 use crate::hir_ty_lowering::HirTyLowerer;
 
@@ -412,7 +413,7 @@ fn infer_placeholder_type<'tcx>(
     kind: &'static str,
 ) -> Ty<'tcx> {
     let tcx = cx.tcx();
-    let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
+    let ty = tcx.typeck(def_id).node_type(body_id.hir_id);
 
     // If this came from a free `const` or `static mut?` item,
     // then the user may have written e.g. `const A = 42;`.
@@ -447,13 +448,37 @@ fn infer_placeholder_type<'tcx>(
             }
         })
         .unwrap_or_else(|| {
-            let mut diag = bad_placeholder(cx, vec![span], kind);
-
-            if !ty.references_error() {
+            let mut visitor = HirPlaceholderCollector::default();
+            let node = tcx.hir_node_by_def_id(def_id);
+            if let Some(ty) = node.ty() {
+                visitor.visit_ty(ty);
+            }
+            // If we have just one span, let's try to steal a const `_` feature error.
+            let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.spans.len() == 1
+            {
+                visitor.spans.first().copied()
+            } else {
+                None
+            };
+            // If we didn't find any infer tys, then just fallback to `span`.
+            if visitor.spans.is_empty() {
+                visitor.spans.push(span);
+            }
+            let mut diag = bad_placeholder(cx, visitor.spans, kind);
+
+            // HACK(#69396): Stashing and stealing diagnostics does not interact
+            // well with macros which may delay more than one diagnostic on the
+            // same span. If this happens, we will fall through to this arm, so
+            // we need to suppress the suggestion since it's invalid. Ideally we
+            // would suppress the duplicated error too, but that's really hard.
+            if span.is_empty() && span.from_expansion() {
+                // An approximately better primary message + no suggestion...
+                diag.primary_message("missing type for item");
+            } else if !ty.references_error() {
                 if let Some(ty) = ty.make_suggestable(tcx, false, None) {
-                    diag.span_suggestion(
+                    diag.span_suggestion_verbose(
                         span,
-                        "replace with the correct type",
+                        "replace this with a fully-specified type",
                         ty,
                         Applicability::MachineApplicable,
                     );
@@ -464,7 +489,16 @@ fn infer_placeholder_type<'tcx>(
                     ));
                 }
             }
-            diag.emit()
+
+            if let Some(try_steal_span) = try_steal_span {
+                cx.dcx().try_steal_replace_and_emit_err(
+                    try_steal_span,
+                    StashKey::UnderscoreForArrayLengths,
+                    diag,
+                )
+            } else {
+                diag.emit()
+            }
         });
     Ty::new_error(tcx, guar)
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 66255829dcf..c933095fd3d 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -187,7 +187,7 @@ impl TaitConstraintLocator<'_> {
             "foreign items cannot constrain opaque types",
         );
         if let Some(hir_sig) = hir_node.fn_sig()
-            && hir_sig.decl.output.get_infer_ret_ty().is_some()
+            && hir_sig.decl.output.is_suggestable_infer_ty().is_some()
         {
             let guar = self.tcx.dcx().span_delayed_bug(
                 hir_sig.decl.output.span(),
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 2f7ed8dd2a8..9edf2485238 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1771,12 +1771,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| {
             !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }))
         });
-        let Some((
-            _,
-            hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. })
-            | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }),
-        )) = parent_node
-        else {
+        let Some((_, hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }))) = parent_node else {
             return;
         };
         if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 91ea34eb54d..5a0a855147d 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -87,21 +87,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
 }
 
 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
-    let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
-    typeck_with_fallback(tcx, def_id, fallback, None)
-}
-
-/// Used only to get `TypeckResults` for type inference during error recovery.
-/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
-fn diagnostic_only_typeck<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-) -> &'tcx ty::TypeckResults<'tcx> {
-    let fallback = move || {
-        let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
-        Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used")
-    };
-    typeck_with_fallback(tcx, def_id, fallback, None)
+    typeck_with_fallback(tcx, def_id, None)
 }
 
 /// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation.
@@ -113,15 +99,13 @@ pub fn inspect_typeck<'tcx>(
     def_id: LocalDefId,
     inspect: ObligationInspector<'tcx>,
 ) -> &'tcx ty::TypeckResults<'tcx> {
-    let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
-    typeck_with_fallback(tcx, def_id, fallback, Some(inspect))
+    typeck_with_fallback(tcx, def_id, Some(inspect))
 }
 
-#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)]
+#[instrument(level = "debug", skip(tcx, inspector), ret)]
 fn typeck_with_fallback<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-    fallback: impl Fn() -> Ty<'tcx> + 'tcx,
     inspector: Option<ObligationInspector<'tcx>>,
 ) -> &'tcx ty::TypeckResults<'tcx> {
     // Closures' typeck results come from their outermost function,
@@ -150,7 +134,11 @@ fn typeck_with_fallback<'tcx>(
     let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id);
 
     if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
-        let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
+        let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() {
+            // In the case that we're recovering `fn() -> W<_>` or some other return
+            // type that has an infer in it, lower the type directly so that it'll
+            // be correctly filled with infer. We'll use this inference to provide
+            // a suggestion later on.
             fcx.lowerer().lower_fn_ty(id, header.safety, header.abi, decl, None, None)
         } else {
             tcx.fn_sig(def_id).instantiate_identity()
@@ -164,8 +152,19 @@ fn typeck_with_fallback<'tcx>(
 
         check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params());
     } else {
-        let expected_type = infer_type_if_missing(&fcx, node);
-        let expected_type = expected_type.unwrap_or_else(fallback);
+        let expected_type = if let Some(infer_ty) = infer_type_if_missing(&fcx, node) {
+            infer_ty
+        } else if let Some(ty) = node.ty()
+            && ty.is_suggestable_infer_ty()
+        {
+            // In the case that we're recovering `const X: [T; _]` or some other
+            // type that has an infer in it, lower the type directly so that it'll
+            // be correctly filled with infer. We'll use this inference to provide
+            // a suggestion later on.
+            fcx.lowerer().lower_ty(ty)
+        } else {
+            tcx.type_of(def_id).instantiate_identity()
+        };
 
         let expected_type = fcx.normalize(body.value.span, expected_type);
 
@@ -506,5 +505,5 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
 
 pub fn provide(providers: &mut Providers) {
     method::provide(providers);
-    *providers = Providers { typeck, diagnostic_only_typeck, used_trait_imports, ..*providers };
+    *providers = Providers { typeck, used_trait_imports, ..*providers };
 }
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index b1d5d688295..0383c81f2af 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -363,6 +363,13 @@ where
             return;
         }
 
+        if alias_ty.has_non_region_infer() {
+            self.tcx
+                .dcx()
+                .span_delayed_bug(origin.span(), "an alias has infers during region solving");
+            return;
+        }
+
         // This case is thorny for inference. The fundamental problem is
         // that there are many cases where we have choice, and inference
         // doesn't like choice (the current region inference in
@@ -388,26 +395,9 @@ where
         // Compute the bounds we can derive from the environment. This
         // is an "approximate" match -- in some cases, these bounds
         // may not apply.
-        let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
+        let approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
         debug!(?approx_env_bounds);
 
-        // Remove outlives bounds that we get from the environment but
-        // which are also deducible from the trait. This arises (cc
-        // #55756) in cases where you have e.g., `<T as Foo<'a>>::Item:
-        // 'a` in the environment but `trait Foo<'b> { type Item: 'b
-        // }` in the trait definition.
-        approx_env_bounds.retain(|bound_outlives| {
-            // OK to skip binder because we only manipulate and compare against other values from
-            // the same binder. e.g. if we have (e.g.) `for<'a> <T as Trait<'a>>::Item: 'a` in
-            // `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. If the
-            // declaration is `trait Trait<'b> { type Item: 'b; }`, then
-            // `projection_declared_bounds_from_trait` will be invoked with `['b => ^1]` and so we
-            // will get `^1` returned.
-            let bound = bound_outlives.skip_binder();
-            let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") };
-            self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1)
-        });
-
         // If declared bounds list is empty, the only applicable rule is
         // OutlivesProjectionComponent. If there are inference variables,
         // then, we can break down the outlives into more primitive
@@ -425,7 +415,7 @@ where
         let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
         if approx_env_bounds.is_empty()
             && trait_bounds.is_empty()
-            && (alias_ty.has_infer() || is_opaque)
+            && (alias_ty.has_infer_regions() || is_opaque)
         {
             debug!("no declared bounds");
             let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 247fbc25965..7a21c2883d1 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -192,7 +192,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     /// Obviously these must be approximate -- they are in fact both *over* and
     /// and *under* approximated:
     ///
-    /// * Over-approximated because we erase regions, so
+    /// * Over-approximated because we don't consider equality of regions.
     /// * Under-approximated because we look for syntactic equality and so for complex types
     ///   like `<T as Foo<fn(&u32, &u32)>>::Item` or whatever we may fail to figure out
     ///   all the subtleties.
@@ -205,13 +205,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         erased_ty: Ty<'tcx>,
     ) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
         let tcx = self.tcx;
+        let mut bounds = vec![];
 
         // To start, collect bounds from user environment. Note that
         // parameter environments are already elaborated, so we don't
         // have to worry about that.
-        let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| {
+        bounds.extend(self.caller_bounds.iter().copied().filter(move |outlives_predicate| {
             super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
-        });
+        }));
 
         // Next, collect regions we scraped from the well-formedness
         // constraints in the fn signature. To do that, we walk the list
@@ -224,37 +225,27 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         // The problem is that the type of `x` is `&'a A`. To be
         // well-formed, then, A must outlive `'a`, but we don't know that
         // this holds from first principles.
-        let from_region_bound_pairs =
-            self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
-                debug!(
-                    "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
-                    (r, p)
-                );
-                // Fast path for the common case.
-                match (&p, erased_ty.kind()) {
-                    // In outlive routines, all types are expected to be fully normalized.
-                    // And therefore we can safely use structural equality for alias types.
-                    (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
-                    (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {}
-                    (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {}
-                    _ => return None,
-                }
+        bounds.extend(self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
+            debug!(
+                "declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
+                (r, p)
+            );
+            // Fast path for the common case.
+            match (&p, erased_ty.kind()) {
+                // In outlive routines, all types are expected to be fully normalized.
+                // And therefore we can safely use structural equality for alias types.
+                (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
+                (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {}
+                (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {}
+                _ => return None,
+            }
 
-                let p_ty = p.to_ty(tcx);
-                let erased_p_ty = self.tcx.erase_regions(p_ty);
-                (erased_p_ty == erased_ty)
-                    .then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
-            });
+            let p_ty = p.to_ty(tcx);
+            let erased_p_ty = self.tcx.erase_regions(p_ty);
+            (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
+        }));
 
-        param_bounds
-            .chain(from_region_bound_pairs)
-            .inspect(|bound| {
-                debug!(
-                    "declared_generic_bounds_from_env_for_erased_ty: result predicate = {:?}",
-                    bound
-                )
-            })
-            .collect()
+        bounds
     }
 
     /// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 7e7b602c560..b6934495e44 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1100,9 +1100,6 @@ rustc_queries! {
         desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if(tcx) { !tcx.is_typeck_child(key.to_def_id()) }
     }
-    query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
-        desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
-    }
 
     query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet<LocalDefId> {
         desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) }
diff --git a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
index 8c3bff2a906..4e8a9d55f9a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
@@ -23,7 +23,7 @@ pub(crate) fn target() -> Target {
             linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
             linker: None,
             relocation_model: RelocModel::Static,
-            panic_strategy: PanicStrategy::Abort,
+            panic_strategy: PanicStrategy::Unwind,
             features: "+thumb2,+neon,+vfp3".into(),
             max_atomic_width: Some(64),
             emit_debug_gdb_scripts: false,
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 6f1cbb0fee7..64e5a609b2f 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -31,7 +31,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
             // If the type of the item uses `_`, we're gonna error out anyway, but
             // typeck (which type_of invokes below), will call back into opaque_types_defined_by
             // causing a cycle. So we just bail out in this case.
-            if hir_sig.output.get_infer_ret_ty().is_some() {
+            if hir_sig.output.is_suggestable_infer_ty().is_some() {
                 return V::Result::output();
             }
             let ty_sig = tcx.fn_sig(item).instantiate_identity();
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 1981675f409..8c28bb5c5b0 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -46,7 +46,7 @@ cfg_if::cfg_if! {
         target_os = "psp",
         target_os = "xous",
         target_os = "solid_asp3",
-        all(target_family = "unix", not(any(target_os = "espidf", target_os = "rtems", target_os = "nuttx"))),
+        all(target_family = "unix", not(any(target_os = "espidf", target_os = "nuttx"))),
         all(target_vendor = "fortanix", target_env = "sgx"),
         target_family = "wasm",
     ))] {
diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs
index 9754e840d15..2e1d2e53a29 100644
--- a/library/std/src/sys/personality/mod.rs
+++ b/library/std/src/sys/personality/mod.rs
@@ -31,7 +31,7 @@ cfg_if::cfg_if! {
         target_os = "psp",
         target_os = "xous",
         target_os = "solid_asp3",
-        all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "rtems"), not(target_os = "nuttx")),
+        all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "nuttx")),
         all(target_vendor = "fortanix", target_env = "sgx"),
     ))] {
         mod gcc;
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 40d409310ff..7af1882ab73 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -20,7 +20,6 @@ cfg_if::cfg_if! {
         target_os = "l4re",
         target_os = "none",
         target_os = "espidf",
-        target_os = "rtems",
         target_os = "nuttx",
     ))] {
         // These "unix" family members do not have unwinder.
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index ca337aa9f4c..148b96181d1 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -93,7 +93,7 @@ impl Step for Std {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.crate_or_deps("sysroot").path("library")
+        run.crate_or_deps("sysroot").path("library").alias("core")
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 1e9f7cbd9b4..75edc8ff781 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -574,7 +574,10 @@ impl Step for Std {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.crate_or_deps("sysroot").path("library").default_condition(builder.config.docs)
+        run.crate_or_deps("sysroot")
+            .path("library")
+            .alias("core")
+            .default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 30e42a5bfb7..04d51fab5d5 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -3,7 +3,7 @@ mod cargo;
 use std::any::{Any, type_name};
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
-use std::fmt::{Debug, Write};
+use std::fmt::{self, Debug, Write};
 use std::hash::Hash;
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
@@ -271,16 +271,17 @@ impl PathSet {
     /// This is used for `StepDescription::krate`, which passes all matching crates at once to
     /// `Step::make_run`, rather than calling it many times with a single crate.
     /// See `tests.rs` for examples.
-    fn intersection_removing_matches(&self, needles: &mut Vec<PathBuf>, module: Kind) -> PathSet {
+    fn intersection_removing_matches(&self, needles: &mut [CLIStepPath], module: Kind) -> PathSet {
         let mut check = |p| {
-            for (i, n) in needles.iter().enumerate() {
-                let matched = Self::check(p, n, module);
+            let mut result = false;
+            for n in needles.iter_mut() {
+                let matched = Self::check(p, &n.path, module);
                 if matched {
-                    needles.remove(i);
-                    return true;
+                    n.will_be_executed = true;
+                    result = true;
                 }
             }
-            false
+            result
         };
         match self {
             PathSet::Set(set) => PathSet::Set(set.iter().filter(|&p| check(p)).cloned().collect()),
@@ -361,6 +362,32 @@ fn remap_paths(paths: &mut Vec<PathBuf>) {
     paths.append(&mut add);
 }
 
+#[derive(Clone, PartialEq)]
+struct CLIStepPath {
+    path: PathBuf,
+    will_be_executed: bool,
+}
+
+#[cfg(test)]
+impl CLIStepPath {
+    fn will_be_executed(mut self, will_be_executed: bool) -> Self {
+        self.will_be_executed = will_be_executed;
+        self
+    }
+}
+
+impl Debug for CLIStepPath {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.path.display())
+    }
+}
+
+impl From<PathBuf> for CLIStepPath {
+    fn from(path: PathBuf) -> Self {
+        Self { path, will_be_executed: false }
+    }
+}
+
 impl StepDescription {
     fn from<S: Step>(kind: Kind) -> StepDescription {
         StepDescription {
@@ -478,7 +505,8 @@ impl StepDescription {
             return;
         }
 
-        let mut path_lookup: Vec<(PathBuf, bool)> =
+        let mut paths: Vec<CLIStepPath> = paths.into_iter().map(|p| p.into()).collect();
+        let mut path_lookup: Vec<(CLIStepPath, bool)> =
             paths.clone().into_iter().map(|p| (p, false)).collect();
 
         // List of `(usize, &StepDescription, Vec<PathSet>)` where `usize` is the closest index of a path
@@ -518,8 +546,10 @@ impl StepDescription {
             }
         }
 
+        paths.retain(|p| !p.will_be_executed);
+
         if !paths.is_empty() {
-            eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths,);
+            eprintln!("ERROR: no `{}` rules matched {:?}", builder.kind.as_str(), paths);
             eprintln!(
                 "HELP: run `x.py {} --help --verbose` to show a list of available paths",
                 builder.kind.as_str()
@@ -682,7 +712,7 @@ impl<'a> ShouldRun<'a> {
     /// (for now, just `all_krates` and `paths`, but we may want to add an `aliases` function in the future?)
     fn pathset_for_paths_removing_matches(
         &self,
-        paths: &mut Vec<PathBuf>,
+        paths: &mut [CLIStepPath],
         kind: Kind,
     ) -> Vec<PathSet> {
         let mut sets = vec![];
@@ -825,12 +855,8 @@ impl<'a> Builder<'a> {
         match kind {
             Kind::Build => describe!(
                 compile::Std,
-                // FIXME(#135022): `compile::Assemble` **must** come before `compile::Rustc` after
-                // `PathSet` also permits prefix-matching, because `compile::Rustc` can consume the
-                // `"compiler"` path filter first, causing `compile::Assemble` to no longer run when
-                // the user writes `./x build compiler --stage 0`.
-                compile::Assemble,
                 compile::Rustc,
+                compile::Assemble,
                 compile::CodegenBackend,
                 compile::StartupObjects,
                 tool::BuildManifest,
@@ -929,14 +955,10 @@ impl<'a> Builder<'a> {
                 test::Rustdoc,
                 test::CoverageRunRustdoc,
                 test::Pretty,
-                test::Crate,
-                test::CrateLibrustc,
-                // The cranelift and gcc tests need to be listed after the
-                // compiler unit tests (CrateLibrustc) so that they don't
-                // hijack the whole `compiler` directory during path matching.
-                // <https://github.com/rust-lang/rust/pull/134919>
                 test::CodegenCranelift,
                 test::CodegenGCC,
+                test::Crate,
+                test::CrateLibrustc,
                 test::CrateRustdoc,
                 test::CrateRustdocJsonTypes,
                 test::CrateBootstrap,
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 21694cf46fe..5769198afac 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -108,13 +108,37 @@ fn test_intersection() {
     };
     let library_set = set(&["library/core", "library/alloc", "library/std"]);
     let mut command_paths = vec![
-        PathBuf::from("library/core"),
-        PathBuf::from("library/alloc"),
-        PathBuf::from("library/stdarch"),
+        CLIStepPath::from(PathBuf::from("library/core")),
+        CLIStepPath::from(PathBuf::from("library/alloc")),
+        CLIStepPath::from(PathBuf::from("library/stdarch")),
     ];
     let subset = library_set.intersection_removing_matches(&mut command_paths, Kind::Build);
     assert_eq!(subset, set(&["library/core", "library/alloc"]),);
-    assert_eq!(command_paths, vec![PathBuf::from("library/stdarch")]);
+    assert_eq!(command_paths, vec![
+        CLIStepPath::from(PathBuf::from("library/core")).will_be_executed(true),
+        CLIStepPath::from(PathBuf::from("library/alloc")).will_be_executed(true),
+        CLIStepPath::from(PathBuf::from("library/stdarch")).will_be_executed(false),
+    ]);
+}
+
+#[test]
+fn test_resolve_parent_and_subpaths() {
+    let set = |paths: &[&str]| {
+        PathSet::Set(paths.into_iter().map(|p| TaskPath { path: p.into(), kind: None }).collect())
+    };
+
+    let mut command_paths = vec![
+        CLIStepPath::from(PathBuf::from("src/tools/miri")),
+        CLIStepPath::from(PathBuf::from("src/tools/miri/cargo-miri")),
+    ];
+
+    let library_set = set(&["src/tools/miri", "src/tools/miri/cargo-miri"]);
+    library_set.intersection_removing_matches(&mut command_paths, Kind::Build);
+
+    assert_eq!(command_paths, vec![
+        CLIStepPath::from(PathBuf::from("src/tools/miri")).will_be_executed(true),
+        CLIStepPath::from(PathBuf::from("src/tools/miri/cargo-miri")).will_be_executed(true),
+    ]);
 }
 
 #[test]
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3c4fad4bca9..dcee96978d2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -400,7 +400,27 @@ impl Item {
     }
 
     pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
-        self.def_id().and_then(|did| tcx.lookup_deprecation(did))
+        self.def_id().and_then(|did| tcx.lookup_deprecation(did)).or_else(|| {
+            // `allowed_through_unstable_modules` is a bug-compatibility hack for old rustc
+            // versions; the paths that are exposed through it are "deprecated" because they
+            // were never supposed to work at all.
+            let stab = self.stability(tcx)?;
+            if let rustc_attr_parsing::StabilityLevel::Stable {
+                allowed_through_unstable_modules: true,
+                ..
+            } = stab.level
+            {
+                Some(Deprecation {
+                    // FIXME(#131676, #135003): when a note is added to this stability tag,
+                    // translate it here
+                    since: rustc_attr_parsing::DeprecatedSince::Unspecified,
+                    note: None,
+                    suggestion: None,
+                })
+            } else {
+                None
+            }
+        })
     }
 
     pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs
index 4c682c3d4ca..d892c585837 100644
--- a/src/librustdoc/passes/propagate_stability.rs
+++ b/src/librustdoc/passes/propagate_stability.rs
@@ -107,6 +107,14 @@ fn merge_stability(
             || parent_stab.stable_since().is_some_and(|parent_since| parent_since > own_since))
     {
         parent_stability
+    } else if let Some(mut own_stab) = own_stability
+        && let StabilityLevel::Stable { since, allowed_through_unstable_modules: true } =
+            own_stab.level
+        && parent_stability.is_some_and(|stab| stab.is_stable())
+    {
+        // this property does not apply transitively through re-exports
+        own_stab.level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
+        Some(own_stab)
     } else {
         own_stability
     }
diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs
deleted file mode 100644
index e84a3cf633f..00000000000
--- a/src/tools/run-make-support/src/assertion_helpers.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-//! Collection of assertions and assertion-related helpers.
-
-use std::panic;
-use std::path::Path;
-
-use crate::{fs, regex};
-
-fn print<'a, 'e, A: AsRef<str>, E: AsRef<str>>(
-    assertion_kind: &str,
-    haystack: &'a A,
-    needle: &'e E,
-) -> (&'a str, &'e str) {
-    let haystack = haystack.as_ref();
-    let needle = needle.as_ref();
-    eprintln!("{assertion_kind}:");
-    eprintln!("=== HAYSTACK ===");
-    eprintln!("{}", haystack);
-    eprintln!("=== NEEDLE ===");
-    eprintln!("{}", needle);
-    (haystack, needle)
-}
-
-/// Assert that `actual` is equal to `expected`.
-#[track_caller]
-pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
-    let actual = actual.as_ref();
-    let expected = expected.as_ref();
-    eprintln!("=== ACTUAL TEXT ===");
-    eprintln!("{}", actual);
-    eprintln!("=== EXPECTED ===");
-    eprintln!("{}", expected);
-    if actual != expected {
-        panic!("expected text was not found in actual text");
-    }
-}
-
-/// Assert that `haystack` contains `needle`.
-#[track_caller]
-pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
-    let (haystack, needle) = print("assert_contains", &haystack, &needle);
-    if !haystack.contains(needle) {
-        panic!("needle was not found in haystack");
-    }
-}
-
-/// Assert that `haystack` does not contain `needle`.
-#[track_caller]
-pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
-    let (haystack, needle) = print("assert_not_contains", &haystack, &needle);
-    if haystack.contains(needle) {
-        panic!("needle was unexpectedly found in haystack");
-    }
-}
-
-/// Assert that `haystack` contains the regex pattern `needle`.
-#[track_caller]
-pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
-    let (haystack, needle) = print("assert_contains_regex", &haystack, &needle);
-    let re = regex::Regex::new(needle).unwrap();
-    if !re.is_match(haystack) {
-        panic!("needle was not found in haystack");
-    }
-}
-
-/// Assert that `haystack` does not contain the regex pattern `needle`.
-#[track_caller]
-pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
-    let (haystack, needle) = print("assert_not_contains_regex", &haystack, &needle);
-    let re = regex::Regex::new(needle).unwrap();
-    if re.is_match(haystack) {
-        panic!("needle was unexpectedly found in haystack");
-    }
-}
-
-/// Assert that `haystack` contains `needle` a `count` number of times.
-#[track_caller]
-pub fn assert_count_is<H: AsRef<str>, N: AsRef<str>>(count: usize, haystack: H, needle: N) {
-    let (haystack, needle) = print("assert_count_is", &haystack, &needle);
-    if count != haystack.matches(needle).count() {
-        panic!("needle did not appear {count} times in haystack");
-    }
-}
-
-/// Assert that all files in `dir1` exist and have the same content in `dir2`
-pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
-    let dir2 = dir2.as_ref();
-    fs::read_dir_entries(dir1, |entry_path| {
-        let entry_name = entry_path.file_name().unwrap();
-        if entry_path.is_dir() {
-            assert_dirs_are_equal(&entry_path, &dir2.join(entry_name));
-        } else {
-            let path2 = dir2.join(entry_name);
-            let file1 = fs::read(&entry_path);
-            let file2 = fs::read(&path2);
-
-            // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
-            // Why not using String? Because there might be minified files or even potentially
-            // binary ones, so that would display useless output.
-            assert!(
-                file1 == file2,
-                "`{}` and `{}` have different content",
-                entry_path.display(),
-                path2.display(),
-            );
-        }
-    });
-}
diff --git a/src/tools/run-make-support/src/assertion_helpers/mod.rs b/src/tools/run-make-support/src/assertion_helpers/mod.rs
new file mode 100644
index 00000000000..9b666473b5b
--- /dev/null
+++ b/src/tools/run-make-support/src/assertion_helpers/mod.rs
@@ -0,0 +1,135 @@
+//! Collection of assertions and assertion-related helpers.
+
+#[cfg(test)]
+mod tests;
+
+use std::panic;
+use std::path::Path;
+
+use crate::{fs, regex};
+
+/// Assert that `actual` is equal to `expected`.
+#[track_caller]
+pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
+    let actual = actual.as_ref();
+    let expected = expected.as_ref();
+
+    if actual != expected {
+        eprintln!("=== ACTUAL TEXT ===");
+        eprintln!("{}", actual);
+        eprintln!("=== EXPECTED ===");
+        eprintln!("{}", expected);
+        panic!("expected text does not match actual text");
+    }
+}
+
+struct SearchDetails<'assertion_name, 'haystack, 'needle> {
+    assertion_name: &'assertion_name str,
+    haystack: &'haystack str,
+    needle: &'needle str,
+}
+
+impl<'assertion_name, 'haystack, 'needle> SearchDetails<'assertion_name, 'haystack, 'needle> {
+    fn dump(&self) {
+        eprintln!("{}:", self.assertion_name);
+        eprintln!("=== HAYSTACK ===");
+        eprintln!("{}", self.haystack);
+        eprintln!("=== NEEDLE ===");
+        eprintln!("{}", self.needle);
+    }
+}
+
+/// Assert that `haystack` contains `needle`.
+#[track_caller]
+pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    if !haystack.contains(needle) {
+        SearchDetails { assertion_name: "assert_contains", haystack, needle }.dump();
+        panic!("needle was not found in haystack");
+    }
+}
+
+/// Assert that `haystack` does not contain `needle`.
+#[track_caller]
+pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    if haystack.contains(needle) {
+        SearchDetails { assertion_name: "assert_not_contains", haystack, needle }.dump();
+        panic!("needle was unexpectedly found in haystack");
+    }
+}
+
+/// Assert that `haystack` contains the regex `needle`.
+#[track_caller]
+pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    let re = regex::Regex::new(needle).unwrap();
+    if !re.is_match(haystack) {
+        SearchDetails { assertion_name: "assert_contains_regex", haystack, needle }.dump();
+        panic!("regex was not found in haystack");
+    }
+}
+
+/// Assert that `haystack` does not contain the regex `needle`.
+#[track_caller]
+pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    let re = regex::Regex::new(needle).unwrap();
+    if re.is_match(haystack) {
+        SearchDetails { assertion_name: "assert_not_contains_regex", haystack, needle }.dump();
+        panic!("regex was unexpectedly found in haystack");
+    }
+}
+
+/// Assert that `haystack` contains regex `needle` an `expected_count` number of times.
+#[track_caller]
+pub fn assert_count_is<H: AsRef<str>, N: AsRef<str>>(
+    expected_count: usize,
+    haystack: H,
+    needle: N,
+) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+
+    let actual_count = haystack.matches(needle).count();
+    if expected_count != actual_count {
+        let count_fmt = format!(
+            "assert_count_is (expected_count = {expected_count}, actual_count = {actual_count})"
+        );
+        SearchDetails { assertion_name: &count_fmt, haystack, needle }.dump();
+        panic!(
+            "regex did not appear {expected_count} times in haystack (expected_count = \
+            {expected_count}, actual_count = {actual_count})"
+        );
+    }
+}
+
+/// Assert that all files in `dir1` exist and have the same content in `dir2`
+// FIXME(#135037): not robust against symlinks, lacks sanity test coverage.
+pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
+    let dir2 = dir2.as_ref();
+    fs::read_dir_entries(dir1, |entry_path| {
+        let entry_name = entry_path.file_name().unwrap();
+        if entry_path.is_dir() {
+            assert_dirs_are_equal(&entry_path, &dir2.join(entry_name));
+        } else {
+            let path2 = dir2.join(entry_name);
+            let file1 = fs::read(&entry_path);
+            let file2 = fs::read(&path2);
+
+            // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
+            // Why not using String? Because there might be minified files or even potentially
+            // binary ones, so that would display useless output.
+            assert!(
+                file1 == file2,
+                "`{}` and `{}` have different content",
+                entry_path.display(),
+                path2.display(),
+            );
+        }
+    });
+}
diff --git a/src/tools/run-make-support/src/assertion_helpers/tests.rs b/src/tools/run-make-support/src/assertion_helpers/tests.rs
new file mode 100644
index 00000000000..8bf7740d2e6
--- /dev/null
+++ b/src/tools/run-make-support/src/assertion_helpers/tests.rs
@@ -0,0 +1,100 @@
+//! Basic sanity checks for assertion helpers.
+use super::*;
+
+mod test_assert_equals {
+    use super::*;
+
+    #[test]
+    fn assert_equals_same() {
+        assert_equals("foo", "foo");
+        assert_equals("", "");
+    }
+
+    #[test]
+    #[should_panic]
+    fn assert_equals_different() {
+        assert_equals("foo", "bar");
+    }
+}
+
+mod test_assert_contains {
+    use super::*;
+
+    #[test]
+    fn assert_contains_yes() {
+        assert_contains("", "");
+        assert_contains(" ", "");
+        assert_contains("a", "a");
+        assert_contains("ab", "a");
+    }
+
+    #[test]
+    #[should_panic]
+    fn assert_contains_no() {
+        assert_contains("a", "b");
+    }
+}
+
+mod test_assert_not_contains {
+    use super::*;
+
+    #[test]
+    fn assert_not_contains_yes() {
+        assert_not_contains("a", "b");
+    }
+
+    #[test]
+    #[should_panic]
+    fn assert_not_contains_no() {
+        assert_not_contains(" ", "");
+    }
+}
+
+mod assert_contains_regex {
+    use super::*;
+
+    #[test]
+    fn assert_contains_regex_yes() {
+        assert_contains_regex("", "");
+        assert_contains_regex("", ".*");
+        assert_contains_regex("abcde", ".*");
+        assert_contains_regex("abcde", ".+");
+    }
+
+    #[test]
+    #[should_panic]
+    fn assert_contains_regex_no() {
+        assert_contains_regex("", ".+");
+    }
+}
+
+mod assert_not_contains_regex_regex {
+    use super::*;
+
+    #[test]
+    fn assert_not_contains_regex_yes() {
+        assert_not_contains_regex("abc", "d");
+    }
+
+    #[test]
+    #[should_panic]
+    fn assert_not_contains_regex_no() {
+        assert_not_contains_regex("abc", ".*");
+    }
+}
+
+mod test_assert_count_is {
+    use super::*;
+
+    #[test]
+    fn assert_count_is_yes() {
+        assert_count_is(0, "", "b");
+        assert_count_is(3, "abcbdb", "b");
+    }
+
+    #[test]
+    #[should_panic]
+    fn assert_count_is_no() {
+        assert_count_is(2, "abcbdb", "b");
+    }
+}
diff --git a/tests/rustdoc-js-std/core-transmute.js b/tests/rustdoc-js-std/core-transmute.js
new file mode 100644
index 00000000000..8c9910a32d7
--- /dev/null
+++ b/tests/rustdoc-js-std/core-transmute.js
@@ -0,0 +1,11 @@
+const FILTER_CRATE = "core";
+const EXPECTED = [
+    {
+        'query': 'generic:T -> generic:U',
+        'others': [
+            { 'path': 'core::intrinsics::simd', 'name': 'simd_as' },
+            { 'path': 'core::intrinsics::simd', 'name': 'simd_cast' },
+            { 'path': 'core::mem', 'name': 'transmute' },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js-std/transmute-fail.js b/tests/rustdoc-js-std/transmute-fail.js
index c4dddf3cf3c..ddfb2761948 100644
--- a/tests/rustdoc-js-std/transmute-fail.js
+++ b/tests/rustdoc-js-std/transmute-fail.js
@@ -1,4 +1,5 @@
 // should-fail
+const FILTER_CRATE = "std";
 const EXPECTED = [
     {
         // Keep this test case identical to `transmute`, except the
@@ -7,7 +8,7 @@ const EXPECTED = [
         'others': [
             { 'path': 'std::intrinsics::simd', 'name': 'simd_as' },
             { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' },
-            { 'path': 'std::intrinsics', 'name': 'transmute' },
+            { 'path': 'std::mem', 'name': 'transmute' },
         ],
     },
 ];
diff --git a/tests/rustdoc-js-std/transmute.js b/tests/rustdoc-js-std/transmute.js
index 0e52e21e0de..f52e0ab1436 100644
--- a/tests/rustdoc-js-std/transmute.js
+++ b/tests/rustdoc-js-std/transmute.js
@@ -1,3 +1,4 @@
+const FILTER_CRATE = "std";
 const EXPECTED = [
     {
         // Keep this test case identical to `transmute-fail`, except the
@@ -6,7 +7,7 @@ const EXPECTED = [
         'others': [
             { 'path': 'std::intrinsics::simd', 'name': 'simd_as' },
             { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' },
-            { 'path': 'std::intrinsics', 'name': 'transmute' },
+            { 'path': 'std::mem', 'name': 'transmute' },
         ],
     },
 ];
diff --git a/tests/ui/array-slice-vec/suggest-array-length.fixed b/tests/ui/array-slice-vec/suggest-array-length.fixed
index 29f85da56e5..2eacc2517d3 100644
--- a/tests/ui/array-slice-vec/suggest-array-length.fixed
+++ b/tests/ui/array-slice-vec/suggest-array-length.fixed
@@ -3,24 +3,21 @@
 
 fn main() {
     const Foo: [i32; 3] = [1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
     const REF_FOO: &[u8; 1] = &[1];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
+    static Statik: [i32; 3] = [1, 2, 3];
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
+    static REF_STATIK: &[u8; 1] = &[1];
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
     let foo: [i32; 3] = [1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let bar: [i32; 3] = [0; 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let ref_foo: &[i32; 3] = &[1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let ref_bar: &[i32; 3] = &[0; 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let multiple_ref_foo: &&[i32; 3] = &&[1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
 }
diff --git a/tests/ui/array-slice-vec/suggest-array-length.rs b/tests/ui/array-slice-vec/suggest-array-length.rs
index 82d871cf875..fb4424cfed9 100644
--- a/tests/ui/array-slice-vec/suggest-array-length.rs
+++ b/tests/ui/array-slice-vec/suggest-array-length.rs
@@ -3,24 +3,21 @@
 
 fn main() {
     const Foo: [i32; _] = [1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
     const REF_FOO: &[u8; _] = &[1];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
+    static Statik: [i32; _] = [1, 2, 3];
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
+    static REF_STATIK: &[u8; _] = &[1];
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
     let foo: [i32; _] = [1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let bar: [i32; _] = [0; 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let ref_foo: &[i32; _] = &[1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let ref_bar: &[i32; _] = &[0; 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
-    //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment
-    //~| ERROR using `_` for array lengths is unstable
+    //~^ ERROR using `_` for array lengths is unstable
 }
diff --git a/tests/ui/array-slice-vec/suggest-array-length.stderr b/tests/ui/array-slice-vec/suggest-array-length.stderr
index fdab7ba7064..b71be306780 100644
--- a/tests/ui/array-slice-vec/suggest-array-length.stderr
+++ b/tests/ui/array-slice-vec/suggest-array-length.stderr
@@ -1,67 +1,49 @@
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:11:20
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/suggest-array-length.rs:5:22
    |
-LL |     let foo: [i32; _] = [1, 2, 3];
-   |                    ^ `_` not allowed here
-
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:14:20
+LL |     const Foo: [i32; _] = [1, 2, 3];
+   |                      ^ not allowed in type signatures
    |
-LL |     let bar: [i32; _] = [0; 3];
-   |                    ^ `_` not allowed here
-
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:17:25
+help: replace this with a fully-specified type
    |
-LL |     let ref_foo: &[i32; _] = &[1, 2, 3];
-   |                         ^ `_` not allowed here
+LL |     const Foo: [i32; 3] = [1, 2, 3];
+   |                ~~~~~~~~
 
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:20:25
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/suggest-array-length.rs:7:26
    |
-LL |     let ref_bar: &[i32; _] = &[0; 3];
-   |                         ^ `_` not allowed here
-
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:23:35
+LL |     const REF_FOO: &[u8; _] = &[1];
+   |                          ^ not allowed in type signatures
    |
-LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
-   |                                   ^ `_` not allowed here
-
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:5:22
+help: replace this with a fully-specified type
    |
-LL |     const Foo: [i32; _] = [1, 2, 3];
-   |                      ^ `_` not allowed here
+LL |     const REF_FOO: &[u8; 1] = &[1];
+   |                    ~~~~~~~~
 
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/suggest-array-length.rs:8:26
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/suggest-array-length.rs:9:26
    |
-LL |     const REF_FOO: &[u8; _] = &[1];
-   |                          ^ `_` not allowed here
-
-error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:5:22
+LL |     static Statik: [i32; _] = [1, 2, 3];
+   |                          ^ not allowed in type signatures
    |
-LL |     const Foo: [i32; _] = [1, 2, 3];
-   |                      ^ help: consider specifying the array length: `3`
+help: replace this with a fully-specified type
    |
-   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
-   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+LL |     static Statik: [i32; 3] = [1, 2, 3];
+   |                    ~~~~~~~~
 
-error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:8:26
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
+  --> $DIR/suggest-array-length.rs:11:30
    |
-LL |     const REF_FOO: &[u8; _] = &[1];
-   |                          ^ help: consider specifying the array length: `1`
+LL |     static REF_STATIK: &[u8; _] = &[1];
+   |                              ^ not allowed in type signatures
    |
-   = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information
-   = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+help: replace this with a fully-specified type
+   |
+LL |     static REF_STATIK: &[u8; 1] = &[1];
+   |                        ~~~~~~~~
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:11:20
+  --> $DIR/suggest-array-length.rs:13:20
    |
 LL |     let foo: [i32; _] = [1, 2, 3];
    |                    ^ help: consider specifying the array length: `3`
@@ -71,7 +53,7 @@ LL |     let foo: [i32; _] = [1, 2, 3];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:14:20
+  --> $DIR/suggest-array-length.rs:15:20
    |
 LL |     let bar: [i32; _] = [0; 3];
    |                    ^ help: consider specifying the array length: `3`
@@ -91,7 +73,7 @@ LL |     let ref_foo: &[i32; _] = &[1, 2, 3];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:20:25
+  --> $DIR/suggest-array-length.rs:19:25
    |
 LL |     let ref_bar: &[i32; _] = &[0; 3];
    |                         ^ help: consider specifying the array length: `3`
@@ -101,7 +83,7 @@ LL |     let ref_bar: &[i32; _] = &[0; 3];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/suggest-array-length.rs:23:35
+  --> $DIR/suggest-array-length.rs:21:35
    |
 LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
    |                                   ^ help: consider specifying the array length: `3`
@@ -110,6 +92,7 @@ LL |     let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3];
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 14 previous errors
+error: aborting due to 9 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0121, E0658.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/async-await/issues/issue-95307.rs b/tests/ui/async-await/issues/issue-95307.rs
index 40700c610f3..27903a667fb 100644
--- a/tests/ui/async-await/issues/issue-95307.rs
+++ b/tests/ui/async-await/issues/issue-95307.rs
@@ -5,8 +5,8 @@
 
 pub trait C {
     async fn new() -> [u8; _];
-    //~^ ERROR: using `_` for array lengths is unstable
-    //~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
+    //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions
+    //~| ERROR using `_` for array lengths is unstable
 }
 
 fn main() {}
diff --git a/tests/ui/async-await/issues/issue-95307.stderr b/tests/ui/async-await/issues/issue-95307.stderr
index dd8fcd3690a..90100f39163 100644
--- a/tests/ui/async-await/issues/issue-95307.stderr
+++ b/tests/ui/async-await/issues/issue-95307.stderr
@@ -1,8 +1,8 @@
-error: in expressions, `_` can only be used on the left-hand side of an assignment
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/issue-95307.rs:7:28
    |
 LL |     async fn new() -> [u8; _];
-   |                            ^ `_` not allowed here
+   |                            ^ not allowed in type signatures
 
 error[E0658]: using `_` for array lengths is unstable
   --> $DIR/issue-95307.rs:7:28
@@ -16,4 +16,5 @@ LL |     async fn new() -> [u8; _];
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0121, E0658.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr
index fcac95732d1..5999bc18204 100644
--- a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr
+++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr
@@ -27,52 +27,74 @@ LL | fn ty_fn_mixed() -> Bar<_, _> {
    |                     help: replace with the correct return type: `Bar<i32, 3>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/in-signature.rs:22:15
+  --> $DIR/in-signature.rs:22:20
    |
 LL | const ARR_CT: [u8; _] = [0; 3];
-   |               ^^^^^^^ not allowed in type signatures
+   |                    ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const ARR_CT: [u8; 3] = [0; 3];
+   |               ~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/in-signature.rs:24:20
+  --> $DIR/in-signature.rs:24:25
    |
 LL | static ARR_STATIC: [u8; _] = [0; 3];
-   |                    ^^^^^^^ not allowed in type signatures
+   |                         ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static ARR_STATIC: [u8; 3] = [0; 3];
+   |                    ~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/in-signature.rs:26:14
+  --> $DIR/in-signature.rs:26:23
    |
 LL | const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0);
-   |              ^^^^^^^^^^^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `Bar<i32, 3>`
+   |                       ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const TY_CT: Bar<i32, 3> = Bar::<i32, 3>(0);
+   |              ~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/in-signature.rs:28:19
+  --> $DIR/in-signature.rs:28:28
    |
 LL | static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0);
-   |                   ^^^^^^^^^^^
-   |                   |
-   |                   not allowed in type signatures
-   |                   help: replace with the correct type: `Bar<i32, 3>`
+   |                            ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static TY_STATIC: Bar<i32, 3> = Bar::<i32, 3>(0);
+   |                   ~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/in-signature.rs:30:20
+  --> $DIR/in-signature.rs:30:24
    |
 LL | const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
-   |                    ^^^^^^^^^
-   |                    |
-   |                    not allowed in type signatures
-   |                    help: replace with the correct type: `Bar<i32, 3>`
+   |                        ^  ^ not allowed in type signatures
+   |                        |
+   |                        not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const TY_CT_MIXED: Bar<i32, 3> = Bar::<i32, 3>(0);
+   |                    ~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/in-signature.rs:32:25
+  --> $DIR/in-signature.rs:32:29
    |
 LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
-   |                         ^^^^^^^^^
-   |                         |
-   |                         not allowed in type signatures
-   |                         help: replace with the correct type: `Bar<i32, 3>`
+   |                             ^  ^ not allowed in type signatures
+   |                             |
+   |                             not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static TY_STATIC_MIXED: Bar<i32, 3> = Bar::<i32, 3>(0);
+   |                         ~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
   --> $DIR/in-signature.rs:51:23
diff --git a/tests/ui/consts/issue-104768.rs b/tests/ui/consts/issue-104768.rs
index 3192daafa0b..52a8070be4e 100644
--- a/tests/ui/consts/issue-104768.rs
+++ b/tests/ui/consts/issue-104768.rs
@@ -1,4 +1,5 @@
 const A: &_ = 0_u32;
 //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants
+//~| ERROR: mismatched types
 
 fn main() {}
diff --git a/tests/ui/consts/issue-104768.stderr b/tests/ui/consts/issue-104768.stderr
index 8a4a41e4d68..41a9bab0961 100644
--- a/tests/ui/consts/issue-104768.stderr
+++ b/tests/ui/consts/issue-104768.stderr
@@ -1,12 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-104768.rs:1:15
+   |
+LL | const A: &_ = 0_u32;
+   |               ^^^^^ expected `&_`, found `u32`
+   |
+   = note: expected reference `&'static _`
+                   found type `u32`
+help: consider borrowing here
+   |
+LL | const A: &_ = &0_u32;
+   |               +
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/issue-104768.rs:1:10
+  --> $DIR/issue-104768.rs:1:11
    |
 LL | const A: &_ = 0_u32;
-   |          ^^
-   |          |
-   |          not allowed in type signatures
-   |          help: replace with the correct type: `u32`
+   |           ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const A: u32 = 0_u32;
+   |          ~~~
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0121`.
+Some errors have detailed explanations: E0121, E0308.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/error-codes/E0121.stderr b/tests/ui/error-codes/E0121.stderr
index 023d7e011bf..5f5df0fd0ae 100644
--- a/tests/ui/error-codes/E0121.stderr
+++ b/tests/ui/error-codes/E0121.stderr
@@ -11,10 +11,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/E0121.rs:3:13
    |
 LL | static BAR: _ = "test";
-   |             ^
-   |             |
-   |             not allowed in type signatures
-   |             help: replace with the correct type: `&str`
+   |             ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static BAR: &str = "test";
+   |             ~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr
index 97370f0489b..96fb4a53609 100644
--- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr
+++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr
@@ -1,17 +1,5 @@
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/feature-gate-generic_arg_infer.rs:11:27
-   |
-LL |     let _x: [u8; 3] = [0; _];
-   |                           ^ `_` not allowed here
-
-error: in expressions, `_` can only be used on the left-hand side of an assignment
-  --> $DIR/feature-gate-generic_arg_infer.rs:14:18
-   |
-LL |     let _y: [u8; _] = [0; 3];
-   |                  ^ `_` not allowed here
-
 error[E0658]: using `_` for array lengths is unstable
-  --> $DIR/feature-gate-generic_arg_infer.rs:14:18
+  --> $DIR/feature-gate-generic_arg_infer.rs:13:18
    |
 LL |     let _y: [u8; _] = [0; 3];
    |                  ^ help: consider specifying the array length: `3`
@@ -21,7 +9,7 @@ LL |     let _y: [u8; _] = [0; 3];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0747]: type provided when a constant was expected
-  --> $DIR/feature-gate-generic_arg_infer.rs:20:20
+  --> $DIR/feature-gate-generic_arg_infer.rs:18:20
    |
 LL |     let _x = foo::<_>([1,2]);
    |                    ^
@@ -42,7 +30,7 @@ LL |     let _x: [u8; 3] = [0; _];
    = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0658, E0747.
 For more information about an error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs
index 0473253004a..de4b7078ea6 100644
--- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs
+++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs
@@ -10,10 +10,8 @@ fn foo<const N: usize>(_: [u8; N]) -> [u8; N] {
 fn bar() {
     let _x: [u8; 3] = [0; _];
     //[normal]~^ ERROR: using `_` for array lengths is unstable
-    //[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
     let _y: [u8; _] = [0; 3];
     //[normal]~^ ERROR: using `_` for array lengths is unstable
-    //[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment
 }
 
 fn main() {
diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs
index 93160f0b575..0c94a4262ef 100644
--- a/tests/ui/generic-const-items/assoc-const-missing-type.rs
+++ b/tests/ui/generic-const-items/assoc-const-missing-type.rs
@@ -12,7 +12,6 @@ impl Trait for () {
     const K<T> = ();
     //~^ ERROR missing type for `const` item
     //~| ERROR mismatched types
-    //~| ERROR mismatched types
     const Q = "";
     //~^ ERROR missing type for `const` item
     //~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration
diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr
index 6f35c0958d4..5af119dffa7 100644
--- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr
+++ b/tests/ui/generic-const-items/assoc-const-missing-type.stderr
@@ -16,7 +16,7 @@ LL |     const K<T> = ();
    |               ^ help: provide a type for the associated constant: `()`
 
 error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration
-  --> $DIR/assoc-const-missing-type.rs:16:12
+  --> $DIR/assoc-const-missing-type.rs:15:12
    |
 LL |     const Q<'a>: &'a str;
    |            ---- lifetimes in impl do not match this const in trait
@@ -25,24 +25,12 @@ LL |     const Q = "";
    |            ^ lifetimes do not match const in trait
 
 error: missing type for `const` item
-  --> $DIR/assoc-const-missing-type.rs:16:12
+  --> $DIR/assoc-const-missing-type.rs:15:12
    |
 LL |     const Q = "";
    |            ^ help: provide a type for the associated constant: `: &str`
 
-error[E0308]: mismatched types
-  --> $DIR/assoc-const-missing-type.rs:12:18
-   |
-LL |     const K<T> = ();
-   |             -    ^^ expected type parameter `T`, found `()`
-   |             |
-   |             expected this type parameter
-   |
-   = note: expected type parameter `T`
-                   found unit type `()`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0195, E0308.
 For more information about an error, try `rustc --explain E0195`.
diff --git a/tests/ui/macros/issue-69396-const-no-type-in-macro.rs b/tests/ui/macros/issue-69396-const-no-type-in-macro.rs
index 45a30857413..c200a1fd0b4 100644
--- a/tests/ui/macros/issue-69396-const-no-type-in-macro.rs
+++ b/tests/ui/macros/issue-69396-const-no-type-in-macro.rs
@@ -4,7 +4,7 @@ macro_rules! suite {
             const A = "A".$fn();
             //~^ ERROR the name `A` is defined multiple times
             //~| ERROR missing type for `const` item
-            //~| ERROR the placeholder `_` is not allowed within types on item signatures for constants
+            //~| ERROR missing type for item
         )*
     }
 }
diff --git a/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr b/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr
index 89aeafebac4..4342d7d88f5 100644
--- a/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr
+++ b/tests/ui/macros/issue-69396-const-no-type-in-macro.stderr
@@ -27,14 +27,11 @@ LL | | }
    |
    = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+error[E0121]: missing type for item
   --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20
    |
 LL |               const A = "A".$fn();
-   |                      ^
-   |                      |
-   |                      not allowed in type signatures
-   |                      help: replace with the correct type: `bool`
+   |                      ^ not allowed in type signatures
 ...
 LL | / suite! {
 LL | |     len;
diff --git a/tests/ui/parser/issues/issue-89574.rs b/tests/ui/parser/issues/issue-89574.rs
index bafb0ce5e66..276abfe7110 100644
--- a/tests/ui/parser/issues/issue-89574.rs
+++ b/tests/ui/parser/issues/issue-89574.rs
@@ -2,5 +2,4 @@ fn main() {
     const EMPTY_ARRAY = [];
     //~^ missing type for `const` item
     //~| ERROR type annotations needed
-    //~| ERROR type annotations needed
 }
diff --git a/tests/ui/parser/issues/issue-89574.stderr b/tests/ui/parser/issues/issue-89574.stderr
index aa5e66b18a9..f40f5aded8e 100644
--- a/tests/ui/parser/issues/issue-89574.stderr
+++ b/tests/ui/parser/issues/issue-89574.stderr
@@ -15,14 +15,6 @@ help: provide a type for the item
 LL |     const EMPTY_ARRAY: <type> = [];
    |                      ++++++++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-89574.rs:2:25
-   |
-LL |     const EMPTY_ARRAY = [];
-   |                         ^^ cannot infer type
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs
index dd2c3536eb9..094584ff850 100644
--- a/tests/ui/suggestions/unnamable-types.rs
+++ b/tests/ui/suggestions/unnamable-types.rs
@@ -10,7 +10,7 @@ const A = 5;
 static B: _ = "abc";
 //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables
 //~| NOTE: not allowed in type signatures
-//~| HELP: replace with the correct type
+//~| HELP: replace this with a fully-specified type
 
 
 // FIXME: this should also suggest a function pointer, as the closure is non-capturing
diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr
index 6623678fd0c..dc236af91f8 100644
--- a/tests/ui/suggestions/unnamable-types.stderr
+++ b/tests/ui/suggestions/unnamable-types.stderr
@@ -8,10 +8,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/unnamable-types.rs:10:11
    |
 LL | static B: _ = "abc";
-   |           ^
-   |           |
-   |           not allowed in type signatures
-   |           help: replace with the correct type: `&str`
+   |           ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static B: &str = "abc";
+   |           ~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/unnamable-types.rs:17:10
diff --git a/tests/ui/typeck/issue-79040.rs b/tests/ui/typeck/issue-79040.rs
index 03e00820756..f8e38e7867d 100644
--- a/tests/ui/typeck/issue-79040.rs
+++ b/tests/ui/typeck/issue-79040.rs
@@ -1,6 +1,6 @@
 fn main() {
-    const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str`
-    //~^ missing type for `const` item
-    //~| ERROR cannot add `{integer}` to `&str`
+    const FOO = "hello" + 1;
+    //~^ ERROR cannot add `{integer}` to `&str`
+    //~| missing type for `const` item
     println!("{}", FOO);
 }
diff --git a/tests/ui/typeck/issue-79040.stderr b/tests/ui/typeck/issue-79040.stderr
index 39636db85a7..4ab8df8f6c9 100644
--- a/tests/ui/typeck/issue-79040.stderr
+++ b/tests/ui/typeck/issue-79040.stderr
@@ -17,16 +17,6 @@ help: provide a type for the item
 LL |     const FOO: <type> = "hello" + 1;
    |              ++++++++
 
-error[E0369]: cannot add `{integer}` to `&str`
-  --> $DIR/issue-79040.rs:2:25
-   |
-LL |     const FOO = "hello" + 1;
-   |                 ------- ^ - {integer}
-   |                 |
-   |                 &str
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs
index 437a1aed403..9f1bfd7909e 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_item.rs
@@ -221,6 +221,7 @@ fn value() -> Option<&'static _> {
 
 const _: Option<_> = map(value);
 //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
+//~| ERROR cannot call non-const function `map::<u8>` in constants
 
 fn evens_squared(n: usize) -> _ {
 //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index e62ebae5fd2..c97b9312076 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -67,25 +67,36 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:13:15
    |
 LL | static TEST3: _ = "test";
-   |               ^
-   |               |
-   |               not allowed in type signatures
-   |               help: replace with the correct type: `&str`
+   |               ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static TEST3: &str = "test";
+   |               ~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:16:15
    |
 LL | static TEST4: _ = 145;
-   |               ^
-   |               |
-   |               not allowed in type signatures
-   |               help: replace with the correct type: `i32`
+   |               ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static TEST4: i32 = 145;
+   |               ~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:19:15
+  --> $DIR/typeck_type_placeholder_item.rs:19:16
    |
 LL | static TEST5: (_, _) = (1, 2);
-   |               ^^^^^^ not allowed in type signatures
+   |                ^  ^ not allowed in type signatures
+   |                |
+   |                not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | static TEST5: (i32, i32) = (1, 2);
+   |               ~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:22:13
@@ -220,16 +231,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:75:15
    |
 LL |     static B: _ = 42;
-   |               ^
-   |               |
-   |               not allowed in type signatures
-   |               help: replace with the correct type: `i32`
+   |               ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     static B: i32 = 42;
+   |               ~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:77:15
+  --> $DIR/typeck_type_placeholder_item.rs:77:22
    |
 LL |     static C: Option<_> = Some(42);
-   |               ^^^^^^^^^ not allowed in type signatures
+   |                      ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     static C: Option<i32> = Some(42);
+   |               ~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/typeck_type_placeholder_item.rs:79:21
@@ -254,25 +272,36 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:85:22
    |
 LL |     static FN_TEST3: _ = "test";
-   |                      ^
-   |                      |
-   |                      not allowed in type signatures
-   |                      help: replace with the correct type: `&str`
+   |                      ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     static FN_TEST3: &str = "test";
+   |                      ~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
   --> $DIR/typeck_type_placeholder_item.rs:88:22
    |
 LL |     static FN_TEST4: _ = 145;
-   |                      ^
-   |                      |
-   |                      not allowed in type signatures
-   |                      help: replace with the correct type: `i32`
+   |                      ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     static FN_TEST4: i32 = 145;
+   |                      ~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:91:22
+  --> $DIR/typeck_type_placeholder_item.rs:91:23
    |
 LL |     static FN_TEST5: (_, _) = (1, 2);
-   |                      ^^^^^^ not allowed in type signatures
+   |                       ^  ^ not allowed in type signatures
+   |                       |
+   |                       not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     static FN_TEST5: (i32, i32) = (1, 2);
+   |                      ~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:94:20
@@ -539,10 +568,12 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:194:14
    |
 LL |     const D: _ = 42;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `i32`
+   |              ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     const D: i32 = 42;
+   |              ~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
   --> $DIR/typeck_type_placeholder_item.rs:209:14
@@ -569,16 +600,18 @@ LL | fn value() -> Option<&'static _> {
    |               help: replace with the correct return type: `Option<&'static u8>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:222:10
+  --> $DIR/typeck_type_placeholder_item.rs:222:17
    |
 LL | const _: Option<_> = map(value);
-   |          ^^^^^^^^^
-   |          |
-   |          not allowed in type signatures
-   |          help: replace with the correct type: `Option<u8>`
+   |                 ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const _: Option<u8> = map(value);
+   |          ~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:225:31
+  --> $DIR/typeck_type_placeholder_item.rs:226:31
    |
 LL | fn evens_squared(n: usize) -> _ {
    |                               ^
@@ -587,13 +620,13 @@ LL | fn evens_squared(n: usize) -> _ {
    |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:230:10
+  --> $DIR/typeck_type_placeholder_item.rs:231:10
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |          ^ not allowed in type signatures
    |
-note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named
-  --> $DIR/typeck_type_placeholder_item.rs:230:14
+note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:231:29}>, {closure@typeck_type_placeholder_item.rs:231:49}>` cannot be named
+  --> $DIR/typeck_type_placeholder_item.rs:231:14
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -668,23 +701,31 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
 LL |     type F: std::ops::Fn(_);
    |                          ^ not allowed in type signatures
 
-error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}>` in constants
-  --> $DIR/typeck_type_placeholder_item.rs:230:22
+error[E0015]: cannot call non-const function `map::<u8>` in constants
+  --> $DIR/typeck_type_placeholder_item.rs:222:22
+   |
+LL | const _: Option<_> = map(value);
+   |                      ^^^^^^^^^^
+   |
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:231:29: 231:32}>` in constants
+  --> $DIR/typeck_type_placeholder_item.rs:231:22
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |                      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:230:49: 230:52}>` in constants
-  --> $DIR/typeck_type_placeholder_item.rs:230:45
+error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:231:29: 231:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:231:49: 231:52}>` in constants
+  --> $DIR/typeck_type_placeholder_item.rs:231:45
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |                                             ^^^^^^^^^^^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 74 previous errors
+error: aborting due to 75 previous errors
 
 Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr
index 32585e2937b..a05e27cebfc 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr
@@ -11,19 +11,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:7:14
    |
 LL | const TEST2: _ = 42u32;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `u32`
+   |              ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const TEST2: u32 = 42u32;
+   |              ~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
   --> $DIR/typeck_type_placeholder_item_help.rs:10:14
    |
 LL | const TEST3: _ = Some(42);
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `Option<i32>`
+   |              ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL | const TEST3: Option<i32> = Some(42);
+   |              ~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item_help.rs:13:22
@@ -41,19 +45,23 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:25:18
    |
 LL |     const TEST6: _ = 13;
-   |                  ^
-   |                  |
-   |                  not allowed in type signatures
-   |                  help: replace with the correct type: `i32`
+   |                  ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     const TEST6: i32 = 13;
+   |                  ~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
   --> $DIR/typeck_type_placeholder_item_help.rs:18:18
    |
 LL |     const TEST5: _ = 42;
-   |                  ^
-   |                  |
-   |                  not allowed in type signatures
-   |                  help: replace with the correct type: `i32`
+   |                  ^ not allowed in type signatures
+   |
+help: replace this with a fully-specified type
+   |
+LL |     const TEST5: i32 = 42;
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/typeck_type_placeholder_item_help.rs:30:28