about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir/src/hir.rs14
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs90
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs14
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs35
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs32
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/effects.rs106
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs43
-rw-r--r--src/bootstrap/src/core/builder/mod.rs4
-rw-r--r--src/doc/rustc/src/SUMMARY.md19
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/win7-windows-gnu.md48
-rw-r--r--src/doc/rustc/src/platform-support/win7-windows-msvc.md8
-rw-r--r--src/tools/replace-version-placeholder/src/main.rs7
-rw-r--r--tests/assembly/targets/targets-pe.rs6
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr93
-rw-r--r--tests/ui/consts/promoted_const_call.stderr4
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr19
-rw-r--r--tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs70
-rw-r--r--tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr124
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.rs3
-rw-r--r--tests/ui/traits/const-traits/const-drop-bound.stderr17
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr9
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr9
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr (renamed from tests/ui/traits/const-traits/const-drop-fail.precise.stderr)8
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr (renamed from tests/ui/traits/const-traits/const-drop-fail.stock.stderr)8
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr33
-rw-r--r--tests/ui/traits/const-traits/const-drop-fail.rs7
35 files changed, 739 insertions, 159 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 951e95a6385..dd96b30fefc 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -7,7 +7,7 @@ use rustc_ast::token::CommentKind;
 use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
 use rustc_ast::{
     self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
-    IntTy, Label, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
+    IntTy, Label, LitIntType, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
 };
 pub use rustc_ast::{
     BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
@@ -2094,6 +2094,18 @@ impl Expr<'_> {
         }
     }
 
+    /// Check if expression is an integer literal that can be used
+    /// where `usize` is expected.
+    pub fn is_size_lit(&self) -> bool {
+        matches!(
+            self.kind,
+            ExprKind::Lit(Lit {
+                node: LitKind::Int(_, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::Usize)),
+                ..
+            })
+        )
+    }
+
     /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
     /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
     /// silent, only signaling the ownership system. By doing this, suggestions that check the
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index a93da52b270..0f424a39840 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -165,6 +165,8 @@ hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this ret
 hir_typeck_remove_semi_for_coerce_semi = the `match` is a statement because of this semicolon, consider removing it
 hir_typeck_remove_semi_for_coerce_suggestion = remove this semicolon
 
+hir_typeck_replace_comma_with_semicolon = replace the comma with a semicolon to create {$descr}
+
 hir_typeck_return_stmt_outside_of_fn_body =
     {$statement_kind} statement outside of function body
     .encl_body_label = the {$statement_kind} is part of this body...
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index e51323fc5c8..56f7a2c1150 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -30,7 +30,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if expr_ty == expected {
             return;
         }
-
         self.annotate_alternative_method_deref(err, expr, error);
         self.explain_self_literal(err, expr, expected, expr_ty);
 
@@ -39,6 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
             || self.suggest_remove_last_method_call(err, expr, expected)
             || self.suggest_associated_const(err, expr, expected)
