summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs112
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs26
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs10
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs8
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs9
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs20
-rw-r--r--library/coretests/tests/floats/mod.rs548
-rw-r--r--library/coretests/tests/num/mod.rs353
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/path.rs2
-rw-r--r--library/std/tests/path.rs1
-rw-r--r--src/ci/docker/host-x86_64/mingw-check-2/Dockerfile1
-rw-r--r--src/tools/build-manifest/src/main.rs2
-rw-r--r--tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr10
-rw-r--r--tests/ui/async-await/drop-track-bad-field-in-fru.stderr10
-rw-r--r--tests/ui/async-await/issue-101715.stderr9
-rw-r--r--tests/ui/async-await/unnecessary-await.stderr20
-rw-r--r--tests/ui/cast/cast-to-slice.stderr18
-rw-r--r--tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr18
-rw-r--r--tests/ui/coercion/issue-73886.stderr3
-rw-r--r--tests/ui/coercion/non-primitive-cast-135412.stderr6
-rw-r--r--tests/ui/consts/const-blocks/fn-call-in-non-const.stderr5
-rw-r--r--tests/ui/consts/const-blocks/trait-error.stderr9
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-4b.stderr2
-rw-r--r--tests/ui/consts/const-fn-in-vec.stderr27
-rw-r--r--tests/ui/coroutine/unresolved-ct-var.stderr11
-rw-r--r--tests/ui/error-codes/E0604.stderr11
-rw-r--r--tests/ui/error-codes/E0620.stderr9
-rw-r--r--tests/ui/error-emitter/error-festival.stderr11
-rw-r--r--tests/ui/issues/issue-16048.stderr8
-rw-r--r--tests/ui/issues/issue-17441.stderr18
-rw-r--r--tests/ui/mismatched_types/cast-rfc0401.stderr11
-rw-r--r--tests/ui/nonscalar-cast.stderr8
-rw-r--r--tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr9
-rw-r--r--tests/ui/tag-variant-cast-non-nullary.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr7
51 files changed, 815 insertions, 570 deletions
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index e144a6ab599..e17cfc15a43 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -380,20 +380,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 err.span_label(self.span, "invalid cast");
                 if self.expr_ty.is_numeric() {
                     if self.expr_ty == fcx.tcx.types.u32 {
-                        match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
-                            Ok(snippet) => err.span_suggestion(
-                                self.span,
-                                "try `char::from_u32` instead",
-                                format!("char::from_u32({snippet})"),
-                                Applicability::MachineApplicable,
-                            ),
-
-                            Err(_) => err.span_help(self.span, "try `char::from_u32` instead"),
-                        };
+                        err.multipart_suggestion(
+                            "consider using `char::from_u32` instead",
+                            vec![
+                                (self.expr_span.shrink_to_lo(), "char::from_u32(".to_string()),
+                                (self.expr_span.shrink_to_hi().to(self.cast_span), ")".to_string()),
+                            ],
+                            Applicability::MachineApplicable,
+                        );
                     } else if self.expr_ty == fcx.tcx.types.i8 {
-                        err.span_help(self.span, "try casting from `u8` instead");
+                        err.span_help(self.span, "consider casting from `u8` instead");
                     } else {
-                        err.span_help(self.span, "try `char::from_u32` instead (via a `u32`)");
+                        err.span_help(
+                            self.span,
+                            "consider using `char::from_u32` instead (via a `u32`)",
+                        );
                     };
                 }
                 err.emit();
@@ -494,11 +495,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     self.cast_ty.kind(),
                     ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..)
                 ) {
-                    let mut label = true;
                     // Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
-                    if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
-                        && let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From)
-                    {
+                    if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
                         let ty = fcx.resolve_vars_if_possible(self.cast_ty);
                         let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
                         if fcx
@@ -506,26 +504,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                             .type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env)
                             .must_apply_modulo_regions()
                         {
-                            label = false;
-                            if let ty::Adt(def, args) = self.cast_ty.kind() {
-                                err.span_suggestion_verbose(
-                                    self.span,
-                                    "consider using the `From` trait instead",
-                                    format!(
-                                        "{}::from({})",
-                                        fcx.tcx.value_path_str_with_args(def.did(), args),
-                                        snippet
-                                    ),
-                                    Applicability::MaybeIncorrect,
-                                );
+                            let to_ty = if let ty::Adt(def, args) = self.cast_ty.kind() {
+                                fcx.tcx.value_path_str_with_args(def.did(), args)
                             } else {
-                                err.span_suggestion(
-                                    self.span,
-                                    "consider using the `From` trait instead",
-                                    format!("{}::from({})", self.cast_ty, snippet),
-                                    Applicability::MaybeIncorrect,
-                                );
+                                self.cast_ty.to_string()
                             };
+                            err.multipart_suggestion(
+                                "consider using the `From` trait instead",
+                                vec![
+                                    (self.expr_span.shrink_to_lo(), format!("{to_ty}::from(")),
+                                    (
+                                        self.expr_span.shrink_to_hi().to(self.cast_span),
+                                        ")".to_string(),
+                                    ),
+                                ],
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                     }
 
@@ -548,11 +542,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                         )
                     };
 
-                    if label {
-                        err.span_label(self.span, msg);
-                    } else {
-                        err.note(msg);
-                    }
+                    err.span_label(self.span, msg);
 
                     if let Some(note) = note {
                         err.note(note);
@@ -654,38 +644,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         match self.expr_ty.kind() {
             ty::Ref(_, _, mt) => {
                 let mtstr = mt.prefix_str();
-                match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
-                    Ok(s) => {
-                        err.span_suggestion(
-                            self.cast_span,
-                            "try casting to a reference instead",
-                            format!("&{mtstr}{s}"),
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                    Err(_) => {
-                        let msg = format!("did you mean `&{mtstr}{tstr}`?");
-                        err.span_help(self.cast_span, msg);
-                    }
-                }
+                err.span_suggestion_verbose(
+                    self.cast_span.shrink_to_lo(),
+                    "consider casting to a reference instead",
+                    format!("&{mtstr}"),
+                    Applicability::MachineApplicable,
+                );
             }
             ty::Adt(def, ..) if def.is_box() => {
-                match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
-                    Ok(s) => {
-                        err.span_suggestion(
-                            self.cast_span,
-                            "you can cast to a `Box` instead",
-                            format!("Box<{s}>"),
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                    Err(_) => {
-                        err.span_help(
-                            self.cast_span,
-                            format!("you might have meant `Box<{tstr}>`"),
-                        );
-                    }
-                }
+                err.multipart_suggestion(
+                    "you can cast to a `Box` instead",
+                    vec![
+                        (self.cast_span.shrink_to_lo(), "Box<".to_string()),
+                        (self.cast_span.shrink_to_hi(), ">".to_string()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
             }
             _ => {
                 err.span_help(self.expr_span, "consider using a box or reference as appropriate");
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index cb3fdd4d3f7..7135b8f04a2 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -51,6 +51,7 @@
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(ptr_alignment_type)]
+#![feature(round_char_boundary)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
 #![feature(trusted_len)]
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 7243f87ee63..47ba850d50d 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
 use std::fmt;
 use std::hash::Hash;
 
@@ -468,6 +469,29 @@ impl<'tcx> CodegenUnit<'tcx> {
         hash.as_u128().to_base_fixed_len(CASE_INSENSITIVE)
     }
 
+    pub fn shorten_name(human_readable_name: &str) -> Cow<'_, str> {
+        // Set a limit a somewhat below the common platform limits for file names.
+        const MAX_CGU_NAME_LENGTH: usize = 200;
+        const TRUNCATED_NAME_PREFIX: &str = "-trunc-";
+        if human_readable_name.len() > MAX_CGU_NAME_LENGTH {
+            let mangled_name = Self::mangle_name(human_readable_name);
+            // Determine a safe byte offset to truncate the name to
+            let truncate_to = human_readable_name.floor_char_boundary(
+                MAX_CGU_NAME_LENGTH - TRUNCATED_NAME_PREFIX.len() - mangled_name.len(),
+            );
+            format!(
+                "{}{}{}",
+                &human_readable_name[..truncate_to],
+                TRUNCATED_NAME_PREFIX,
+                mangled_name
+            )
+            .into()
+        } else {
+            // If the name is short enough, we can just return it as is.
+            human_readable_name.into()
+        }
+    }
+
     pub fn compute_size_estimate(&mut self) {
         // The size of a codegen unit as the sum of the sizes of the items
         // within it.
@@ -604,7 +628,7 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
         let cgu_name = self.build_cgu_name_no_mangle(cnum, components, special_suffix);
 
         if self.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
-            cgu_name
+            Symbol::intern(&CodegenUnit::shorten_name(cgu_name.as_str()))
         } else {
             Symbol::intern(&CodegenUnit::mangle_name(cgu_name.as_str()))
         }
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index b4169a060d4..49025673bbd 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -461,15 +461,15 @@ fn merge_codegen_units<'tcx>(
 
         for cgu in codegen_units.iter_mut() {
             if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
-                if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
-                    cgu.set_name(Symbol::intern(new_cgu_name));
+                let new_cgu_name = if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
+                    Symbol::intern(&CodegenUnit::shorten_name(new_cgu_name))
                 } else {
                     // If we don't require CGU names to be human-readable,
                     // we use a fixed length hash of the composite CGU name
                     // instead.
-                    let new_cgu_name = CodegenUnit::mangle_name(new_cgu_name);
-                    cgu.set_name(Symbol::intern(&new_cgu_name));
-                }
+                    Symbol::intern(&CodegenUnit::mangle_name(new_cgu_name))
+                };
+                cgu.set_name(new_cgu_name);
             }
         }
 
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index 46fcd7d5c51..aa6d1ec7009 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -124,7 +124,13 @@ pub(crate) fn base(
         // to v4, so we do the same.
         // https://github.com/llvm/llvm-project/blob/378778a0d10c2f8d5df8ceff81f95b6002984a4b/clang/lib/Driver/ToolChains/Darwin.cpp#L1203
         default_dwarf_version: 4,
-        frame_pointer: FramePointer::Always,
+        frame_pointer: match arch {
+            // clang ignores `-fomit-frame-pointer` for Armv7, it only accepts `-momit-leaf-frame-pointer`
+            Armv7k | Armv7s => FramePointer::Always,
+            // clang supports omitting frame pointers for the rest, but... don't?
+            Arm64 | Arm64e | Arm64_32 => FramePointer::NonLeaf,
+            I386 | I686 | X86_64 | X86_64h => FramePointer::Always,
+        },
         has_rpath: true,
         dll_suffix: ".dylib".into(),
         archive_format: "darwin".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 6587abb2ba7..4dd39877715 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
@@ -17,7 +17,6 @@ pub(crate) fn target() -> Target {
         arch,
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
-            frame_pointer: FramePointer::NonLeaf,
             cpu: "apple-m1".into(),
             max_atomic_width: Some(128),
             // FIXME: The leak sanitizer currently fails the tests, see #88132.
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 183a6c6f2d7..769a7b6c391 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
             ..opts
         },
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index ce9ae03e699..4bb2f73e4f9 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
             ..opts
         },
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index 4405e3fec02..7d04034e759 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
             ..opts
         },
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index 037685db1b3..ec92a40e255 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             ..opts
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index a386220e6fc..74fbe5a89ca 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             ..opts
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index 2c1dfdd55ed..dc595fbe7b6 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a16".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
             ..opts
         },
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index c0b8b409797..06ff1bfb2f0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a16".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
             ..opts
         },
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index 62968f5b555..bad9f6c1485 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             ..opts
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index 79b95dbde52..326f2b16d59 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
@@ -17,7 +17,6 @@ pub(crate) fn target() -> Target {
         arch,
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
-            frame_pointer: FramePointer::NonLeaf,
             cpu: "apple-m1".into(),
             max_atomic_width: Some(128),
             // FIXME: The leak sanitizer currently fails the tests, see #88132.
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index 848dbeec199..01c6f0b888d 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
             ..opts
         },
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
index 3dbe169e826..cad3650bda1 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
             max_atomic_width: Some(128),