+            || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty)
             || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
             || self.suggest_option_to_bool(err, expr, expr_ty, expected)
             || self.suggest_compatible_variants(err, expr, expected, expr_ty)
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ff09583cc65..4eed2bc1238 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -846,3 +846,16 @@ pub(crate) struct PassFnItemToVariadicFunction {
     pub sugg_span: Span,
     pub replace: String,
 }
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    hir_typeck_replace_comma_with_semicolon,
+    applicability = "machine-applicable",
+    style = "verbose",
+    code = "; "
+)]
+pub(crate) struct ReplaceCommaWithSemicolon {
+    #[primary_span]
+    pub comma_span: Span,
+    pub descr: &'static str,
+}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 3756f6339a4..39511ca30e0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1320,14 +1320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let span = expr.span.shrink_to_hi();
                 let subdiag = if self.type_is_copy_modulo_regions(self.param_env, ty) {
                     errors::OptionResultRefMismatch::Copied { span, def_path }
-                } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
-                    && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
-                        self,
-                        self.param_env,
-                        ty,
-                        clone_did,
-                    )
-                {
+                } else if self.type_is_clone_modulo_regions(self.param_env, ty) {
                     errors::OptionResultRefMismatch::Cloned { span, def_path }
                 } else {
                     return false;
@@ -2182,6 +2175,87 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    /// Suggest replacing comma with semicolon in incorrect repeat expressions
+    /// like `["_", 10]` or `vec![String::new(), 10]`.
+    pub(crate) fn suggest_semicolon_in_repeat_expr(
+        &self,
+        err: &mut Diag<'_>,
+        expr: &hir::Expr<'_>,
+        expr_ty: Ty<'tcx>,
+    ) -> bool {
+        // Check if `expr` is contained in array of two elements
+        if let hir::Node::Expr(array_expr) = self.tcx.parent_hir_node(expr.hir_id)
+            && let hir::ExprKind::Array(elements) = array_expr.kind
+            && let [first, second] = &elements[..]
+            && second.hir_id == expr.hir_id
+        {
+            // Span between the two elements of the array
+            let comma_span = first.span.between(second.span);
+
+            // Check if `expr` is a constant value of type `usize`.
+            // This can only detect const variable declarations and
+            // calls to const functions.
+
+            // Checking this here instead of rustc_hir::hir because
+            // this check needs access to `self.tcx` but rustc_hir
+            // has no access to `TyCtxt`.
+            let expr_is_const_usize = expr_ty.is_usize()
+                && match expr.kind {
+                    ExprKind::Path(QPath::Resolved(
+                        None,
+                        Path { res: Res::Def(DefKind::Const, _), .. },
+                    )) => true,
+                    ExprKind::Call(
+                        Expr {
+                            kind:
+                                ExprKind::Path(QPath::Resolved(
+                                    None,
+                                    Path { res: Res::Def(DefKind::Fn, fn_def_id), .. },
+                                )),
+                            ..
+                        },
+                        _,
+                    ) => self.tcx.is_const_fn(*fn_def_id),
+                    _ => false,
+                };
+
+            // Type of the first element is guaranteed to be checked
+            // when execution reaches here because `mismatched types`
+            // error occurs only when type of second element of array
+            // is not the same as type of first element.
+            let first_ty = self.typeck_results.borrow().expr_ty(first);
+
+            // `array_expr` is from a macro `vec!["a", 10]` if
+            // 1. array expression's span is imported from a macro
+            // 2. first element of array implements `Clone` trait
+            // 3. second element is an integer literal or is an expression of `usize` like type
+            if self.tcx.sess.source_map().is_imported(array_expr.span)
+                && self.type_is_clone_modulo_regions(self.param_env, first_ty)
+                && (expr.is_size_lit() || expr_ty.is_usize_like())
+            {
+                err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
+                    comma_span,
+                    descr: "a vector",
+                });
+                return true;
+            }
+
+            // `array_expr` is from an array `["a", 10]` if
+            // 1. first element of array implements `Copy` trait
+            // 2. second element is an integer literal or is a const value of type `usize`
+            if self.type_is_copy_modulo_regions(self.param_env, first_ty)
+                && (expr.is_size_lit() || expr_is_const_usize)
+            {
+                err.subdiagnostic(errors::ReplaceCommaWithSemicolon {
+                    comma_span,
+                    descr: "an array",
+                });
+                return true;
+            }
+        }
+        false
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     pub(crate) fn suggest_compatible_variants(
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5e929fbec0b..2d69386176b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1417,8 +1417,8 @@ impl Hash for FieldDef {
 impl<'tcx> FieldDef {
     /// Returns the type of this field. The resulting type is not normalized. The `arg` is
     /// typically obtained via the second field of [`TyKind::Adt`].
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, arg: GenericArgsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).instantiate(tcx, arg)
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).instantiate(tcx, args)
     }
 
     /// Computes the `Ident` of this variant by looking up the `Span`
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 92b3632c8ac..2980964898c 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -27,7 +27,7 @@ use crate::infer::canonical::Canonical;
 use crate::ty::InferTy::*;
 use crate::ty::{
     self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
-    Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
 };
 
 // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
@@ -1017,6 +1017,18 @@ impl<'tcx> Ty<'tcx> {
         }
     }
 
+    /// Check if type is an `usize`.
+    #[inline]
+    pub fn is_usize(self) -> bool {
+        matches!(self.kind(), Uint(UintTy::Usize))
+    }
+
+    /// Check if type is an `usize` or an integral type variable.
+    #[inline]
+    pub fn is_usize_like(self) -> bool {
+        matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
+    }
+
     #[inline]
     pub fn is_never(self) -> bool {
         matches!(self.kind(), Never)
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 7da4f5e0107..3c5d9b95e77 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -712,6 +712,8 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable<I: Interner>(
     }
 }
 