-            frame_pointer: FramePointer::NonLeaf,
             ..opts
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 161db9a08bb..d1339c57b00 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, Target, TargetMetadata, TargetOptions};
+use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
@@ -16,11 +16,6 @@ pub(crate) fn target() -> Target {
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
             .into(),
         arch,
-        options: TargetOptions {
-            mcount: "\u{1}mcount".into(),
-            max_atomic_width: Some(64),
-            frame_pointer: FramePointer::Always,
-            ..opts
-        },
+        options: TargetOptions { mcount: "\u{1}mcount".into(), max_atomic_width: Some(64), ..opts },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 64c17054780..eba595ba7dd 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
@@ -18,7 +18,6 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
             max_atomic_width: Some(128), // penryn+ supports cmpxchg16b
-            frame_pointer: FramePointer::Always,
             supported_sanitizers: SanitizerSet::ADDRESS
                 | SanitizerSet::CFI
                 | SanitizerSet::LEAK
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index 11010b7d92f..e64556c4132 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,10 +1,9 @@
 use crate::spec::base::apple::{Arch, TargetAbi, base};
-use crate::spec::{FramePointer, SanitizerSet, Target, TargetMetadata, TargetOptions};
+use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
     opts.max_atomic_width = Some(128);
-    opts.frame_pointer = FramePointer::Always;
     opts.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 3b7fd8b7a20..68bd9440538 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -1411,7 +1411,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
         }
 