+// NOTE: Keep this in sync with `evaluate_host_effect_for_destruct_goal` in
+// the old solver, for as long as that exists.
 pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
     cx: I,
     self_ty: I::Ty,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0dc1d795a8e..a149f682c56 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1812,9 +1812,11 @@ supported_targets! {
     ("aarch64-unknown-illumos", aarch64_unknown_illumos),
 
     ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
+    ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
+    ("x86_64-win7-windows-gnu", x86_64_win7_windows_gnu),
     ("i686-pc-windows-gnu", i686_pc_windows_gnu),
     ("i686-uwp-windows-gnu", i686_uwp_windows_gnu),
-    ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu),
+    ("i686-win7-windows-gnu", i686_win7_windows_gnu),
 
     ("aarch64-pc-windows-gnullvm", aarch64_pc_windows_gnullvm),
     ("i686-pc-windows-gnullvm", i686_pc_windows_gnullvm),
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
new file mode 100644
index 00000000000..086a799a68c
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
@@ -0,0 +1,35 @@
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::windows_gnu::opts();
+    base.vendor = "win7".into();
+    base.cpu = "pentium4".into();
+    base.max_atomic_width = Some(64);
+    base.frame_pointer = FramePointer::Always; // Required for backtraces
+    base.linker = Some("i686-w64-mingw32-gcc".into());
+
+    // Mark all dynamic libraries and executables as compatible with the larger 4GiB address
+    // space available to x86 Windows binaries on x86_64.
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[
+        "-m",
+        "i386pe",
+        "--large-address-aware",
+    ]);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,--large-address-aware"]);
+
+    Target {
+        llvm_target: "i686-pc-windows-gnu".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("32-bit MinGW (Windows 7+)".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: Some(true),
+        },
+        pointer_width: 32,
+        data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
+            i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
+            .into(),
+        arch: "x86".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
new file mode 100644
index 00000000000..d40df5a3e7d
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_gnu.rs
@@ -0,0 +1,32 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, base};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::windows_gnu::opts();
+    base.vendor = "win7".into();
+    base.cpu = "x86-64".into();
+    base.plt_by_default = false;
+    // Use high-entropy 64 bit address space for ASLR
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[
+        "-m",
+        "i386pep",
+        "--high-entropy-va",
+    ]);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
+    base.max_atomic_width = Some(64);
+    base.linker = Some("x86_64-w64-mingw32-gcc".into());
+
+    Target {
+        llvm_target: "x86_64-pc-windows-gnu".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("64-bit MinGW (Windows 7+)".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout:
+            "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
+        arch: "x86_64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index ee708564a80..f373706b296 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -47,6 +47,12 @@ impl<'tcx> InferCtxt<'tcx> {
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
     }
 
+    fn type_is_clone_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
+        let ty = self.resolve_vars_if_possible(ty);
+        let clone_def_id = self.tcx.require_lang_item(LangItem::Clone, None);
+        traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, clone_def_id)
+    }
+
     fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
         let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 0ac24eb54e7..b32909efe0b 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -1,4 +1,4 @@
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
 use rustc_infer::traits::{
     ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
@@ -48,6 +48,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
         Err(EvaluationFailure::NoSolution) => {}
     }
 
+    match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
+        Ok(result) => return Ok(result),
+        Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
+        Err(EvaluationFailure::NoSolution) => {}
+    }
+
     match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
         Ok(result) => return Ok(result),
         Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
@@ -228,6 +234,104 @@ fn evaluate_host_effect_from_item_bounds<'tcx>(
     }
 }
 
+fn evaluate_host_effect_from_builtin_impls<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
+        Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
+        _ => Err(EvaluationFailure::NoSolution),
+    }
+}
+
+// NOTE: Keep this in sync with `const_conditions_for_destruct` in the new solver.
+fn evaluate_host_effect_for_destruct_goal<'tcx>(
+    selcx: &mut SelectionContext<'_, 'tcx>,
+    obligation: &HostEffectObligation<'tcx>,
+) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
+    let tcx = selcx.tcx();
+    let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, None);
+    let self_ty = obligation.predicate.self_ty();
+
+    let const_conditions = match *self_ty.kind() {
+        // An ADT is `~const Destruct` only if all of the fields are,
+        // *and* if there is a `Drop` impl, that `Drop` impl is also `~const`.
+        ty::Adt(adt_def, args) => {
+            let mut const_conditions: ThinVec<_> = adt_def
+                .all_fields()
+                .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
+                .collect();
+            match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
+                // `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
+                Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
+                // `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
+                Some(hir::Constness::Const) => {
+                    let drop_def_id = tcx.require_lang_item(LangItem::Drop, None);
+                    let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
+                    const_conditions.push(drop_trait_ref);
+                }
+                // No `Drop` impl, no need to require anything else.
+                None => {}
+            }
+            const_conditions
+        }
+
+        ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
+            thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
+        }
+
+        ty::Tuple(tys) => {
+            tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
+        }
+
+        // Trivially implement `~const Destruct`
+        ty::Bool
+        | ty::Char
+        | ty::Int(..)
+        | ty::Uint(..)
+        | ty::Float(..)
+        | ty::Str
+        | ty::RawPtr(..)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(..)
+        | ty::Never
+        | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
+        | ty::Error(_) => thin_vec![],
+
+        // Coroutines and closures could implement `~const Drop`,
+        // but they don't really need to right now.
+        ty::Closure(_, _)
+        | ty::CoroutineClosure(_, _)
+        | ty::Coroutine(_, _)
+        | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
+
+        // FIXME(unsafe_binders): Unsafe binders could implement `~const Drop`
+        // if their inner type implements it.
+        ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
+
+        ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
+            return Err(EvaluationFailure::NoSolution);
+        }
+
+        ty::Bound(..)
+        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+            panic!("unexpected type `{self_ty:?}`")
+        }
+    };
+
+    Ok(const_conditions
+        .into_iter()
+        .map(|trait_ref| {
+            obligation.with(
+                tcx,
+                ty::Binder::dummy(trait_ref)
+                    .to_host_effect_clause(tcx, obligation.predicate.constness),
+            )
+        })
+        .collect())
+}
+
 fn evaluate_host_effect_from_selection_candiate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &HostEffectObligation<'tcx>,
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index dc6dbbac9d2..914260e38d1 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -31,6 +31,7 @@ use crate::{CLang, DocTests, GitRepo, Mode, PathSet, envify};
 
 const ADB_TEST_DIR: &str = "/data/local/tmp/work";
 