-        err.span_suggestion(
+        err.span_suggestion_verbose(
             obligation.cause.span.shrink_to_lo(),
             format!(
                 "consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
@@ -1574,7 +1574,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     .span_extend_while_whitespace(expr_span)
                     .shrink_to_hi()
                     .to(await_expr.span.shrink_to_hi());
-                err.span_suggestion(
+                err.span_suggestion_verbose(
                     removal_span,
                     "remove the `.await`",
                     "",
@@ -2126,7 +2126,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 ));
 
                 if !assoc_item.is_impl_trait_in_trait() {
-                    err.span_suggestion(
+                    err.span_suggestion_verbose(
                         span,
                         "use the fully qualified path to an implementation",
                         format!(
@@ -2924,12 +2924,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 );
                 let sm = tcx.sess.source_map();
                 if matches!(is_constable, IsConstable::Fn | IsConstable::Ctor)
-                    && let Ok(snip) = sm.span_to_snippet(elt_span)
+                    && let Ok(_) = sm.span_to_snippet(elt_span)
                 {
-                    err.span_suggestion(
-                        elt_span,
+                    err.multipart_suggestion(
                         "create an inline `const` block",
-                        format!("const {{ {snip} }}"),
+                        vec![
+                            (elt_span.shrink_to_lo(), "const { ".to_string()),
+                            (elt_span.shrink_to_hi(), " }".to_string()),
+                        ],
                         Applicability::MachineApplicable,
                     );
                 } else {
@@ -3127,13 +3129,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     }
                 }
                 err.help("change the field's type to have a statically known size");
-                err.span_suggestion(
+                err.span_suggestion_verbose(
                     span.shrink_to_lo(),
                     "borrowed types always have a statically known size",
                     "&",
                     Applicability::MachineApplicable,
                 );
-                err.multipart_suggestion(
+                err.multipart_suggestion_verbose(
                     "the `Box` type always has a statically known size and allocates its contents \
                      in the heap",
                     vec![
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
index 7e27028a2a2..f9b6c85f871 100644
--- a/library/coretests/tests/floats/mod.rs
+++ b/library/coretests/tests/floats/mod.rs
@@ -52,6 +52,119 @@ macro_rules! assert_biteq {
     };
 }
 
+mod const_asserts {
+    // Shadow some assert implementations that would otherwise not compile in a const-context.
+    // Every macro added here also needs to be added in the `float_test!` macro below.
+    macro_rules! assert_eq {
+        ($left:expr, $right:expr $(,)?) => {
+            std::assert!($left == $right)
+        };
+        ($left:expr, $right:expr, $($arg:tt)+) => {
+            std::assert!($left == $right, $($arg)+)
+        };
+    }
+
+    pub(crate) use assert_eq;
+}
+
+/// Generate float tests for all our float types, for compile-time and run-time behavior.
+///
+/// By default all tests run for all float types. Configuration can be applied via `attrs`.
+///
+/// ```ignore (this is only a sketch)
+/// float_test! {
+///     name: fn_name, /* function under test */
+///     attrs: {
+///         // Apply a configuration to the test for a single type
+///         f16: #[cfg(target_has_reliable_f16_math)],
+///         // Types can be excluded with `cfg(false)`
+///         f64: #[cfg(false)],
+///     },
+///     test<Float> {
+///         /* write tests here, using `Float` as the type */
+///     }
+/// }
+macro_rules! float_test {
+    (
+        name: $name:ident,
+        attrs: {
+            $(const: #[ $($const_meta:meta),+ ] ,)?
+            $(f16: #[ $($f16_meta:meta),+ ] ,)?
+            $(const f16: #[ $($f16_const_meta:meta),+ ] ,)?
+            $(f32: #[ $($f32_meta:meta),+ ] ,)?
+            $(const f32: #[ $($f32_const_meta:meta),+ ] ,)?
+            $(f64: #[ $($f64_meta:meta),+ ] ,)?
+            $(const f64: #[ $($f64_const_meta:meta),+ ] ,)?
+            $(f128: #[ $($f128_meta:meta),+ ] ,)?
+            $(const f128: #[ $($f128_const_meta:meta),+ ] ,)?
+        },
+        test<$fty:ident> $test:block
+    ) => {
+        mod $name {
+            #[test]
+            $( $( #[$f16_meta] )+ )?
+            fn test_f16() {
+                type $fty = f16;
+                $test
+            }
+
+            #[test]
+            $( $( #[$f32_meta] )+ )?
+            fn test_f32() {
+                type $fty = f32;
+                $test
+            }
+
+            #[test]
+            $( $( #[$f64_meta] )+ )?
+            fn test_f64() {
+                type $fty = f64;
+                $test
+            }
+
+            #[test]
+            $( $( #[$f128_meta] )+ )?
+            fn test_f128() {
+                type $fty = f128;
+                $test
+            }
+
+            $( $( #[$const_meta] )+ )?
+            mod const_ {
+                use $crate::floats::const_asserts::assert_eq;
+
+                #[test]
+                $( $( #[$f16_const_meta] )+ )?
+                fn test_f16() {
+                    type $fty = f16;
+                    const { $test }
+                }
+
+                #[test]
+                $( $( #[$f32_const_meta] )+ )?
+                fn test_f32() {
+                    type $fty = f32;
+                    const { $test }
+                }
+
+                #[test]
+                $( $( #[$f64_const_meta] )+ )?
+                fn test_f64() {
+                    type $fty = f64;
+                    const { $test }
+                }
+
+                #[test]
+                $( $( #[$f128_const_meta] )+ )?
+                fn test_f128() {
+                    type $fty = f128;
+                    const { $test }
+                }
+            }
+        }
+    };
+}
+
 /// Helper function for testing numeric operations
 pub fn test_num<T>(ten: T, two: T)
 where
@@ -75,3 +188,438 @@ mod f128;
 mod f16;
 mod f32;
 mod f64;
+
+float_test! {
+    name: min,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).min(0.0), 0.0);
+        assert!((0.0 as Float).min(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).min(-0.0), -0.0);
+        assert!((-0.0 as Float).min(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).min(9.0), 9.0);
+        assert_eq!((-9.0 as Float).min(0.0), -9.0);
+        assert_eq!((0.0 as Float).min(9.0), 0.0);
+        assert!((0.0 as Float).min(9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).min(9.0), -0.0);
+        assert!((-0.0 as Float).min(9.0).is_sign_negative());
+        assert_eq!((-0.0 as Float).min(-9.0), -9.0);
+        assert_eq!(Float::INFINITY.min(9.0), 9.0);
+        assert_eq!((9.0 as Float).min(Float::INFINITY), 9.0);
+        assert_eq!(Float::INFINITY.min(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).min(Float::INFINITY), -9.0);
+        assert_eq!(Float::NEG_INFINITY.min(9.0), Float::NEG_INFINITY);
+        assert_eq!((9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert_eq!(Float::NEG_INFINITY.min(-9.0), Float::NEG_INFINITY);
+        assert_eq!((-9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert_eq!(Float::NAN.min(9.0), 9.0);
+        assert_eq!(Float::NAN.min(-9.0), -9.0);
+        assert_eq!((9.0 as Float).min(Float::NAN), 9.0);
+        assert_eq!((-9.0 as Float).min(Float::NAN), -9.0);
+        assert!(Float::NAN.min(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: max,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).max(0.0), 0.0);
+        assert!((0.0 as Float).max(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).max(-0.0), -0.0);
+        assert!((-0.0 as Float).max(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).max(9.0), 9.0);
+        assert_eq!((-9.0 as Float).max(0.0), 0.0);
+        assert!((-9.0 as Float).max(0.0).is_sign_positive());
+        assert_eq!((-9.0 as Float).max(-0.0), -0.0);
+        assert!((-9.0 as Float).max(-0.0).is_sign_negative());
+        assert_eq!((0.0 as Float).max(9.0), 9.0);
+        assert_eq!((0.0 as Float).max(-9.0), 0.0);
+        assert!((0.0 as Float).max(-9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).max(-9.0), -0.0);
+        assert!((-0.0 as Float).max(-9.0).is_sign_negative());
+        assert_eq!(Float::INFINITY.max(9.0), Float::INFINITY);
+        assert_eq!((9.0 as Float).max(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::INFINITY.max(-9.0), Float::INFINITY);
+        assert_eq!((-9.0 as Float).max(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.max(9.0), 9.0);
+        assert_eq!((9.0 as Float).max(Float::NEG_INFINITY), 9.0);
+        assert_eq!(Float::NEG_INFINITY.max(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).max(Float::NEG_INFINITY), -9.0);
+        assert_eq!(Float::NAN.max(9.0), 9.0);
+        assert_eq!(Float::NAN.max(-9.0), -9.0);
+        assert_eq!((9.0 as Float).max(Float::NAN), 9.0);
+        assert_eq!((-9.0 as Float).max(Float::NAN), -9.0);
+        assert!(Float::NAN.max(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: minimum,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).minimum(0.0), 0.0);
+        assert!((0.0 as Float).minimum(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).minimum(0.0), -0.0);
+        assert!((-0.0 as Float).minimum(0.0).is_sign_negative());
+        assert_eq!((-0.0 as Float).minimum(-0.0), -0.0);
+        assert!((-0.0 as Float).minimum(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).minimum(9.0), 9.0);
+        assert_eq!((-9.0 as Float).minimum(0.0), -9.0);
+        assert_eq!((0.0 as Float).minimum(9.0), 0.0);
+        assert!((0.0 as Float).minimum(9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).minimum(9.0), -0.0);
+        assert!((-0.0 as Float).minimum(9.0).is_sign_negative());
+        assert_eq!((-0.0 as Float).minimum(-9.0), -9.0);
+        assert_eq!(Float::INFINITY.minimum(9.0), 9.0);
+        assert_eq!((9.0 as Float).minimum(Float::INFINITY), 9.0);
+        assert_eq!(Float::INFINITY.minimum(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).minimum(Float::INFINITY), -9.0);
+        assert_eq!(Float::NEG_INFINITY.minimum(9.0), Float::NEG_INFINITY);
+        assert_eq!((9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert_eq!(Float::NEG_INFINITY.minimum(-9.0), Float::NEG_INFINITY);
+        assert_eq!((-9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert!(Float::NAN.minimum(9.0).is_nan());
+        assert!(Float::NAN.minimum(-9.0).is_nan());
+        assert!((9.0 as Float).minimum(Float::NAN).is_nan());
+        assert!((-9.0 as Float).minimum(Float::NAN).is_nan());
+        assert!(Float::NAN.minimum(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: maximum,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).maximum(0.0), 0.0);
+        assert!((0.0 as Float).maximum(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).maximum(0.0), 0.0);
+        assert!((-0.0 as Float).maximum(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).maximum(-0.0), -0.0);
+        assert!((-0.0 as Float).maximum(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).maximum(9.0), 9.0);
+        assert_eq!((-9.0 as Float).maximum(0.0), 0.0);
+        assert!((-9.0 as Float).maximum(0.0).is_sign_positive());
+        assert_eq!((-9.0 as Float).maximum(-0.0), -0.0);
+        assert!((-9.0 as Float).maximum(-0.0).is_sign_negative());
+        assert_eq!((0.0 as Float).maximum(9.0), 9.0);
+        assert_eq!((0.0 as Float).maximum(-9.0), 0.0);
+        assert!((0.0 as Float).maximum(-9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).maximum(-9.0), -0.0);
+        assert!((-0.0 as Float).maximum(-9.0).is_sign_negative());
+        assert_eq!(Float::INFINITY.maximum(9.0), Float::INFINITY);
+        assert_eq!((9.0 as Float).maximum(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::INFINITY.maximum(-9.0), Float::INFINITY);
+        assert_eq!((-9.0 as Float).maximum(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.maximum(9.0), 9.0);
+        assert_eq!((9.0 as Float).maximum(Float::NEG_INFINITY), 9.0);
+        assert_eq!(Float::NEG_INFINITY.maximum(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).maximum(Float::NEG_INFINITY), -9.0);
+        assert!(Float::NAN.maximum(9.0).is_nan());
+        assert!(Float::NAN.maximum(-9.0).is_nan());
+        assert!((9.0 as Float).maximum(Float::NAN).is_nan());
+        assert!((-9.0 as Float).maximum(Float::NAN).is_nan());
+        assert!(Float::NAN.maximum(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: midpoint,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.5 as Float).midpoint(0.5), 0.5);
+        assert_eq!((0.5 as Float).midpoint(2.5), 1.5);
+        assert_eq!((3.0 as Float).midpoint(4.0), 3.5);
+        assert_eq!((-3.0 as Float).midpoint(4.0), 0.5);
+        assert_eq!((3.0 as Float).midpoint(-4.0), -0.5);
+        assert_eq!((-3.0 as Float).midpoint(-4.0), -3.5);
+        assert_eq!((0.0 as Float).midpoint(0.0), 0.0);
+        assert_eq!((-0.0 as Float).midpoint(-0.0), -0.0);
+        assert_eq!((-5.0 as Float).midpoint(5.0), 0.0);
+        assert_eq!(Float::MAX.midpoint(Float::MIN), 0.0);
+        assert_eq!(Float::MIN.midpoint(Float::MAX), -0.0);
+        assert_eq!(Float::MAX.midpoint(Float::MIN_POSITIVE), Float::MAX / 2.);
+        assert_eq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.);
+        assert_eq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.);
+        assert_eq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.);
+        assert_eq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
+        assert_eq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
+        assert_eq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
+        assert_eq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
+        assert_eq!(Float::MAX.midpoint(Float::MAX), Float::MAX);
+        assert_eq!(
+            (Float::MIN_POSITIVE).midpoint(Float::MIN_POSITIVE),
+            Float::MIN_POSITIVE
+        );
+        assert_eq!(
+            (-Float::MIN_POSITIVE).midpoint(-Float::MIN_POSITIVE),
+            -Float::MIN_POSITIVE
+        );
+        assert_eq!(Float::MAX.midpoint(5.0), Float::MAX / 2.0 + 2.5);
+        assert_eq!(Float::MAX.midpoint(-5.0), Float::MAX / 2.0 - 2.5);
+        assert_eq!(Float::INFINITY.midpoint(Float::INFINITY), Float::INFINITY);
+        assert_eq!(
+            Float::NEG_INFINITY.midpoint(Float::NEG_INFINITY),
+            Float::NEG_INFINITY
+        );
+        assert!(Float::NAN.midpoint(1.0).is_nan());
+        assert!((1.0 as Float).midpoint(Float::NAN).is_nan());
+        assert!(Float::NAN.midpoint(Float::NAN).is_nan());
+    }
+}
+
+// Separate test since the `for` loops cannot be run in `const`.
+float_test! {
+    name: midpoint_large_magnitude,
+    attrs: {
+        const: #[cfg(false)],
+        // FIXME(f16_f128): `powi` does not work in Miri for these types
+        f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+        f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        // test if large differences in magnitude are still correctly computed.
+        // NOTE: that because of how small x and y are, x + y can never overflow
+        // so (x + y) / 2.0 is always correct
+        // in particular, `2.pow(i)` will  never be at the max exponent, so it could
+        // be safely doubled, while j is significantly smaller.
+        for i in Float::MAX_EXP.saturating_sub(64)..Float::MAX_EXP {
+            for j in 0..64u8 {
+                let large = (2.0 as Float).powi(i);
+                // a much smaller number, such that there is no chance of overflow to test
+                // potential double rounding in midpoint's implementation.
+                let small = (2.0 as Float).powi(Float::MAX_EXP - 1)
+                    * Float::EPSILON
+                    * Float::from(j);
+
+                let naive = (large + small) / 2.0;
+                let midpoint = large.midpoint(small);
+
+                assert_eq!(naive, midpoint);
+            }
+        }
+    }
+}
+
+float_test! {
+    name: abs,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((-1.0 as Float).abs(), 1.0);
+        assert_eq!((1.0 as Float).abs(), 1.0);
+        assert_eq!(Float::NEG_INFINITY.abs(), Float::INFINITY);
+        assert_eq!(Float::INFINITY.abs(), Float::INFINITY);
+    }
+}
+
+float_test! {
+    name: copysign,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((1.0 as Float).copysign(-2.0), -1.0);
+        assert_eq!((-1.0 as Float).copysign(2.0), 1.0);
+        assert_eq!(Float::INFINITY.copysign(-0.0), Float::NEG_INFINITY);
+        assert_eq!(Float::NEG_INFINITY.copysign(0.0), Float::INFINITY);
+    }
+}
+
+float_test! {
+    name: rem_euclid,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert!(Float::INFINITY.rem_euclid(42.0 as Float).is_nan());
+        assert_eq!((42.0 as Float).rem_euclid(Float::INFINITY), (42.0 as Float));
+        assert!((42.0 as Float).rem_euclid(Float::NAN).is_nan());
+        assert!(Float::INFINITY.rem_euclid(Float::INFINITY).is_nan());
+        assert!(Float::INFINITY.rem_euclid(Float::NAN).is_nan());
+        assert!(Float::NAN.rem_euclid(Float::INFINITY).is_nan());
+    }
+}
+
+float_test! {
+    name: div_euclid,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((42.0 as Float).div_euclid(Float::INFINITY), 0.0);
+        assert!((42.0 as Float).div_euclid(Float::NAN).is_nan());
+        assert!(Float::INFINITY.div_euclid(Float::INFINITY).is_nan());
+        assert!(Float::INFINITY.div_euclid(Float::NAN).is_nan());
+        assert!(Float::NAN.div_euclid(Float::INFINITY).is_nan());
+    }
+}
+
+float_test! {
+    name: floor,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).floor(), 0.0);
+        assert!((0.0 as Float).floor().is_sign_positive());
+        assert_eq!((-0.0 as Float).floor(), -0.0);
+        assert!((-0.0 as Float).floor().is_sign_negative());
+        assert_eq!((0.5 as Float).floor(), 0.0);
+        assert_eq!((-0.5 as Float).floor(), -1.0);
+        assert_eq!((1.5 as Float).floor(), 1.0);
+        assert_eq!(Float::MAX.floor(), Float::MAX);
+        assert_eq!(Float::MIN.floor(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.floor(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).floor(), -1.0);
+        assert!(Float::NAN.floor().is_nan());
+        assert_eq!(Float::INFINITY.floor(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.floor(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: ceil,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).ceil(), 0.0);
+        assert!((0.0 as Float).ceil().is_sign_positive());
+        assert_eq!((-0.0 as Float).ceil(), 0.0);
+        assert!((-0.0 as Float).ceil().is_sign_negative());
+        assert_eq!((0.5 as Float).ceil(), 1.0);
+        assert_eq!((-0.5 as Float).ceil(), 0.0);
+        assert_eq!(Float::MAX.ceil(), Float::MAX);
+        assert_eq!(Float::MIN.ceil(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.ceil(), 1.0);
+        assert_eq!((-Float::MIN_POSITIVE).ceil(), 0.0);
+        assert!(Float::NAN.ceil().is_nan());
+        assert_eq!(Float::INFINITY.ceil(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.ceil(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: round,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).round(), 0.0);
+        assert!((0.0 as Float).round().is_sign_positive());
+        assert_eq!((-0.0 as Float).round(), -0.0);
+        assert!((-0.0 as Float).round().is_sign_negative());
+        assert_eq!((0.5 as Float).round(), 1.0);
+        assert_eq!((-0.5 as Float).round(), -1.0);
+        assert_eq!(Float::MAX.round(), Float::MAX);
+        assert_eq!(Float::MIN.round(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.round(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).round(), 0.0);
+        assert!(Float::NAN.round().is_nan());
+        assert_eq!(Float::INFINITY.round(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.round(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: round_ties_even,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).round_ties_even(), 0.0);
+        assert!((0.0 as Float).round_ties_even().is_sign_positive());
+        assert_eq!((-0.0 as Float).round_ties_even(), -0.0);
+        assert!((-0.0 as Float).round_ties_even().is_sign_negative());
+        assert_eq!((0.5 as Float).round_ties_even(), 0.0);
+        assert!((0.5 as Float).round_ties_even().is_sign_positive());
+        assert_eq!((-0.5 as Float).round_ties_even(), -0.0);
+        assert!((-0.5 as Float).round_ties_even().is_sign_negative());
+        assert_eq!(Float::MAX.round_ties_even(), Float::MAX);
+        assert_eq!(Float::MIN.round_ties_even(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.round_ties_even(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).round_ties_even(), 0.0);
+        assert!(Float::NAN.round_ties_even().is_nan());
+        assert_eq!(Float::INFINITY.round_ties_even(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.round_ties_even(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: trunc,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).trunc(), 0.0);
+        assert!((0.0 as Float).trunc().is_sign_positive());
+        assert_eq!((-0.0 as Float).trunc(), -0.0);
+        assert!((-0.0 as Float).trunc().is_sign_negative());
+        assert_eq!((0.5 as Float).trunc(), 0.0);
+        assert!((0.5 as Float).trunc().is_sign_positive());
+        assert_eq!((-0.5 as Float).trunc(), -0.0);
+        assert!((-0.5 as Float).trunc().is_sign_negative());
+        assert_eq!(Float::MAX.trunc(), Float::MAX);
+        assert_eq!(Float::MIN.trunc(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.trunc(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).trunc(), 0.0);
+        assert!(Float::NAN.trunc().is_nan());
+        assert_eq!(Float::INFINITY.trunc(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.trunc(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: fract,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).fract(), 0.0);
+        assert!((0.0 as Float).fract().is_sign_positive());
+        assert_eq!((-0.0 as Float).fract(), 0.0);
+        assert!((-0.0 as Float).fract().is_sign_positive());
+        assert_eq!((0.5 as Float).fract(), 0.5);
+        assert!((0.5 as Float).fract().is_sign_positive());
+        assert_eq!((-0.5 as Float).fract(), -0.5);
+        assert!((-0.5 as Float).fract().is_sign_negative());
+        assert_eq!(Float::MAX.fract(), 0.0);
+        assert_eq!(Float::MIN.fract(), 0.0);
+        assert_eq!(Float::MIN_POSITIVE.fract(), Float::MIN_POSITIVE);
+        assert!(Float::MIN_POSITIVE.fract().is_sign_positive());
+        assert_eq!((-Float::MIN_POSITIVE).fract(), -Float::MIN_POSITIVE);
+        assert!((-Float::MIN_POSITIVE).fract().is_sign_negative());
+        assert!(Float::NAN.fract().is_nan());
+        assert!(Float::INFINITY.fract().is_nan());
+        assert!(Float::NEG_INFINITY.fract().is_nan());
+    }
+}
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index c68b569f86b..6611aa57866 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -730,356 +730,3 @@ assume_usize_width! {
         }
     }
 }
-
-// FIXME(141726): there is a lot of duplication between the following tests and
-// the tests in `coretests/tests/floats/f*.rs`
-// See issue https://github.com/rust-lang/rust/issues/141726 for more details.
-macro_rules! test_float {
-    ($modname: ident, $fassert: ident, $fty: ty) => {
-        mod $modname {
-            #[test]
-            fn min() {
-                $fassert!((0.0 as $fty).min(0.0), 0.0);
-                $fassert!((0.0 as $fty).min(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).min(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).min(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).min(9.0), 9.0);
-                $fassert!((-9.0 as $fty).min(0.0), -9.0);
-                $fassert!((0.0 as $fty).min(9.0), 0.0);
-                $fassert!((0.0 as $fty).min(9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).min(9.0), -0.0);
-                $fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
-                $fassert!((-0.0 as $fty).min(-9.0), -9.0);
-                $fassert!(<$fty>::INFINITY.min(9.0), 9.0);
-                $fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0);
-                $fassert!(<$fty>::INFINITY.min(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0);
-                $fassert!(<$fty>::NEG_INFINITY.min(9.0), <$fty>::NEG_INFINITY);
-                $fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.min(-9.0), <$fty>::NEG_INFINITY);
-                $fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NAN.min(9.0), 9.0);
-                $fassert!(<$fty>::NAN.min(-9.0), -9.0);
-                $fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0);
-                $fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0);
-                $fassert!(<$fty>::NAN.min(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn max() {
-                $fassert!((0.0 as $fty).max(0.0), 0.0);
-                $fassert!((0.0 as $fty).max(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).max(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).max(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).max(9.0), 9.0);
-                $fassert!((-9.0 as $fty).max(0.0), 0.0);
-                $fassert!((-9.0 as $fty).max(0.0).is_sign_positive());
-                $fassert!((-9.0 as $fty).max(-0.0), -0.0);
-                $fassert!((-9.0 as $fty).max(-0.0).is_sign_negative());
-                $fassert!((0.0 as $fty).max(9.0), 9.0);
-                $fassert!((0.0 as $fty).max(-9.0), 0.0);
-                $fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).max(-9.0), -0.0);
-                $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
-                $fassert!(<$fty>::INFINITY.max(9.0), <$fty>::INFINITY);
-                $fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::INFINITY.max(-9.0), <$fty>::INFINITY);
-                $fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.max(9.0), 9.0);
-                $fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0);
-                $fassert!(<$fty>::NEG_INFINITY.max(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0);
-                $fassert!(<$fty>::NAN.max(9.0), 9.0);
-                $fassert!(<$fty>::NAN.max(-9.0), -9.0);
-                $fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0);
-                $fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0);
-                $fassert!(<$fty>::NAN.max(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn minimum() {
-                $fassert!((0.0 as $fty).minimum(0.0), 0.0);
-                $fassert!((0.0 as $fty).minimum(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).minimum(0.0), -0.0);
-                $fassert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
-                $fassert!((-0.0 as $fty).minimum(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).minimum(9.0), 9.0);
-                $fassert!((-9.0 as $fty).minimum(0.0), -9.0);
-                $fassert!((0.0 as $fty).minimum(9.0), 0.0);
-                $fassert!((0.0 as $fty).minimum(9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).minimum(9.0), -0.0);
-                $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
-                $fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
-                $fassert!(<$fty>::INFINITY.minimum(9.0), 9.0);
-                $fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0);
-                $fassert!(<$fty>::INFINITY.minimum(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0);
-                $fassert!(<$fty>::NEG_INFINITY.minimum(9.0), <$fty>::NEG_INFINITY);
-                $fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.minimum(-9.0), <$fty>::NEG_INFINITY);
-                $fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NAN.minimum(9.0).is_nan());
-                $fassert!(<$fty>::NAN.minimum(-9.0).is_nan());
-                $fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan());
-                $fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan());
-                $fassert!(<$fty>::NAN.minimum(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn maximum() {
-                $fassert!((0.0 as $fty).maximum(0.0), 0.0);
-                $fassert!((0.0 as $fty).maximum(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).maximum(0.0), 0.0);
-                $fassert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).maximum(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).maximum(9.0), 9.0);
-                $fassert!((-9.0 as $fty).maximum(0.0), 0.0);
-                $fassert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
-                $fassert!((-9.0 as $fty).maximum(-0.0), -0.0);
-                $fassert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
-                $fassert!((0.0 as $fty).maximum(9.0), 9.0);
-                $fassert!((0.0 as $fty).maximum(-9.0), 0.0);
-                $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
-                $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
-                $fassert!(<$fty>::INFINITY.maximum(9.0), <$fty>::INFINITY);
-                $fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::INFINITY.maximum(-9.0), <$fty>::INFINITY);
-                $fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.maximum(9.0), 9.0);
-                $fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0);
-                $fassert!(<$fty>::NEG_INFINITY.maximum(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0);
-                $fassert!(<$fty>::NAN.maximum(9.0).is_nan());
-                $fassert!(<$fty>::NAN.maximum(-9.0).is_nan());
-                $fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan());
-                $fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan());
-                $fassert!(<$fty>::NAN.maximum(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn midpoint() {
-                $fassert!((0.5 as $fty).midpoint(0.5), 0.5);
-                $fassert!((0.5 as $fty).midpoint(2.5), 1.5);
-                $fassert!((3.0 as $fty).midpoint(4.0), 3.5);
-                $fassert!((-3.0 as $fty).midpoint(4.0), 0.5);
-                $fassert!((3.0 as $fty).midpoint(-4.0), -0.5);
-                $fassert!((-3.0 as $fty).midpoint(-4.0), -3.5);
-                $fassert!((0.0 as $fty).midpoint(0.0), 0.0);
-                $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
-                $fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
-                $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN), 0.0);
-                $fassert!(<$fty>::MIN.midpoint(<$fty>::MAX), -0.0);
-                $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MAX).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
-                $fassert!(<$fty>::MAX.midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MAX).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
-                $fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
-                $fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
-                $fassert!(<$fty>::MAX.midpoint(<$fty>::MAX), <$fty>::MAX);
-                $fassert!(
-                    (<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE),
-                    <$fty>::MIN_POSITIVE
-                );
-                $fassert!(
-                    (-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE),
-                    -<$fty>::MIN_POSITIVE
-                );
-                $fassert!(<$fty>::MAX.midpoint(5.0), <$fty>::MAX / 2.0 + 2.5);
-                $fassert!(<$fty>::MAX.midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5);
-                $fassert!(<$fty>::INFINITY.midpoint(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(
-                    <$fty>::NEG_INFINITY.midpoint(<$fty>::NEG_INFINITY),
-                    <$fty>::NEG_INFINITY
-                );
-                $fassert!(<$fty>::NAN.midpoint(1.0).is_nan());
-                $fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan());
-                $fassert!(<$fty>::NAN.midpoint(<$fty>::NAN).is_nan());
-
-                // test if large differences in magnitude are still correctly computed.
-                // NOTE: that because of how small x and y are, x + y can never overflow
-                // so (x + y) / 2.0 is always correct
-                // in particular, `2.pow(i)` will  never be at the max exponent, so it could
-                // be safely doubled, while j is significantly smaller.
-                for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP {
-                    for j in 0..64u8 {
-                        let large = (2.0 as $fty).powi(i);
-                        // a much smaller number, such that there is no chance of overflow to test
-                        // potential double rounding in midpoint's implementation.
-                        let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1)
-                            * <$fty>::EPSILON
-                            * <$fty>::from(j);
-
-                        let naive = (large + small) / 2.0;
-                        let midpoint = large.midpoint(small);
-
-                        assert_eq!(naive, midpoint);
-                    }
-                }
-            }
-            #[test]
-            fn abs() {
-                $fassert!((-1.0 as $fty).abs(), 1.0);
-                $fassert!((1.0 as $fty).abs(), 1.0);
-                $fassert!(<$fty>::NEG_INFINITY.abs(), <$fty>::INFINITY);
-                $fassert!(<$fty>::INFINITY.abs(), <$fty>::INFINITY);
-            }
-            #[test]
-            fn copysign() {
-                $fassert!((1.0 as $fty).copysign(-2.0), -1.0);
-                $fassert!((-1.0 as $fty).copysign(2.0), 1.0);
-                $fassert!(<$fty>::INFINITY.copysign(-0.0), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.copysign(0.0), <$fty>::INFINITY);
-            }
-            #[test]
-            fn rem_euclid() {
-                // FIXME: Use $fassert when rem_euclid becomes const
-                assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan());
-                assert_eq!((42.0 as $fty).rem_euclid(<$fty>::INFINITY), (42.0 as $fty));
-                assert!((42.0 as $fty).rem_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::INFINITY.rem_euclid(<$fty>::INFINITY).is_nan());
-                assert!(<$fty>::INFINITY.rem_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::NAN.rem_euclid(<$fty>::INFINITY).is_nan());
-            }
-            #[test]
-            fn div_euclid() {
-                // FIXME: Use $fassert when div_euclid becomes const
-                assert_eq!((42.0 as $fty).div_euclid(<$fty>::INFINITY), 0.0);
-                assert!((42.0 as $fty).div_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::INFINITY.div_euclid(<$fty>::INFINITY).is_nan());
-                assert!(<$fty>::INFINITY.div_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan());
-            }
-            #[test]
-            fn floor() {
-                $fassert!((0.0 as $fty).floor(), 0.0);
-                $fassert!((0.0 as $fty).floor().is_sign_positive());
-                $fassert!((-0.0 as $fty).floor(), -0.0);
-                $fassert!((-0.0 as $fty).floor().is_sign_negative());
-                $fassert!((0.5 as $fty).floor(), 0.0);
-                $fassert!((-0.5 as $fty).floor(), -1.0);
-                $fassert!((1.5 as $fty).floor(), 1.0);
-                $fassert!(<$fty>::MAX.floor(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.floor(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.floor(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).floor(), -1.0);
-                $fassert!(<$fty>::NAN.floor().is_nan());
-                $fassert!(<$fty>::INFINITY.floor(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.floor(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn ceil() {
-                $fassert!((0.0 as $fty).ceil(), 0.0);
-                $fassert!((0.0 as $fty).ceil().is_sign_positive());
-                $fassert!((-0.0 as $fty).ceil(), 0.0);
-                $fassert!((-0.0 as $fty).ceil().is_sign_negative());
-                $fassert!((0.5 as $fty).ceil(), 1.0);
-                $fassert!((-0.5 as $fty).ceil(), 0.0);
-                $fassert!(<$fty>::MAX.ceil(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.ceil(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.ceil(), 1.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).ceil(), 0.0);
-                $fassert!(<$fty>::NAN.ceil().is_nan());
-                $fassert!(<$fty>::INFINITY.ceil(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.ceil(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn round() {
-                $fassert!((0.0 as $fty).round(), 0.0);
-                $fassert!((0.0 as $fty).round().is_sign_positive());
-                $fassert!((-0.0 as $fty).round(), -0.0);
-                $fassert!((-0.0 as $fty).round().is_sign_negative());
-                $fassert!((0.5 as $fty).round(), 1.0);
-                $fassert!((-0.5 as $fty).round(), -1.0);
-                $fassert!(<$fty>::MAX.round(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.round(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.round(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).round(), 0.0);
-                $fassert!(<$fty>::NAN.round().is_nan());
-                $fassert!(<$fty>::INFINITY.round(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.round(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn round_ties_even() {
-                $fassert!((0.0 as $fty).round_ties_even(), 0.0);
-                $fassert!((0.0 as $fty).round_ties_even().is_sign_positive());
-                $fassert!((-0.0 as $fty).round_ties_even(), -0.0);
-                $fassert!((-0.0 as $fty).round_ties_even().is_sign_negative());
-                $fassert!((0.5 as $fty).round_ties_even(), 0.0);
-                $fassert!((0.5 as $fty).round_ties_even().is_sign_positive());
-                $fassert!((-0.5 as $fty).round_ties_even(), -0.0);
-                $fassert!((-0.5 as $fty).round_ties_even().is_sign_negative());
-                $fassert!(<$fty>::MAX.round_ties_even(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.round_ties_even(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.round_ties_even(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).round_ties_even(), 0.0);
-                $fassert!(<$fty>::NAN.round_ties_even().is_nan());
-                $fassert!(<$fty>::INFINITY.round_ties_even(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.round_ties_even(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn trunc() {
-                $fassert!((0.0 as $fty).trunc(), 0.0);
-                $fassert!((0.0 as $fty).trunc().is_sign_positive());
-                $fassert!((-0.0 as $fty).trunc(), -0.0);
-                $fassert!((-0.0 as $fty).trunc().is_sign_negative());
-                $fassert!((0.5 as $fty).trunc(), 0.0);
-                $fassert!((0.5 as $fty).trunc().is_sign_positive());
-                $fassert!((-0.5 as $fty).trunc(), -0.0);
-                $fassert!((-0.5 as $fty).trunc().is_sign_negative());
-                $fassert!(<$fty>::MAX.trunc(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.trunc(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.trunc(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).trunc(), 0.0);
-                $fassert!(<$fty>::NAN.trunc().is_nan());
-                $fassert!(<$fty>::INFINITY.trunc(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.trunc(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn fract() {
-                $fassert!((0.0 as $fty).fract(), 0.0);
-                $fassert!((0.0 as $fty).fract().is_sign_positive());
-                $fassert!((-0.0 as $fty).fract(), 0.0);
-                $fassert!((-0.0 as $fty).fract().is_sign_positive());
-                $fassert!((0.5 as $fty).fract(), 0.5);
-                $fassert!((0.5 as $fty).fract().is_sign_positive());
-                $fassert!((-0.5 as $fty).fract(), -0.5);
-                $fassert!((-0.5 as $fty).fract().is_sign_negative());
-                $fassert!(<$fty>::MAX.fract(), 0.0);
-                $fassert!(<$fty>::MIN.fract(), 0.0);
-                $fassert!(<$fty>::MIN_POSITIVE.fract(), <$fty>::MIN_POSITIVE);
-                $fassert!(<$fty>::MIN_POSITIVE.fract().is_sign_positive());
-                $fassert!((-<$fty>::MIN_POSITIVE).fract(), -<$fty>::MIN_POSITIVE);
-                $fassert!((-<$fty>::MIN_POSITIVE).fract().is_sign_negative());
-                $fassert!(<$fty>::NAN.fract().is_nan());
-                $fassert!(<$fty>::INFINITY.fract().is_nan());
-                $fassert!(<$fty>::NEG_INFINITY.fract().is_nan());
-            }
-        }
-    };
-}
-
-// Custom assert macro that distribute between assert! and assert_eq! in a non-const context
-macro_rules! float_assert {
-    ($b:expr) => {
-        assert!($b);
-    };
-    ($left:expr, $right:expr) => {
-        assert_eq!($left, $right);
-    };
-}
-
-// Custom assert macro that only uses assert! in a const context
-macro_rules! float_const_assert {
-    ($b:expr) => {
-        assert!(const { $b });
-    };
-    ($left:expr, $right:expr) => {
-        assert!(const { $left == $right });
-    };
-}
-
-test_float!(f32, float_assert, f32);
-test_float!(f32_const, float_const_assert, f32);
-test_float!(f64, float_assert, f64);
-test_float!(f64_const, float_const_assert, f64);
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 21d5b7292e8..3cc225004ea 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -568,7 +568,7 @@ impl OsString {
     /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
     ///
     /// [`into_boxed_os_str`]: Self::into_boxed_os_str
-    #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
+    #[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub fn leak<'a>(self) -> &'a mut OsStr {
         OsStr::from_inner_mut(self.inner.leak())
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 014b56d28f4..826d9f0f39d 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1252,7 +1252,7 @@ impl PathBuf {
     /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
     ///
     /// [`into_boxed_path`]: Self::into_boxed_path
-    #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]
+    #[stable(feature = "os_string_pathbuf_leak", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub fn leak<'a>(self) -> &'a mut Path {
         Path::from_inner_mut(self.inner.leak())
diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs
index 781855a2d14..be0dda1d426 100644
--- a/library/std/tests/path.rs
+++ b/library/std/tests/path.rs
@@ -3,7 +3,6 @@
     path_add_extension,
     path_file_prefix,
     maybe_uninit_slice,
-    os_string_pathbuf_leak,
     normalize_lexically
 )]
 
diff --git a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile
index 11a66a1c013..a1d04bd984c 100644
--- a/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check-2/Dockerfile
@@ -30,6 +30,7 @@ ENV SCRIPT \
         python3 ../x.py check && \
         python3 ../x.py clippy ci && \
         python3 ../x.py test --stage 1 core alloc std test proc_macro && \
+        python3 ../x.py doc --stage 0 bootstrap && \
         # Build both public and internal documentation.
         RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \
         RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library && \
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 741d7e3fa16..f8209f2c8cd 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -40,7 +40,9 @@ static HOSTS: &[&str] = &[
     "powerpc64le-unknown-linux-musl",
     "riscv64gc-unknown-linux-gnu",
     "s390x-unknown-linux-gnu",
+    "sparcv9-sun-solaris",
     "x86_64-apple-darwin",
+    "x86_64-pc-solaris",
     "x86_64-pc-windows-gnu",
     "x86_64-pc-windows-msvc",
     "x86_64-unknown-freebsd",
diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr
index 8c9d06c79ca..40d44db205f 100644
--- a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr
+++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr
@@ -2,14 +2,16 @@ error[E0277]: `[usize; usize::MAX]` is not a future
   --> $DIR/debug-ice-attempted-to-add-with-overflow.rs:8:37
    |
 LL |     [0usize; 0xffff_ffff_ffff_ffff].await;
-   |                                    -^^^^^
-   |                                    ||
-   |                                    |`[usize; usize::MAX]` is not a future
-   |                                    help: remove the `.await`
+   |                                     ^^^^^ `[usize; usize::MAX]` is not a future
    |
    = help: the trait `Future` is not implemented for `[usize; usize::MAX]`
    = note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited
    = note: required for `[usize; usize::MAX]` to implement `IntoFuture`
+help: remove the `.await`
+   |
+LL -     [0usize; 0xffff_ffff_ffff_ffff].await;
+LL +     [0usize; 0xffff_ffff_ffff_ffff];
+   |
 
 error[E0752]: `main` function is not allowed to be `async`
   --> $DIR/debug-ice-attempted-to-add-with-overflow.rs:6:1
diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
index 721e0106293..644a7c7717c 100644
--- a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
+++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr
@@ -10,14 +10,16 @@ error[E0277]: `Option<_>` is not a future
   --> $DIR/drop-track-bad-field-in-fru.rs:6:46
    |
 LL |     None { value: (), ..Default::default() }.await;
-   |                                             -^^^^^
-   |                                             ||
-   |                                             |`Option<_>` is not a future
-   |                                             help: remove the `.await`
+   |                                              ^^^^^ `Option<_>` is not a future
    |
    = help: the trait `Future` is not implemented for `Option<_>`
    = note: Option<_> must be a future or must implement `IntoFuture` to be awaited
    = note: required for `Option<_>` to implement `IntoFuture`
+help: remove the `.await`
+   |
+LL -     None { value: (), ..Default::default() }.await;
+LL +     None { value: (), ..Default::default() };
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr
index f6af15c00d6..87302dce130 100644
--- a/tests/ui/async-await/issue-101715.stderr
+++ b/tests/ui/async-await/issue-101715.stderr
@@ -2,14 +2,15 @@ error[E0277]: `()` is not a future
   --> $DIR/issue-101715.rs:11:10
    |
 LL |         .await
-   |         -^^^^^
-   |         ||
-   |         |`()` is not a future
-   |         help: remove the `.await`
+   |          ^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
+help: remove the `.await`
+   |
+LL -         .await
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr
index 620370a6113..f60b4ecb990 100644
--- a/tests/ui/async-await/unnecessary-await.stderr
+++ b/tests/ui/async-await/unnecessary-await.stderr
@@ -23,14 +23,16 @@ error[E0277]: `()` is not a future
   --> $DIR/unnecessary-await.rs:28:10
    |
 LL |     e!().await;
-   |         -^^^^^
-   |         ||
-   |         |`()` is not a future
-   |         help: remove the `.await`
+   |          ^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
+help: remove the `.await`
+   |
+LL -     e!().await;
+LL +     e!();
+   |
 
 error[E0277]: `()` is not a future
   --> $DIR/unnecessary-await.rs:22:15
@@ -53,14 +55,16 @@ error[E0277]: `()` is not a future
   --> $DIR/unnecessary-await.rs:36:20
    |
 LL |     for x in [] {}.await
-   |                   -^^^^^
-   |                   ||
-   |                   |`()` is not a future
-   |                   help: remove the `.await`
+   |                    ^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
    = note: required for `()` to implement `IntoFuture`
+help: remove the `.await`
+   |
+LL -     for x in [] {}.await
+LL +     for x in [] {}
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/cast/cast-to-slice.stderr b/tests/ui/cast/cast-to-slice.stderr
index 8f862c00014..382ccc3d10c 100644
--- a/tests/ui/cast/cast-to-slice.stderr
+++ b/tests/ui/cast/cast-to-slice.stderr
@@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[u8]` as `[char]`
   --> $DIR/cast-to-slice.rs:2:5
    |
 LL |     "example".as_bytes() as [char];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^------
-   |                             |
-   |                             help: try casting to a reference instead: `&[char]`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider casting to a reference instead
+   |
+LL |     "example".as_bytes() as &[char];
+   |                             +
 
 error[E0620]: cast to unsized type: `&[u8]` as `[char]`
   --> $DIR/cast-to-slice.rs:6:5
    |
 LL |     arr as [char];
-   |     ^^^^^^^------
-   |            |
-   |            help: try casting to a reference instead: `&[char]`
+   |     ^^^^^^^^^^^^^
+   |
+help: consider casting to a reference instead
+   |
+LL |     arr as &[char];
+   |            +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
index 3b5b8ea69c1..2803c3380d7 100644
--- a/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
+++ b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
@@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&{integer}` as `dyn Send`
   --> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5
    |
 LL |     &1 as dyn Send;
-   |     ^^^^^^--------
-   |           |
-   |           help: try casting to a reference instead: `&dyn Send`
+   |     ^^^^^^^^^^^^^^
+   |
+help: consider casting to a reference instead
+   |
+LL |     &1 as &dyn Send;
+   |           +
 
 error[E0620]: cast to unsized type: `Box<{integer}>` as `dyn Send`
   --> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5
    |
 LL |     Box::new(1) as dyn Send;
-   |     ^^^^^^^^^^^^^^^--------
-   |                    |
-   |                    help: you can cast to a `Box` instead: `Box<dyn Send>`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: you can cast to a `Box` instead
+   |
+LL |     Box::new(1) as Box<dyn Send>;
+   |                    ++++        +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr
index a287aa29e11..891931d0bf8 100644
--- a/tests/ui/coercion/issue-73886.stderr
+++ b/tests/ui/coercion/issue-73886.stderr
@@ -10,9 +10,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
   --> $DIR/issue-73886.rs:4:13
    |
 LL |     let _ = 7u32 as Option<_>;
-   |             ^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
    |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 help: consider using the `From` trait instead
    |
 LL -     let _ = 7u32 as Option<_>;
diff --git a/tests/ui/coercion/non-primitive-cast-135412.stderr b/tests/ui/coercion/non-primitive-cast-135412.stderr
index 7e5861f83e9..e5e9ee13459 100644
--- a/tests/ui/coercion/non-primitive-cast-135412.stderr
+++ b/tests/ui/coercion/non-primitive-cast-135412.stderr
@@ -2,9 +2,8 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
   --> $DIR/non-primitive-cast-135412.rs:6:13
    |
 LL |     let _ = 7u32 as Option<_>;
-   |             ^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
    |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 help: consider using the `From` trait instead
    |
 LL -     let _ = 7u32 as Option<_>;
@@ -15,9 +14,8 @@ error[E0605]: non-primitive cast: `&'static str` as `Arc<str>`
   --> $DIR/non-primitive-cast-135412.rs:8:13
    |
 LL |     let _ = "String" as Arc<str>;
-   |             ^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
    |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 help: consider using the `From` trait instead
    |
 LL -     let _ = "String" as Arc<str>;
diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
index a3d5054ced3..54982391b66 100644
--- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
+++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr
@@ -13,9 +13,8 @@ LL | struct Bar;
    |
 help: create an inline `const` block
    |
-LL -     let _: [Option<Bar>; 2] = [no_copy(); 2];
-LL +     let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
-   |
+LL |     let _: [Option<Bar>; 2] = [const { no_copy() }; 2];
+   |                                +++++++           +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr
index 58ddc047d03..601d067e3d8 100644
--- a/tests/ui/consts/const-blocks/trait-error.stderr
+++ b/tests/ui/consts/const-blocks/trait-error.stderr
@@ -2,10 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/trait-error.rs:5:6
    |
 LL |     [Foo(String::new()); 4];
-   |      ^^^^^^^^^^^^^^^^^^
-   |      |
-   |      the trait `Copy` is not implemented for `String`
-   |      help: create an inline `const` block: `const { Foo(String::new()) }`
+   |      ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
    |
 note: required for `Foo<String>` to implement `Copy`
   --> $DIR/trait-error.rs:1:10
@@ -13,6 +10,10 @@ note: required for `Foo<String>` to implement `Copy`
 LL | #[derive(Copy, Clone)]
    |          ^^^^ unsatisfied trait bound introduced in this `derive` macro
    = note: the `Copy` trait is required because this value will be copied for each element of the array
+help: create an inline `const` block
+   |
+LL |     [const { Foo(String::new()) }; 4];
+   |      +++++++                    +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
index 1a0832b8ba0..b996370ea3d 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
+++ b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -23,7 +23,7 @@ error[E0604]: only `u8` can be cast as `char`, not `i8`
 LL |     : [u32; 5i8 as char as usize]
    |             ^^^^^^^^^^^ invalid cast
    |
-help: try casting from `u8` instead
+help: consider casting from `u8` instead
   --> $DIR/const-eval-overflow-4b.rs:24:13
    |
 LL |     : [u32; 5i8 as char as usize]
diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr
index 5be26d7c121..890eb8040b9 100644
--- a/tests/ui/consts/const-fn-in-vec.stderr
+++ b/tests/ui/consts/const-fn-in-vec.stderr
@@ -2,36 +2,39 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/const-fn-in-vec.rs:1:47
    |
 LL | static _MAYBE_STRINGS: [Option<String>; 5] = [None; 5];
-   |                                               ^^^^
-   |                                               |
-   |                                               the trait `Copy` is not implemented for `String`
-   |                                               help: create an inline `const` block: `const { None }`
+   |                                               ^^^^ the trait `Copy` is not implemented for `String`
    |
    = note: required for `Option<String>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
+help: create an inline `const` block
+   |
+LL | static _MAYBE_STRINGS: [Option<String>; 5] = [const { None }; 5];
+   |                                               +++++++      +
 
 error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/const-fn-in-vec.rs:7:34
    |
 LL |     let _strings: [String; 5] = [String::new(); 5];
-   |                                  ^^^^^^^^^^^^^
-   |                                  |
-   |                                  the trait `Copy` is not implemented for `String`
-   |                                  help: create an inline `const` block: `const { String::new() }`
+   |                                  ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
    |
    = note: the `Copy` trait is required because this value will be copied for each element of the array
+help: create an inline `const` block
+   |
+LL |     let _strings: [String; 5] = [const { String::new() }; 5];
+   |                                  +++++++               +
 
 error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/const-fn-in-vec.rs:12:48
    |
 LL |     let _maybe_strings: [Option<String>; 5] = [None; 5];
-   |                                                ^^^^
-   |                                                |
-   |                                                the trait `Copy` is not implemented for `String`
-   |                                                help: create an inline `const` block: `const { None }`
+   |                                                ^^^^ the trait `Copy` is not implemented for `String`
    |
    = note: required for `Option<String>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
+help: create an inline `const` block
+   |
+LL |     let _maybe_strings: [Option<String>; 5] = [const { None }; 5];
+   |                                                +++++++      +
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/coroutine/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr
index da2ec272f9f..86b73e4b062 100644
--- a/tests/ui/coroutine/unresolved-ct-var.stderr
+++ b/tests/ui/coroutine/unresolved-ct-var.stderr
@@ -2,15 +2,18 @@ error[E0277]: `[(); _]` is not a future
   --> $DIR/unresolved-ct-var.rs:6:45
    |
 LL |         let s = std::array::from_fn(|_| ()).await;
-   |                 ----------------------------^^^^^
-   |                 |                          ||
-   |                 |                          |`[(); _]` is not a future
-   |                 |                          help: remove the `.await`
+   |                 --------------------------- ^^^^^ `[(); _]` is not a future
+   |                 |
    |                 this call returns `[(); _]`
    |
    = help: the trait `Future` is not implemented for `[(); _]`
    = note: [(); _] must be a future or must implement `IntoFuture` to be awaited
    = note: required for `[(); _]` to implement `IntoFuture`
+help: remove the `.await`
+   |
+LL -         let s = std::array::from_fn(|_| ()).await;
+LL +         let s = std::array::from_fn(|_| ());
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0604.stderr b/tests/ui/error-codes/E0604.stderr
index e91f74d6b3f..67bbb25958f 100644
--- a/tests/ui/error-codes/E0604.stderr
+++ b/tests/ui/error-codes/E0604.stderr
@@ -2,10 +2,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/E0604.rs:2:5
    |
 LL |     1u32 as char;
-   |     ^^^^^^^^^^^^
-   |     |
-   |     invalid cast
-   |     help: try `char::from_u32` instead: `char::from_u32(1u32)`
+   |     ^^^^^^^^^^^^ invalid cast
+   |
+help: consider using `char::from_u32` instead
+   |
+LL -     1u32 as char;
+LL +     char::from_u32(1u32);
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0620.stderr b/tests/ui/error-codes/E0620.stderr
index 644ba813c96..696407c6f7e 100644
--- a/tests/ui/error-codes/E0620.stderr
+++ b/tests/ui/error-codes/E0620.stderr
@@ -2,9 +2,12 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
   --> $DIR/E0620.rs:2:16
    |
 LL |     let _foo = &[1_usize, 2] as [usize];
-   |                ^^^^^^^^^^^^^^^^^-------
-   |                                 |
-   |                                 help: try casting to a reference instead: `&[usize]`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider casting to a reference instead
+   |
+LL |     let _foo = &[1_usize, 2] as &[usize];
+   |                                 +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-emitter/error-festival.stderr b/tests/ui/error-emitter/error-festival.stderr
index be484bc8094..6c661eb17a8 100644
--- a/tests/ui/error-emitter/error-festival.stderr
+++ b/tests/ui/error-emitter/error-festival.stderr
@@ -58,10 +58,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:27:5
    |
 LL |     0u32 as char;
-   |     ^^^^^^^^^^^^
-   |     |
-   |     invalid cast
-   |     help: try `char::from_u32` instead: `char::from_u32(0u32)`
+   |     ^^^^^^^^^^^^ invalid cast
+   |
+help: consider using `char::from_u32` instead
+   |
+LL -     0u32 as char;
+LL +     char::from_u32(0u32);
+   |
 
 error[E0605]: non-primitive cast: `u8` as `Vec<u8>`
   --> $DIR/error-festival.rs:31:5
diff --git a/tests/ui/issues/issue-16048.stderr b/tests/ui/issues/issue-16048.stderr
index 73610942d7a..f97f13152bc 100644
--- a/tests/ui/issues/issue-16048.stderr
+++ b/tests/ui/issues/issue-16048.stderr
@@ -11,9 +11,13 @@ error[E0605]: non-primitive cast: `Foo<'a>` as `T`
   --> $DIR/issue-16048.rs:24:16
    |
 LL |         return *self as T;
-   |                ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)`
+   |                ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |
+help: consider using the `From` trait instead
+   |
+LL -         return *self as T;
+LL +         return T::from(*self);
    |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-17441.stderr b/tests/ui/issues/issue-17441.stderr
index 29e50b91c7c..96aad879e24 100644
--- a/tests/ui/issues/issue-17441.stderr
+++ b/tests/ui/issues/issue-17441.stderr
@@ -2,17 +2,23 @@ error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
   --> $DIR/issue-17441.rs:2:16
    |
 LL |     let _foo = &[1_usize, 2] as [usize];
-   |                ^^^^^^^^^^^^^^^^^-------
-   |                                 |
-   |                                 help: try casting to a reference instead: `&[usize]`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider casting to a reference instead
+   |
+LL |     let _foo = &[1_usize, 2] as &[usize];
+   |                                 +
 
 error[E0620]: cast to unsized type: `Box<usize>` as `dyn Debug`
   --> $DIR/issue-17441.rs:5:16
    |
 LL |     let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
-   |                ^^^^^^^^^^^^^^^^^^^^^-------------------
-   |                                     |
-   |                                     help: you can cast to a `Box` instead: `Box<dyn std::fmt::Debug>`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: you can cast to a `Box` instead
+   |
+LL |     let _bar = Box::new(1_usize) as Box<dyn std::fmt::Debug>;
+   |                                     ++++                   +
 
 error[E0620]: cast to unsized type: `usize` as `dyn Debug`
   --> $DIR/issue-17441.rs:8:16
diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr
index a4276395944..a188b7791fd 100644
--- a/tests/ui/mismatched_types/cast-rfc0401.stderr
+++ b/tests/ui/mismatched_types/cast-rfc0401.stderr
@@ -104,10 +104,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/cast-rfc0401.rs:41:13
    |
 LL |     let _ = 0x61u32 as char;
-   |             ^^^^^^^^^^^^^^^
-   |             |
-   |             invalid cast
-   |             help: try `char::from_u32` instead: `char::from_u32(0x61u32)`
+   |             ^^^^^^^^^^^^^^^ invalid cast
+   |
+help: consider using `char::from_u32` instead
+   |
+LL -     let _ = 0x61u32 as char;
+LL +     let _ = char::from_u32(0x61u32);
+   |
 
 error[E0606]: casting `bool` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:43:13
diff --git a/tests/ui/nonscalar-cast.stderr b/tests/ui/nonscalar-cast.stderr
index 01b4a9a7ce0..834d4ea241c 100644
--- a/tests/ui/nonscalar-cast.stderr
+++ b/tests/ui/nonscalar-cast.stderr
@@ -2,9 +2,13 @@ error[E0605]: non-primitive cast: `Foo` as `isize`
   --> $DIR/nonscalar-cast.rs:15:20
    |
 LL |     println!("{}", Foo { x: 1 } as isize);
-   |                    ^^^^^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(Foo { x: 1 })`
+   |                    ^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |
+help: consider using the `From` trait instead
+   |
+LL -     println!("{}", Foo { x: 1 } as isize);
+LL +     println!("{}", isize::from(Foo { x: 1 }));
    |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr
index d974f5add50..1c862f2b606 100644
--- a/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr
+++ b/tests/ui/repeat-expr/copy-check-when-count-inferred-later.stderr
@@ -2,12 +2,13 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/copy-check-when-count-inferred-later.rs:8:14
    |
 LL |     let a = [String::new(); _];
-   |              ^^^^^^^^^^^^^
-   |              |
-   |              the trait `Copy` is not implemented for `String`
-   |              help: create an inline `const` block: `const { String::new() }`
+   |              ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
    |
    = note: the `Copy` trait is required because this value will be copied for each element of the array
+help: create an inline `const` block
+   |
+LL |     let a = [const { String::new() }; _];
+   |              +++++++               +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/tag-variant-cast-non-nullary.stderr b/tests/ui/tag-variant-cast-non-nullary.stderr
index 2e1dde27d0f..8ec1c5f11ec 100644
--- a/tests/ui/tag-variant-cast-non-nullary.stderr
+++ b/tests/ui/tag-variant-cast-non-nullary.stderr
@@ -2,10 +2,14 @@ error[E0605]: non-primitive cast: `NonNullary` as `isize`
   --> $DIR/tag-variant-cast-non-nullary.rs:19:15
    |
 LL |     let val = v as isize;
-   |               ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)`
+   |               ^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
    |
-   = note: an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
    = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
+help: consider using the `From` trait instead
+   |
+LL -     let val = v as isize;
+LL +     let val = isize::from(v);
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
index 7c09ab6a91a..72a253c4be8 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
@@ -2,7 +2,7 @@ error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
   --> $DIR/constrain_in_projection2.rs:28:14
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
-   |              ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
+   |              ^^^
    |
 note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
   --> $DIR/constrain_in_projection2.rs:18:1
@@ -13,6 +13,11 @@ LL | impl Trait<()> for Foo {
 LL | impl Trait<u32> for Foo {
    | ^^^^^^^^^^^^^^^^^^^^^^^
    = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+help: use the fully qualified path to an implementation
+   |
+LL -     let x = <Foo as Trait<Bar>>::Assoc::default();
+LL +     let x = <<Type as Trait>::Assoc as Trait<Bar>>::Assoc::default();
+   |
 
 error: aborting due to 1 previous error