+/// Runs `cargo test` on various internal tools used by bootstrap.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateBootstrap {
     path: PathBuf,
@@ -43,13 +44,21 @@ impl Step for CrateBootstrap {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        // This step is responsible for several different tool paths. By default
+        // it will test all of them, but requesting specific tools on the
+        // command-line (e.g. `./x test suggest-tests`) will test only the
+        // specified tools.
         run.path("src/tools/jsondoclint")
             .path("src/tools/suggest-tests")
             .path("src/tools/replace-version-placeholder")
+            // We want `./x test tidy` to _run_ the tidy tool, not its tests.
+            // So we need a separate alias to test the tidy tool itself.
             .alias("tidyselftest")
     }
 
     fn make_run(run: RunConfig<'_>) {
+        // Create and ensure a separate instance of this step for each path
+        // that was selected on the command-line (or selected by default).
         for path in run.paths {
             let path = path.assert_single_path().path.clone();
             run.builder.ensure(CrateBootstrap { host: run.target, path });
@@ -60,6 +69,8 @@ impl Step for CrateBootstrap {
         let bootstrap_host = builder.config.build;
         let compiler = builder.compiler(0, bootstrap_host);
         let mut path = self.path.to_str().unwrap();
+
+        // Map alias `tidyselftest` back to the actual crate path of tidy.
         if path == "tidyselftest" {
             path = "src/tools/tidy";
         }
@@ -212,6 +223,9 @@ impl Step for HtmlCheck {
     }
 }
 
+/// Builds cargo and then runs the `src/tools/cargotest` tool, which checks out
+/// some representative crate repositories and runs `cargo test` on them, in
+/// order to test cargo.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Cargotest {
     stage: u32,
@@ -257,6 +271,7 @@ impl Step for Cargotest {
     }
 }
 
+/// Runs `cargo test` for cargo itself.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Cargo {
     stage: u32,
@@ -385,6 +400,7 @@ impl Step for RustAnalyzer {
     }
 }
 
+/// Runs `cargo test` for rustfmt.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Rustfmt {
     stage: u32,
@@ -589,6 +605,8 @@ impl Step for Miri {
     }
 }
 
+/// Runs `cargo miri test` to demonstrate that `src/tools/miri/cargo-miri`
+/// works and that libtest works under miri.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CargoMiri {
     target: TargetSelection,
@@ -1020,6 +1038,10 @@ impl Step for RustdocGUI {
     }
 }
 
+/// Runs `src/tools/tidy` and `cargo fmt --check` to detect various style
+/// problems in the repository.
+///
+/// (To run the tidy tool's internal tests, use the alias "tidyselftest" instead.)
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Tidy;
 
@@ -1230,6 +1252,8 @@ impl Step for RunMakeSupport {
     }
 }
 
+/// Runs `cargo test` on the `src/tools/run-make-support` crate.
+/// That crate is used by run-make tests.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateRunMakeSupport {
     host: TargetSelection,
@@ -2466,6 +2490,10 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
     }
 }
 
+/// Runs `cargo test` for the compiler crates in `compiler/`.
+///
+/// (This step does not test `rustc_codegen_cranelift` or `rustc_codegen_gcc`,
+/// which have their own separate test steps.)
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateLibrustc {
     compiler: Compiler,
@@ -2494,6 +2522,7 @@ impl Step for CrateLibrustc {
     fn run(self, builder: &Builder<'_>) {
         builder.ensure(compile::Std::new(self.compiler, self.target));
 
+        // To actually run the tests, delegate to a copy of the `Crate` step.
         builder.ensure(Crate {
             compiler: self.compiler,
             target: self.target,
@@ -2619,6 +2648,13 @@ fn prepare_cargo_test(
     cargo
 }
 
+/// Runs `cargo test` for standard library crates.
+///
+/// (Also used internally to run `cargo test` for compiler crates.)
+///
+/// FIXME(Zalathar): Try to split this into two separate steps: a user-visible
+/// step for testing standard library crates, and an internal step used for both
+/// library crates and compiler crates.
 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Crate {
     pub compiler: Compiler,
@@ -3552,6 +3588,10 @@ impl Step for CodegenGCC {
     }
 }
 
+/// Test step that does two things:
+/// - Runs `cargo test` for the `src/etc/test-float-parse` tool.
+/// - Invokes the `test-float-parse` tool to test the standard library's
+///   float parsing routines.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct TestFloatParse {
     path: PathBuf,
@@ -3625,6 +3665,9 @@ impl Step for TestFloatParse {
     }
 }
 
+/// Runs the tool `src/tools/collect-license-metadata` in `ONLY_CHECK=1` mode,
+/// which verifies that `license-metadata.json` is up-to-date and therefore
+/// running the tool normally would not update anything.
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct CollectLicenseMetadata;
 
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index da2ce5b5976..848a283d538 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1,5 +1,3 @@
-mod cargo;
-
 use std::any::{Any, type_name};
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
@@ -25,6 +23,8 @@ use crate::utils::exec::{BootstrapCommand, command};
 use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t};
 use crate::{Build, Crate};
 
+mod cargo;
+
 #[cfg(test)]
 mod tests;
 
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index d7e368cc87f..670e4bd1be6 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -70,8 +70,8 @@
     - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
     - [powerpc64-ibm-aix](platform-support/aix.md)
     - [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md)
-    - [riscv32e*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
-    - [riscv32i*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
+    - [riscv32e\*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
+    - [riscv32i\*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
     - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
@@ -80,14 +80,14 @@
     - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
     - [sparcv9-sun-solaris](platform-support/solaris.md)
-    - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
+    - [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
-    - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
-    - [*-unknown-hermit](platform-support/hermit.md)
-    - [*-unknown-freebsd](platform-support/freebsd.md)
+    - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
+    - [\*-unknown-hermit](platform-support/hermit.md)
+    - [\*-unknown-freebsd](platform-support/freebsd.md)
     - [\*-unknown-netbsd\*](platform-support/netbsd.md)
-    - [*-unknown-openbsd](platform-support/openbsd.md)
-    - [*-unknown-redox](platform-support/redox.md)
+    - [\*-unknown-openbsd](platform-support/openbsd.md)
+    - [\*-unknown-redox](platform-support/redox.md)
     - [\*-unknown-uefi](platform-support/unknown-uefi.md)
     - [\*-uwp-windows-msvc](platform-support/uwp-windows-msvc.md)
     - [\*-wrs-vxworks](platform-support/vxworks.md)
@@ -98,13 +98,14 @@
     - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
     - [wasm32v1-none](platform-support/wasm32v1-none.md)
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
+    - [\*-win7-windows-gnu](platform-support/win7-windows-gnu.md)
     - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
     - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
     - [x86_64-pc-solaris](platform-support/solaris.md)
     - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
     - [xtensa-\*-none-elf](platform-support/xtensa.md)
-    - [*-nuttx-\*](platform-support/nuttx.md)
+    - [\*-nuttx-\*](platform-support/nuttx.md)
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index a68efcda1f3..deeabd810d3 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -313,6 +313,7 @@ target | std | host | notes
 [`i686-unknown-redox`](platform-support/redox.md) | ✓ |  | i686 Redox OS
 `i686-uwp-windows-gnu` | ✓ |  | [^x86_32-floats-return-ABI]
 [`i686-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  | [^x86_32-floats-return-ABI]
+[`i686-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 [`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |   | LoongArch64 OpenHarmony
@@ -410,6 +411,7 @@ target | std | host | notes
 [`x86_64-unknown-trusty`](platform-support/trusty.md) | ? |  |
 `x86_64-uwp-windows-gnu` | ✓ |  |
 [`x86_64-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | ✓ |  |
+[`x86_64-win7-windows-gnu`](platform-support/win7-windows-gnu.md) | ✓ |   | 64-bit Windows 7 support
 [`x86_64-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 64-bit Windows 7 support
 [`x86_64-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  |
 [`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell)
diff --git a/src/doc/rustc/src/platform-support/win7-windows-gnu.md b/src/doc/rustc/src/platform-support/win7-windows-gnu.md
new file mode 100644
index 00000000000..180a1dc6d26
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/win7-windows-gnu.md
@@ -0,0 +1,48 @@
+# \*-win7-windows-gnu
+
+**Tier: 3**
+
+Windows targets continuing support of Windows 7.
+
+Target triples:
+- `i686-win7-windows-gnu`
+- `x86_64-win7-windows-gnu`
+
+## Target maintainers
+
+- @tbu-
+
+## Requirements
+
+This target supports all of core, alloc, std and test. Host
+tools may also work, though those are not currently tested.
+
+Those targets follow Windows calling convention for extern "C".
+
+Like any other Windows target, the created binaries are in PE format.
+
+## Building the target
+
+You can build Rust with support for the targets by adding it to the target list in config.toml:
+
+```toml
+[build]
+build-stage = 1
+target = ["x86_64-win7-windows-gnu"]
+```
+
+## Building Rust programs
+
+Rust does not ship pre-compiled artifacts for this target. To compile for this
+target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy by using `build-std` or
+similar.
+
+## Testing
+
+Created binaries work fine on Windows or Wine using native hardware. Remote
+testing is possible using the `remote-test-server` described [here](https://rustc-dev-guide.rust-lang.org/tests/running.html#running-tests-on-a-remote-machine).
+
+## Cross-compilation toolchains and C code
+
+Compatible C code can be built with gcc's `{i686,x86_64}-w64-mingw32-gcc`.
diff --git a/src/doc/rustc/src/platform-support/win7-windows-msvc.md b/src/doc/rustc/src/platform-support/win7-windows-msvc.md
index 45b00a2be82..77b7d68212b 100644
--- a/src/doc/rustc/src/platform-support/win7-windows-msvc.md
+++ b/src/doc/rustc/src/platform-support/win7-windows-msvc.md
@@ -1,8 +1,12 @@
-# *-win7-windows-msvc
+# \*-win7-windows-msvc
 
 **Tier: 3**
 
-Windows targets continuing support of windows7.
+Windows targets continuing support of Windows 7.
+
+Target triples:
+- `i686-win7-windows-msvc`
+- `x86_64-win7-windows-msvc`
 
 ## Target maintainers
 
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 88118cab235..fb2838a4ea0 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -10,7 +10,12 @@ fn main() {
     let version_str = t!(std::fs::read_to_string(&version_path), version_path);
     let version_str = version_str.trim();
     walk::walk_many(
-        &[&root_path.join("compiler"), &root_path.join("library")],
+        &[
+            &root_path.join("compiler"),
+            &root_path.join("library"),
+            &root_path.join("src/doc/rustc"),
+            &root_path.join("src/doc/rustdoc"),
+        ],
         |path, _is_dir| walk::filter_dirs(path),
         &mut |entry, contents| {
             if !contents.contains(VERSION_PLACEHOLDER) {
diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs
index 6415aee6fae..ab74de5c8ec 100644
--- a/tests/assembly/targets/targets-pe.rs
+++ b/tests/assembly/targets/targets-pe.rs
@@ -39,6 +39,9 @@
 //@ revisions: i686_uwp_windows_gnu
 //@ [i686_uwp_windows_gnu] compile-flags: --target i686-uwp-windows-gnu
 //@ [i686_uwp_windows_gnu] needs-llvm-components: x86
+//@ revisions: i686_win7_windows_gnu
+//@ [i686_win7_windows_gnu] compile-flags: --target i686-win7-windows-gnu
+//@ [i686_win7_windows_gnu] needs-llvm-components: x86
 //@ revisions: i686_unknown_uefi
 //@ [i686_unknown_uefi] compile-flags: --target i686-unknown-uefi
 //@ [i686_unknown_uefi] needs-llvm-components: x86
@@ -72,6 +75,9 @@
 //@ revisions: x86_64_uwp_windows_gnu
 //@ [x86_64_uwp_windows_gnu] compile-flags: --target x86_64-uwp-windows-gnu
 //@ [x86_64_uwp_windows_gnu] needs-llvm-components: x86
+//@ revisions: x86_64_win7_windows_gnu
+//@ [x86_64_win7_windows_gnu] compile-flags: --target x86_64-win7-windows-gnu
+//@ [x86_64_win7_windows_gnu] needs-llvm-components: x86
 //@ revisions: x86_64_uwp_windows_msvc
 //@ [x86_64_uwp_windows_msvc] compile-flags: --target x86_64-uwp-windows-msvc
 //@ [x86_64_uwp_windows_msvc] needs-llvm-components: x86
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index e0dbecff8e5..d688bfbde2b 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -155,90 +155,21 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:70:32
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:71:17
    |
-LL |         let test_one = test_fn(one);
-   |                        ------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
+LL |         assert!(test_one == (1, 1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^
    |
-note: required by a bound in `test_fn`
-  --> $DIR/fn_trait_refs.rs:35:24
-   |
-LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output)
-   |          ------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `test_fn`
-
-error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:73:36
-   |
-LL |         let test_two = test_fn_mut(two);
-   |                        ----------- ^^^
-   |                        |
-   |                        required by a bound introduced by this call
-   |
-note: required by a bound in `test_fn_mut`
-  --> $DIR/fn_trait_refs.rs:49:27
-   |
-LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output)
-   |          ----------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `test_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:39:19
-   |
-LL |         tester_fn(&f),
-   |         --------- ^^
-   |         |
-   |         required by a bound introduced by this call
+error[E0015]: cannot call non-const operator in constants
+  --> $DIR/fn_trait_refs.rs:74:17
    |
-note: required by a bound in `tester_fn`
-  --> $DIR/fn_trait_refs.rs:14:24
+LL |         assert!(test_two == (2, 2));
+   |                 ^^^^^^^^^^^^^^^^^^
    |
-LL | const fn tester_fn<T>(f: T) -> T::Output
-   |          --------- required by a bound in this function
-LL | where
-LL |     T: ~const Fn<()> + ~const Destruct,
-   |                        ^^^^^^ required by this bound in `tester_fn`
-
-error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:41:23
-   |
-LL |         tester_fn_mut(&f),
-   |         ------------- ^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
-
-error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied
-  --> $DIR/fn_trait_refs.rs:53:23
-   |
-LL |         tester_fn_mut(&mut f),
-   |         ------------- ^^^^^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-note: required by a bound in `tester_fn_mut`
-  --> $DIR/fn_trait_refs.rs:21:27
-   |
-LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output
-   |          ------------- required by a bound in this function
-LL | where
-LL |     T: ~const FnMut<()> + ~const Destruct,
-   |                           ^^^^^^ required by this bound in `tester_fn_mut`
+   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/fn_trait_refs.rs:16:5
@@ -264,7 +195,7 @@ LL |     f()
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 25 previous errors
+error: aborting due to 22 previous errors
 
-Some errors have detailed explanations: E0015, E0277, E0635.
+Some errors have detailed explanations: E0015, E0635.
 For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr
index dd70bb601c4..40c6d083b06 100644
--- a/tests/ui/consts/promoted_const_call.stderr
+++ b/tests/ui/consts/promoted_const_call.stderr
@@ -5,6 +5,10 @@ LL |     let _: &'static _ = &id(&Panic);
    |                              ^^^^^ - value is dropped here
    |                              |
    |                              the destructor for this type cannot be evaluated in constants
+   |
+   = note: see issue #133214 <https://github.com/rust-lang/rust/issues/133214> for more information
+   = help: add `#![feature(const_destruct)]` 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[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_const_call.rs:16:26
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index 0f79cefeaec..f4e8a872cec 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -17,20 +17,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied
-  --> $DIR/normalize-tait-in-const.rs:33:19
-   |
-LL |     with_positive(foo);
-   |     ------------- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `with_positive`
-  --> $DIR/normalize-tait-in-const.rs:26:62
-   |
-LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
-   |                                                              ^^^^^^ required by this bound in `with_positive`
-
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/normalize-tait-in-const.rs:27:5
    |
@@ -39,7 +25,6 @@ LL |     fun(filter_positive());
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs
new file mode 100644
index 00000000000..c76e7a1d716
--- /dev/null
+++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.rs
@@ -0,0 +1,70 @@
+#[derive(Copy, Clone)]
+struct Type;
+
+struct NewType;
+
+const fn get_size() -> usize {
+    10
+}
+
+fn get_dyn_size() -> usize {
+    10
+}
+
+fn main() {
+    let a = ["a", 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    const size_b: usize = 20;
+    let b = [Type, size_b];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    let size_c: usize = 13;
+    let c = [Type, size_c];
+    //~^ ERROR mismatched types
+
+    const size_d: bool = true;
+    let d = [Type, size_d];
+    //~^ ERROR mismatched types
+
+    let e = [String::new(), 10];
+    //~^ ERROR mismatched types
+    //~| HELP try using a conversion method
+
+    let f = ["f", get_size()];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create an array
+
+    let m = ["m", get_dyn_size()];
+    //~^ ERROR mismatched types
+
+    // is_vec, is_clone, is_usize_like
+    let g = vec![String::new(), 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let dyn_size = 10;
+    let h = vec![Type, dyn_size];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let i = vec![Type, get_dyn_size()];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let k = vec!['c', 10];
+    //~^ ERROR mismatched types
+    //~| HELP replace the comma with a semicolon to create a vector
+
+    let j = vec![Type, 10_u8];
+    //~^ ERROR mismatched types
+
+    let l = vec![NewType, 10];
+    //~^ ERROR mismatched types
+
+    let byte_size: u8 = 10;
+    let h = vec![Type, byte_size];
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr
new file mode 100644
index 00000000000..95eddbde9e6
--- /dev/null
+++ b/tests/ui/repeat-expr/typo-in-repeat-expr-issue-80173.stderr
@@ -0,0 +1,124 @@
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:15:19
+   |
+LL |     let a = ["a", 10];
+   |                   ^^ expected `&str`, found integer
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let a = ["a"; 10];
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:20:20
+   |
+LL |     let b = [Type, size_b];
+   |                    ^^^^^^ expected `Type`, found `usize`
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let b = [Type; size_b];
+   |                  ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:25:20
+   |
+LL |     let c = [Type, size_c];
+   |                    ^^^^^^ expected `Type`, found `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:29:20
+   |
+LL |     let d = [Type, size_d];
+   |                    ^^^^^^ expected `Type`, found `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:32:29
+   |
+LL |     let e = [String::new(), 10];
+   |                             ^^- help: try using a conversion method: `.to_string()`
+   |                             |
+   |                             expected `String`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:36:19
+   |
+LL |     let f = ["f", get_size()];
+   |                   ^^^^^^^^^^ expected `&str`, found `usize`
+   |
+help: replace the comma with a semicolon to create an array
+   |
+LL |     let f = ["f"; get_size()];
+   |                 ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:40:19
+   |
+LL |     let m = ["m", get_dyn_size()];
+   |                   ^^^^^^^^^^^^^^ expected `&str`, found `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:44:33
+   |
+LL |     let g = vec![String::new(), 10];
+   |                                 ^^ expected `String`, found integer
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let g = vec![String::new(); 10];
+   |                               ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:49:24
+   |
+LL |     let h = vec![Type, dyn_size];
+   |                        ^^^^^^^^ expected `Type`, found integer
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let h = vec![Type; dyn_size];
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:53:24
+   |
+LL |     let i = vec![Type, get_dyn_size()];
+   |                        ^^^^^^^^^^^^^^ expected `Type`, found `usize`
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let i = vec![Type; get_dyn_size()];
+   |                      ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:57:23
+   |
+LL |     let k = vec!['c', 10];
+   |                       ^^ expected `char`, found `u8`
+   |
+help: replace the comma with a semicolon to create a vector
+   |
+LL |     let k = vec!['c'; 10];
+   |                     ~
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:61:24
+   |
+LL |     let j = vec![Type, 10_u8];
+   |                        ^^^^^ expected `Type`, found `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:64:27
+   |
+LL |     let l = vec![NewType, 10];
+   |                           ^^ expected `NewType`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/typo-in-repeat-expr-issue-80173.rs:68:24
+   |
+LL |     let h = vec![Type, byte_size];
+   |                        ^^^^^^^^^ expected `Type`, found `u8`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs
index 398fb390640..4819da7c3a4 100644
--- a/tests/ui/traits/const-traits/const-drop-bound.rs
+++ b/tests/ui/traits/const-traits/const-drop-bound.rs
@@ -1,5 +1,4 @@
-//@ known-bug: #110395
-// FIXME check-pass
+//@ check-pass
 
 #![feature(const_trait_impl)]
 #![feature(const_precise_live_drops, const_destruct)]
diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr
deleted file mode 100644
index 78ba0279566..00000000000
--- a/tests/ui/traits/const-traits/const-drop-bound.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Foo<E>: ~const Destruct` is not satisfied
-  --> $DIR/const-drop-bound.rs:23:9
-   |
-LL |     foo(res)
-   |     --- ^^^
-   |     |
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `foo`
-  --> $DIR/const-drop-bound.rs:9:61
-   |
-LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
-   |                                                             ^^^^^^ required by this bound in `foo`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
index 7b2cafb6124..2b5e66b1a08 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr
@@ -1,9 +1,16 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
+  --> $DIR/const-drop-fail-2.rs:25:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |         ------          ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
 note: required by a bound in `check`
   --> $DIR/const-drop-fail-2.rs:21:19
    |
diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
index 7b2cafb6124..2b5e66b1a08 100644
--- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr
@@ -1,9 +1,16 @@
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: const Destruct` is not satisfied
+error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
   --> $DIR/const-drop-fail-2.rs:31:23
    |
 LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
+  --> $DIR/const-drop-fail-2.rs:25:25
+   |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+   |         ------          ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
 note: required by a bound in `check`
   --> $DIR/const-drop-fail-2.rs:21:19
    |
diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
index 8b3e777a0b0..682f48fe07a 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
index 8b3e777a0b0..682f48fe07a 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr
+++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:32:5
+  --> $DIR/const-drop-fail.rs:33:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -8,13 +8,13 @@ LL |     NonTrivialDrop,
    |     ^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:34:5
+  --> $DIR/const-drop-fail.rs:35:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -23,7 +23,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:23:19
+  --> $DIR/const-drop-fail.rs:24:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^ required by this bound in `check`
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
new file mode 100644
index 00000000000..682f48fe07a
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
new file mode 100644
index 00000000000..682f48fe07a
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:33:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied
+  --> $DIR/const-drop-fail.rs:35:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:24:19
+   |
+LL | const fn check<T: ~const Destruct>(_: T) {}
+   |                   ^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs
index 5e05b9db474..a7f3d5654de 100644
--- a/tests/ui/traits/const-traits/const-drop-fail.rs
+++ b/tests/ui/traits/const-traits/const-drop-fail.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -Znext-solver
-//@ revisions: stock precise
+//@[new_precise] compile-flags: -Znext-solver
+//@[new_stock] compile-flags: -Znext-solver
+//@ revisions: new_stock old_stock new_precise old_precise
 
 #![feature(const_trait_impl, const_destruct)]
-#![cfg_attr(precise, feature(const_precise_live_drops))]
+#![cfg_attr(any(new_precise, old_precise), feature(const_precise_live_drops))]
 
 use std::marker::{Destruct, PhantomData};