about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs54
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs1
-rw-r--r--compiler/rustc_data_structures/src/memmap.rs16
-rw-r--r--compiler/rustc_data_structures/src/stack.rs12
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs8
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs92
-rw-r--r--compiler/rustc_hir/src/intravisit.rs8
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs71
-rw-r--r--compiler/rustc_interface/src/interface.rs1
-rw-r--r--compiler/rustc_interface/src/passes.rs5
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/late.rs4
-rw-r--r--compiler/rustc_lint/src/passes.rs1
-rw-r--r--compiler/rustc_lint/src/types.rs13
-rw-r--r--compiler/rustc_lint/src/types/literal.rs74
-rw-r--r--compiler/rustc_middle/src/hooks/mod.rs4
-rw-r--r--compiler/rustc_middle/src/thir.rs17
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs58
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/match_pair.rs34
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs152
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/simplify.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/test.rs37
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/util.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs20
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs11
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs12
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs8
-rw-r--r--compiler/rustc_passes/src/check_attr.rs57
-rw-r--r--compiler/rustc_session/src/config/cfg.rs2
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/session.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs26
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs3
-rw-r--r--library/std/src/collections/hash/map.rs32
-rw-r--r--library/std/src/process/tests.rs15
-rw-r--r--src/bootstrap/src/utils/render_tests.rs3
-rw-r--r--src/tools/clippy/CHANGELOG.md4
-rw-r--r--src/tools/clippy/book/src/attribs.md2
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md1
-rw-r--r--src/tools/clippy/book/src/lints.md13
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs28
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs67
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/endian_bytes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/format_push_string.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs111
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_div_ceil.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs225
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/return_and_then.rs67
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/precedence.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_else.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/to_digit_is_some.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs64
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs2
-rw-r--r--src/tools/clippy/clippy_utils/README.md2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs15
-rw-r--r--src/tools/clippy/clippy_utils/src/str_utils.rs10
-rw-r--r--src/tools/clippy/lintcheck/src/config.rs9
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs53
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui/cmp_null.fixed32
-rw-r--r--src/tools/clippy/tests/ui/cmp_null.rs12
-rw-r--r--src/tools/clippy/tests/ui/cmp_null.stderr26
-rw-r--r--src/tools/clippy/tests/ui/eta.fixed5
-rw-r--r--src/tools/clippy/tests/ui/eta.rs5
-rw-r--r--src/tools/clippy/tests/ui/eta.stderr54
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.fixed15
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.rs15
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.stderr18
-rw-r--r--src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs7
-rw-r--r--src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr36
-rw-r--r--src/tools/clippy/tests/ui/manual_option_as_slice.fixed62
-rw-r--r--src/tools/clippy/tests/ui/manual_option_as_slice.rs71
-rw-r--r--src/tools/clippy/tests/ui/manual_option_as_slice.stderr58
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_fill.fixed101
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_fill.rs110
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_fill.stderr38
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.rs15
-rw-r--r--src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.stderr34
-rw-r--r--src/tools/clippy/tests/ui/needless_option_take.fixed58
-rw-r--r--src/tools/clippy/tests/ui/needless_option_take.stderr36
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.rs3
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.stderr28
-rw-r--r--src/tools/clippy/tests/ui/precedence.fixed8
-rw-r--r--src/tools/clippy/tests/ui/precedence.stderr26
-rw-r--r--src/tools/clippy/tests/ui/precedence_bits.fixed35
-rw-r--r--src/tools/clippy/tests/ui/precedence_bits.rs35
-rw-r--r--src/tools/clippy/tests/ui/precedence_bits.stderr29
-rw-r--r--src/tools/clippy/tests/ui/print_literal.fixed14
-rw-r--r--src/tools/clippy/tests/ui/print_literal.rs15
-rw-r--r--src/tools/clippy/tests/ui/print_literal.stderr38
-rw-r--r--src/tools/clippy/tests/ui/redundant_else.fixed154
-rw-r--r--src/tools/clippy/tests/ui/redundant_else.stderr77
-rw-r--r--src/tools/clippy/tests/ui/return_and_then.fixed67
-rw-r--r--src/tools/clippy/tests/ui/return_and_then.rs63
-rw-r--r--src/tools/clippy/tests/ui/return_and_then.stderr101
-rw-r--r--src/tools/clippy/tests/ui/size_of_in_element_count/expressions.rs17
-rw-r--r--src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr12
-rw-r--r--src/tools/clippy/tests/ui/size_of_in_element_count/functions.rs43
-rw-r--r--src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr110
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_semicolon.edition2021.fixed6
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_semicolon.edition2024.fixed6
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_semicolon.rs6
-rw-r--r--src/tools/clippy/tests/ui/write_literal.fixed16
-rw-r--r--src/tools/clippy/tests/ui/write_literal.rs17
-rw-r--r--src/tools/clippy/tests/ui/write_literal.stderr38
-rw-r--r--src/tools/clippy/util/gh-pages/index_template.html23
-rw-r--r--src/tools/clippy/util/gh-pages/script.js87
-rw-r--r--src/tools/clippy/util/gh-pages/style.css8
-rw-r--r--src/tools/clippy/util/gh-pages/theme.js9
-rw-r--r--tests/crashes/132391.rs8
-rw-r--r--tests/mir-opt/pattern_types.main.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pattern_types.rs2
-rw-r--r--tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs3
-rw-r--r--tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr2
-rw-r--r--tests/ui/diagnostic-width/binop.rs17
-rw-r--r--tests/ui/diagnostic-width/binop.stderr24
-rw-r--r--tests/ui/feature-gates/feature-gate-fn_align.rs5
-rw-r--r--tests/ui/feature-gates/feature-gate-fn_align.stderr12
-rw-r--r--tests/ui/force-inlining/deny-async.rs4
-rw-r--r--tests/ui/force-inlining/deny-async.stderr19
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.rs3
-rw-r--r--tests/ui/pattern/overflowing-literals.rs21
-rw-r--r--tests/ui/pattern/overflowing-literals.stderr37
-rw-r--r--tests/ui/repr/attr-usage-repr.rs31
-rw-r--r--tests/ui/repr/attr-usage-repr.stderr36
-rw-r--r--tests/ui/traits/trait-upcasting/mono-impossible.rs26
-rw-r--r--tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr4
172 files changed, 3407 insertions, 1070 deletions
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index b44d2a01d57..ed5489652fb 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -51,6 +51,8 @@ pub fn provide(providers: &mut Providers) {
     providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
         util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
     };
+    providers.hooks.validate_scalar_in_layout =
+        |tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout);
 }
 
 /// `rustc_driver::main` installs a handler that will set this to `true` if
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index a729d9325c8..79baf91c3ce 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,9 +1,10 @@
 use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants};
-use rustc_middle::bug;
 use rustc_middle::ty::layout::{
     HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
 };
-use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt};
+use rustc_middle::ty::{PseudoCanonicalInput, ScalarInt, Ty, TyCtxt};
+use rustc_middle::{bug, ty};
+use rustc_span::DUMMY_SP;
 
 use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
 use crate::interpret::{InterpCx, MemoryKind};
@@ -34,7 +35,7 @@ pub fn check_validity_requirement<'tcx>(
 
     let layout_cx = LayoutCx::new(tcx, input.typing_env);
     if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
-        check_validity_requirement_strict(layout, &layout_cx, kind)
+        Ok(check_validity_requirement_strict(layout, &layout_cx, kind))
     } else {
         check_validity_requirement_lax(layout, &layout_cx, kind)
     }
@@ -46,10 +47,10 @@ fn check_validity_requirement_strict<'tcx>(
     ty: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx>,
     kind: ValidityRequirement,
-) -> Result<bool, &'tcx LayoutError<'tcx>> {
+) -> bool {
     let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
 
-    let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine);
+    let mut cx = InterpCx::new(cx.tcx(), DUMMY_SP, cx.typing_env, machine);
 
     let allocated = cx
         .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
@@ -69,14 +70,13 @@ fn check_validity_requirement_strict<'tcx>(
     // due to this.
     // The value we are validating is temporary and discarded at the end of this function, so
     // there is no point in reseting provenance and padding.
-    Ok(cx
-        .validate_operand(
-            &allocated.into(),
-            /*recursive*/ false,
-            /*reset_provenance_and_padding*/ false,
-        )
-        .discard_err()
-        .is_some())
+    cx.validate_operand(
+        &allocated.into(),
+        /*recursive*/ false,
+        /*reset_provenance_and_padding*/ false,
+    )
+    .discard_err()
+    .is_some()
 }
 
 /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
@@ -168,3 +168,31 @@ fn check_validity_requirement_lax<'tcx>(
 
     Ok(true)
 }
+
+pub(crate) fn validate_scalar_in_layout<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    scalar: ScalarInt,
+    ty: Ty<'tcx>,
+) -> bool {
+    let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
+
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+    let mut cx = InterpCx::new(tcx, DUMMY_SP, typing_env, machine);
+
+    let Ok(layout) = cx.layout_of(ty) else {
+        bug!("could not compute layout of {scalar:?}:{ty:?}")
+    };
+    let allocated = cx
+        .allocate(layout, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
+        .expect("OOM: failed to allocate for uninit check");
+
+    cx.write_scalar(scalar, &allocated).unwrap();
+
+    cx.validate_operand(
+        &allocated.into(),
+        /*recursive*/ false,
+        /*reset_provenance_and_padding*/ false,
+    )
+    .discard_err()
+    .is_some()
+}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 25a9dbb2c11..5be5ee8d1ae 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -8,6 +8,7 @@ mod type_name;
 
 pub use self::alignment::{is_disaligned, is_within_packed};
 pub use self::check_validity_requirement::check_validity_requirement;
+pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
 pub use self::compare_types::{relate_types, sub_types};
 pub use self::type_name::type_name;
 
diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs
index c7f66b2fee8..d64a5862f4e 100644
--- a/compiler/rustc_data_structures/src/memmap.rs
+++ b/compiler/rustc_data_structures/src/memmap.rs
@@ -3,13 +3,13 @@ use std::io;
 use std::ops::{Deref, DerefMut};
 
 /// A trivial wrapper for [`memmap2::Mmap`] (or `Vec<u8>` on WASM).
-#[cfg(not(target_arch = "wasm32"))]
+#[cfg(not(any(miri, target_arch = "wasm32")))]
 pub struct Mmap(memmap2::Mmap);
 
-#[cfg(target_arch = "wasm32")]
+#[cfg(any(miri, target_arch = "wasm32"))]
 pub struct Mmap(Vec<u8>);
 
-#[cfg(not(target_arch = "wasm32"))]
+#[cfg(not(any(miri, target_arch = "wasm32")))]
 impl Mmap {
     /// # Safety
     ///
@@ -29,7 +29,7 @@ impl Mmap {
     }
 }
 
-#[cfg(target_arch = "wasm32")]
+#[cfg(any(miri, target_arch = "wasm32"))]
 impl Mmap {
     #[inline]
     pub unsafe fn map(mut file: File) -> io::Result<Self> {
@@ -56,13 +56,13 @@ impl AsRef<[u8]> for Mmap {
     }
 }
 
-#[cfg(not(target_arch = "wasm32"))]
+#[cfg(not(any(miri, target_arch = "wasm32")))]
 pub struct MmapMut(memmap2::MmapMut);
 
-#[cfg(target_arch = "wasm32")]
+#[cfg(any(miri, target_arch = "wasm32"))]
 pub struct MmapMut(Vec<u8>);
 
-#[cfg(not(target_arch = "wasm32"))]
+#[cfg(not(any(miri, target_arch = "wasm32")))]
 impl MmapMut {
     #[inline]
     pub fn map_anon(len: usize) -> io::Result<Self> {
@@ -82,7 +82,7 @@ impl MmapMut {
     }
 }
 
-#[cfg(target_arch = "wasm32")]
+#[cfg(any(miri, target_arch = "wasm32"))]
 impl MmapMut {
     #[inline]
     pub fn map_anon(len: usize) -> io::Result<Self> {
diff --git a/compiler/rustc_data_structures/src/stack.rs b/compiler/rustc_data_structures/src/stack.rs
index 3d6d0003483..102b3640911 100644
--- a/compiler/rustc_data_structures/src/stack.rs
+++ b/compiler/rustc_data_structures/src/stack.rs
@@ -17,6 +17,18 @@ const STACK_PER_RECURSION: usize = 16 * 1024 * 1024; // 16MB
 ///
 /// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
 #[inline]
+#[cfg(not(miri))]
 pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
     stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
 }
+
+/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations
+/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit
+/// from this.
+///
+/// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
+#[cfg(miri)]
+#[inline]
+pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
+    f()
+}
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 6ea14d15c14..4c47ce93dd5 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -89,10 +89,10 @@ pub mod pretty;
 #[macro_use]
 mod print;
 mod session_diagnostics;
-#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
+#[cfg(all(not(miri), unix, any(target_env = "gnu", target_os = "macos")))]
 mod signal_handler;
 
-#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
+#[cfg(not(all(not(miri), unix, any(target_env = "gnu", target_os = "macos"))))]
 mod signal_handler {
     /// On platforms which don't support our signal handler's requirements,
     /// simply use the default signal handler provided by std.
@@ -1024,7 +1024,7 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
     let wall = matches.opt_strs("W");
     if wall.iter().any(|x| *x == "all") {
         print_wall_help();
-        rustc_errors::FatalError.raise();
+        return true;
     }
 
     // Don't handle -W help here, because we might first load additional lints.
@@ -1474,7 +1474,7 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
 /// Install our usual `ctrlc` handler, which sets [`rustc_const_eval::CTRL_C_RECEIVED`].
 /// Making this handler optional lets tools can install a different handler, if they wish.
 pub fn install_ctrlc_handler() {
-    #[cfg(not(target_family = "wasm"))]
+    #[cfg(all(not(miri), not(target_family = "wasm")))]
     ctrlc::set_handler(move || {
         // Indicate that we have been signaled to stop, then give the rest of the compiler a bit of
         // time to check CTRL_C_RECEIVED and run its own shutdown logic, but after a short amount
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 8aa30db6d5a..15cf285e7ff 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1765,7 +1765,7 @@ impl HumanEmitter {
 
                 let column_width = if let Some(width) = self.diagnostic_width {
                     width.saturating_sub(code_offset)
-                } else if self.ui_testing {
+                } else if self.ui_testing || cfg!(miri) {
                     DEFAULT_COLUMN_WIDTH
                 } else {
                     termize::dimensions()
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 7a02e0dd2f0..9af17db9a6e 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1048,8 +1048,8 @@ impl<'a> DiagCtxtHandle<'a> {
     /// bad results, such as spurious/uninteresting additional errors -- when
     /// returning an error `Result` is difficult.
     pub fn abort_if_errors(&self) {
-        if self.has_errors().is_some() {
-            FatalError.raise();
+        if let Some(guar) = self.has_errors() {
+            guar.raise_fatal();
         }
     }
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 1c87a0eb1a7..e7b6a97c9d9 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -206,7 +206,7 @@ pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
 
 impl Path<'_> {
     pub fn is_global(&self) -> bool {
-        !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
+        self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
     }
 }
 
@@ -1061,10 +1061,7 @@ impl Attribute {
 
     pub fn value_lit(&self) -> Option<&MetaItemLit> {
         match &self.kind {
-            AttrKind::Normal(n) => match n.as_ref() {
-                AttrItem { args: AttrArgs::Eq { expr, .. }, .. } => Some(expr),
-                _ => None,
-            },
+            AttrKind::Normal(box AttrItem { args: AttrArgs::Eq { expr, .. }, .. }) => Some(expr),
             _ => None,
         }
     }
@@ -1077,12 +1074,9 @@ impl AttributeExt for Attribute {
 
     fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
         match &self.kind {
-            AttrKind::Normal(n) => match n.as_ref() {
-                AttrItem { args: AttrArgs::Delimited(d), .. } => {
-                    ast::MetaItemKind::list_from_tokens(d.tokens.clone())
-                }
-                _ => None,
-            },
+            AttrKind::Normal(box AttrItem { args: AttrArgs::Delimited(d), .. }) => {
+                ast::MetaItemKind::list_from_tokens(d.tokens.clone())
+            }
             _ => None,
         }
     }
@@ -1098,23 +1092,16 @@ impl AttributeExt for Attribute {
     /// For a single-segment attribute, returns its name; otherwise, returns `None`.
     fn ident(&self) -> Option<Ident> {
         match &self.kind {
-            AttrKind::Normal(n) => {
-                if let [ident] = n.path.segments.as_ref() {
-                    Some(*ident)
-                } else {
-                    None
-                }
-            }
-            AttrKind::DocComment(..) => None,
+            AttrKind::Normal(box AttrItem {
+                path: AttrPath { segments: box [ident], .. }, ..
+            }) => Some(*ident),
+            _ => None,
         }
     }
 
     fn path_matches(&self, name: &[Symbol]) -> bool {
         match &self.kind {
-            AttrKind::Normal(n) => {
-                n.path.segments.len() == name.len()
-                    && n.path.segments.iter().zip(name).all(|(s, n)| s.name == *n)
-            }
+            AttrKind::Normal(n) => n.path.segments.iter().map(|segment| &segment.name).eq(name),
             AttrKind::DocComment(..) => false,
         }
     }
@@ -1128,12 +1115,7 @@ impl AttributeExt for Attribute {
     }
 
     fn is_word(&self) -> bool {
-        match &self.kind {
-            AttrKind::Normal(n) => {
-                matches!(n.args, AttrArgs::Empty)
-            }
-            AttrKind::DocComment(..) => false,
-        }
+        matches!(self.kind, AttrKind::Normal(box AttrItem { args: AttrArgs::Empty, .. }))
     }
 
     fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
@@ -1990,7 +1972,7 @@ impl fmt::Display for ConstContext {
 }
 
 // NOTE: `IntoDiagArg` impl for `ConstContext` lives in `rustc_errors`
-// due to a cyclical dependency between hir that crate.
+// due to a cyclical dependency between hir and that crate.
 
 /// A literal.
 pub type Lit = Spanned<LitKind>;
@@ -3604,10 +3586,10 @@ impl<'hir> FnRetTy<'hir> {
     }
 
     pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> {
-        if let Self::Return(ty) = self {
-            if ty.is_suggestable_infer_ty() {
-                return Some(*ty);
-            }
+        if let Self::Return(ty) = self
+            && ty.is_suggestable_infer_ty()
+        {
+            return Some(*ty);
         }
         None
     }
@@ -3976,11 +3958,11 @@ pub struct FnHeader {
 
 impl FnHeader {
     pub fn is_async(&self) -> bool {
-        matches!(&self.asyncness, IsAsync::Async(_))
+        matches!(self.asyncness, IsAsync::Async(_))
     }
 
     pub fn is_const(&self) -> bool {
-        matches!(&self.constness, Constness::Const)
+        matches!(self.constness, Constness::Const)
     }
 
     pub fn is_unsafe(&self) -> bool {
@@ -4076,16 +4058,16 @@ pub struct Impl<'hir> {
 
 impl ItemKind<'_> {
     pub fn generics(&self) -> Option<&Generics<'_>> {
-        Some(match *self {
-            ItemKind::Fn { ref generics, .. }
-            | ItemKind::TyAlias(_, ref generics)
-            | ItemKind::Const(_, ref generics, _)
-            | ItemKind::Enum(_, ref generics)
-            | ItemKind::Struct(_, ref generics)
-            | ItemKind::Union(_, ref generics)
-            | ItemKind::Trait(_, _, ref generics, _, _)
-            | ItemKind::TraitAlias(ref generics, _)
-            | ItemKind::Impl(Impl { ref generics, .. }) => generics,
+        Some(match self {
+            ItemKind::Fn { generics, .. }
+            | ItemKind::TyAlias(_, generics)
+            | ItemKind::Const(_, generics, _)
+            | ItemKind::Enum(_, generics)
+            | ItemKind::Struct(_, generics)
+            | ItemKind::Union(_, generics)
+            | ItemKind::Trait(_, _, generics, _, _)
+            | ItemKind::TraitAlias(generics, _)
+            | ItemKind::Impl(Impl { generics, .. }) => generics,
             _ => return None,
         })
     }
@@ -4484,16 +4466,14 @@ impl<'hir> Node<'hir> {
 
     /// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
     pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
-        match self {
-            Node::Item(Item { kind: ItemKind::Impl(impl_block), .. })
-                if impl_block
-                    .of_trait
-                    .and_then(|trait_ref| trait_ref.trait_def_id())
-                    .is_some_and(|trait_id| trait_id == trait_def_id) =>
-            {
-                Some(impl_block)
-            }
-            _ => None,
+        if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self
+            && let Some(trait_ref) = impl_block.of_trait
+            && let Some(trait_id) = trait_ref.trait_def_id()
+            && trait_id == trait_def_id
+        {
+            Some(impl_block)
+        } else {
+            None
         }
     }
 
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 6519552d604..f632041dba9 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -345,6 +345,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
         walk_pat_expr(self, expr)
     }
+    fn visit_lit(&mut self, _hir_id: HirId, _lit: &'v Lit, _negated: bool) -> Self::Result {
+        Self::Result::output()
+    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
         walk_anon_const(self, c)
     }
@@ -764,7 +767,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
 pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
     try_visit!(visitor.visit_id(expr.hir_id));
     match &expr.kind {
-        PatExprKind::Lit { .. } => V::Result::output(),
+        PatExprKind::Lit { lit, negated } => visitor.visit_lit(expr.hir_id, lit, *negated),
         PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
         PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
     }
@@ -912,7 +915,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             try_visit!(visitor.visit_expr(expr));
             visit_opt!(visitor, visit_ty_unambig, ty);
         }
-        ExprKind::Lit(_) | ExprKind::Err(_) => {}
+        ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(expression.hir_id, lit, false)),
+        ExprKind::Err(_) => {}
     }
     V::Result::output()
 }
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 705c167e258..270d4fbec30 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -5,6 +5,7 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![feature(associated_type_defaults)]
+#![feature(box_patterns)]
 #![feature(closure_track_caller)]
 #![feature(debug_closure_helpers)]
 #![feature(exhaustive_patterns)]
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 6c534d58a7d..9ed56d7bde5 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -19,7 +19,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::error::TypeErrorToStringExt;
 use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
-use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
+use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{
     AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
@@ -257,30 +257,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
 
     // First, try to look at any opaque expansion cycles, considering coroutine fields
     // (even though these aren't necessarily true errors).
-    if tcx
-        .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
-        .is_err()
-    {
-        // Look for true opaque expansion cycles, but ignore coroutines.
-        // This will give us any true errors. Coroutines are only problematic
-        // if they cause layout computation errors.
-        if tcx
-            .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
-            .is_err()
-        {
-            let reported = opaque_type_cycle_error(tcx, def_id);
-            return Err(reported);
-        }
-
-        // And also look for cycle errors in the layout of coroutines.
-        if let Err(&LayoutError::Cycle(guar)) =
-            tcx.layout_of(
-                ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
-                    .as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)),
-            )
-        {
-            return Err(guar);
-        }
+    if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
+        let reported = opaque_type_cycle_error(tcx, def_id);
+        return Err(reported);
     }
 
     Ok(())
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 805079afdb0..47c1f784448 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -306,6 +306,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
                 let missing_trait = trait_def_id
                     .map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id)));
+                let mut path = None;
+                let lhs_ty_str = self.tcx.short_string(lhs_ty, &mut path);
+                let rhs_ty_str = self.tcx.short_string(rhs_ty, &mut path);
                 let (mut err, output_def_id) = match is_assign {
                     IsAssign::Yes => {
                         let mut err = struct_span_code_err!(
@@ -314,11 +317,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             E0368,
                             "binary assignment operation `{}=` cannot be applied to type `{}`",
                             op.node.as_str(),
-                            lhs_ty,
+                            lhs_ty_str,
                         );
                         err.span_label(
                             lhs_expr.span,
-                            format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
+                            format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty_str),
                         );
                         self.note_unmet_impls_on_type(&mut err, errors, false);
                         (err, None)
@@ -326,41 +329,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     IsAssign::No => {
                         let message = match op.node {
                             hir::BinOpKind::Add => {
-                                format!("cannot add `{rhs_ty}` to `{lhs_ty}`")
+                                format!("cannot add `{rhs_ty_str}` to `{lhs_ty_str}`")
                             }
                             hir::BinOpKind::Sub => {
-                                format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`")
+                                format!("cannot subtract `{rhs_ty_str}` from `{lhs_ty_str}`")
                             }
                             hir::BinOpKind::Mul => {
-                                format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`")
+                                format!("cannot multiply `{lhs_ty_str}` by `{rhs_ty_str}`")
                             }
                             hir::BinOpKind::Div => {
-                                format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
+                                format!("cannot divide `{lhs_ty_str}` by `{rhs_ty_str}`")
                             }
                             hir::BinOpKind::Rem => {
                                 format!(
-                                    "cannot calculate the remainder of `{lhs_ty}` divided by `{rhs_ty}`"
+                                    "cannot calculate the remainder of `{lhs_ty_str}` divided by \
+                                     `{rhs_ty_str}`"
                                 )
                             }
                             hir::BinOpKind::BitAnd => {
-                                format!("no implementation for `{lhs_ty} & {rhs_ty}`")
+                                format!("no implementation for `{lhs_ty_str} & {rhs_ty_str}`")
                             }
                             hir::BinOpKind::BitXor => {
-                                format!("no implementation for `{lhs_ty} ^ {rhs_ty}`")
+                                format!("no implementation for `{lhs_ty_str} ^ {rhs_ty_str}`")
                             }
                             hir::BinOpKind::BitOr => {
-                                format!("no implementation for `{lhs_ty} | {rhs_ty}`")
+                                format!("no implementation for `{lhs_ty_str} | {rhs_ty_str}`")
                             }
                             hir::BinOpKind::Shl => {
-                                format!("no implementation for `{lhs_ty} << {rhs_ty}`")
+                                format!("no implementation for `{lhs_ty_str} << {rhs_ty_str}`")
                             }
                             hir::BinOpKind::Shr => {
-                                format!("no implementation for `{lhs_ty} >> {rhs_ty}`")
+                                format!("no implementation for `{lhs_ty_str} >> {rhs_ty_str}`")
                             }
                             _ => format!(
                                 "binary operation `{}` cannot be applied to type `{}`",
                                 op.node.as_str(),
-                                lhs_ty
+                                lhs_ty_str,
                             ),
                         };
                         let output_def_id = trait_def_id.and_then(|def_id| {
@@ -375,14 +379,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let mut err =
                             struct_span_code_err!(self.dcx(), op.span, E0369, "{message}");
                         if !lhs_expr.span.eq(&rhs_expr.span) {
-                            err.span_label(lhs_expr.span, lhs_ty.to_string());
-                            err.span_label(rhs_expr.span, rhs_ty.to_string());
+                            err.span_label(lhs_expr.span, lhs_ty_str.clone());
+                            err.span_label(rhs_expr.span, rhs_ty_str);
                         }
                         let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);
                         self.note_unmet_impls_on_type(&mut err, errors, suggest_derive);
                         (err, output_def_id)
                     }
                 };
+                *err.long_ty_path() = path;
 
                 // Try to suggest a semicolon if it's `A \n *B` where `B` is a place expr
                 let maybe_missing_semi = self.check_for_missing_semi(expr, &mut err);
@@ -417,7 +422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 IsAssign::Yes => "=",
                                 IsAssign::No => "",
                             },
-                            lhs_deref_ty,
+                            self.tcx.short_string(lhs_deref_ty, err.long_ty_path()),
                         );
                         err.span_suggestion_verbose(
                             lhs_expr.span.shrink_to_lo(),
@@ -443,8 +448,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             )
                             .is_ok()
                         {
-                            let op_str = op.node.as_str();
-                            err.note(format!("an implementation for `{lhs_adjusted_ty} {op_str} {rhs_adjusted_ty}` exists"));
+                            let lhs = self.tcx.short_string(lhs_adjusted_ty, err.long_ty_path());
+                            let rhs = self.tcx.short_string(rhs_adjusted_ty, err.long_ty_path());
+                            let op = op.node.as_str();
+                            err.note(format!("an implementation for `{lhs} {op} {rhs}` exists"));
 
                             if let Some(lhs_new_mutbl) = lhs_new_mutbl
                                 && let Some(rhs_new_mutbl) = rhs_new_mutbl
@@ -628,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // When we know that a missing bound is responsible, we don't show
                             // this note as it is redundant.
                             err.note(format!(
-                                "the trait `{missing_trait}` is not implemented for `{lhs_ty}`"
+                                "the trait `{missing_trait}` is not implemented for `{lhs_ty_str}`"
                             ));
                         }
                     }
@@ -654,24 +661,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         hir::BinOpKind::Sub => {
                             if lhs_ty.is_unsafe_ptr() && rhs_ty.is_integral() {
                                 err.multipart_suggestion(
-                                    "consider using `wrapping_sub` or `sub` for pointer - {integer}",
+                                    "consider using `wrapping_sub` or `sub` for \
+                                     pointer - {integer}",
                                     vec![
-                                        (lhs_expr.span.between(rhs_expr.span), ".wrapping_sub(".to_owned()),
+                                        (
+                                            lhs_expr.span.between(rhs_expr.span),
+                                            ".wrapping_sub(".to_owned(),
+                                        ),
                                         (rhs_expr.span.shrink_to_hi(), ")".to_owned()),
                                     ],
-                                    Applicability::MaybeIncorrect
+                                    Applicability::MaybeIncorrect,
                                 );
                             }
 
                             if lhs_ty.is_unsafe_ptr() && rhs_ty.is_unsafe_ptr() {
                                 err.multipart_suggestion(
-                                    "consider using `offset_from` for pointer - pointer if the pointers point to the same allocation",
+                                    "consider using `offset_from` for pointer - pointer if the \
+                                     pointers point to the same allocation",
                                     vec![
                                         (lhs_expr.span.shrink_to_lo(), "unsafe { ".to_owned()),
-                                        (lhs_expr.span.between(rhs_expr.span), ".offset_from(".to_owned()),
+                                        (
+                                            lhs_expr.span.between(rhs_expr.span),
+                                            ".offset_from(".to_owned(),
+                                        ),
                                         (rhs_expr.span.shrink_to_hi(), ") }".to_owned()),
                                     ],
-                                    Applicability::MaybeIncorrect
+                                    Applicability::MaybeIncorrect,
                                 );
                             }
                         }
@@ -793,14 +808,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Err(errors) => {
                 let actual = self.resolve_vars_if_possible(operand_ty);
                 let guar = actual.error_reported().err().unwrap_or_else(|| {
+                    let mut file = None;
+                    let ty_str = self.tcx.short_string(actual, &mut file);
                     let mut err = struct_span_code_err!(
                         self.dcx(),
                         ex.span,
                         E0600,
-                        "cannot apply unary operator `{}` to type `{}`",
+                        "cannot apply unary operator `{}` to type `{ty_str}`",
                         op.as_str(),
-                        actual
                     );
+                    *err.long_ty_path() = file;
                     err.span_label(
                         ex.span,
                         format!("cannot apply unary operator `{}`", op.as_str()),
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 97fc542910c..b35703d8e73 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -442,7 +442,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             locale_resources.push(codegen_backend.locale_resource());
 
             let mut sess = rustc_session::build_session(
-                early_dcx,
                 config.opts,
                 CompilerIO {
                     input: config.input,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index cb79602c9f6..eda9c4e03fe 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -909,6 +909,11 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
                 tcx.ensure_ok().check_coroutine_obligations(
                     tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
                 );
+                // Eagerly check the unsubstituted layout for cycles.
+                tcx.ensure_ok().layout_of(
+                    ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
+                        .as_query_input(tcx.type_of(def_id).instantiate_identity()),
+                );
             }
         });
     });
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index fb69dd54811..46d6f37a91c 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -65,7 +65,6 @@ where
         static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false);
 
         let sess = build_session(
-            early_dcx,
             sessopts,
             io,
             None,
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 826ecc22c24..3ee908ba9bf 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -152,6 +152,10 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
         hir_visit::walk_pat(self, p);
     }
 
+    fn visit_lit(&mut self, hir_id: HirId, lit: &'tcx hir::Lit, negated: bool) {
+        lint_callback!(self, check_lit, hir_id, lit, negated);
+    }
+
     fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
         self.with_lint_attrs(field.hir_id, |cx| hir_visit::walk_expr_field(cx, field))
     }
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 8cc8f911d3a..77bd13aacf7 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -23,6 +23,7 @@ macro_rules! late_lint_methods {
             fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>);
             fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>);
             fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
+            fn check_lit(hir_id: rustc_hir::HirId, a: &'tcx rustc_hir::Lit, negated: bool);
             fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
             fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
             fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 0060f33888e..80007f34db3 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -5,7 +5,7 @@ use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, Wrapp
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::intravisit::VisitorExt;
-use rustc_hir::{AmbigArg, Expr, ExprKind, LangItem};
+use rustc_hir::{AmbigArg, Expr, ExprKind, HirId, LangItem};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
 use rustc_middle::ty::{
@@ -536,6 +536,16 @@ fn lint_fn_pointer<'tcx>(
 }
 
 impl<'tcx> LateLintPass<'tcx> for TypeLimits {
+    fn check_lit(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        hir_id: HirId,
+        lit: &'tcx hir::Lit,
+        negated: bool,
+    ) {
+        lint_literal(cx, self, hir_id, lit.span, lit, negated)
+    }
+
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
         match e.kind {
             hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
@@ -557,7 +567,6 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                     }
                 }
             }
-            hir::ExprKind::Lit(lit) => lint_literal(cx, self, e, lit),
             hir::ExprKind::Call(path, [l, r])
                 if let ExprKind::Path(ref qpath) = path.kind
                     && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs
index 4b5163522f8..71e6e229907 100644
--- a/compiler/rustc_lint/src/types/literal.rs
+++ b/compiler/rustc_lint/src/types/literal.rs
@@ -1,8 +1,10 @@
 use hir::{ExprKind, Node, is_range_literal};
 use rustc_abi::{Integer, Size};
+use rustc_hir::HirId;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::{bug, ty};
+use rustc_span::Span;
 use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
 
 use crate::LateContext;
@@ -21,21 +23,22 @@ fn lint_overflowing_range_endpoint<'tcx>(
     lit: &hir::Lit,
     lit_val: u128,
     max: u128,
-    expr: &'tcx hir::Expr<'tcx>,
+    hir_id: HirId,
+    lit_span: Span,
     ty: &str,
 ) -> bool {
     // Look past casts to support cases like `0..256 as u8`
-    let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(expr.hir_id)
+    let (hir_id, span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(hir_id)
         && let ExprKind::Cast(_, _) = par_expr.kind
     {
-        (par_expr, expr.span)
+        (par_expr.hir_id, par_expr.span)
     } else {
-        (expr, expr.span)
+        (hir_id, lit_span)
     };
 
     // We only want to handle exclusive (`..`) ranges,
     // which are represented as `ExprKind::Struct`.
-    let Node::ExprField(field) = cx.tcx.parent_hir_node(expr.hir_id) else { return false };
+    let Node::ExprField(field) = cx.tcx.parent_hir_node(hir_id) else { return false };
     let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { return false };
     if !is_range_literal(struct_expr) {
         return false;
@@ -45,7 +48,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
     // We can suggest using an inclusive range
     // (`..=`) instead only if it is the `end` that is
     // overflowing and only by 1.
-    if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) {
+    if !(end.expr.hir_id == hir_id && lit_val - 1 == max) {
         return false;
     };
 
@@ -57,7 +60,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
         _ => bug!(),
     };
 
-    let sub_sugg = if expr.span.lo() == lit_span.lo() {
+    let sub_sugg = if span.lo() == lit_span.lo() {
         let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false };
         UseInclusiveRange::WithoutParen {
             sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
@@ -67,7 +70,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
         }
     } else {
         UseInclusiveRange::WithParen {
-            eq_sugg: expr.span.shrink_to_lo(),
+            eq_sugg: span.shrink_to_lo(),
             lit_sugg: lit_span,
             literal: lit_val - 1,
             suffix,
@@ -125,7 +128,8 @@ fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option<String> {
 
 fn report_bin_hex_error(
     cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
+    hir_id: HirId,
+    span: Span,
     ty: attr::IntType,
     size: Size,
     repr_str: String,
@@ -144,11 +148,11 @@ fn report_bin_hex_error(
     };
     let sign =
         if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive };
-    let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map(
+    let sub = get_type_suggestion(cx.typeck_results().node_type(hir_id), val, negative).map(
         |suggestion_ty| {
             if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
                 let (sans_suffix, _) = repr_str.split_at(pos);
-                OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix }
+                OverflowingBinHexSub::Suggestion { span, suggestion_ty, sans_suffix }
             } else {
                 OverflowingBinHexSub::Help { suggestion_ty }
             }
@@ -156,7 +160,7 @@ fn report_bin_hex_error(
     );
     let sign_bit_sub = (!negative)
         .then(|| {
-            let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
+            let ty::Int(int_ty) = cx.typeck_results().node_type(hir_id).kind() else {
                 return None;
             };
 
@@ -177,7 +181,7 @@ fn report_bin_hex_error(
                 };
 
             Some(OverflowingBinHexSignBitSub {
-                span: expr.span,
+                span,
                 lit_no_suffix,
                 negative_val: actually.clone(),
                 int_ty: int_ty.name_str(),
@@ -186,7 +190,7 @@ fn report_bin_hex_error(
         })
         .flatten();
 
-    cx.emit_span_lint(OVERFLOWING_LITERALS, expr.span, OverflowingBinHex {
+    cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingBinHex {
         ty: t,
         lit: repr_str.clone(),
         dec: val,
@@ -236,15 +240,17 @@ fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {
 fn lint_int_literal<'tcx>(
     cx: &LateContext<'tcx>,
     type_limits: &TypeLimits,
-    e: &'tcx hir::Expr<'tcx>,
+    hir_id: HirId,
+    span: Span,
     lit: &hir::Lit,
     t: ty::IntTy,
     v: u128,
+    negated: bool,
 ) {
     let int_type = t.normalize(cx.sess().target.pointer_width);
     let (min, max) = int_ty_range(int_type);
     let max = max as u128;
-    let negative = type_limits.negated_expr_id == Some(e.hir_id);
+    let negative = negated ^ (type_limits.negated_expr_id == Some(hir_id));
 
     // Detect literal value out of range [min, max] inclusive
     // avoiding use of -min to prevent overflow/panic
@@ -252,7 +258,8 @@ fn lint_int_literal<'tcx>(
         if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
             report_bin_hex_error(
                 cx,
-                e,
+                hir_id,
+                span,
                 attr::IntType::SignedInt(ty::ast_int_ty(t)),
                 Integer::from_int_ty(cx, t).size(),
                 repr_str,
@@ -262,18 +269,18 @@ fn lint_int_literal<'tcx>(
             return;
         }
 
-        if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
+        if lint_overflowing_range_endpoint(cx, lit, v, max, hir_id, span, t.name_str()) {
             // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
             return;
         }
 
-        let span = if negative { type_limits.negated_expr_span.unwrap() } else { e.span };
+        let span = if negative { type_limits.negated_expr_span.unwrap() } else { span };
         let lit = cx
             .sess()
             .source_map()
             .span_to_snippet(span)
             .unwrap_or_else(|_| if negative { format!("-{v}") } else { v.to_string() });
-        let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
+        let help = get_type_suggestion(cx.typeck_results().node_type(hir_id), v, negative)
             .map(|suggestion_ty| OverflowingIntHelp { suggestion_ty });
 
         cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingInt {
@@ -288,7 +295,8 @@ fn lint_int_literal<'tcx>(
 
 fn lint_uint_literal<'tcx>(
     cx: &LateContext<'tcx>,
-    e: &'tcx hir::Expr<'tcx>,
+    hir_id: HirId,
+    span: Span,
     lit: &hir::Lit,
     t: ty::UintTy,
 ) {
@@ -302,7 +310,7 @@ fn lint_uint_literal<'tcx>(
     };
 
     if lit_val < min || lit_val > max {
-        if let Node::Expr(par_e) = cx.tcx.parent_hir_node(e.hir_id) {
+        if let Node::Expr(par_e) = cx.tcx.parent_hir_node(hir_id) {
             match par_e.kind {
                 hir::ExprKind::Cast(..) => {
                     if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
@@ -316,14 +324,15 @@ fn lint_uint_literal<'tcx>(
                 _ => {}
             }
         }
-        if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
+        if lint_overflowing_range_endpoint(cx, lit, lit_val, max, hir_id, span, t.name_str()) {
             // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
             return;
         }
         if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
             report_bin_hex_error(
                 cx,
-                e,
+                hir_id,
+                span,
                 attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
                 Integer::from_uint_ty(cx, t).size(),
                 repr_str,
@@ -332,7 +341,7 @@ fn lint_uint_literal<'tcx>(
             );
             return;
         }
-        cx.emit_span_lint(OVERFLOWING_LITERALS, e.span, OverflowingUInt {
+        cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingUInt {
             ty: t.name_str(),
             lit: cx
                 .sess()
@@ -348,19 +357,24 @@ fn lint_uint_literal<'tcx>(
 pub(crate) fn lint_literal<'tcx>(
     cx: &LateContext<'tcx>,
     type_limits: &TypeLimits,
-    e: &'tcx hir::Expr<'tcx>,
+    hir_id: HirId,
+    span: Span,
     lit: &hir::Lit,
+    negated: bool,
 ) {
-    match *cx.typeck_results().node_type(e.hir_id).kind() {
+    match *cx.typeck_results().node_type(hir_id).kind() {
         ty::Int(t) => {
             match lit.node {
                 ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
-                    lint_int_literal(cx, type_limits, e, lit, t, v.get())
+                    lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get(), negated)
                 }
                 _ => bug!(),
             };
         }
-        ty::Uint(t) => lint_uint_literal(cx, e, lit, t),
+        ty::Uint(t) => {
+            assert!(!negated);
+            lint_uint_literal(cx, hir_id, span, lit, t)
+        }
         ty::Float(t) => {
             let (is_infinite, sym) = match lit.node {
                 ast::LitKind::Float(v, _) => match t {
@@ -374,7 +388,7 @@ pub(crate) fn lint_literal<'tcx>(
                 _ => bug!(),
             };
             if is_infinite == Ok(true) {
-                cx.emit_span_lint(OVERFLOWING_LITERALS, e.span, OverflowingLiteral {
+                cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingLiteral {
                     ty: t.name_str(),
                     lit: cx
                         .sess()
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index 276a02b4e0f..c5ce6efcb81 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -98,6 +98,10 @@ declare_hooks! {
     hook save_dep_graph() -> ();
 
     hook query_key_hash_verify_all() -> ();
+
+    /// Ensure the given scalar is valid for the given type.
+    /// This checks non-recursive runtime validity.
+    hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool;
 }
 
 #[cold]
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index e2e2029a362..4dc8f279553 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -11,6 +11,7 @@
 use std::cmp::Ordering;
 use std::fmt;
 use std::ops::Index;
+use std::sync::Arc;
 
 use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
 use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
@@ -618,7 +619,7 @@ pub enum InlineAsmOperand<'tcx> {
 #[derive(Debug, HashStable, TypeVisitable)]
 pub struct FieldPat<'tcx> {
     pub field: FieldIdx,
-    pub pattern: Box<Pat<'tcx>>,
+    pub pattern: Pat<'tcx>,
 }
 
 #[derive(Debug, HashStable, TypeVisitable)]
@@ -679,7 +680,7 @@ impl<'tcx> Pat<'tcx> {
             Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
             Array { box ref prefix, ref slice, box ref suffix }
             | Slice { box ref prefix, ref slice, box ref suffix } => {
-                prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
+                prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it))
             }
         }
     }
@@ -836,28 +837,28 @@ pub enum PatKind<'tcx> {
         subpattern: Box<Pat<'tcx>>,
     },
 
-    Range(Box<PatRange<'tcx>>),
+    Range(Arc<PatRange<'tcx>>),
 
     /// Matches against a slice, checking the length and extracting elements.
     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
     /// e.g., `&[ref xs @ ..]`.
     Slice {
-        prefix: Box<[Box<Pat<'tcx>>]>,
+        prefix: Box<[Pat<'tcx>]>,
         slice: Option<Box<Pat<'tcx>>>,
-        suffix: Box<[Box<Pat<'tcx>>]>,
+        suffix: Box<[Pat<'tcx>]>,
     },
 
     /// Fixed match against an array; irrefutable.
     Array {
-        prefix: Box<[Box<Pat<'tcx>>]>,
+        prefix: Box<[Pat<'tcx>]>,
         slice: Option<Box<Pat<'tcx>>>,
-        suffix: Box<[Box<Pat<'tcx>>]>,
+        suffix: Box<[Pat<'tcx>]>,
     },
 
     /// An or-pattern, e.g. `p | q`.
     /// Invariant: `pats.len() >= 2`.
     Or {
-        pats: Box<[Box<Pat<'tcx>>]>,
+        pats: Box<[Pat<'tcx>]>,
     },
 
     /// A never pattern `!`.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 3431081b189..feae8ea312e 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1741,7 +1741,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     " as ",
                 )?;
             }
-            ty::Pat(base_ty, pat) => {
+            ty::Pat(base_ty, pat) if self.tcx().validate_scalar_in_layout(int, ty) => {
                 self.pretty_print_const_scalar_int(int, *base_ty, print_ty)?;
                 p!(write(" is {pat:?}"));
             }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 318bd0c7ec0..6fd0fb9a0a4 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -777,7 +777,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
-        inspect_coroutine_fields: InspectCoroutineFields,
     ) -> Result<Ty<'tcx>, Ty<'tcx>> {
         let mut visitor = OpaqueTypeExpander {
             seen_opaque_tys: FxHashSet::default(),
@@ -786,9 +785,7 @@ impl<'tcx> TyCtxt<'tcx> {
             found_recursion: false,
             found_any_recursion: false,
             check_recursion: true,
-            expand_coroutines: true,
             tcx: self,
-            inspect_coroutine_fields,
         };
 
         let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
@@ -965,19 +962,11 @@ struct OpaqueTypeExpander<'tcx> {
     primary_def_id: Option<DefId>,
     found_recursion: bool,
     found_any_recursion: bool,
-    expand_coroutines: bool,
     /// Whether or not to check for recursive opaque types.
     /// This is `true` when we're explicitly checking for opaque type
     /// recursion, and 'false' otherwise to avoid unnecessary work.
     check_recursion: bool,
     tcx: TyCtxt<'tcx>,
-    inspect_coroutine_fields: InspectCoroutineFields,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum InspectCoroutineFields {
-    No,
-    Yes,
 }
 
 impl<'tcx> OpaqueTypeExpander<'tcx> {
@@ -1009,41 +998,6 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
             None
         }
     }
-
-    fn expand_coroutine(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
-        if self.found_any_recursion {
-            return None;
-        }
-        let args = args.fold_with(self);
-        if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
-            let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
-                Some(expanded_ty) => *expanded_ty,
-                None => {
-                    if matches!(self.inspect_coroutine_fields, InspectCoroutineFields::Yes) {
-                        for bty in self.tcx.bound_coroutine_hidden_types(def_id) {
-                            let hidden_ty = self.tcx.instantiate_bound_regions_with_erased(
-                                bty.instantiate(self.tcx, args),
-                            );
-                            self.fold_ty(hidden_ty);
-                        }
-                    }
-                    let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
-                    self.expanded_cache.insert((def_id, args), expanded_ty);
-                    expanded_ty
-                }
-            };
-            if self.check_recursion {
-                self.seen_opaque_tys.remove(&def_id);
-            }
-            Some(expanded_ty)
-        } else {
-            // If another opaque type that we contain is recursive, then it
-            // will report the error, so we don't have to.
-            self.found_any_recursion = true;
-            self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
-            None
-        }
-    }
 }
 
 impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
@@ -1052,19 +1006,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
+        if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
             self.expand_opaque_ty(def_id, args).unwrap_or(t)
-        } else if t.has_opaque_types() || t.has_coroutines() {
+        } else if t.has_opaque_types() {
             t.super_fold_with(self)
         } else {
             t
-        };
-        if self.expand_coroutines {
-            if let ty::CoroutineWitness(def_id, args) = *t.kind() {
-                t = self.expand_coroutine(def_id, args).unwrap_or(t);
-            }
         }
-        t
     }
 
     fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
@@ -1753,9 +1701,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
         found_recursion: false,
         found_any_recursion: false,
         check_recursion: false,
-        expand_coroutines: false,
         tcx,
-        inspect_coroutine_fields: InspectCoroutineFields::No,
     };
     val.fold_with(&mut visitor)
 }
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 9d59ffc88ba..bca57817d66 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -1,3 +1,5 @@
+use std::sync::Arc;
+
 use rustc_middle::mir::*;
 use rustc_middle::thir::{self, *};
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -12,11 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// [`PatKind::Leaf`].
     ///
     /// Used internally by [`MatchPairTree::for_pattern`].
-    fn field_match_pairs<'pat>(
+    fn field_match_pairs(
         &mut self,
         place: PlaceBuilder<'tcx>,
-        subpatterns: &'pat [FieldPat<'tcx>],
-    ) -> Vec<MatchPairTree<'pat, 'tcx>> {
+        subpatterns: &[FieldPat<'tcx>],
+    ) -> Vec<MatchPairTree<'tcx>> {
         subpatterns
             .iter()
             .map(|fieldpat| {
@@ -31,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// array pattern or slice pattern, and adds those trees to `match_pairs`.
     ///
     /// Used internally by [`MatchPairTree::for_pattern`].
-    fn prefix_slice_suffix<'pat>(
+    fn prefix_slice_suffix(
         &mut self,
-        match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
+        match_pairs: &mut Vec<MatchPairTree<'tcx>>,
         place: &PlaceBuilder<'tcx>,
-        prefix: &'pat [Box<Pat<'tcx>>],
-        opt_slice: &'pat Option<Box<Pat<'tcx>>>,
-        suffix: &'pat [Box<Pat<'tcx>>],
+        prefix: &[Pat<'tcx>],
+        opt_slice: &Option<Box<Pat<'tcx>>>,
+        suffix: &[Pat<'tcx>],
     ) {
         let tcx = self.tcx;
         let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
@@ -83,14 +85,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 }
 
-impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
+impl<'tcx> MatchPairTree<'tcx> {
     /// Recursively builds a match pair tree for the given pattern and its
     /// subpatterns.
     pub(in crate::builder) fn for_pattern(
         mut place_builder: PlaceBuilder<'tcx>,
-        pattern: &'pat Pat<'tcx>,
+        pattern: &Pat<'tcx>,
         cx: &mut Builder<'_, 'tcx>,
-    ) -> MatchPairTree<'pat, 'tcx> {
+    ) -> MatchPairTree<'tcx> {
         // Force the place type to the pattern's type.
         // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
         if let Some(resolved) = place_builder.resolve_upvar(cx) {
@@ -125,7 +127,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
                 if range.is_full_range(cx.tcx) == Some(true) {
                     default_irrefutable()
                 } else {
-                    TestCase::Range(range)
+                    TestCase::Range(Arc::clone(range))
                 }
             }
 
@@ -255,6 +257,12 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
             PatKind::Never => TestCase::Never,
         };
 
-        MatchPairTree { place, test_case, subpairs, pattern }
+        MatchPairTree {
+            place,
+            test_case,
+            subpairs,
+            pattern_ty: pattern.ty,
+            pattern_span: pattern.span,
+        }
     }
 }
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index b21ec8f3083..a2f92a93ec5 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -33,6 +33,7 @@ mod util;
 use std::assert_matches::assert_matches;
 use std::borrow::Borrow;
 use std::mem;
+use std::sync::Arc;
 
 /// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
 /// to recursive invocations.
@@ -361,11 +362,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let scrutinee_place =
             unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
 
-        let arms = arms.iter().map(|arm| &self.thir[*arm]);
         let match_start_span = span.shrink_to_lo().to(scrutinee_span);
         let patterns = arms
-            .clone()
-            .map(|arm| {
+            .iter()
+            .map(|&arm| {
+                let arm = &self.thir[arm];
                 let has_match_guard =
                     if arm.guard.is_some() { HasMatchGuard::Yes } else { HasMatchGuard::No };
                 (&*arm.pattern, has_match_guard)
@@ -412,20 +413,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// (by [Builder::lower_match_tree]).
     ///
     /// `outer_source_info` is the SourceInfo for the whole match.
-    fn lower_match_arms<'pat>(
+    fn lower_match_arms(
         &mut self,
         destination: Place<'tcx>,
         scrutinee_place_builder: PlaceBuilder<'tcx>,
         scrutinee_span: Span,
-        arms: impl IntoIterator<Item = &'pat Arm<'tcx>>,
+        arms: &[ArmId],
         built_match_tree: BuiltMatchTree<'tcx>,
         outer_source_info: SourceInfo,
-    ) -> BlockAnd<()>
-    where
-        'tcx: 'pat,
-    {
+    ) -> BlockAnd<()> {
         let arm_end_blocks: Vec<BasicBlock> = arms
-            .into_iter()
+            .iter()
+            .map(|&arm| &self.thir[arm])
             .zip(built_match_tree.branches)
             .map(|(arm, branch)| {
                 debug!("lowering arm {:?}\ncorresponding branch = {:?}", arm, branch);
@@ -604,19 +603,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // Optimize the case of `let x: T = ...` to write directly
             // into `x` and then require that `T == typeof(x)`.
             PatKind::AscribeUserType {
-                subpattern:
-                    box Pat {
-                        kind:
-                            PatKind::Binding {
-                                mode: BindingMode(ByRef::No, _),
-                                var,
-                                subpattern: None,
-                                ..
-                            },
-                        ..
-                    },
+                ref subpattern,
                 ascription: thir::Ascription { ref annotation, variance: _ },
-            } => {
+            } if let PatKind::Binding {
+                mode: BindingMode(ByRef::No, _),
+                var,
+                subpattern: None,
+                ..
+            } = subpattern.kind =>
+            {
                 let place = self.storage_live_binding(
                     block,
                     var,
@@ -989,23 +984,19 @@ impl<'tcx> PatternExtraData<'tcx> {
 ///
 /// Will typically be incorporated into a [`Candidate`].
 #[derive(Debug, Clone)]
-struct FlatPat<'pat, 'tcx> {
+struct FlatPat<'tcx> {
     /// To match the pattern, all of these must be satisfied...
     // Invariant: all the match pairs are recursively simplified.
     // Invariant: or-patterns must be sorted to the end.
-    match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
+    match_pairs: Vec<MatchPairTree<'tcx>>,
 
     extra_data: PatternExtraData<'tcx>,
 }
 
-impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
+impl<'tcx> FlatPat<'tcx> {
     /// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest
     /// for the given pattern.
-    fn new(
-        place: PlaceBuilder<'tcx>,
-        pattern: &'pat Pat<'tcx>,
-        cx: &mut Builder<'_, 'tcx>,
-    ) -> Self {
+    fn new(place: PlaceBuilder<'tcx>, pattern: &Pat<'tcx>, cx: &mut Builder<'_, 'tcx>) -> Self {
         // First, recursively build a tree of match pairs for the given pattern.
         let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)];
         let mut extra_data = PatternExtraData {
@@ -1033,7 +1024,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
 /// of candidates, where each "leaf" candidate represents one of the ways for
 /// the arm pattern to successfully match.
 #[derive(Debug)]
-struct Candidate<'pat, 'tcx> {
+struct Candidate<'tcx> {
     /// For the candidate to match, all of these must be satisfied...
     ///
     /// ---
@@ -1055,7 +1046,7 @@ struct Candidate<'pat, 'tcx> {
     /// Invariants:
     /// - All [`TestCase::Irrefutable`] patterns have been removed by simplification.
     /// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
-    match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
+    match_pairs: Vec<MatchPairTree<'tcx>>,
 
     /// ...and if this is non-empty, one of these subcandidates also has to match...
     ///
@@ -1072,7 +1063,7 @@ struct Candidate<'pat, 'tcx> {
     /// Invariant: at the end of match tree lowering, this must not contain an
     /// `is_never` candidate, because that would break binding consistency.
     /// - See [`Builder::remove_never_subcandidates`].
-    subcandidates: Vec<Candidate<'pat, 'tcx>>,
+    subcandidates: Vec<Candidate<'tcx>>,
 
     /// ...and if there is a guard it must be evaluated; if it's `false` then branch to `otherwise_block`.
     ///
@@ -1107,10 +1098,10 @@ struct Candidate<'pat, 'tcx> {
     false_edge_start_block: Option<BasicBlock>,
 }
 
-impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
+impl<'tcx> Candidate<'tcx> {
     fn new(
         place: PlaceBuilder<'tcx>,
-        pattern: &'pat Pat<'tcx>,
+        pattern: &Pat<'tcx>,
         has_guard: HasMatchGuard,
         cx: &mut Builder<'_, 'tcx>,
     ) -> Self {
@@ -1123,7 +1114,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
     }
 
     /// Incorporates an already-simplified [`FlatPat`] into a new candidate.
-    fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
+    fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
         Candidate {
             match_pairs: flat_pat.match_pairs,
             extra_data: flat_pat.extra_data,
@@ -1172,7 +1163,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
 /// reference or by value, and to allow a mutable "context" to be shared by the
 /// traversal callbacks. Most traversals can use the simpler
 /// [`Candidate::visit_leaves`] wrapper instead.
-fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
+fn traverse_candidate<'tcx, C, T, I>(
     candidate: C,
     context: &mut T,
     // Called when visiting a "leaf" candidate (with no subcandidates).
@@ -1184,7 +1175,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
     // Called after visiting a "node" candidate's children.
     complete_children: impl Copy + Fn(&mut T),
 ) where
-    C: Borrow<Candidate<'pat, 'tcx>>, // Typically `Candidate` or `&mut Candidate`
+    C: Borrow<Candidate<'tcx>>, // Typically `Candidate` or `&mut Candidate`
     I: Iterator<Item = C>,
 {
     if candidate.borrow().subcandidates.is_empty() {
@@ -1234,20 +1225,20 @@ struct Ascription<'tcx> {
 ///   participate in or-pattern expansion, where they are transformed into subcandidates.
 ///   - See [`Builder::expand_and_match_or_candidates`].
 #[derive(Debug, Clone)]
-enum TestCase<'pat, 'tcx> {
+enum TestCase<'tcx> {
     Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
     Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
     Constant { value: mir::Const<'tcx> },
-    Range(&'pat PatRange<'tcx>),
+    Range(Arc<PatRange<'tcx>>),
     Slice { len: usize, variable_length: bool },
     Deref { temp: Place<'tcx>, mutability: Mutability },
     Never,
-    Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
+    Or { pats: Box<[FlatPat<'tcx>]> },
 }
 
-impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
-    fn as_range(&self) -> Option<&'pat PatRange<'tcx>> {
-        if let Self::Range(v) = self { Some(*v) } else { None }
+impl<'tcx> TestCase<'tcx> {
+    fn as_range(&self) -> Option<&PatRange<'tcx>> {
+        if let Self::Range(v) = self { Some(v.as_ref()) } else { None }
     }
 }
 
@@ -1257,7 +1248,7 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
 /// Each node also has a list of subpairs (possibly empty) that must also match,
 /// and a reference to the THIR pattern it represents.
 #[derive(Debug, Clone)]
-pub(crate) struct MatchPairTree<'pat, 'tcx> {
+pub(crate) struct MatchPairTree<'tcx> {
     /// This place...
     ///
     /// ---
@@ -1272,7 +1263,7 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> {
     /// ---
     /// Invariant: after creation and simplification in [`FlatPat::new`],
     /// this must not be [`TestCase::Irrefutable`].
-    test_case: TestCase<'pat, 'tcx>,
+    test_case: TestCase<'tcx>,
 
     /// ... and these subpairs must match.
     ///
@@ -1283,8 +1274,10 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> {
     /// that tests its field for the value `3`.
     subpairs: Vec<Self>,
 
-    /// The pattern this was created from.
-    pattern: &'pat Pat<'tcx>,
+    /// Type field of the pattern this node was created from.
+    pattern_ty: Ty<'tcx>,
+    /// Span field of the pattern this node was created from.
+    pattern_span: Span,
 }
 
 /// See [`Test`] for more.
@@ -1320,7 +1313,7 @@ enum TestKind<'tcx> {
     },
 
     /// Test whether the value falls within an inclusive or exclusive range.
-    Range(Box<PatRange<'tcx>>),
+    Range(Arc<PatRange<'tcx>>),
 
     /// Test that the length of the slice is `== len` or `>= len`.
     Len { len: u64, op: BinOp },
@@ -1423,7 +1416,7 @@ struct BuiltMatchTree<'tcx> {
 
 impl<'tcx> MatchTreeSubBranch<'tcx> {
     fn from_sub_candidate(
-        candidate: Candidate<'_, 'tcx>,
+        candidate: Candidate<'tcx>,
         parent_data: &Vec<PatternExtraData<'tcx>>,
     ) -> Self {
         debug_assert!(candidate.match_pairs.is_empty());
@@ -1449,12 +1442,12 @@ impl<'tcx> MatchTreeSubBranch<'tcx> {
 }
 
 impl<'tcx> MatchTreeBranch<'tcx> {
-    fn from_candidate(candidate: Candidate<'_, 'tcx>) -> Self {
+    fn from_candidate(candidate: Candidate<'tcx>) -> Self {
         let mut sub_branches = Vec::new();
         traverse_candidate(
             candidate,
             &mut Vec::new(),
-            &mut |candidate: Candidate<'_, '_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
+            &mut |candidate: Candidate<'_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
                 sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data));
             },
             |inner_candidate, parent_data| {
@@ -1485,23 +1478,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
     /// or not (for `let` and `match`). In the refutable case we return the block to which we branch
     /// on failure.
-    fn lower_match_tree<'pat>(
+    fn lower_match_tree(
         &mut self,
         block: BasicBlock,
         scrutinee_span: Span,
         scrutinee_place_builder: &PlaceBuilder<'tcx>,
         match_start_span: Span,
-        patterns: Vec<(&'pat Pat<'tcx>, HasMatchGuard)>,
+        patterns: Vec<(&Pat<'tcx>, HasMatchGuard)>,
         refutable: bool,
-    ) -> BuiltMatchTree<'tcx>
-    where
-        'tcx: 'pat,
-    {
+    ) -> BuiltMatchTree<'tcx> {
         // Assemble the initial list of candidates. These top-level candidates are 1:1 with the
         // input patterns, but other parts of match lowering also introduce subcandidates (for
         // sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
         // match arms directly.
-        let mut candidates: Vec<Candidate<'_, '_>> = patterns
+        let mut candidates: Vec<Candidate<'_>> = patterns
             .into_iter()
             .map(|(pat, has_guard)| {
                 Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self)
@@ -1664,7 +1654,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         span: Span,
         scrutinee_span: Span,
         start_block: BasicBlock,
-        candidates: &mut [&mut Candidate<'_, 'tcx>],
+        candidates: &mut [&mut Candidate<'tcx>],
     ) -> BasicBlock {
         ensure_sufficient_stack(|| {
             self.match_candidates_inner(span, scrutinee_span, start_block, candidates)
@@ -1678,7 +1668,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         span: Span,
         scrutinee_span: Span,
         mut start_block: BasicBlock,
-        candidates: &mut [&mut Candidate<'_, 'tcx>],
+        candidates: &mut [&mut Candidate<'tcx>],
     ) -> BasicBlock {
         if let [first, ..] = candidates {
             if first.false_edge_start_block.is_none() {
@@ -1747,7 +1737,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// [otherwise block]: Candidate::otherwise_block
     fn select_matched_candidate(
         &mut self,
-        candidate: &mut Candidate<'_, 'tcx>,
+        candidate: &mut Candidate<'tcx>,
         start_block: BasicBlock,
     ) -> BasicBlock {
         assert!(candidate.otherwise_block.is_none());
@@ -1765,13 +1755,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Takes a list of candidates such that some of the candidates' first match pairs are
     /// or-patterns. This expands as many or-patterns as possible and processes the resulting
     /// candidates. Returns the unprocessed candidates if any.
-    fn expand_and_match_or_candidates<'pat, 'b, 'c>(
+    fn expand_and_match_or_candidates<'b, 'c>(
         &mut self,
         span: Span,
         scrutinee_span: Span,
         start_block: BasicBlock,
-        candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
-    ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
+        candidates: &'b mut [&'c mut Candidate<'tcx>],
+    ) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> {
         // We can't expand or-patterns freely. The rule is:
         // - If a candidate doesn't start with an or-pattern, we include it in
         //   the expansion list as-is (i.e. it "expands" to itself).
@@ -1865,14 +1855,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
     /// subcandidate. Any candidate that has been expanded this way should also be postprocessed
     /// at the end of [`Self::expand_and_match_or_candidates`].
-    fn create_or_subcandidates<'pat>(
+    fn create_or_subcandidates(
         &mut self,
-        candidate: &mut Candidate<'pat, 'tcx>,
-        match_pair: MatchPairTree<'pat, 'tcx>,
+        candidate: &mut Candidate<'tcx>,
+        match_pair: MatchPairTree<'tcx>,
     ) {
         let TestCase::Or { pats } = match_pair.test_case else { bug!() };
         debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
-        candidate.or_span = Some(match_pair.pattern.span);
+        candidate.or_span = Some(match_pair.pattern_span);
         candidate.subcandidates = pats
             .into_vec()
             .into_iter()
@@ -1938,7 +1928,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// Note that this takes place _after_ the subcandidates have participated
     /// in match tree lowering.
-    fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
+    fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
         assert!(!candidate.subcandidates.is_empty());
         if candidate.has_guard {
             // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
@@ -1981,7 +1971,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Never subcandidates may have a set of bindings inconsistent with their siblings,
     /// which would break later code. So we filter them out. Note that we can't filter out
     /// top-level candidates this way.
-    fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
+    fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
         if candidate.subcandidates.is_empty() {
             return;
         }
@@ -2020,7 +2010,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         span: Span,
         scrutinee_span: Span,
-        candidate: &mut Candidate<'_, 'tcx>,
+        candidate: &mut Candidate<'tcx>,
     ) {
         if candidate.match_pairs.is_empty() {
             return;
@@ -2086,7 +2076,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// [`Switch`]: TestKind::Switch
     /// [`SwitchInt`]: TestKind::SwitchInt
     /// [`Range`]: TestKind::Range
-    fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
+    fn pick_test(&mut self, candidates: &[&mut Candidate<'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
         // Extract the match-pair from the highest priority candidate
         let match_pair = &candidates[0].match_pairs[0];
         let test = self.pick_test_for_match_pair(match_pair);
@@ -2137,18 +2127,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The sorted candidates are mutated to remove entailed match pairs:
     /// - candidate 0 becomes `[z @ true]` since we know that `x` was `true`;
     /// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
-    fn sort_candidates<'b, 'c, 'pat>(
+    fn sort_candidates<'b, 'c>(
         &mut self,
         match_place: Place<'tcx>,
         test: &Test<'tcx>,
-        mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
+        mut candidates: &'b mut [&'c mut Candidate<'tcx>],
     ) -> (
-        &'b mut [&'c mut Candidate<'pat, 'tcx>],
-        FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'pat, 'tcx>>>,
+        &'b mut [&'c mut Candidate<'tcx>],
+        FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'tcx>>>,
     ) {
         // For each of the possible outcomes, collect vector of candidates that apply if the test
         // has that particular outcome.
-        let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default();
+        let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_>>> = Default::default();
 
         let total_candidate_count = candidates.len();
 
@@ -2274,13 +2264,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// ```
     ///
     /// We return the unprocessed candidates.
-    fn test_candidates<'pat, 'b, 'c>(
+    fn test_candidates<'b, 'c>(
         &mut self,
         span: Span,
         scrutinee_span: Span,
-        candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
+        candidates: &'b mut [&'c mut Candidate<'tcx>],
         start_block: BasicBlock,
-    ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
+    ) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> {
         // Choose a match pair from the first candidate, and use it to determine a
         // test to perform that will confirm or refute that match pair.
         let (match_place, test) = self.pick_test(candidates);
diff --git a/compiler/rustc_mir_build/src/builder/matches/simplify.rs b/compiler/rustc_mir_build/src/builder/matches/simplify.rs
index ebaed1e431b..15c860151dc 100644
--- a/compiler/rustc_mir_build/src/builder/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/simplify.rs
@@ -23,9 +23,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
     /// ascriptions in `extra_data`.
     #[instrument(skip(self), level = "debug")]
-    pub(super) fn simplify_match_pairs<'pat>(
+    pub(super) fn simplify_match_pairs(
         &mut self,
-        match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
+        match_pairs: &mut Vec<MatchPairTree<'tcx>>,
         extra_data: &mut PatternExtraData<'tcx>,
     ) {
         // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs
index afe6b4475be..834f8be0d00 100644
--- a/compiler/rustc_mir_build/src/builder/matches/test.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/test.rs
@@ -6,6 +6,7 @@
 // the candidates based on the result.
 
 use std::cmp::Ordering;
+use std::sync::Arc;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir::{LangItem, RangeEnd};
@@ -26,20 +27,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
     /// It is a bug to call this with a not-fully-simplified pattern.
-    pub(super) fn pick_test_for_match_pair<'pat>(
+    pub(super) fn pick_test_for_match_pair(
         &mut self,
-        match_pair: &MatchPairTree<'pat, 'tcx>,
+        match_pair: &MatchPairTree<'tcx>,
     ) -> Test<'tcx> {
         let kind = match match_pair.test_case {
             TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
 
-            TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If,
-            TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt,
-            TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
+            TestCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
+            TestCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => TestKind::SwitchInt,
+            TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern_ty },
 
-            TestCase::Range(range) => {
-                assert_eq!(range.ty, match_pair.pattern.ty);
-                TestKind::Range(Box::new(range.clone()))
+            TestCase::Range(ref range) => {
+                assert_eq!(range.ty, match_pair.pattern_ty);
+                TestKind::Range(Arc::clone(range))
             }
 
             TestCase::Slice { len, variable_length } => {
@@ -56,13 +57,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
 
             TestCase::Irrefutable { .. } => span_bug!(
-                match_pair.pattern.span,
+                match_pair.pattern_span,
                 "simplifiable pattern found: {:?}",
-                match_pair.pattern
+                match_pair.pattern_span
             ),
         };
 
-        Test { span: match_pair.pattern.span, kind }
+        Test { span: match_pair.pattern_span, kind }
     }
 
     #[instrument(skip(self, target_blocks, place), level = "debug")]
@@ -521,8 +522,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         test_place: Place<'tcx>,
         test: &Test<'tcx>,
-        candidate: &mut Candidate<'_, 'tcx>,
-        sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
+        candidate: &mut Candidate<'tcx>,
+        sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'tcx>>>,
     ) -> Option<TestBranch<'tcx>> {
         // Find the match_pair for this place (if any). At present,
         // afaik, there can be at most one. (In the future, if we
@@ -558,14 +559,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // FIXME(#29623) we could use PatKind::Range to rule
             // things out here, in some cases.
             (TestKind::SwitchInt, &TestCase::Constant { value })
-                if is_switch_ty(match_pair.pattern.ty) =>
+                if is_switch_ty(match_pair.pattern_ty) =>
             {
                 // An important invariant of candidate sorting is that a candidate
                 // must not match in multiple branches. For `SwitchInt` tests, adding
                 // a new value might invalidate that property for range patterns that
                 // have already been sorted into the failure arm, so we must take care
                 // not to add such values here.
-                let is_covering_range = |test_case: &TestCase<'_, 'tcx>| {
+                let is_covering_range = |test_case: &TestCase<'tcx>| {
                     test_case.as_range().is_some_and(|range| {
                         matches!(
                             range.contains(value, self.tcx, self.typing_env()),
@@ -573,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         )
                     })
                 };
-                let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| {
+                let is_conflicting_candidate = |candidate: &&mut Candidate<'tcx>| {
                     candidate
                         .match_pairs
                         .iter()
@@ -685,8 +686,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
 
-            (TestKind::Range(test), &TestCase::Range(pat)) => {
-                if test.as_ref() == pat {
+            (TestKind::Range(test), TestCase::Range(pat)) => {
+                if test == pat {
                     fully_matched = true;
                     Some(TestBranch::Success)
                 } else {
diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs
index 1bd399e511b..83e79572b2a 100644
--- a/compiler/rustc_mir_build/src/builder/matches/util.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/util.rs
@@ -67,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 ///    a MIR pass run after borrow checking.
 pub(super) fn collect_fake_borrows<'tcx>(
     cx: &mut Builder<'_, 'tcx>,
-    candidates: &[Candidate<'_, 'tcx>],
+    candidates: &[Candidate<'tcx>],
     temp_span: Span,
     scrutinee_base: PlaceBase,
 ) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
@@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
         }
     }
 
-    fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
+    fn visit_candidate(&mut self, candidate: &Candidate<'tcx>) {
         for binding in &candidate.extra_data.bindings {
             self.visit_binding(binding);
         }
@@ -144,7 +144,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
         }
     }
 
-    fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
+    fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'tcx>) {
         for binding in &flat_pat.extra_data.bindings {
             self.visit_binding(binding);
         }
@@ -153,7 +153,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
         }
     }
 
-    fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
+    fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'tcx>) {
         if let TestCase::Or { pats, .. } = &match_pair.test_case {
             for flat_pat in pats.iter() {
                 self.visit_flat_pat(flat_pat)
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 8247a6c6a32..697cb7cf37a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -676,12 +676,14 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
         let mut interpreted_as_const = None;
         let mut interpreted_as_const_sugg = None;
 
-        if let PatKind::ExpandedConstant { def_id, is_inline: false, .. }
-        | PatKind::AscribeUserType {
-            subpattern:
-                box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. },
-            ..
-        } = pat.kind
+        // These next few matches want to peek through `AscribeUserType` to see
+        // the underlying pattern.
+        let mut unpeeled_pat = pat;
+        while let PatKind::AscribeUserType { ref subpattern, .. } = unpeeled_pat.kind {
+            unpeeled_pat = subpattern;
+        }
+
+        if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind
             && let DefKind::Const = self.tcx.def_kind(def_id)
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
             // We filter out paths with multiple path::segments.
@@ -692,11 +694,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
             // When we encounter a constant as the binding name, point at the `const` definition.
             interpreted_as_const = Some(span);
             interpreted_as_const_sugg = Some(InterpretedAsConst { span: pat.span, variable });
-        } else if let PatKind::Constant { .. }
-        | PatKind::AscribeUserType {
-            subpattern: box Pat { kind: PatKind::Constant { .. }, .. },
-            ..
-        } = pat.kind
+        } else if let PatKind::Constant { .. } = unpeeled_pat.kind
             && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
         {
             // If the pattern to match is an integer literal:
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index cc6d69710e4..551ec5cf4e9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -208,7 +208,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 let field = FieldIdx::new(idx);
                 // Patterns can only use monomorphic types.
                 let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
-                FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
+                FieldPat { field, pattern: *self.valtree_to_pat(val, ty) }
             })
             .collect()
     }
@@ -277,7 +277,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 prefix: cv
                     .unwrap_branch()
                     .iter()
-                    .map(|val| self.valtree_to_pat(*val, *elem_ty))
+                    .map(|val| *self.valtree_to_pat(*val, *elem_ty))
                     .collect(),
                 slice: None,
                 suffix: Box::new([]),
@@ -286,7 +286,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 prefix: cv
                     .unwrap_branch()
                     .iter()
-                    .map(|val| self.valtree_to_pat(*val, *elem_ty))
+                    .map(|val| *self.valtree_to_pat(*val, *elem_ty))
                     .collect(),
                 slice: None,
                 suffix: Box::new([]),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 8ecdbecf165..c862d012f4e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -4,6 +4,7 @@ mod check_match;
 mod const_to_pat;
 
 use std::cmp::Ordering;
+use std::sync::Arc;
 
 use rustc_abi::{FieldIdx, Integer};
 use rustc_errors::MultiSpan;
@@ -262,7 +263,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
 
         let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
-        let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
+        let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
         match (end, cmp) {
             // `x..y` where `x < y`.
             (RangeEnd::Excluded, Some(Ordering::Less)) => {}
@@ -418,7 +419,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     .iter()
                     .map(|field| FieldPat {
                         field: self.typeck_results.field_index(field.hir_id),
-                        pattern: self.lower_pattern(field.pat),
+                        pattern: *self.lower_pattern(field.pat),
                     })
                     .collect();
 
@@ -446,13 +447,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             .enumerate_and_adjust(expected_len, gap_pos)
             .map(|(i, subpattern)| FieldPat {
                 field: FieldIdx::new(i),
-                pattern: self.lower_pattern(subpattern),
+                pattern: *self.lower_pattern(subpattern),
             })
             .collect()
     }
 
-    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box<Pat<'tcx>>]> {
-        pats.iter().map(|p| self.lower_pattern(p)).collect()
+    fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
+        pats.iter().map(|p| *self.lower_pattern(p)).collect()
     }
 
     fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 729c8f784ba..9ab87dd99ff 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -643,8 +643,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
         print_indented!(self, "}", depth_lvl);
     }
 
-    fn print_pat(&mut self, pat: &Box<Pat<'tcx>>, depth_lvl: usize) {
-        let Pat { ty, span, kind } = &**pat;
+    fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
+        let &Pat { ty, span, ref kind } = pat;
 
         print_indented!(self, "Pat: {", depth_lvl);
         print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 39e365806cb..a0d41110d96 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -453,13 +453,11 @@ where
 {
     // In case any fresh inference variables have been created between `state`
     // and the previous instantiation, extend `orig_values` for it.
-    assert!(orig_values.len() <= state.value.var_values.len());
-    for &arg in &state.value.var_values.var_values.as_slice()
-        [orig_values.len()..state.value.var_values.len()]
-    {
-        let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span);
-        orig_values.push(unconstrained);
-    }
+    orig_values.extend(
+        state.value.var_values.var_values.as_slice()[orig_values.len()..]
+            .iter()
+            .map(|&arg| delegate.fresh_var_for_kind_with_span(arg, span)),
+    );
 
     let instantiation =
         EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state, span);
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 76b7dc0e48a..8b8c81a77a0 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -26,7 +26,7 @@ use crate::parser::{ForceCollect, Parser};
 use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
 
 fn psess() -> ParseSess {
-    ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE])
+    ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE])
 }
 
 /// Map string to parser (via tts).
@@ -41,10 +41,8 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
 fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
     let output = Arc::new(Mutex::new(Vec::new()));
     let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
-    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-        vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE],
-        false,
-    );
+    let fallback_bundle =
+        rustc_errors::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
     let mut emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
         .sm(Some(source_map.clone()))
         .diagnostic_width(Some(140));
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 837da6e7724..4c683c82b6c 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1851,6 +1851,34 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let mut is_simd = false;
         let mut is_transparent = false;
 
+        // catch `repr()` with no arguments, applied to an item (i.e. not `#![repr()]`)
+        if hints.is_empty() && item.is_some() {
+            for attr in attrs.iter().filter(|attr| attr.has_name(sym::repr)) {
+                match target {
+                    Target::Struct | Target::Union | Target::Enum => {}
+                    Target::Fn | Target::Method(_) => {
+                        feature_err(
+                            &self.tcx.sess,
+                            sym::fn_align,
+                            attr.span,
+                            fluent::passes_repr_align_function,
+                        )
+                        .emit();
+                    }
+                    _ => {
+                        self.dcx().emit_err(
+                            errors::AttrApplication::StructEnumFunctionMethodUnion {
+                                hint_span: attr.span,
+                                span,
+                            },
+                        );
+                    }
+                }
+            }
+
+            return;
+        }
+
         for hint in &hints {
             if !hint.is_meta_item() {
                 self.dcx().emit_err(errors::ReprIdent { span: hint.span() });
@@ -1883,24 +1911,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     }
                 }
                 sym::align => {
-                    if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
-                        (target, self.tcx.features().fn_align())
-                    {
-                        feature_err(
-                            &self.tcx.sess,
-                            sym::fn_align,
-                            hint.span(),
-                            fluent::passes_repr_align_function,
-                        )
-                        .emit();
-                    }
-
                     match target {
-                        Target::Struct
-                        | Target::Union
-                        | Target::Enum
-                        | Target::Fn
-                        | Target::Method(_) => {}
+                        Target::Struct | Target::Union | Target::Enum => {}
+                        Target::Fn | Target::Method(_) => {
+                            if !self.tcx.features().fn_align() {
+                                feature_err(
+                                    &self.tcx.sess,
+                                    sym::fn_align,
+                                    hint.span(),
+                                    fluent::passes_repr_align_function,
+                                )
+                                .emit();
+                            }
+                        }
                         _ => {
                             self.dcx().emit_err(
                                 errors::AttrApplication::StructEnumFunctionMethodUnion {
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 52920e0372e..4762281c329 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -427,7 +427,7 @@ impl CheckCfg {
                     Some(values_target_os),
                     Some(values_target_pointer_width),
                     Some(values_target_vendor),
-                ] = self.expecteds.get_many_mut(VALUES)
+                ] = self.expecteds.get_disjoint_mut(VALUES)
                 else {
                     panic!("unable to get all the check-cfg values buckets");
                 };
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 924350b8cbc..112adde3740 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -2,7 +2,6 @@
 #![allow(internal_features)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
-#![feature(map_many_mut)]
 #![feature(rustc_attrs)]
 // To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums
 // with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers").
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 1a3e80d6659..0851e859a0f 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -965,7 +965,6 @@ fn default_emitter(
 #[allow(rustc::bad_opt_access)]
 #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub fn build_session(
-    early_dcx: EarlyDiagCtxt,
     sopts: config::Options,
     io: CompilerIO,
     bundle: Option<Arc<rustc_errors::FluentBundle>>,
@@ -990,14 +989,6 @@ pub fn build_session(
     let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
     let can_emit_warnings = !(warnings_allow || cap_lints_allow);
 
-    let host_triple = TargetTuple::from_tuple(config::host_tuple());
-    let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
-        early_dcx.early_fatal(format!("Error loading host specification: {e}"))
-    });
-    for warning in target_warnings.warning_messages() {
-        early_dcx.early_warn(warning)
-    }
-
     let fallback_bundle = fallback_fluent_bundle(
         fluent_resources,
         sopts.unstable_opts.translate_directionality_markers,
@@ -1012,9 +1003,12 @@ pub fn build_session(
         dcx = dcx.with_ice_file(ice_file);
     }
 
-    // Now that the proper handler has been constructed, drop early_dcx to
-    // prevent accidental use.
-    drop(early_dcx);
+    let host_triple = TargetTuple::from_tuple(config::host_tuple());
+    let (host, target_warnings) = Target::search(&host_triple, &sysroot)
+        .unwrap_or_else(|e| dcx.handle().fatal(format!("Error loading host specification: {e}")));
+    for warning in target_warnings.warning_messages() {
+        dcx.handle().warn(warning)
+    }
 
     let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.unstable_opts.self_profile
     {
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 000e6a765d3..0024316b877 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -318,9 +318,17 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
         bug!();
     };
     let source_principal = tcx.instantiate_bound_regions_with_erased(
-        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self),
+        source.principal().unwrap().with_self_ty(tcx, key.self_ty()),
     );
 
+    // We're monomorphizing a call to a dyn trait object that can never be constructed.
+    if tcx.instantiate_and_check_impossible_predicates((
+        source_principal.def_id,
+        source_principal.args,
+    )) {
+        return 0;
+    }
+
     let target_principal = ty::ExistentialTraitRef::erase_self_ty(tcx, key);
 
     let vtable_segment_callback = {
@@ -373,19 +381,27 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     let (source, target) = key;
 
     // If the target principal is `None`, we can just return `None`.
-    let ty::Dynamic(target, _, _) = *target.kind() else {
+    let ty::Dynamic(target_data, _, _) = *target.kind() else {
         bug!();
     };
-    let target_principal = tcx.instantiate_bound_regions_with_erased(target.principal()?);
+    let target_principal = tcx.instantiate_bound_regions_with_erased(target_data.principal()?);
 
     // Given that we have a target principal, it is a bug for there not to be a source principal.
-    let ty::Dynamic(source, _, _) = *source.kind() else {
+    let ty::Dynamic(source_data, _, _) = *source.kind() else {
         bug!();
     };
     let source_principal = tcx.instantiate_bound_regions_with_erased(
-        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self),
+        source_data.principal().unwrap().with_self_ty(tcx, source),
     );
 
+    // We're monomorphizing a dyn trait object upcast that can never be constructed.
+    if tcx.instantiate_and_check_impossible_predicates((
+        source_principal.def_id,
+        source_principal.args,
+    )) {
+        return None;
+    }
+
     let vtable_segment_callback = {
         let mut vptr_offset = 0;
         move |segment| {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 4038a1d68fa..cbe49d000b7 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -373,7 +373,8 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
 
         match pat.kind {
             thir::PatKind::Constant { value } => value.has_non_region_param(),
-            thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
+            thir::PatKind::Range(ref range) => {
+                let &thir::PatRange { lo, hi, .. } = range.as_ref();
                 lo.has_non_region_param() || hi.has_non_region_param()
             }
             _ => false,
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index d2342d8fd51..5013826cb9b 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -969,7 +969,6 @@ where
     /// # Examples
     ///
     /// ```
-    /// #![feature(map_many_mut)]
     /// use std::collections::HashMap;
     ///
     /// let mut libraries = HashMap::new();
@@ -979,13 +978,13 @@ where
     /// libraries.insert("Library of Congress".to_string(), 1800);
     ///
     /// // Get Athenæum and Bodleian Library
-    /// let [Some(a), Some(b)] = libraries.get_many_mut([
+    /// let [Some(a), Some(b)] = libraries.get_disjoint_mut([
     ///     "Athenæum",
     ///     "Bodleian Library",
     /// ]) else { panic!() };
     ///
     /// // Assert values of Athenæum and Library of Congress
-    /// let got = libraries.get_many_mut([
+    /// let got = libraries.get_disjoint_mut([
     ///     "Athenæum",
     ///     "Library of Congress",
     /// ]);
@@ -998,7 +997,7 @@ where
     /// );
     ///
     /// // Missing keys result in None
-    /// let got = libraries.get_many_mut([
+    /// let got = libraries.get_disjoint_mut([
     ///     "Athenæum",
     ///     "New York Public Library",
     /// ]);
@@ -1012,21 +1011,24 @@ where
     /// ```
     ///
     /// ```should_panic
-    /// #![feature(map_many_mut)]
     /// use std::collections::HashMap;
     ///
     /// let mut libraries = HashMap::new();
     /// libraries.insert("Athenæum".to_string(), 1807);
     ///
     /// // Duplicate keys panic!
-    /// let got = libraries.get_many_mut([
+    /// let got = libraries.get_disjoint_mut([
     ///     "Athenæum",
     ///     "Athenæum",
     /// ]);
     /// ```
     #[inline]
-    #[unstable(feature = "map_many_mut", issue = "97601")]
-    pub fn get_many_mut<Q: ?Sized, const N: usize>(&mut self, ks: [&Q; N]) -> [Option<&'_ mut V>; N]
+    #[doc(alias = "get_many_mut")]
+    #[stable(feature = "map_many_mut", since = "CURRENT_RUSTC_VERSION")]
+    pub fn get_disjoint_mut<Q: ?Sized, const N: usize>(
+        &mut self,
+        ks: [&Q; N],
+    ) -> [Option<&'_ mut V>; N]
     where
         K: Borrow<Q>,
         Q: Hash + Eq,
@@ -1040,7 +1042,7 @@ where
     /// Returns an array of length `N` with the results of each query. `None` will be used if
     /// the key is missing.
     ///
-    /// For a safe alternative see [`get_many_mut`](`HashMap::get_many_mut`).
+    /// For a safe alternative see [`get_disjoint_mut`](`HashMap::get_disjoint_mut`).
     ///
     /// # Safety
     ///
@@ -1052,7 +1054,6 @@ where
     /// # Examples
     ///
     /// ```
-    /// #![feature(map_many_mut)]
     /// use std::collections::HashMap;
     ///
     /// let mut libraries = HashMap::new();
@@ -1062,13 +1063,13 @@ where
     /// libraries.insert("Library of Congress".to_string(), 1800);
     ///
     /// // SAFETY: The keys do not overlap.
-    /// let [Some(a), Some(b)] = (unsafe { libraries.get_many_unchecked_mut([
+    /// let [Some(a), Some(b)] = (unsafe { libraries.get_disjoint_unchecked_mut([
     ///     "Athenæum",
     ///     "Bodleian Library",
     /// ]) }) else { panic!() };
     ///
     /// // SAFETY: The keys do not overlap.
-    /// let got = unsafe { libraries.get_many_unchecked_mut([
+    /// let got = unsafe { libraries.get_disjoint_unchecked_mut([
     ///     "Athenæum",
     ///     "Library of Congress",
     /// ]) };
@@ -1081,7 +1082,7 @@ where
     /// );
     ///
     /// // SAFETY: The keys do not overlap.
-    /// let got = unsafe { libraries.get_many_unchecked_mut([
+    /// let got = unsafe { libraries.get_disjoint_unchecked_mut([
     ///     "Athenæum",
     ///     "New York Public Library",
     /// ]) };
@@ -1089,8 +1090,9 @@ where
     /// assert_eq!(got, [Some(&mut 1807), None]);
     /// ```
     #[inline]
-    #[unstable(feature = "map_many_mut", issue = "97601")]
-    pub unsafe fn get_many_unchecked_mut<Q: ?Sized, const N: usize>(
+    #[doc(alias = "get_many_unchecked_mut")]
+    #[stable(feature = "map_many_mut", since = "CURRENT_RUSTC_VERSION")]
+    pub unsafe fn get_disjoint_unchecked_mut<Q: ?Sized, const N: usize>(
         &mut self,
         ks: [&Q; N],
     ) -> [Option<&'_ mut V>; N]
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index e8cbfe337bc..1323aba38b7 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -418,8 +418,13 @@ fn test_creation_flags() {
     const EXIT_PROCESS_DEBUG_EVENT: u32 = 5;
     const DBG_EXCEPTION_NOT_HANDLED: u32 = 0x80010001;
 
-    let mut child =
-        Command::new("cmd").creation_flags(DEBUG_PROCESS).stdin(Stdio::piped()).spawn().unwrap();
+    let mut child = Command::new("cmd")
+        .creation_flags(DEBUG_PROCESS)
+        .stdin(Stdio::piped())
+        .stdout(Stdio::null())
+        .stderr(Stdio::null())
+        .spawn()
+        .unwrap();
     child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap();
     let mut events = 0;
     let mut event = DEBUG_EVENT { event_code: 0, process_id: 0, thread_id: 0, _junk: [0; 164] };
@@ -486,9 +491,13 @@ fn test_proc_thread_attributes() {
         }
     }
 
-    let parent = ProcessDropGuard(Command::new("cmd").spawn().unwrap());
+    let mut parent = Command::new("cmd");
+    parent.stdout(Stdio::null()).stderr(Stdio::null());
+
+    let parent = ProcessDropGuard(parent.spawn().unwrap());
 
     let mut child_cmd = Command::new("cmd");
+    child_cmd.stdout(Stdio::null()).stderr(Stdio::null());
 
     let parent_process_handle = parent.0.as_raw_handle();
 
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index 42b444464e5..3f58328a5b5 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -310,6 +310,9 @@ impl<'a> Renderer<'a> {
         match message {
             Message::Suite(SuiteMessage::Started { test_count }) => {
                 println!("\nrunning {test_count} tests");
+                self.benches = vec![];
+                self.failures = vec![];
+                self.ignored_tests = 0;
                 self.executed_tests = 0;
                 self.terse_tests_in_line = 0;
                 self.tests_count = Some(test_count);
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index bc42c07224e..fa03c953aa5 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5765,6 +5765,7 @@ Released 2018-09-13
 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 [`manual_ok_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_err
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
+[`manual_option_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_as_slice
 [`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
 [`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns
@@ -5773,6 +5774,7 @@ Released 2018-09-13
 [`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain
 [`manual_rotate`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rotate
 [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
+[`manual_slice_fill`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_fill
 [`manual_slice_size_calculation`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_size_calculation
 [`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once
 [`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat
@@ -5954,6 +5956,7 @@ Released 2018-09-13
 [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
 [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
 [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
+[`precedence_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence_bits
 [`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_in_format_impl
 [`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal
 [`print_stderr`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr
@@ -6026,6 +6029,7 @@ Released 2018-09-13
 [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else
 [`result_unit_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unit_err
 [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
+[`return_and_then`]: https://rust-lang.github.io/rust-clippy/master/index.html#return_and_then
 [`return_self_not_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use
 [`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop
 [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges
diff --git a/src/tools/clippy/book/src/attribs.md b/src/tools/clippy/book/src/attribs.md
index cf99497bc0f..9b7f5970504 100644
--- a/src/tools/clippy/book/src/attribs.md
+++ b/src/tools/clippy/book/src/attribs.md
@@ -5,7 +5,7 @@ To do this, Clippy provides attributes that can be applied to items in the 3rd p
 
 ## `#[clippy::format_args]`
 
-_Available since Clippy v1.84_
+_Available since Clippy v1.85_
 
 This attribute can be added to a macro that supports `format!`, `println!`, or similar syntax.
 It tells Clippy that the macro is a formatting macro, and that the arguments to the macro
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index b8f9fff9c61..dab2630a56f 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -752,6 +752,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 * [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
 * [`manual_repeat_n`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_repeat_n)
 * [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
+* [`manual_slice_fill`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_fill)
 * [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once)
 * [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat)
 * [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
diff --git a/src/tools/clippy/book/src/lints.md b/src/tools/clippy/book/src/lints.md
index 442dc63914e..1dd51797660 100644
--- a/src/tools/clippy/book/src/lints.md
+++ b/src/tools/clippy/book/src/lints.md
@@ -101,5 +101,18 @@ The `clippy::cargo` group gives you suggestions on how to improve your
 your crate and are not sure if you have all useful information in your
 `Cargo.toml`.
 
+## Nursery
+
+The `clippy::nursery` group contains lints which are buggy or need more work. It is **not** 
+recommended to enable the whole group, but rather cherry-pick lints that are useful for your 
+code base and your use case. 
+
+## Deprecated
+
+The `clippy::deprecated` is empty lints that exist to ensure that `#[allow(lintname)]` still 
+compiles after the lint was deprecated. Deprecation "removes" lints by removing their 
+functionality and marking them as deprecated, which may cause further warnings but cannot 
+cause a compiler error.
+
 [Clippy lint documentation]: https://rust-lang.github.io/rust-clippy/
 [Clippy 1.0 RFC]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 552141476f3..a1591188bee 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -621,6 +621,7 @@ define_Conf! {
         manual_rem_euclid,
         manual_repeat_n,
         manual_retain,
+        manual_slice_fill,
         manual_split_once,
         manual_str_repeat,
         manual_strip,
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 35dd986ff61..cc4b26867a2 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -255,8 +255,9 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
     let name_camel = to_camel_case(lint.name);
     let name_upper = lint_name.to_uppercase();
 
-    result.push_str(&if enable_msrv {
-        formatdoc!(
+    if enable_msrv {
+        let _: fmt::Result = writedoc!(
+            result,
             r"
             use clippy_utils::msrvs::{{self, Msrv}};
             use clippy_config::Conf;
@@ -265,22 +266,24 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
             use rustc_session::impl_lint_pass;
 
         "
-        )
+        );
     } else {
-        formatdoc!(
+        let _: fmt::Result = writedoc!(
+            result,
             r"
             {pass_import}
             use rustc_lint::{{{context_import}, {pass_type}}};
             use rustc_session::declare_lint_pass;
 
         "
-        )
-    });
+        );
+    }
 
     let _: fmt::Result = writeln!(result, "{}", get_lint_declaration(&name_upper, category));
 
-    result.push_str(&if enable_msrv {
-        formatdoc!(
+    if enable_msrv {
+        let _: fmt::Result = writedoc!(
+            result,
             r"
             pub struct {name_camel} {{
                 msrv: Msrv,
@@ -301,16 +304,17 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
             // TODO: Add MSRV level to `clippy_config/src/msrvs.rs` if needed.
             // TODO: Update msrv config comment in `clippy_config/src/conf.rs`
         "
-        )
+        );
     } else {
-        formatdoc!(
+        let _: fmt::Result = writedoc!(
+            result,
             r"
             declare_lint_pass!({name_camel} => [{name_upper}]);
 
             impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
         "
-        )
-    });
+        );
+    }
 
     result
 }
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index fc0780f89a7..b80ee5aac7e 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -985,17 +985,23 @@ mod tests {
             Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
         ];
         let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
-        expected.insert("group1".to_string(), vec![
-            Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
-            Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
-        ]);
-        expected.insert("group2".to_string(), vec![Lint::new(
-            "should_assert_eq2",
-            "group2",
-            "\"abc\"",
-            "module_name",
-            Range::default(),
-        )]);
+        expected.insert(
+            "group1".to_string(),
+            vec![
+                Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
+                Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
+            ],
+        );
+        expected.insert(
+            "group2".to_string(),
+            vec![Lint::new(
+                "should_assert_eq2",
+                "group2",
+                "\"abc\"",
+                "module_name",
+                Range::default(),
+            )],
+        );
         assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 95c85f250e9..95f64b74044 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -3,10 +3,10 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_attr_parsing::RustcVersion;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{HirId, Lit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol;
+use rustc_span::{Span, symbol};
 use std::f64::consts as f64;
 
 declare_clippy_lint! {
@@ -73,22 +73,28 @@ impl ApproxConstant {
             msrv: conf.msrv.clone(),
         }
     }
+}
 
-    fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
-        match *lit {
+impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
+    fn check_lit(&mut self, cx: &LateContext<'_>, _hir_id: HirId, lit: &Lit, _negated: bool) {
+        match lit.node {
             LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
-                FloatTy::F16 => self.check_known_consts(cx, e, s, "f16"),
-                FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"),
-                FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"),
-                FloatTy::F128 => self.check_known_consts(cx, e, s, "f128"),
+                FloatTy::F16 => self.check_known_consts(cx, lit.span, s, "f16"),
+                FloatTy::F32 => self.check_known_consts(cx, lit.span, s, "f32"),
+                FloatTy::F64 => self.check_known_consts(cx, lit.span, s, "f64"),
+                FloatTy::F128 => self.check_known_consts(cx, lit.span, s, "f128"),
             },
             // FIXME(f16_f128): add `f16` and `f128` when these types become stable.
-            LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"),
+            LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, lit.span, s, "f{32, 64}"),
             _ => (),
         }
     }
 
-    fn check_known_consts(&self, cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) {
+    extract_msrv_attr!(LateContext);
+}
+
+impl ApproxConstant {
+    fn check_known_consts(&self, cx: &LateContext<'_>, span: Span, s: symbol::Symbol, module: &str) {
         let s = s.as_str();
         if s.parse::<f64>().is_ok() {
             for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
@@ -96,7 +102,7 @@ impl ApproxConstant {
                     span_lint_and_help(
                         cx,
                         APPROX_CONSTANT,
-                        e.span,
+                        span,
                         format!("approximate value of `{module}::consts::{name}` found"),
                         None,
                         "consider using the constant directly",
@@ -110,16 +116,6 @@ impl ApproxConstant {
 
 impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
 
-impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Lit(lit) = &e.kind {
-            self.check_lit(cx, &lit.node, e);
-        }
-    }
-
-    extract_msrv_attr!(LateContext);
-}
-
 /// Returns `false` if the number of significant figures in `value` are
 /// less than `min_digits`; otherwise, returns true if `value` is equal
 /// to `constant`, rounded to the number of digits present in `value`.
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 86bcf8edd57..9fbeab5bf2e 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -292,6 +292,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::loops::MANUAL_FIND_INFO,
     crate::loops::MANUAL_FLATTEN_INFO,
     crate::loops::MANUAL_MEMCPY_INFO,
+    crate::loops::MANUAL_SLICE_FILL_INFO,
     crate::loops::MANUAL_WHILE_LET_SOME_INFO,
     crate::loops::MISSING_SPIN_LOOP_INFO,
     crate::loops::MUT_RANGE_BOUND_INFO,
@@ -321,6 +322,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::manual_let_else::MANUAL_LET_ELSE_INFO,
     crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO,
     crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
+    crate::manual_option_as_slice::MANUAL_OPTION_AS_SLICE_INFO,
     crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_INFO,
     crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO,
     crate::manual_retain::MANUAL_RETAIN_INFO,
@@ -463,6 +465,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::methods::REPEAT_ONCE_INFO,
     crate::methods::RESULT_FILTER_MAP_INFO,
     crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO,
+    crate::methods::RETURN_AND_THEN_INFO,
     crate::methods::SEARCH_IS_SOME_INFO,
     crate::methods::SEEK_FROM_CURRENT_INFO,
     crate::methods::SEEK_TO_START_INSTEAD_OF_REWIND_INFO,
@@ -626,6 +629,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
     crate::pointers_in_nomem_asm_block::POINTERS_IN_NOMEM_ASM_BLOCK_INFO,
     crate::precedence::PRECEDENCE_INFO,
+    crate::precedence::PRECEDENCE_BITS_INFO,
     crate::ptr::CMP_NULL_INFO,
     crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
     crate::ptr::MUT_FROM_REF_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 123e358d7c3..233ebe00d8e 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -291,10 +291,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             && let Some(ty) = use_node.defined_ty(cx)
                             && TyCoercionStability::for_defined_ty(cx, ty, use_node.is_return()).is_deref_stable()
                         {
-                            self.state = Some((State::ExplicitDeref { mutability: None }, StateData {
-                                first_expr: expr,
-                                adjusted_ty,
-                            }));
+                            self.state = Some((
+                                State::ExplicitDeref { mutability: None },
+                                StateData {
+                                    first_expr: expr,
+                                    adjusted_ty,
+                                },
+                            ));
                         }
                     },
                     RefOp::Method { mutbl, is_ufcs }
@@ -456,10 +459,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                             && next_adjust.is_none_or(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
                             && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
                         {
-                            self.state = Some((State::Borrow { mutability }, StateData {
-                                first_expr: expr,
-                                adjusted_ty,
-                            }));
+                            self.state = Some((
+                                State::Borrow { mutability },
+                                StateData {
+                                    first_expr: expr,
+                                    adjusted_ty,
+                                },
+                            ));
                         }
                     },
                     _ => {},
@@ -503,10 +509,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                 let stability = state.stability;
                 report(cx, expr, State::DerefedBorrow(state), data, typeck);
                 if stability.is_deref_stable() {
-                    self.state = Some((State::Borrow { mutability }, StateData {
-                        first_expr: expr,
-                        adjusted_ty,
-                    }));
+                    self.state = Some((
+                        State::Borrow { mutability },
+                        StateData {
+                            first_expr: expr,
+                            adjusted_ty,
+                        },
+                    ));
                 }
             },
             (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
@@ -531,10 +540,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                 } else if stability.is_deref_stable()
                     && let Some(parent) = get_parent_expr(cx, expr)
                 {
-                    self.state = Some((State::ExplicitDeref { mutability: None }, StateData {
-                        first_expr: parent,
-                        adjusted_ty,
-                    }));
+                    self.state = Some((
+                        State::ExplicitDeref { mutability: None },
+                        StateData {
+                            first_expr: parent,
+                            adjusted_ty,
+                        },
+                    ));
                 }
             },
 
@@ -1124,17 +1136,20 @@ impl<'tcx> Dereferencing<'tcx> {
         if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
             if let Some(pat) = outer_pat {
                 // Check for auto-deref
-                if !matches!(cx.typeck_results().expr_adjustments(e), [
-                    Adjustment {
-                        kind: Adjust::Deref(_),
-                        ..
-                    },
-                    Adjustment {
-                        kind: Adjust::Deref(_),
+                if !matches!(
+                    cx.typeck_results().expr_adjustments(e),
+                    [
+                        Adjustment {
+                            kind: Adjust::Deref(_),
+                            ..
+                        },
+                        Adjustment {
+                            kind: Adjust::Deref(_),
+                            ..
+                        },
                         ..
-                    },
-                    ..
-                ]) {
+                    ]
+                ) {
                     match get_parent_expr(cx, e) {
                         // Field accesses are the same no matter the number of references.
                         Some(Expr {
diff --git a/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs
index 099194d4e74..6e85c6af642 100644
--- a/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs
@@ -233,10 +233,13 @@ fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
             if let Some(owner) = cx.last_node_with_lint_attrs.as_owner() {
                 let def_id = owner.to_def_id();
                 let def_descr = cx.tcx.def_descr(def_id);
-                diag.span_label(cx.tcx.def_span(def_id), match kind {
-                    StopKind::Attr => format!("the attribute applies to this {def_descr}"),
-                    StopKind::Doc(_) => format!("the comment documents this {def_descr}"),
-                });
+                diag.span_label(
+                    cx.tcx.def_span(def_id),
+                    match kind {
+                        StopKind::Attr => format!("the attribute applies to this {def_descr}"),
+                        StopKind::Doc(_) => format!("the comment documents this {def_descr}"),
+                    },
+                );
             }
 
             diag.multipart_suggestion_with_style(
diff --git a/src/tools/clippy/clippy_lints/src/endian_bytes.rs b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
index 29deaaf3bc7..a7670ffce88 100644
--- a/src/tools/clippy/clippy_lints/src/endian_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
@@ -6,6 +6,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::Ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::Symbol;
+use std::fmt::Write;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -183,7 +184,7 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
                     help_str.push_str("either of ");
                 }
 
-                help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));
+                write!(help_str, "`{ty}::{}` ", lint.as_name(prefix)).unwrap();
 
                 if i != len && !only_one {
                     help_str.push_str("or ");
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 52b699274bb..f90bf9157aa 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -1,13 +1,13 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::higher::VecArgs;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{snippet_opt, snippet_with_applicability};
 use clippy_utils::ty::get_type_diagnostic_name;
 use clippy_utils::usage::{local_used_after_expr, local_used_in};
 use clippy_utils::{
     get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id,
 };
 use rustc_errors::Applicability;
-use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Safety, TyKind};
+use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{
@@ -239,6 +239,11 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
                 && !cx.tcx.has_attr(method_def_id, sym::track_caller)
                 && check_sig(closure_sig, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder())
             {
+                let mut app = Applicability::MachineApplicable;
+                let generic_args = match path.args.and_then(GenericArgs::span_ext) {
+                    Some(span) => format!("::{}", snippet_with_applicability(cx, span, "<..>", &mut app)),
+                    None => String::new(),
+                };
                 span_lint_and_then(
                     cx,
                     REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
@@ -251,8 +256,8 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
                         diag.span_suggestion(
                             expr.span,
                             "replace the closure with the method itself",
-                            format!("{}::{}", type_name, path.ident.name),
-                            Applicability::MachineApplicable,
+                            format!("{}::{}{}", type_name, path.ident.name, generic_args),
+                            app,
                         );
                     },
                 );
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index 36567b3ded0..1d3ae894944 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -124,7 +124,9 @@ struct NestingVisitor<'conf, 'cx> {
 
 impl NestingVisitor<'_, '_> {
     fn check_indent(&mut self, span: Span, id: NodeId) -> bool {
-        if self.nest_level > self.conf.excessive_nesting_threshold && !span.in_external_macro(self.cx.sess().source_map()) {
+        if self.nest_level > self.conf.excessive_nesting_threshold
+            && !span.in_external_macro(self.cx.sess().source_map())
+        {
             self.conf.nodes.insert(id);
 
             return true;
diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs
index 8b1f86cbb91..68cc50f3939 100644
--- a/src/tools/clippy/clippy_lints/src/format_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs
@@ -11,7 +11,7 @@ declare_clippy_lint! {
     /// Detects cases where the result of a `format!` call is
     /// appended to an existing `String`.
     ///
-    /// ### Why restrict this?
+    /// ### Why is this bad?
     /// Introduces an extra, avoidable heap allocation.
     ///
     /// ### Known problems
@@ -35,7 +35,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.62.0"]
     pub FORMAT_PUSH_STRING,
-    restriction,
+    pedantic,
     "`format!(..)` appended to existing `String`"
 }
 declare_lint_pass!(FormatPushString => [FORMAT_PUSH_STRING]);
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index 6f5c5d6b3ea..c68499ce9f7 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -7,8 +7,8 @@ use clippy_utils::macros::macro_backtrace;
 use clippy_utils::source::snippet;
 use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::impl_lint_pass;
 use rustc_span::{Span, sym};
 
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 4b700673d0f..8887ab7ec0d 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -217,6 +217,7 @@ mod manual_is_power_of_two;
 mod manual_let_else;
 mod manual_main_separator_str;
 mod manual_non_exhaustive;
+mod manual_option_as_slice;
 mod manual_range_patterns;
 mod manual_rem_euclid;
 mod manual_retain;
@@ -976,5 +977,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(unneeded_struct_pattern::UnneededStructPattern));
     store.register_late_pass(|_| Box::<unnecessary_semicolon::UnnecessarySemicolon>::default());
     store.register_late_pass(move |_| Box::new(non_std_lazy_statics::NonStdLazyStatic::new(conf)));
+    store.register_late_pass(|_| Box::new(manual_option_as_slice::ManualOptionAsSlice::new(conf)));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs b/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs
new file mode 100644
index 00000000000..7c656423579
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs
@@ -0,0 +1,111 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::eager_or_lazy::switch_to_eager_eval;
+use clippy_utils::macros::span_is_local;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::{HasSession, snippet_with_applicability};
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{higher, peel_blocks_with_stmt, span_contains_comment};
+use rustc_ast::ast::LitKind;
+use rustc_ast::{RangeLimits, UnOp};
+use rustc_data_structures::packed::Pu128;
+use rustc_errors::Applicability;
+use rustc_hir::QPath::Resolved;
+use rustc_hir::def::Res;
+use rustc_hir::{Expr, ExprKind, Pat};
+use rustc_lint::LateContext;
+use rustc_span::source_map::Spanned;
+use rustc_span::sym;
+
+use super::MANUAL_SLICE_FILL;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    pat: &'tcx Pat<'_>,
+    arg: &'tcx Expr<'_>,
+    body: &'tcx Expr<'_>,
+    expr: &'tcx Expr<'_>,
+    msrv: &Msrv,
+) {
+    if !msrv.meets(msrvs::SLICE_FILL) {
+        return;
+    }
+
+    // `for _ in 0..slice.len() { slice[_] = value; }`
+    if let Some(higher::Range {
+        start: Some(start),
+        end: Some(end),
+        limits: RangeLimits::HalfOpen,
+    }) = higher::Range::hir(arg)
+        && let ExprKind::Lit(Spanned {
+            node: LitKind::Int(Pu128(0), _),
+            ..
+        }) = start.kind
+        && let ExprKind::Block(..) = body.kind
+        // Check if the body is an assignment to a slice element.
+        && let ExprKind::Assign(assignee, assignval, _) = peel_blocks_with_stmt(body).kind
+        && let ExprKind::Index(slice, _, _) = assignee.kind
+        // Check if `len()` is used for the range end.
+        && let ExprKind::MethodCall(path, recv,..) = end.kind
+        && path.ident.name == sym::len
+        // Check if the slice which is being assigned to is the same as the one being iterated over.
+        && let ExprKind::Path(Resolved(_, recv_path)) = recv.kind
+        && let ExprKind::Path(Resolved(_, slice_path)) = slice.kind
+        && recv_path.res == slice_path.res
+        && !assignval.span.from_expansion()
+        // It is generally not equivalent to use the `fill` method if `assignval` can have side effects
+        && switch_to_eager_eval(cx, assignval)
+        && span_is_local(assignval.span)
+        // The `fill` method requires that the slice's element type implements the `Clone` trait.
+        && let Some(clone_trait) = cx.tcx.lang_items().clone_trait()
+        && implements_trait(cx, cx.typeck_results().expr_ty(slice), clone_trait, &[])
+    {
+        sugg(cx, body, expr, slice.span, assignval.span);
+    }
+    // `for _ in &mut slice { *_ = value; }`
+    else if let ExprKind::AddrOf(_, _, recv) = arg.kind
+        // Check if the body is an assignment to a slice element.
+        && let ExprKind::Assign(assignee, assignval, _) = peel_blocks_with_stmt(body).kind
+        && let ExprKind::Unary(UnOp::Deref, slice_iter) = assignee.kind
+        && let ExprKind::Path(Resolved(_, recv_path)) = recv.kind
+        // Check if the slice which is being assigned to is the same as the one being iterated over.
+        && let ExprKind::Path(Resolved(_, slice_path)) = slice_iter.kind
+        && let Res::Local(local) = slice_path.res
+        && local == pat.hir_id
+        && !assignval.span.from_expansion()
+        && switch_to_eager_eval(cx, assignval)
+        && span_is_local(assignval.span)
+        // The `fill` method cannot be used if the slice's element type does not implement the `Clone` trait.
+        && let Some(clone_trait) = cx.tcx.lang_items().clone_trait()
+        && implements_trait(cx, cx.typeck_results().expr_ty(recv), clone_trait, &[])
+    {
+        sugg(cx, body, expr, recv_path.span, assignval.span);
+    }
+}
+
+fn sugg<'tcx>(
+    cx: &LateContext<'tcx>,
+    body: &'tcx Expr<'_>,
+    expr: &'tcx Expr<'_>,
+    slice_span: rustc_span::Span,
+    assignval_span: rustc_span::Span,
+) {
+    let mut app = if span_contains_comment(cx.sess().source_map(), body.span) {
+        Applicability::MaybeIncorrect // Comments may be informational.
+    } else {
+        Applicability::MachineApplicable
+    };
+
+    span_lint_and_sugg(
+        cx,
+        MANUAL_SLICE_FILL,
+        expr.span,
+        "manually filling a slice",
+        "try",
+        format!(
+            "{}.fill({});",
+            snippet_with_applicability(cx, slice_span, "..", &mut app),
+            snippet_with_applicability(cx, assignval_span, "..", &mut app),
+        ),
+        app,
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index c5e75af2303..cdc8c18c3b7 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -8,6 +8,7 @@ mod iter_next_loop;
 mod manual_find;
 mod manual_flatten;
 mod manual_memcpy;
+mod manual_slice_fill;
 mod manual_while_let_some;
 mod missing_spin_loop;
 mod mut_range_bound;
@@ -714,6 +715,31 @@ declare_clippy_lint! {
     "possibly unintended infinite loop"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for manually filling a slice with a value.
+    ///
+    /// ### Why is this bad?
+    /// Using the `fill` method is more idiomatic and concise.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let mut some_slice = [1, 2, 3, 4, 5];
+    /// for i in 0..some_slice.len() {
+    ///     some_slice[i] = 0;
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let mut some_slice = [1, 2, 3, 4, 5];
+    /// some_slice.fill(0);
+    /// ```
+    #[clippy::version = "1.86.0"]
+    pub MANUAL_SLICE_FILL,
+    style,
+    "manually filling a slice with a value"
+}
+
 pub struct Loops {
     msrv: Msrv,
     enforce_iter_loop_reborrow: bool,
@@ -750,6 +776,7 @@ impl_lint_pass!(Loops => [
     MANUAL_WHILE_LET_SOME,
     UNUSED_ENUMERATE_INDEX,
     INFINITE_LOOP,
+    MANUAL_SLICE_FILL,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Loops {
@@ -823,6 +850,7 @@ impl Loops {
     ) {
         let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr);
         if !is_manual_memcpy_triggered {
+            manual_slice_fill::check(cx, pat, arg, body, expr, &self.msrv);
             needless_range_loop::check(cx, pat, arg, body, expr);
             explicit_counter_loop::check(cx, pat, arg, body, expr, label);
         }
diff --git a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
index 816ca17b3d2..04357cdd8f6 100644
--- a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
@@ -181,13 +181,16 @@ fn build_suggestion(
             ExprKind::Lit(Spanned {
                 node: LitKind::Int(_, LitIntType::Unsuffixed),
                 ..
-            }) | ExprKind::Unary(UnOp::Neg, Expr {
-                kind: ExprKind::Lit(Spanned {
-                    node: LitKind::Int(_, LitIntType::Unsuffixed),
+            }) | ExprKind::Unary(
+                UnOp::Neg,
+                Expr {
+                    kind: ExprKind::Lit(Spanned {
+                        node: LitKind::Int(_, LitIntType::Unsuffixed),
+                        ..
+                    }),
                     ..
-                }),
-                ..
-            })
+                }
+            )
         ) {
         format!("_{}", cx.typeck_results().expr_ty(rhs))
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
new file mode 100644
index 00000000000..5c40c945c69
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs
@@ -0,0 +1,225 @@
+use clippy_config::Conf;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs};
+use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Arm, Expr, ExprKind, LangItem, Pat, PatKind, QPath, is_range_literal};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
+use rustc_session::impl_lint_pass;
+use rustc_span::{Span, Symbol, sym};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// This detects various manual reimplementations of `Option::as_slice`.
+    ///
+    /// ### Why is this bad?
+    /// Those implementations are both more complex than calling `as_slice`
+    /// and unlike that incur a branch, pessimizing performance and leading
+    /// to more generated code.
+    ///
+    /// ### Example
+    /// ```no_run
+    ///# let opt = Some(1);
+    /// _ = opt.as_ref().map_or(&[][..], std::slice::from_ref);
+    /// _ = match opt.as_ref() {
+    ///     Some(f) => std::slice::from_ref(f),
+    ///     None => &[],
+    /// };
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    ///# let opt = Some(1);
+    /// _ = opt.as_slice();
+    /// _ = opt.as_slice();
+    /// ```
+    #[clippy::version = "1.85.0"]
+    pub MANUAL_OPTION_AS_SLICE,
+    complexity,
+    "manual `Option::as_slice`"
+}
+
+pub struct ManualOptionAsSlice {
+    msrv: msrvs::Msrv,
+}
+
+impl ManualOptionAsSlice {
+    pub fn new(conf: &Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
+}
+
+impl_lint_pass!(ManualOptionAsSlice => [MANUAL_OPTION_AS_SLICE]);
+
+impl LateLintPass<'_> for ManualOptionAsSlice {
+    extract_msrv_attr!(LateContext);
+
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let span = expr.span;
+        if span.from_expansion()
+            || !self.msrv.meets(if clippy_utils::is_in_const_context(cx) {
+                msrvs::CONST_OPTION_AS_SLICE
+            } else {
+                msrvs::OPTION_AS_SLICE
+            })
+        {
+            return;
+        }
+        match expr.kind {
+            ExprKind::Match(scrutinee, [arm1, arm2], _) => {
+                if is_none_arm(cx, arm2) && check_arms(cx, arm2, arm1)
+                    || is_none_arm(cx, arm1) && check_arms(cx, arm1, arm2)
+                {
+                    check_as_ref(cx, scrutinee, span);
+                }
+            },
+            ExprKind::If(cond, then, Some(other)) => {
+                if let ExprKind::Let(let_expr) = cond.kind
+                    && let Some(binding) = extract_ident_from_some_pat(cx, let_expr.pat)
+                    && check_some_body(cx, binding, then)
+                    && is_empty_slice(cx, other.peel_blocks())
+                {
+                    check_as_ref(cx, let_expr.init, span);
+                }
+            },
+            ExprKind::MethodCall(seg, callee, [], _) => {
+                if seg.ident.name.as_str() == "unwrap_or_default" {
+                    check_map(cx, callee, span);
+                }
+            },
+            ExprKind::MethodCall(seg, callee, [or], _) => match seg.ident.name.as_str() {
+                "unwrap_or" => {
+                    if is_empty_slice(cx, or) {
+                        check_map(cx, callee, span);
+                    }
+                },
+                "unwrap_or_else" => {
+                    if returns_empty_slice(cx, or) {
+                        check_map(cx, callee, span);
+                    }
+                },
+                _ => {},
+            },
+            ExprKind::MethodCall(seg, callee, [or_else, map], _) => match seg.ident.name.as_str() {
+                "map_or" => {
+                    if is_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) {
+                        check_as_ref(cx, callee, span);
+                    }
+                },
+                "map_or_else" => {
+                    if returns_empty_slice(cx, or_else) && is_slice_from_ref(cx, map) {
+                        check_as_ref(cx, callee, span);
+                    }
+                },
+                _ => {},
+            },
+            _ => {},
+        }
+    }
+}
+
+fn check_map(cx: &LateContext<'_>, map: &Expr<'_>, span: Span) {
+    if let ExprKind::MethodCall(seg, callee, [mapping], _) = map.kind
+        && seg.ident.name == sym::map
+        && is_slice_from_ref(cx, mapping)
+    {
+        check_as_ref(cx, callee, span);
+    }
+}
+
+fn check_as_ref(cx: &LateContext<'_>, expr: &Expr<'_>, span: Span) {
+    if let ExprKind::MethodCall(seg, callee, [], _) = expr.kind
+        && seg.ident.name == sym::as_ref
+        && let ty::Adt(adtdef, ..) = cx.typeck_results().expr_ty(callee).kind()
+        && cx.tcx.is_diagnostic_item(sym::Option, adtdef.did())
+    {
+        if let Some(snippet) = clippy_utils::source::snippet_opt(cx, callee.span) {
+            span_lint_and_sugg(
+                cx,
+                MANUAL_OPTION_AS_SLICE,
+                span,
+                "use `Option::as_slice`",
+                "use",
+                format!("{snippet}.as_slice()"),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            span_lint(cx, MANUAL_OPTION_AS_SLICE, span, "use `Option_as_slice`");
+        }
+    }
+}
+
+fn extract_ident_from_some_pat(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<Symbol> {
+    if let PatKind::TupleStruct(QPath::Resolved(None, path), [binding], _) = pat.kind
+        && let Res::Def(DefKind::Ctor(..), def_id) = path.res
+        && let PatKind::Binding(_mode, _hir_id, ident, _inner_pat) = binding.kind
+        && clippy_utils::is_lang_item_or_ctor(cx, def_id, LangItem::OptionSome)
+    {
+        Some(ident.name)
+    } else {
+        None
+    }
+}
+
+/// Returns true if `expr` is `std::slice::from_ref(<name>)`. Used in `if let`s.
+fn check_some_body(cx: &LateContext<'_>, name: Symbol, expr: &Expr<'_>) -> bool {
+    if let ExprKind::Call(slice_from_ref, [arg]) = expr.peel_blocks().kind
+        && is_slice_from_ref(cx, slice_from_ref)
+        && let ExprKind::Path(QPath::Resolved(None, path)) = arg.kind
+        && let [seg] = path.segments
+    {
+        seg.ident.name == name
+    } else {
+        false
+    }
+}
+
+fn check_arms(cx: &LateContext<'_>, none_arm: &Arm<'_>, some_arm: &Arm<'_>) -> bool {
+    if none_arm.guard.is_none()
+        && some_arm.guard.is_none()
+        && is_empty_slice(cx, none_arm.body)
+        && let Some(name) = extract_ident_from_some_pat(cx, some_arm.pat)
+    {
+        check_some_body(cx, name, some_arm.body)
+    } else {
+        false
+    }
+}
+
+fn returns_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    match expr.kind {
+        ExprKind::Path(_) => clippy_utils::is_path_diagnostic_item(cx, expr, sym::default_fn),
+        ExprKind::Closure(cl) => is_empty_slice(cx, cx.tcx.hir().body(cl.body).value),
+        _ => false,
+    }
+}
+
+/// Returns if expr returns an empty slice. If:
+/// - An indexing operation to an empty array with a built-in range. `[][..]`
+/// - An indexing operation with a zero-ended range. `expr[..0]`
+/// - A reference to an empty array. `&[]`
+/// - Or a call to `Default::default`.
+fn is_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let expr = peel_hir_expr_refs(expr.peel_blocks()).0;
+    match expr.kind {
+        ExprKind::Index(arr, range, _) => match arr.kind {
+            ExprKind::Array([]) => is_range_literal(range),
+            ExprKind::Array(_) => {
+                let Some(range) = clippy_utils::higher::Range::hir(range) else {
+                    return false;
+                };
+                range.end.is_some_and(|e| clippy_utils::is_integer_const(cx, e, 0))
+            },
+            _ => false,
+        },
+        ExprKind::Array([]) => true,
+        ExprKind::Call(def, []) => clippy_utils::is_path_diagnostic_item(cx, def, sym::default_fn),
+        _ => false,
+    }
+}
+
+fn is_slice_from_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    clippy_utils::is_expr_path_def_path(cx, expr, &["core", "slice", "raw", "from_ref"])
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
index 7b95399c907..87d2faa225c 100644
--- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
@@ -9,8 +9,8 @@ use rustc_span::sym;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_default_equivalent, is_in_const_context, peel_blocks, span_contains_comment};
+use clippy_utils::ty::{expr_type_is_certain, implements_trait};
+use clippy_utils::{is_default_equivalent, is_in_const_context, path_res, peel_blocks, span_contains_comment};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -158,6 +158,36 @@ fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, exp
         } else {
             Applicability::MachineApplicable
         };
+
+        // We now check if the condition is a None variant, in which case we need to specify the type
+        if path_res(cx, condition)
+            .opt_def_id()
+            .is_some_and(|id| Some(cx.tcx.parent(id)) == cx.tcx.lang_items().option_none_variant())
+        {
+            return span_lint_and_sugg(
+                cx,
+                MANUAL_UNWRAP_OR_DEFAULT,
+                expr.span,
+                format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
+                "replace it with",
+                format!("{receiver}::<{expr_type}>.unwrap_or_default()"),
+                applicability,
+            );
+        }
+
+        // We check if the expression type is still uncertain, in which case we ask the user to specify it
+        if !expr_type_is_certain(cx, condition) {
+            return span_lint_and_sugg(
+                cx,
+                MANUAL_UNWRAP_OR_DEFAULT,
+                expr.span,
+                format!("{expr_name} can be simplified with `.unwrap_or_default()`"),
+                format!("ascribe the type {expr_type} and replace your expression with"),
+                format!("{receiver}.unwrap_or_default()"),
+                Applicability::Unspecified,
+            );
+        }
+
         span_lint_and_sugg(
             cx,
             MANUAL_UNWRAP_OR_DEFAULT,
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
index b1889d26c93..1cb4b512a30 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
+use clippy_utils::{is_none_arm, is_res_lang_ctor, path_res, peel_blocks};
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatExpr, PatExprKind, PatKind, QPath};
+use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
@@ -55,14 +55,6 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
     }
 }
 
-// Checks if arm has the form `None => None`
-fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
-    matches!(
-        arm.pat.kind,
-        PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), .. }) if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionNone)
-    )
-}
-
 // Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
 fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
     if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 2f447775fa5..f501cf060c2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -95,6 +95,7 @@ mod readonly_write_lock;
 mod redundant_as_str;
 mod repeat_once;
 mod result_map_or_else_none;
+mod return_and_then;
 mod search_is_some;
 mod seek_from_current;
 mod seek_to_start_instead_of_rewind;
@@ -3517,7 +3518,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.73.0"]
     pub FORMAT_COLLECT,
-    perf,
+    pedantic,
     "`format!`ing every element in a collection, then collecting the strings into a new `String`"
 }
 
@@ -4365,7 +4366,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for string slices immediantly followed by `as_bytes`.
+    /// Checks for string slices immediately followed by `as_bytes`.
     ///
     /// ### Why is this bad?
     /// It involves doing an unnecessary UTF-8 alignment check which is less efficient, and can cause a panic.
@@ -4391,6 +4392,46 @@ declare_clippy_lint! {
      "slicing a string and immediately calling as_bytes is less efficient and can lead to panics"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Detect functions that end with `Option::and_then` or `Result::and_then`, and suggest using a question mark (`?`) instead.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// The `and_then` method is used to chain a computation that returns an `Option` or a `Result`.
+    /// This can be replaced with the `?` operator, which is more concise and idiomatic.
+    ///
+    /// ### Example
+    ///
+    /// ```no_run
+    /// fn test(opt: Option<i32>) -> Option<i32> {
+    ///     opt.and_then(|n| {
+    ///         if n > 1 {
+    ///             Some(n + 1)
+    ///         } else {
+    ///             None
+    ///        }
+    ///     })
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// fn test(opt: Option<i32>) -> Option<i32> {
+    ///     let n = opt?;
+    ///     if n > 1 {
+    ///         Some(n + 1)
+    ///     } else {
+    ///         None
+    ///     }
+    /// }
+    /// ```
+    #[clippy::version = "1.86.0"]
+    pub RETURN_AND_THEN,
+    restriction,
+    "using `Option::and_then` or `Result::and_then` to chain a computation that returns an `Option` or a `Result`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -4560,6 +4601,7 @@ impl_lint_pass!(Methods => [
     USELESS_NONZERO_NEW_UNCHECKED,
     MANUAL_REPEAT_N,
     SLICED_STRING_AS_BYTES,
+    RETURN_AND_THEN,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -4789,7 +4831,10 @@ impl Methods {
                     let biom_option_linted = bind_instead_of_map::check_and_then_some(cx, expr, recv, arg);
                     let biom_result_linted = bind_instead_of_map::check_and_then_ok(cx, expr, recv, arg);
                     if !biom_option_linted && !biom_result_linted {
-                        unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
+                        let ule_and_linted = unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
+                        if !ule_and_linted {
+                            return_and_then::check(cx, expr, recv, arg);
+                        }
                     }
                 },
                 ("any", [arg]) => {
@@ -5003,7 +5048,9 @@ impl Methods {
                     get_first::check(cx, expr, recv, arg);
                     get_last_with_len::check(cx, expr, recv, arg);
                 },
-                ("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"),
+                ("get_or_insert_with", [arg]) => {
+                    unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert");
+                },
                 ("hash", [arg]) => {
                     unit_hash::check(cx, expr, recv, arg);
                 },
@@ -5144,7 +5191,9 @@ impl Methods {
                     },
                     _ => iter_nth_zero::check(cx, expr, recv, n_arg),
                 },
-                ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
+                ("ok_or_else", [arg]) => {
+                    unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or");
+                },
                 ("open", [_]) => {
                     open_options::check(cx, expr, recv);
                 },
@@ -5437,9 +5486,12 @@ impl ShouldImplTraitCase {
     fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
         self.lint_explicit_lifetime
             || !impl_item.generics.params.iter().any(|p| {
-                matches!(p.kind, hir::GenericParamKind::Lifetime {
-                    kind: hir::LifetimeParamKind::Explicit
-                })
+                matches!(
+                    p.kind,
+                    hir::GenericParamKind::Lifetime {
+                        kind: hir::LifetimeParamKind::Explicit
+                    }
+                )
             })
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs b/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs
index c41ce2481d7..88b9c69f6f9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_option_take.rs
@@ -1,5 +1,6 @@
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -10,13 +11,22 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
     // Checks if expression type is equal to sym::Option and if the expr is not a syntactic place
     if !recv.is_syntactic_place_expr() && is_expr_option(cx, recv) {
         if let Some(function_name) = source_of_temporary_value(recv) {
-            span_lint_and_note(
+            span_lint_and_then(
                 cx,
                 NEEDLESS_OPTION_TAKE,
                 expr.span,
                 "called `Option::take()` on a temporary value",
-                None,
-                format!("`{function_name}` creates a temporary value, so calling take() has no effect"),
+                |diag| {
+                    diag.note(format!(
+                        "`{function_name}` creates a temporary value, so calling take() has no effect"
+                    ));
+                    diag.span_suggestion(
+                        expr.span.with_lo(recv.span.hi()),
+                        "remove",
+                        "",
+                        Applicability::MachineApplicable,
+                    );
+                },
             );
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs
new file mode 100644
index 00000000000..7b1199ad1e2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs
@@ -0,0 +1,67 @@
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, GenericArg, Ty};
+use rustc_span::sym;
+use std::ops::ControlFlow;
+
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{indent_of, reindent_multiline, snippet_with_applicability};
+use clippy_utils::ty::get_type_diagnostic_name;
+use clippy_utils::visitors::for_each_unconsumed_temporary;
+use clippy_utils::{is_expr_final_block_expr, peel_blocks};
+
+use super::RETURN_AND_THEN;
+
+/// lint if `and_then` is the last expression in a block, and
+/// there are no references or temporaries in the receiver
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'tcx>,
+    arg: &'tcx hir::Expr<'_>,
+) {
+    if !is_expr_final_block_expr(cx.tcx, expr) {
+        return;
+    }
+
+    let recv_type = cx.typeck_results().expr_ty(recv);
+    if !matches!(get_type_diagnostic_name(cx, recv_type), Some(sym::Option | sym::Result)) {
+        return;
+    }
+
+    let has_ref_type = matches!(recv_type.kind(), ty::Adt(_, args) if args
+        .first()
+        .and_then(|arg0: &GenericArg<'tcx>| GenericArg::as_type(*arg0))
+        .is_some_and(Ty::is_ref));
+    let has_temporaries = for_each_unconsumed_temporary(cx, recv, |_| ControlFlow::Break(())).is_break();
+    if has_ref_type && has_temporaries {
+        return;
+    }
+
+    let hir::ExprKind::Closure(&hir::Closure { body, fn_decl, .. }) = arg.kind else {
+        return;
+    };
+
+    let closure_arg = fn_decl.inputs[0];
+    let closure_expr = peel_blocks(cx.tcx.hir().body(body).value);
+
+    let mut applicability = Applicability::MachineApplicable;
+    let arg_snip = snippet_with_applicability(cx, closure_arg.span, "_", &mut applicability);
+    let recv_snip = snippet_with_applicability(cx, recv.span, "_", &mut applicability);
+    let body_snip = snippet_with_applicability(cx, closure_expr.span, "..", &mut applicability);
+    let inner = match body_snip.strip_prefix('{').and_then(|s| s.strip_suffix('}')) {
+        Some(s) => s.trim_start_matches('\n').trim_end(),
+        None => &body_snip,
+    };
+
+    let msg = "use the question mark operator instead of an `and_then` call";
+    let sugg = format!(
+        "let {} = {}?;\n{}",
+        arg_snip,
+        recv_snip,
+        reindent_multiline(inner.into(), false, indent_of(cx, expr.span))
+    );
+
+    span_lint_and_sugg(cx, RETURN_AND_THEN, expr.span, msg, "try", sugg, applicability);
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index c27d1fb4903..e7adf3b43ba 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -123,32 +123,60 @@ pub(super) fn check(
     if let hir::ExprKind::Lit(lit) = init.kind {
         match lit.node {
             ast::LitKind::Bool(false) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, Replacement {
-                    method_name: "any",
-                    has_args: true,
-                    has_generic_return: false,
-                });
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Or,
+                    Replacement {
+                        method_name: "any",
+                        has_args: true,
+                        has_generic_return: false,
+                    },
+                );
             },
             ast::LitKind::Bool(true) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, Replacement {
-                    method_name: "all",
-                    has_args: true,
-                    has_generic_return: false,
-                });
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::And,
+                    Replacement {
+                        method_name: "all",
+                        has_args: true,
+                        has_generic_return: false,
+                    },
+                );
             },
             ast::LitKind::Int(Pu128(0), _) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, Replacement {
-                    method_name: "sum",
-                    has_args: false,
-                    has_generic_return: needs_turbofish(cx, expr),
-                });
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Add,
+                    Replacement {
+                        method_name: "sum",
+                        has_args: false,
+                        has_generic_return: needs_turbofish(cx, expr),
+                    },
+                );
             },
             ast::LitKind::Int(Pu128(1), _) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, Replacement {
-                    method_name: "product",
-                    has_args: false,
-                    has_generic_return: needs_turbofish(cx, expr),
-                });
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Mul,
+                    Replacement {
+                        method_name: "product",
+                        has_args: false,
+                        has_generic_return: needs_turbofish(cx, expr),
+                    },
+                );
             },
             _ => (),
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 1673a6f8b3a..7af550fa7c6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -18,7 +18,7 @@ pub(super) fn check<'tcx>(
     recv: &'tcx hir::Expr<'_>,
     arg: &'tcx hir::Expr<'_>,
     simplify_using: &str,
-) {
+) -> bool {
     let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
     let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
     let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
@@ -29,7 +29,7 @@ pub(super) fn check<'tcx>(
             let body_expr = &body.value;
 
             if usage::BindingUsageFinder::are_params_used(cx, body) || is_from_proc_macro(cx, expr) {
-                return;
+                return false;
             }
 
             if eager_or_lazy::switch_to_eager_eval(cx, body_expr) {
@@ -71,8 +71,10 @@ pub(super) fn check<'tcx>(
                             applicability,
                         );
                     });
+                    return true;
                 }
             }
         }
     }
+    false
 }
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index fa0eb9a94b7..fca416d9e64 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
                         TOPLEVEL_REF_ARG,
                         arg.hir_id,
                         arg.pat.span,
-                        "`ref` directly on a function argument is ignored. \
+                        "`ref` directly on a function parameter does not prevent taking ownership of the passed argument. \
                         Consider using a reference type instead",
                     );
                 }
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 302db2c914c..9acede4f32d 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -152,16 +152,19 @@ fn collect_unsafe_exprs<'tcx>(
             ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
                 if matches!(
                     lhs.kind,
-                    ExprKind::Path(QPath::Resolved(_, hir::Path {
-                        res: Res::Def(
-                            DefKind::Static {
-                                mutability: Mutability::Mut,
-                                ..
-                            },
-                            _
-                        ),
-                        ..
-                    }))
+                    ExprKind::Path(QPath::Resolved(
+                        _,
+                        hir::Path {
+                            res: Res::Def(
+                                DefKind::Static {
+                                    mutability: Mutability::Mut,
+                                    ..
+                                },
+                                _
+                            ),
+                            ..
+                        }
+                    ))
                 ) {
                     unsafe_ops.push(("modification of a mutable static occurs here", expr.span));
                     collect_unsafe_exprs(cx, rhs, unsafe_ops);
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index 86c084423b7..49fd29d1dd6 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -18,11 +18,14 @@ declare_clippy_lint! {
     ///
     /// On the other hand, `Mutex`es are, in general, easier to
     /// verify correctness. An atomic does not behave the same as
-    /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s commentary for more details.
+    /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s
+    /// commentary for more details.
     ///
     /// ### Known problems
-    /// This lint cannot detect if the mutex is actually used
-    /// for waiting before a critical section.
+    /// * This lint cannot detect if the mutex is actually used
+    ///   for waiting before a critical section.
+    /// * This lint has a false positive that warns without considering the case
+    ///   where `Mutex` is used together with `Condvar`.
     ///
     /// ### Example
     /// ```no_run
@@ -48,14 +51,23 @@ declare_clippy_lint! {
     /// Checks for usage of `Mutex<X>` where `X` is an integral
     /// type.
     ///
-    /// ### Why is this bad?
+    /// ### Why restrict this?
     /// Using a mutex just to make access to a plain integer
     /// sequential is
     /// shooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster.
     ///
+    /// On the other hand, `Mutex`es are, in general, easier to
+    /// verify correctness. An atomic does not behave the same as
+    /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s
+    /// commentary for more details.
+    ///
     /// ### Known problems
-    /// This lint cannot detect if the mutex is actually used
-    /// for waiting before a critical section.
+    /// * This lint cannot detect if the mutex is actually used
+    ///   for waiting before a critical section.
+    /// * This lint has a false positive that warns without considering the case
+    ///   where `Mutex` is used together with `Condvar`.
+    /// * This lint suggest using `AtomicU64` instead of `Mutex<u64>`, but
+    ///   `AtomicU64` is not available on some 32-bit platforms.
     ///
     /// ### Example
     /// ```no_run
@@ -70,7 +82,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "pre 1.29.0"]
     pub MUTEX_INTEGER,
-    nursery,
+    restriction,
     "using a mutex for an integer type"
 }
 
@@ -108,7 +120,7 @@ fn get_atomic_name(ty: Ty<'_>) -> Option<&'static str> {
                 UintTy::U32 => Some("AtomicU32"),
                 UintTy::U64 => Some("AtomicU64"),
                 UintTy::Usize => Some("AtomicUsize"),
-                // There's no `AtomicU128`.
+                // `AtomicU128` is unstable and only available on a few platforms: https://github.com/rust-lang/rust/issues/99069
                 UintTy::U128 => None,
             }
         },
@@ -119,7 +131,7 @@ fn get_atomic_name(ty: Ty<'_>) -> Option<&'static str> {
                 IntTy::I32 => Some("AtomicI32"),
                 IntTy::I64 => Some("AtomicI64"),
                 IntTy::Isize => Some("AtomicIsize"),
-                // There's no `AtomicI128`.
+                // `AtomicU128` is unstable and only available on a few platforms: https://github.com/rust-lang/rust/issues/99069
                 IntTy::I128 => None,
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 30846fb46ac..2855703b9d5 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -181,9 +181,14 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 && !is_copy(cx, ty)
                 && ty.is_sized(cx.tcx, cx.typing_env())
                 && !allowed_traits.iter().any(|&t| {
-                    implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, t, None, [None::<
-                        ty::GenericArg<'tcx>,
-                    >])
+                    implements_trait_with_env_from_iter(
+                        cx.tcx,
+                        cx.typing_env(),
+                        ty,
+                        t,
+                        None,
+                        [None::<ty::GenericArg<'tcx>>],
+                    )
                 })
                 && !implements_borrow_trait
                 && !all_borrowable_trait
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index d9845bc3b0f..9ad32c2bd39 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -265,9 +265,6 @@ declare_clippy_lint! {
     /// `x.trailing_zeros() >= 4` is much clearer than `x & 15
     /// == 0`
     ///
-    /// ### Known problems
-    /// llvm generates better code for `x & 15 == 0` on x86
-    ///
     /// ### Example
     /// ```no_run
     /// # let x = 1;
diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs
index 421b2b74755..ec6835db897 100644
--- a/src/tools/clippy/clippy_lints/src/precedence.rs
+++ b/src/tools/clippy/clippy_lints/src/precedence.rs
@@ -3,17 +3,14 @@ use clippy_utils::source::snippet_with_applicability;
 use rustc_ast::ast::BinOpKind::{Add, BitAnd, BitOr, BitXor, Div, Mul, Rem, Shl, Shr, Sub};
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for operations where precedence may be unclear
-    /// and suggests to add parentheses. Currently it catches the following:
-    /// * mixed usage of arithmetic and bit shifting/combining operators without
-    /// parentheses
-    /// * mixed usage of bitmasking and bit shifting operators without parentheses
+    /// Checks for operations where precedence may be unclear and suggests to add parentheses.
+    /// It catches a mixed usage of arithmetic and bit shifting/combining operators without parentheses
     ///
     /// ### Why is this bad?
     /// Not everyone knows the precedence of those operators by
@@ -21,15 +18,32 @@ declare_clippy_lint! {
     /// code.
     ///
     /// ### Example
-    /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
-    /// * `0x2345 & 0xF000 >> 12` equals 5, while `(0x2345 & 0xF000) >> 12` equals 2
+    /// `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
     #[clippy::version = "pre 1.29.0"]
     pub PRECEDENCE,
     complexity,
     "operations where precedence may be unclear"
 }
 
-declare_lint_pass!(Precedence => [PRECEDENCE]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for bit shifting operations combined with bit masking/combining operators
+    /// and suggest using parentheses.
+    ///
+    /// ### Why restrict this?
+    /// Not everyone knows the precedence of those operators by
+    /// heart, so expressions like these may trip others trying to reason about the
+    /// code.
+    ///
+    /// ### Example
+    /// `0x2345 & 0xF000 >> 12` equals 5, while `(0x2345 & 0xF000) >> 12` equals 2
+    #[clippy::version = "1.86.0"]
+    pub PRECEDENCE_BITS,
+    restriction,
+    "operations mixing bit shifting with bit combining/masking"
+}
+
+declare_lint_pass!(Precedence => [PRECEDENCE, PRECEDENCE_BITS]);
 
 impl EarlyLintPass for Precedence {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
@@ -38,10 +52,10 @@ impl EarlyLintPass for Precedence {
         }
 
         if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.kind {
-            let span_sugg = |expr: &Expr, sugg, appl| {
+            let span_sugg = |lint: &'static Lint, expr: &Expr, sugg, appl| {
                 span_lint_and_sugg(
                     cx,
-                    PRECEDENCE,
+                    lint,
                     expr.span,
                     "operator precedence might not be obvious",
                     "consider parenthesizing your expression",
@@ -57,37 +71,41 @@ impl EarlyLintPass for Precedence {
             match (op, get_bin_opt(left), get_bin_opt(right)) {
                 (
                     BitAnd | BitOr | BitXor,
-                    Some(Shl | Shr | Add | Div | Mul | Rem | Sub),
-                    Some(Shl | Shr | Add | Div | Mul | Rem | Sub),
+                    Some(left_op @ (Shl | Shr | Add | Div | Mul | Rem | Sub)),
+                    Some(right_op @ (Shl | Shr | Add | Div | Mul | Rem | Sub)),
                 )
-                | (Shl | Shr, Some(Add | Div | Mul | Rem | Sub), Some(Add | Div | Mul | Rem | Sub)) => {
+                | (
+                    Shl | Shr,
+                    Some(left_op @ (Add | Div | Mul | Rem | Sub)),
+                    Some(right_op @ (Add | Div | Mul | Rem | Sub)),
+                ) => {
                     let sugg = format!(
                         "({}) {} ({})",
                         snippet_with_applicability(cx, left.span, "..", &mut applicability),
                         op.as_str(),
                         snippet_with_applicability(cx, right.span, "..", &mut applicability)
                     );
-                    span_sugg(expr, sugg, applicability);
+                    span_sugg(lint_for(&[op, left_op, right_op]), expr, sugg, applicability);
                 },
-                (BitAnd | BitOr | BitXor, Some(Shl | Shr | Add | Div | Mul | Rem | Sub), _)
-                | (Shl | Shr, Some(Add | Div | Mul | Rem | Sub), _) => {
+                (BitAnd | BitOr | BitXor, Some(side_op @ (Shl | Shr | Add | Div | Mul | Rem | Sub)), _)
+                | (Shl | Shr, Some(side_op @ (Add | Div | Mul | Rem | Sub)), _) => {
                     let sugg = format!(
                         "({}) {} {}",
                         snippet_with_applicability(cx, left.span, "..", &mut applicability),
                         op.as_str(),
                         snippet_with_applicability(cx, right.span, "..", &mut applicability)
                     );
-                    span_sugg(expr, sugg, applicability);
+                    span_sugg(lint_for(&[op, side_op]), expr, sugg, applicability);
                 },
-                (BitAnd | BitOr | BitXor, _, Some(Shl | Shr | Add | Div | Mul | Rem | Sub))
-                | (Shl | Shr, _, Some(Add | Div | Mul | Rem | Sub)) => {
+                (BitAnd | BitOr | BitXor, _, Some(side_op @ (Shl | Shr | Add | Div | Mul | Rem | Sub)))
+                | (Shl | Shr, _, Some(side_op @ (Add | Div | Mul | Rem | Sub))) => {
                     let sugg = format!(
                         "{} {} ({})",
                         snippet_with_applicability(cx, left.span, "..", &mut applicability),
                         op.as_str(),
                         snippet_with_applicability(cx, right.span, "..", &mut applicability)
                     );
-                    span_sugg(expr, sugg, applicability);
+                    span_sugg(lint_for(&[op, side_op]), expr, sugg, applicability);
                 },
                 _ => (),
             }
@@ -106,3 +124,11 @@ fn get_bin_opt(expr: &Expr) -> Option<BinOpKind> {
 fn is_bit_op(op: BinOpKind) -> bool {
     matches!(op, BitXor | BitAnd | BitOr | Shl | Shr)
 }
+
+fn lint_for(ops: &[BinOpKind]) -> &'static Lint {
+    if ops.iter().all(|op| is_bit_op(*op)) {
+        PRECEDENCE_BITS
+    } else {
+        PRECEDENCE
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 506adf0f2cc..0b67594a9b1 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -1,5 +1,6 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
 use clippy_utils::source::SpanRangeExt;
+use clippy_utils::sugg::Sugg;
 use clippy_utils::visitors::contains_unsafe_block;
 use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, std_or_core};
 use hir::LifetimeName;
@@ -250,15 +251,24 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::Binary(ref op, l, r) = expr.kind {
-            if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(cx, l) || is_null_path(cx, r)) {
-                span_lint(
-                    cx,
-                    CMP_NULL,
-                    expr.span,
-                    "comparing with null is better expressed by the `.is_null()` method",
-                );
-            }
+        if let ExprKind::Binary(op, l, r) = expr.kind
+            && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne)
+        {
+            let non_null_path_snippet = match (is_null_path(cx, l), is_null_path(cx, r)) {
+                (true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(),
+                (false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(),
+                _ => return,
+            };
+
+            span_lint_and_sugg(
+                cx,
+                CMP_NULL,
+                expr.span,
+                "comparing with null is better expressed by the `.is_null()` method",
+                "try",
+                format!("{non_null_path_snippet}.is_null()"),
+                Applicability::MachineApplicable,
+            );
         } else {
             check_invalid_ptr_usage(cx, expr);
         }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index b9e0106fc86..fb1bc494bd9 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -349,10 +349,14 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
             local_use_locs: _,
             local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
         },
-    )) = visit_local_usage(&[cloned, clone], mir, mir::Location {
-        block: bb,
-        statement_index: mir.basic_blocks[bb].statements.len(),
-    })
+    )) = visit_local_usage(
+        &[cloned, clone],
+        mir,
+        mir::Location {
+            block: bb,
+            statement_index: mir.basic_blocks[bb].statements.len(),
+        },
+    )
     .map(|mut vec| (vec.remove(0), vec.remove(0)))
     {
         CloneUsage {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs
index 3476f56cf33..a1b5a3aff32 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_else.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs
@@ -1,8 +1,12 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{indent_of, reindent_multiline, snippet};
 use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind};
 use rustc_ast::visit::{Visitor, walk_expr};
+use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -75,13 +79,27 @@ impl EarlyLintPass for RedundantElse {
                 _ => break,
             }
         }
-        span_lint_and_help(
+
+        let mut app = Applicability::MachineApplicable;
+        if let ExprKind::Block(block, _) = &els.kind {
+            for stmt in &block.stmts {
+                // If the `else` block contains a local binding or a macro invocation, Clippy shouldn't auto-fix it
+                if matches!(&stmt.kind, StmtKind::Let(_) | StmtKind::MacCall(_)) {
+                    app = Applicability::Unspecified;
+                    break;
+                }
+            }
+        }
+
+        // FIXME: The indentation of the suggestion would be the same as the one of the macro invocation in this implementation, see https://github.com/rust-lang/rust-clippy/pull/13936#issuecomment-2569548202
+        span_lint_and_sugg(
             cx,
             REDUNDANT_ELSE,
-            els.span,
+            els.span.with_lo(then.span.hi()),
             "redundant else block",
-            None,
             "remove the `else` block and move the contents out",
+            make_sugg(cx, els.span, "..", Some(expr.span)).to_string(),
+            app,
         );
     }
 }
@@ -136,3 +154,23 @@ impl BreakVisitor {
         self.check(stmt, Self::visit_stmt)
     }
 }
+
+// Extract the inner contents of an `else` block str
+// e.g. `{ foo(); bar(); }` -> `foo(); bar();`
+fn extract_else_block(mut block: &str) -> String {
+    block = block.strip_prefix("{").unwrap_or(block);
+    block = block.strip_suffix("}").unwrap_or(block);
+    block.trim_end().to_string()
+}
+
+fn make_sugg<'a>(
+    cx: &EarlyContext<'_>,
+    els_span: Span,
+    default: &'a str,
+    indent_relative_to: Option<Span>,
+) -> Cow<'a, str> {
+    let extracted = extract_else_block(&snippet(cx, els_span, default));
+    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
+
+    reindent_multiline(extracted.into(), false, indent)
+}
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 8d31641d483..29914d4379f 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -62,10 +62,13 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
                 && let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
             {
                 if !map.contains_key(res) {
-                    map.insert(*res, ExistingName {
-                        impl_methods: BTreeMap::new(),
-                        trait_methods: BTreeMap::new(),
-                    });
+                    map.insert(
+                        *res,
+                        ExistingName {
+                            impl_methods: BTreeMap::new(),
+                            trait_methods: BTreeMap::new(),
+                        },
+                    );
                 }
                 let existing_name = map.get_mut(res).unwrap();
 
diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
index f72ff10dd43..b22c638fc36 100644
--- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
+++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
@@ -63,8 +63,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
-    const METHODS: [&str; 11] = [
-        "write_bytes",
+    const METHODS: [&str; 10] = [
         "copy_to",
         "copy_from",
         "copy_to_nonoverlapping",
@@ -79,7 +78,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
 
     if let ExprKind::Call(func, [.., count]) = expr.kind
         // Find calls to ptr::{copy, copy_nonoverlapping}
-        // and ptr::{swap_nonoverlapping, write_bytes},
+        // and ptr::swap_nonoverlapping,
         && let ExprKind::Path(ref func_qpath) = func.kind
         && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
         && matches!(cx.tcx.get_diagnostic_name(def_id), Some(
@@ -88,7 +87,6 @@ fn get_pointee_ty_and_count_expr<'tcx>(
             | sym::ptr_slice_from_raw_parts
             | sym::ptr_slice_from_raw_parts_mut
             | sym::ptr_swap_nonoverlapping
-            | sym::ptr_write_bytes
             | sym::slice_from_raw_parts
             | sym::slice_from_raw_parts_mut
         ))
@@ -99,7 +97,7 @@ fn get_pointee_ty_and_count_expr<'tcx>(
         return Some((pointee_ty, count));
     }
     if let ExprKind::MethodCall(method_path, ptr_self, [.., count], _) = expr.kind
-        // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
+        // Find calls to copy_{from,to}{,_nonoverlapping}
         && let method_ident = method_path.ident.as_str()
         && METHODS.iter().any(|m| *m == method_ident)
 
@@ -121,6 +119,8 @@ impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
              instead of a count of elements of `T`";
 
         if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr)
+            // Using a number of bytes for a byte type isn't suspicious
+            && pointee_ty != cx.tcx.types.u8
             // Find calls to functions with an element count parameter and get
             // the pointee type and count parameter expression
 
diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
index 569812d8106..9993e6ae18b 100644
--- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
@@ -55,13 +55,11 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
                     if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind
                         && let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id)
                         && let Some(to_digits_def_id) = to_digits_call_res.opt_def_id()
-                        && match_def_path(cx, to_digits_def_id, &[
-                            "core",
-                            "char",
-                            "methods",
-                            "<impl char>",
-                            "to_digit",
-                        ])
+                        && match_def_path(
+                            cx,
+                            to_digits_def_id,
+                            &["core", "char", "methods", "<impl char>", "to_digit"],
+                        )
                     {
                         Some((false, char_arg, radix_arg))
                     } else {
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 391c36df492..579cbf447a2 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -386,22 +386,30 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 
         let is_exported = cx.effective_visibilities.is_exported(def_id);
 
-        self.check_fn_decl(cx, decl, CheckTyContext {
-            is_in_trait_impl,
-            in_body: matches!(fn_kind, FnKind::Closure),
-            is_exported,
-            ..CheckTyContext::default()
-        });
+        self.check_fn_decl(
+            cx,
+            decl,
+            CheckTyContext {
+                is_in_trait_impl,
+                in_body: matches!(fn_kind, FnKind::Closure),
+                is_exported,
+                ..CheckTyContext::default()
+            },
+        );
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
 
         match item.kind {
-            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(cx, ty, CheckTyContext {
-                is_exported,
-                ..CheckTyContext::default()
-            }),
+            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(
+                cx,
+                ty,
+                CheckTyContext {
+                    is_exported,
+                    ..CheckTyContext::default()
+                },
+            ),
             // functions, enums, structs, impls and traits are covered
             _ => (),
         }
@@ -419,10 +427,14 @@ impl<'tcx> LateLintPass<'tcx> for Types {
                     false
                 };
 
-                self.check_ty(cx, ty, CheckTyContext {
-                    is_in_trait_impl,
-                    ..CheckTyContext::default()
-                });
+                self.check_ty(
+                    cx,
+                    ty,
+                    CheckTyContext {
+                        is_in_trait_impl,
+                        ..CheckTyContext::default()
+                    },
+                );
             },
             // Methods are covered by check_fn.
             // Type aliases are ignored because oftentimes it's impossible to
@@ -438,10 +450,14 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 
         let is_exported = cx.effective_visibilities.is_exported(field.def_id);
 
-        self.check_ty(cx, field.ty, CheckTyContext {
-            is_exported,
-            ..CheckTyContext::default()
-        });
+        self.check_ty(
+            cx,
+            field.ty,
+            CheckTyContext {
+                is_exported,
+                ..CheckTyContext::default()
+            },
+        );
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) {
@@ -469,10 +485,14 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) {
         if let Some(ty) = local.ty {
-            self.check_ty(cx, ty, CheckTyContext {
-                in_body: true,
-                ..CheckTyContext::default()
-            });
+            self.check_ty(
+                cx,
+                ty,
+                CheckTyContext {
+                    in_body: true,
+                    ..CheckTyContext::default()
+                },
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 3fc08e8192d..207f2ef4563 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -257,10 +257,13 @@ fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>,
             }
             if matches!(
                 ty.kind,
-                TyKind::Path(QPath::Resolved(_, hir::Path {
-                    res: Res::SelfTyAlias { .. },
-                    ..
-                },))
+                TyKind::Path(QPath::Resolved(
+                    _,
+                    hir::Path {
+                        res: Res::SelfTyAlias { .. },
+                        ..
+                    },
+                ))
             ) {
                 return true;
             }
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs b/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs
index efbc536dcb4..e5267620c4f 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs
@@ -37,7 +37,7 @@ declare_clippy_lint! {
 
 #[derive(Default)]
 pub struct UnnecessarySemicolon {
-    last_statements: Vec<HirId>,
+    last_statements: Vec<(HirId, bool)>,
 }
 
 impl_lint_pass!(UnnecessarySemicolon => [UNNECESSARY_SEMICOLON]);
@@ -45,27 +45,25 @@ impl_lint_pass!(UnnecessarySemicolon => [UNNECESSARY_SEMICOLON]);
 impl UnnecessarySemicolon {
     /// Enter or leave a block, remembering the last statement of the block.
     fn handle_block(&mut self, cx: &LateContext<'_>, block: &Block<'_>, enter: bool) {
-        // Up to edition 2021, removing the semicolon of the last statement of a block
-        // may result in the scrutinee temporary values to live longer than the block
-        // variables. To avoid this problem, we do not lint the last statement of an
-        // expressionless block.
-        if cx.tcx.sess.edition() <= Edition2021
-            && block.expr.is_none()
+        // The last statement of an expressionless block deserves a special treatment.
+        if block.expr.is_none()
             && let Some(last_stmt) = block.stmts.last()
         {
             if enter {
-                self.last_statements.push(last_stmt.hir_id);
+                let block_ty = cx.typeck_results().node_type(block.hir_id);
+                self.last_statements.push((last_stmt.hir_id, block_ty.is_unit()));
             } else {
                 self.last_statements.pop();
             }
         }
     }
 
-    /// Checks if `stmt` is the last statement in an expressionless block for edition ≤ 2021.
-    fn is_last_in_block(&self, stmt: &Stmt<'_>) -> bool {
+    /// Checks if `stmt` is the last statement in an expressionless block. In this case,
+    /// return `Some` with a boolean which is `true` if the block type is `()`.
+    fn is_last_in_block(&self, stmt: &Stmt<'_>) -> Option<bool> {
         self.last_statements
             .last()
-            .is_some_and(|last_stmt_id| last_stmt_id == &stmt.hir_id)
+            .and_then(|&(stmt_id, is_unit)| (stmt_id == stmt.hir_id).then_some(is_unit))
     }
 }
 
@@ -90,8 +88,22 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessarySemicolon {
             )
             && cx.typeck_results().expr_ty(expr) == cx.tcx.types.unit
         {
-            if self.is_last_in_block(stmt) && leaks_droppable_temporary_with_limited_lifetime(cx, expr) {
-                return;
+            if let Some(block_is_unit) = self.is_last_in_block(stmt) {
+                if cx.tcx.sess.edition() <= Edition2021 && leaks_droppable_temporary_with_limited_lifetime(cx, expr) {
+                    // The expression contains temporaries with limited lifetimes in edition lower than 2024. Those may
+                    // survive until after the end of the current scope instead of until the end of the statement, so do
+                    // not lint this situation.
+                    return;
+                }
+
+                if !block_is_unit {
+                    // Although the expression returns `()`, the block doesn't. This may happen if the expression
+                    // returns early in all code paths, such as a `return value` in the condition of an `if` statement,
+                    // in which case the block type would be `!`. Do not lint in this case, as the statement would
+                    // become the block expression; the block type would become `()` and this may not type correctly
+                    // if the expected type for the block is not `()`.
+                    return;
+                }
             }
 
             let semi_span = expr.span.shrink_to_hi().to(stmt.span.shrink_to_hi());
diff --git a/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs b/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs
index 40ba70d451d..a74eab8b6ae 100644
--- a/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs
@@ -32,7 +32,7 @@ declare_clippy_lint! {
     ///     None => 0,
     /// };
     /// ```
-    #[clippy::version = "1.83.0"]
+    #[clippy::version = "1.86.0"]
     pub UNNEEDED_STRUCT_PATTERN,
     style,
     "using struct pattern to match against unit variant"
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 31ae002e47d..11c14c14777 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -522,7 +522,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
 
             let replacement = match (format_string_is_raw, replace_raw) {
                 (false, false) => Some(replacement),
-                (false, true) => Some(replacement.replace('"', "\\\"").replace('\\', "\\\\")),
+                (false, true) => Some(replacement.replace('\\', "\\\\").replace('"', "\\\"")),
                 (true, false) => match conservative_unescape(&replacement) {
                     Ok(unescaped) => Some(unescaped),
                     Err(UnescapeErr::Lint) => None,
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
index 251e3dfe41b..41f3b1cbd50 100644
--- a/src/tools/clippy/clippy_utils/README.md
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2025-01-28
+nightly-2025-02-06
 ```
 <!-- end autogenerated nightly -->
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 798f4575c2e..ab5f97199ce 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -662,12 +662,12 @@ pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool {
         && eq_ext(&l.ext, &r.ext)
 }
 
+#[expect(clippy::ref_option, reason = "This is the type how it is stored in the AST")]
 pub fn eq_opt_fn_contract(l: &Option<P<FnContract>>, r: &Option<P<FnContract>>) -> bool {
     match (l, r) {
         (Some(l), Some(r)) => {
-            eq_expr_opt(l.requires.as_ref(), r.requires.as_ref())
-            && eq_expr_opt(l.ensures.as_ref(), r.ensures.as_ref())
-        }
+            eq_expr_opt(l.requires.as_ref(), r.requires.as_ref()) && eq_expr_opt(l.ensures.as_ref(), r.ensures.as_ref())
+        },
         (None, None) => true,
         (Some(_), None) | (None, Some(_)) => false,
     }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 5a5227af907..337684b68f8 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -341,6 +341,15 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
     matches!(pat.kind, PatKind::Wild)
 }
 
+// Checks if arm has the form `None => None`
+pub fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
+    matches!(
+        arm.pat.kind,
+        PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), .. })
+            if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone)
+    )
+}
+
 /// Checks if the given `QPath` belongs to a type alias.
 pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
     match *qpath {
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
index ccbbccd0dbf..85250f81dc4 100644
--- a/src/tools/clippy/clippy_utils/src/mir/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -112,10 +112,14 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool {
 
 /// Convenience wrapper around `visit_local_usage`.
 pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option<bool> {
-    visit_local_usage(&[local], mir, Location {
-        block: START_BLOCK,
-        statement_index: 0,
-    })
+    visit_local_usage(
+        &[local],
+        mir,
+        Location {
+            block: START_BLOCK,
+            statement_index: 0,
+        },
+    )
     .map(|mut vec| {
         let LocalUsage { local_use_locs, .. } = vec.remove(0);
         let mut locations = local_use_locs
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index d73cb7e3561..24f73b9df26 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -1,4 +1,5 @@
 use rustc_ast::attr::AttributeExt;
+
 use rustc_attr_parsing::{RustcVersion, parse_version};
 use rustc_session::Session;
 use rustc_span::{Symbol, sym};
@@ -18,12 +19,14 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,84,0 { CONST_OPTION_AS_SLICE }
     1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP }
     1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
     1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION }
     1,80,0 { BOX_INTO_ITER, LAZY_CELL }
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
+    1,75,0 { OPTION_AS_SLICE }
     1,74,0 { REPR_RUST }
     1,73,0 { MANUAL_DIV_CEIL }
     1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
@@ -40,7 +43,7 @@ msrv_aliases! {
     1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
     1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
     1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
-    1,50,0 { BOOL_THEN, CLAMP }
+    1,50,0 { BOOL_THEN, CLAMP, SLICE_FILL }
     1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN, SATURATING_SUB_CONST }
     1,46,0 { CONST_IF_MATCH }
     1,45,0 { STR_STRIP_PREFIX }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 5a3a3d0cedc..c7890f33f27 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -179,7 +179,10 @@ fn check_rvalue<'tcx>(
                 ))
             }
         },
-        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks | NullOp::ContractChecks, _)
+        Rvalue::NullaryOp(
+            NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks | NullOp::ContractChecks,
+            _,
+        )
         | Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 2700ef139e6..c6a038f7e0c 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -727,12 +727,15 @@ pub fn str_literal_to_char_literal(
             &snip[1..(snip.len() - 1)]
         };
 
-        let hint = format!("'{}'", match ch {
-            "'" => "\\'",
-            r"\" => "\\\\",
-            "\\\"" => "\"", // no need to escape `"` in `'"'`
-            _ => ch,
-        });
+        let hint = format!(
+            "'{}'",
+            match ch {
+                "'" => "\\'",
+                r"\" => "\\\\",
+                "\\\"" => "\"", // no need to escape `"` in `'"'`
+                _ => ch,
+            }
+        );
 
         Some(hint)
     } else {
diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs
index 1588ee452da..421b25a77fe 100644
--- a/src/tools/clippy/clippy_utils/src/str_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/str_utils.rs
@@ -370,11 +370,9 @@ mod test {
         assert_eq!(camel_case_split("AbcDef"), vec!["Abc", "Def"]);
         assert_eq!(camel_case_split("Abc"), vec!["Abc"]);
         assert_eq!(camel_case_split("abcDef"), vec!["abc", "Def"]);
-        assert_eq!(camel_case_split("\u{f6}\u{f6}AabABcd"), vec![
-            "\u{f6}\u{f6}",
-            "Aab",
-            "A",
-            "Bcd"
-        ]);
+        assert_eq!(
+            camel_case_split("\u{f6}\u{f6}AabABcd"),
+            vec!["\u{f6}\u{f6}", "Aab", "A", "Bcd"]
+        );
     }
 }
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index af243f94274..83c3d7aba02 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -2,6 +2,7 @@ use clap::{Parser, Subcommand, ValueEnum};
 use std::num::NonZero;
 use std::path::PathBuf;
 
+#[allow(clippy::struct_excessive_bools)]
 #[derive(Parser, Clone, Debug)]
 #[command(args_conflicts_with_subcommands = true)]
 pub(crate) struct LintcheckConfig {
@@ -11,6 +12,9 @@ pub(crate) struct LintcheckConfig {
         short = 'j',
         value_name = "N",
         default_value_t = 0,
+        default_value_if("perf", "true", Some("1")), // Limit jobs to 1 when benchmarking
+        conflicts_with("perf"),
+        required = false,
         hide_default_value = true
     )]
     pub max_jobs: usize,
@@ -46,6 +50,11 @@ pub(crate) struct LintcheckConfig {
     /// Run clippy on the dependencies of crates specified in crates-toml
     #[clap(long, conflicts_with("max_jobs"))]
     pub recursive: bool,
+    /// Also produce a `perf.data` file, implies --jobs=1,
+    /// the `perf.data` file can be found at
+    /// `target/lintcheck/sources/<package>-<version>/perf.data`
+    #[clap(long)]
+    pub perf: bool,
     #[command(subcommand)]
     pub subcommand: Option<Commands>,
 }
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index e88d9f427be..8d0d41ab945 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -116,7 +116,25 @@ impl Crate {
 
         clippy_args.extend(lint_levels_args.iter().map(String::as_str));
 
-        let mut cmd = Command::new("cargo");
+        let mut cmd;
+
+        if config.perf {
+            cmd = Command::new("perf");
+            cmd.args(&[
+                "record",
+                "-e",
+                "instructions", // Only count instructions
+                "-g",           // Enable call-graph, useful for flamegraphs and produces richer reports
+                "--quiet",      // Do not tamper with lintcheck's normal output
+                "-o",
+                "perf.data",
+                "--",
+                "cargo",
+            ]);
+        } else {
+            cmd = Command::new("cargo");
+        }
+
         cmd.arg(if config.fix { "fix" } else { "check" })
             .arg("--quiet")
             .current_dir(&self.path)
@@ -234,12 +252,22 @@ fn normalize_diag(
 }
 
 /// Builds clippy inside the repo to make sure we have a clippy executable we can use.
-fn build_clippy() -> String {
-    let output = Command::new("cargo")
-        .args(["run", "--bin=clippy-driver", "--", "--version"])
-        .stderr(Stdio::inherit())
-        .output()
-        .unwrap();
+fn build_clippy(release_build: bool) -> String {
+    let mut build_cmd = Command::new("cargo");
+    build_cmd.args([
+        "run",
+        "--bin=clippy-driver",
+        if release_build { "-r" } else { "" },
+        "--",
+        "--version",
+    ]);
+
+    if release_build {
+        build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
+    }
+
+    let output = build_cmd.stderr(Stdio::inherit()).output().unwrap();
+
     if !output.status.success() {
         eprintln!("Error: Failed to compile Clippy!");
         std::process::exit(1);
@@ -270,13 +298,18 @@ fn main() {
 
 #[allow(clippy::too_many_lines)]
 fn lintcheck(config: LintcheckConfig) {
-    let clippy_ver = build_clippy();
-    let clippy_driver_path = fs::canonicalize(format!("target/debug/clippy-driver{EXE_SUFFIX}")).unwrap();
+    let clippy_ver = build_clippy(config.perf);
+    let clippy_driver_path = fs::canonicalize(format!(
+        "target/{}/clippy-driver{EXE_SUFFIX}",
+        if config.perf { "release" } else { "debug" }
+    ))
+    .unwrap();
 
     // assert that clippy is found
     assert!(
         clippy_driver_path.is_file(),
-        "target/debug/clippy-driver binary not found! {}",
+        "target/{}/clippy-driver binary not found! {}",
+        if config.perf { "release" } else { "debug" },
         clippy_driver_path.display()
     );
 
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index c15d1fe6cd3..ab760287e83 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2025-01-28"
+channel = "nightly-2025-02-06"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/tools/clippy/tests/ui/cmp_null.fixed b/src/tools/clippy/tests/ui/cmp_null.fixed
new file mode 100644
index 00000000000..e5ab765bc86
--- /dev/null
+++ b/src/tools/clippy/tests/ui/cmp_null.fixed
@@ -0,0 +1,32 @@
+#![warn(clippy::cmp_null)]
+#![allow(unused_mut)]
+
+use std::ptr;
+
+fn main() {
+    let x = 0;
+    let p: *const usize = &x;
+    if p.is_null() {
+        //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+        //~| NOTE: `-D clippy::cmp-null` implied by `-D warnings`
+        println!("This is surprising!");
+    }
+    if p.is_null() {
+        //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+        println!("This is surprising!");
+    }
+
+    let mut y = 0;
+    let mut m: *mut usize = &mut y;
+    if m.is_null() {
+        //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+        println!("This is surprising, too!");
+    }
+    if m.is_null() {
+        //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+        println!("This is surprising, too!");
+    }
+
+    let _ = (x as *const ()).is_null();
+    //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+}
diff --git a/src/tools/clippy/tests/ui/cmp_null.rs b/src/tools/clippy/tests/ui/cmp_null.rs
index ef1d93940aa..257f7ba2662 100644
--- a/src/tools/clippy/tests/ui/cmp_null.rs
+++ b/src/tools/clippy/tests/ui/cmp_null.rs
@@ -11,10 +11,22 @@ fn main() {
         //~| NOTE: `-D clippy::cmp-null` implied by `-D warnings`
         println!("This is surprising!");
     }
+    if ptr::null() == p {
+        //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+        println!("This is surprising!");
+    }
+
     let mut y = 0;
     let mut m: *mut usize = &mut y;
     if m == ptr::null_mut() {
         //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
         println!("This is surprising, too!");
     }
+    if ptr::null_mut() == m {
+        //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
+        println!("This is surprising, too!");
+    }
+
+    let _ = x as *const () == ptr::null();
+    //~^ ERROR: comparing with null is better expressed by the `.is_null()` method
 }
diff --git a/src/tools/clippy/tests/ui/cmp_null.stderr b/src/tools/clippy/tests/ui/cmp_null.stderr
index 8362904a5ba..f3b35f3afba 100644
--- a/src/tools/clippy/tests/ui/cmp_null.stderr
+++ b/src/tools/clippy/tests/ui/cmp_null.stderr
@@ -2,16 +2,34 @@ error: comparing with null is better expressed by the `.is_null()` method
   --> tests/ui/cmp_null.rs:9:8
    |
 LL |     if p == ptr::null() {
-   |        ^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^ help: try: `p.is_null()`
    |
    = note: `-D clippy::cmp-null` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::cmp_null)]`
 
 error: comparing with null is better expressed by the `.is_null()` method
-  --> tests/ui/cmp_null.rs:16:8
+  --> tests/ui/cmp_null.rs:14:8
+   |
+LL |     if ptr::null() == p {
+   |        ^^^^^^^^^^^^^^^^ help: try: `p.is_null()`
+
+error: comparing with null is better expressed by the `.is_null()` method
+  --> tests/ui/cmp_null.rs:21:8
    |
 LL |     if m == ptr::null_mut() {
-   |        ^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^^^^^ help: try: `m.is_null()`
+
+error: comparing with null is better expressed by the `.is_null()` method
+  --> tests/ui/cmp_null.rs:25:8
+   |
+LL |     if ptr::null_mut() == m {
+   |        ^^^^^^^^^^^^^^^^^^^^ help: try: `m.is_null()`
+
+error: comparing with null is better expressed by the `.is_null()` method
+  --> tests/ui/cmp_null.rs:30:13
+   |
+LL |     let _ = x as *const () == ptr::null();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(x as *const ()).is_null()`
 
-error: aborting due to 2 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index f1baf28200e..abccc30ef87 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -116,6 +116,11 @@ fn test_redundant_closures_containing_method_calls() {
         t.iter().filter(|x| x.trait_foo_ref());
         t.iter().map(|x| x.trait_foo_ref());
     }
+
+    fn issue14096() {
+        let x = Some("42");
+        let _ = x.map(str::parse::<i16>);
+    }
 }
 
 struct Thunk<T>(Box<dyn FnMut() -> T>);
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index c52a51880bf..9bcee4eba34 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -116,6 +116,11 @@ fn test_redundant_closures_containing_method_calls() {
         t.iter().filter(|x| x.trait_foo_ref());
         t.iter().map(|x| x.trait_foo_ref());
     }
+
+    fn issue14096() {
+        let x = Some("42");
+        let _ = x.map(|x| x.parse::<i16>());
+    }
 }
 
 struct Thunk<T>(Box<dyn FnMut() -> T>);
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index 1731a4377f5..ac58e87bc5e 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -71,142 +71,148 @@ LL |     let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_as
    |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
 
 error: redundant closure
-  --> tests/ui/eta.rs:169:22
+  --> tests/ui/eta.rs:122:23
+   |
+LL |         let _ = x.map(|x| x.parse::<i16>());
+   |                       ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `str::parse::<i16>`
+
+error: redundant closure
+  --> tests/ui/eta.rs:174:22
    |
 LL |     requires_fn_once(|| x());
    |                      ^^^^^^ help: replace the closure with the function itself: `x`
 
 error: redundant closure
-  --> tests/ui/eta.rs:176:27
+  --> tests/ui/eta.rs:181:27
    |
 LL |     let a = Some(1u8).map(|a| foo_ptr(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
 
 error: redundant closure
-  --> tests/ui/eta.rs:181:27
+  --> tests/ui/eta.rs:186:27
    |
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
 
 error: redundant closure
-  --> tests/ui/eta.rs:213:28
+  --> tests/ui/eta.rs:218:28
    |
 LL |     x.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> tests/ui/eta.rs:214:28
+  --> tests/ui/eta.rs:219:28
    |
 LL |     y.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> tests/ui/eta.rs:215:28
+  --> tests/ui/eta.rs:220:28
    |
 LL |     z.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
 
 error: redundant closure
-  --> tests/ui/eta.rs:222:21
+  --> tests/ui/eta.rs:227:21
    |
 LL |         Some(1).map(|n| closure(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
 
 error: redundant closure
-  --> tests/ui/eta.rs:226:21
+  --> tests/ui/eta.rs:231:21
    |
 LL |         Some(1).map(|n| in_loop(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
 
 error: redundant closure
-  --> tests/ui/eta.rs:319:18
+  --> tests/ui/eta.rs:324:18
    |
 LL |     takes_fn_mut(|| f());
    |                  ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:322:19
+  --> tests/ui/eta.rs:327:19
    |
 LL |     takes_fn_once(|| f());
    |                   ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:326:26
+  --> tests/ui/eta.rs:331:26
    |
 LL |     move || takes_fn_mut(|| f_used_once())
    |                          ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
 
 error: redundant closure
-  --> tests/ui/eta.rs:338:19
+  --> tests/ui/eta.rs:343:19
    |
 LL |     array_opt.map(|a| a.as_slice());
    |                   ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice`
 
 error: redundant closure
-  --> tests/ui/eta.rs:341:19
+  --> tests/ui/eta.rs:346:19
    |
 LL |     slice_opt.map(|s| s.len());
    |                   ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len`
 
 error: redundant closure
-  --> tests/ui/eta.rs:344:17
+  --> tests/ui/eta.rs:349:17
    |
 LL |     ptr_opt.map(|p| p.is_null());
    |                 ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null`
 
 error: redundant closure
-  --> tests/ui/eta.rs:348:17
+  --> tests/ui/eta.rs:353:17
    |
 LL |     dyn_opt.map(|d| d.method_on_dyn());
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
 
 error: redundant closure
-  --> tests/ui/eta.rs:408:19
+  --> tests/ui/eta.rs:413:19
    |
 LL |     let _ = f(&0, |x, y| f2(x, y));
    |                   ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2`
 
 error: redundant closure
-  --> tests/ui/eta.rs:436:22
+  --> tests/ui/eta.rs:441:22
    |
 LL |             test.map(|t| t.method())
    |                      ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:440:22
+  --> tests/ui/eta.rs:445:22
    |
 LL |             test.map(|t| t.method())
    |                      ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:453:18
+  --> tests/ui/eta.rs:458:18
    |
 LL |         test.map(|t| t.method())
    |                  ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:460:30
+  --> tests/ui/eta.rs:465:30
    |
 LL |                     test.map(|t| t.method())
    |                              ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:479:38
+  --> tests/ui/eta.rs:484:38
    |
 LL |         let x = Box::new(|| None.map(|x| f(x)));
    |                                      ^^^^^^^^ help: replace the closure with the function itself: `&f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:483:38
+  --> tests/ui/eta.rs:488:38
    |
 LL |         let x = Box::new(|| None.map(|x| f(x)));
    |                                      ^^^^^^^^ help: replace the closure with the function itself: `f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:500:35
+  --> tests/ui/eta.rs:505:35
    |
 LL |         let _field = bind.or_else(|| get_default()).unwrap();
    |                                   ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
 
-error: aborting due to 34 previous errors
+error: aborting due to 35 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
index fde40437309..118f0b48895 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
@@ -21,12 +21,15 @@ fn main() {
     let _ = foo().map_err(|()| todo!());
     //~^ ERROR: matching over `()` is more explicit
 
-    println!("{:?}", match foo() {
-        Ok(()) => {},
-        //~^ ERROR: matching over `()` is more explicit
-        Err(()) => {},
-        //~^ ERROR: matching over `()` is more explicit
-    });
+    println!(
+        "{:?}",
+        match foo() {
+            Ok(()) => {},
+            //~^ ERROR: matching over `()` is more explicit
+            Err(()) => {},
+            //~^ ERROR: matching over `()` is more explicit
+        }
+    );
 }
 
 // ignored_unit_patterns in derive macro should be ok
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
index 528844d76e0..92feb9e6c28 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
@@ -21,12 +21,15 @@ fn main() {
     let _ = foo().map_err(|_| todo!());
     //~^ ERROR: matching over `()` is more explicit
 
-    println!("{:?}", match foo() {
-        Ok(_) => {},
-        //~^ ERROR: matching over `()` is more explicit
-        Err(_) => {},
-        //~^ ERROR: matching over `()` is more explicit
-    });
+    println!(
+        "{:?}",
+        match foo() {
+            Ok(_) => {},
+            //~^ ERROR: matching over `()` is more explicit
+            Err(_) => {},
+            //~^ ERROR: matching over `()` is more explicit
+        }
+    );
 }
 
 // ignored_unit_patterns in derive macro should be ok
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
index 54ff4454d6b..00a254e3919 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
@@ -26,31 +26,31 @@ LL |     let _ = foo().map_err(|_| todo!());
    |                            ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:25:12
+  --> tests/ui/ignored_unit_patterns.rs:27:16
    |
-LL |         Ok(_) => {},
-   |            ^ help: use `()` instead of `_`: `()`
+LL |             Ok(_) => {},
+   |                ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:27:13
+  --> tests/ui/ignored_unit_patterns.rs:29:17
    |
-LL |         Err(_) => {},
-   |             ^ help: use `()` instead of `_`: `()`
+LL |             Err(_) => {},
+   |                 ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:38:9
+  --> tests/ui/ignored_unit_patterns.rs:41:9
    |
 LL |     let _ = foo().unwrap();
    |         ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:47:13
+  --> tests/ui/ignored_unit_patterns.rs:50:13
    |
 LL |         (1, _) => unimplemented!(),
    |             ^ help: use `()` instead of `_`: `()`
 
 error: matching over `()` is more explicit
-  --> tests/ui/ignored_unit_patterns.rs:54:13
+  --> tests/ui/ignored_unit_patterns.rs:57:13
    |
 LL |     for (x, _) in v {
    |             ^ help: use `()` instead of `_`: `()`
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
index c917fa7f2d0..2f8640cd3f5 100644
--- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
+++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::manual_memcpy)]
-#![allow(clippy::assigning_clones, clippy::useless_vec, clippy::needless_range_loop)]
+#![allow(
+    clippy::assigning_clones,
+    clippy::useless_vec,
+    clippy::needless_range_loop,
+    clippy::manual_slice_fill
+)]
 
 //@no-rustfix
 const LOOP_OFFSET: usize = 5000;
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
index 803053b2db2..c881e3fac76 100644
--- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
+++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
@@ -1,5 +1,5 @@
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:9:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:14:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -12,7 +12,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::manual_memcpy)]`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:16:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:21:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -21,7 +21,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:22:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:27:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -30,7 +30,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:28:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:33:5
    |
 LL | /     for i in 11..src.len() {
 LL | |
@@ -39,7 +39,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:34:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:39:5
    |
 LL | /     for i in 0..dst.len() {
 LL | |
@@ -48,7 +48,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:48:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:53:5
    |
 LL | /     for i in 10..256 {
 LL | |
@@ -64,7 +64,7 @@ LL +     dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]);
    |
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:61:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:66:5
    |
 LL | /     for i in 10..LOOP_OFFSET {
 LL | |
@@ -73,7 +73,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:75:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:80:5
    |
 LL | /     for i in 0..src_vec.len() {
 LL | |
@@ -82,7 +82,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:105:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:110:5
    |
 LL | /     for i in from..from + src.len() {
 LL | |
@@ -91,7 +91,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:110:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:115:5
    |
 LL | /     for i in from..from + 3 {
 LL | |
@@ -100,7 +100,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:116:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:121:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -109,7 +109,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:122:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:127:5
    |
 LL | /     for i in 0..0 {
 LL | |
@@ -118,7 +118,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:146:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:151:5
    |
 LL | /     for i in 0..4 {
 LL | |
@@ -127,7 +127,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..4]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:152:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:157:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -136,7 +136,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:158:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:163:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -145,7 +145,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:205:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:210:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -154,7 +154,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:211:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:216:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -163,7 +163,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0][1]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:219:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:224:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
diff --git a/src/tools/clippy/tests/ui/manual_option_as_slice.fixed b/src/tools/clippy/tests/ui/manual_option_as_slice.fixed
new file mode 100644
index 00000000000..48337d7654d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_option_as_slice.fixed
@@ -0,0 +1,62 @@
+#![warn(clippy::manual_option_as_slice)]
+#![allow(clippy::redundant_closure, clippy::unwrap_or_default)]
+
+fn check(x: Option<u32>) {
+    _ = x.as_slice();
+
+    _ = x.as_slice();
+
+    _ = x.as_slice();
+    //~^ manual_option_as_slice
+
+    _ = x.as_slice();
+    //~^ manual_option_as_slice
+
+    _ = x.as_slice();
+    //~^ manual_option_as_slice
+
+    _ = x.as_slice();
+    //~^ manual_option_as_slice
+
+    {
+        use std::slice::from_ref;
+        _ = x.as_slice();
+        //~^ manual_option_as_slice
+    }
+
+    // possible false positives
+    let y = x.as_ref();
+    _ = match y {
+        // as_ref outside
+        Some(f) => &[f][..],
+        None => &[][..],
+    };
+    _ = match x.as_ref() {
+        Some(f) => std::slice::from_ref(f),
+        None => &[0],
+    };
+    _ = match x.as_ref() {
+        Some(42) => &[23],
+        Some(f) => std::slice::from_ref(f),
+        None => &[],
+    };
+    let b = &[42];
+    _ = if let Some(_f) = x.as_ref() {
+        std::slice::from_ref(b)
+    } else {
+        &[]
+    };
+    _ = x.as_ref().map_or(&[42][..], std::slice::from_ref);
+    _ = x.as_ref().map_or_else(|| &[42][..1], std::slice::from_ref);
+    _ = x.as_ref().map(|f| std::slice::from_ref(f)).unwrap_or_default();
+}
+
+#[clippy::msrv = "1.74"]
+fn check_msrv(x: Option<u32>) {
+    _ = x.as_ref().map_or(&[][..], std::slice::from_ref);
+}
+
+fn main() {
+    check(Some(1));
+    check_msrv(Some(175));
+}
diff --git a/src/tools/clippy/tests/ui/manual_option_as_slice.rs b/src/tools/clippy/tests/ui/manual_option_as_slice.rs
new file mode 100644
index 00000000000..561a8b53401
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_option_as_slice.rs
@@ -0,0 +1,71 @@
+#![warn(clippy::manual_option_as_slice)]
+#![allow(clippy::redundant_closure, clippy::unwrap_or_default)]
+
+fn check(x: Option<u32>) {
+    _ = match x.as_ref() {
+        //~^ manual_option_as_slice
+        Some(f) => std::slice::from_ref(f),
+        None => &[],
+    };
+
+    _ = if let Some(f) = x.as_ref() {
+        //~^ manual_option_as_slice
+        std::slice::from_ref(f)
+    } else {
+        &[]
+    };
+
+    _ = x.as_ref().map_or(&[][..], std::slice::from_ref);
+    //~^ manual_option_as_slice
+
+    _ = x.as_ref().map_or_else(Default::default, std::slice::from_ref);
+    //~^ manual_option_as_slice
+
+    _ = x.as_ref().map(std::slice::from_ref).unwrap_or_default();
+    //~^ manual_option_as_slice
+
+    _ = x.as_ref().map_or_else(|| &[42][..0], std::slice::from_ref);
+    //~^ manual_option_as_slice
+
+    {
+        use std::slice::from_ref;
+        _ = x.as_ref().map_or_else(<&[_]>::default, from_ref);
+        //~^ manual_option_as_slice
+    }
+
+    // possible false positives
+    let y = x.as_ref();
+    _ = match y {
+        // as_ref outside
+        Some(f) => &[f][..],
+        None => &[][..],
+    };
+    _ = match x.as_ref() {
+        Some(f) => std::slice::from_ref(f),
+        None => &[0],
+    };
+    _ = match x.as_ref() {
+        Some(42) => &[23],
+        Some(f) => std::slice::from_ref(f),
+        None => &[],
+    };
+    let b = &[42];
+    _ = if let Some(_f) = x.as_ref() {
+        std::slice::from_ref(b)
+    } else {
+        &[]
+    };
+    _ = x.as_ref().map_or(&[42][..], std::slice::from_ref);
+    _ = x.as_ref().map_or_else(|| &[42][..1], std::slice::from_ref);
+    _ = x.as_ref().map(|f| std::slice::from_ref(f)).unwrap_or_default();
+}
+
+#[clippy::msrv = "1.74"]
+fn check_msrv(x: Option<u32>) {
+    _ = x.as_ref().map_or(&[][..], std::slice::from_ref);
+}
+
+fn main() {
+    check(Some(1));
+    check_msrv(Some(175));
+}
diff --git a/src/tools/clippy/tests/ui/manual_option_as_slice.stderr b/src/tools/clippy/tests/ui/manual_option_as_slice.stderr
new file mode 100644
index 00000000000..569269d3e2b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_option_as_slice.stderr
@@ -0,0 +1,58 @@
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:5:9
+   |
+LL |       _ = match x.as_ref() {
+   |  _________^
+LL | |
+LL | |         Some(f) => std::slice::from_ref(f),
+LL | |         None => &[],
+LL | |     };
+   | |_____^ help: use: `x.as_slice()`
+   |
+   = note: `-D clippy::manual-option-as-slice` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_option_as_slice)]`
+
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:11:9
+   |
+LL |       _ = if let Some(f) = x.as_ref() {
+   |  _________^
+LL | |
+LL | |         std::slice::from_ref(f)
+LL | |     } else {
+LL | |         &[]
+LL | |     };
+   | |_____^ help: use: `x.as_slice()`
+
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:18:9
+   |
+LL |     _ = x.as_ref().map_or(&[][..], std::slice::from_ref);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()`
+
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:21:9
+   |
+LL |     _ = x.as_ref().map_or_else(Default::default, std::slice::from_ref);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()`
+
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:24:9
+   |
+LL |     _ = x.as_ref().map(std::slice::from_ref).unwrap_or_default();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()`
+
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:27:9
+   |
+LL |     _ = x.as_ref().map_or_else(|| &[42][..0], std::slice::from_ref);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()`
+
+error: use `Option::as_slice`
+  --> tests/ui/manual_option_as_slice.rs:32:13
+   |
+LL |         _ = x.as_ref().map_or_else(<&[_]>::default, from_ref);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.as_slice()`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_slice_fill.fixed b/src/tools/clippy/tests/ui/manual_slice_fill.fixed
new file mode 100644
index 00000000000..397a156a2dc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_slice_fill.fixed
@@ -0,0 +1,101 @@
+#![warn(clippy::manual_slice_fill)]
+#![allow(clippy::needless_range_loop)]
+
+macro_rules! assign_element {
+    ($slice:ident, $index:expr) => {
+        $slice[$index] = 0;
+    };
+}
+
+macro_rules! assign_element_2 {
+    ($i:expr) => {
+        $i = 0;
+    };
+}
+
+struct NoClone;
+
+fn num() -> usize {
+    5
+}
+
+fn should_lint() {
+    let mut some_slice = [1, 2, 3, 4, 5];
+
+    some_slice.fill(0);
+
+    let x = 5;
+    some_slice.fill(x);
+
+    some_slice.fill(0);
+
+    // This should trigger `manual_slice_fill`, but the applicability is `MaybeIncorrect` since comments
+    // within the loop might be purely informational.
+    some_slice.fill(0);
+}
+
+fn should_not_lint() {
+    let mut some_slice = [1, 2, 3, 4, 5];
+
+    // Should not lint because we can't determine if the scope of the loop is intended to access all the
+    // elements of the slice.
+    for i in 0..5 {
+        some_slice[i] = 0;
+    }
+
+    // Should not lint, as using a function to assign values to elements might be
+    // intentional. For example, the contents of `num()` could be temporary and subject to change
+    // later.
+    for i in 0..some_slice.len() {
+        some_slice[i] = num();
+    }
+
+    // Should not lint because this loop isn't equivalent to `fill`.
+    for i in 0..some_slice.len() {
+        some_slice[i] = 0;
+        println!("foo");
+    }
+
+    // Should not lint because it may be intentional to use a macro to perform an operation equivalent
+    // to `fill`.
+    for i in 0..some_slice.len() {
+        assign_element!(some_slice, i);
+    }
+
+    let another_slice = [1, 2, 3];
+    // Should not lint because the range is not for `some_slice`.
+    for i in 0..another_slice.len() {
+        some_slice[i] = 0;
+    }
+
+    let mut vec: Vec<Option<NoClone>> = Vec::with_capacity(5);
+    // Should not lint because `NoClone` does not have `Clone` trait.
+    for i in 0..vec.len() {
+        vec[i] = None;
+    }
+
+    // Should not lint, as using a function to assign values to elements might be
+    // intentional. For example, the contents of `num()` could be temporary and subject to change
+    // later.
+    for i in &mut some_slice {
+        *i = num();
+    }
+
+    // Should not lint because this loop isn't equivalent to `fill`.
+    for i in &mut some_slice {
+        *i = 0;
+        println!("foo");
+    }
+
+    // Should not lint because it may be intentional to use a macro to perform an operation equivalent
+    // to `fill`.
+    for i in &mut some_slice {
+        assign_element_2!(*i);
+    }
+
+    let mut vec: Vec<Option<NoClone>> = Vec::with_capacity(5);
+    // Should not lint because `NoClone` does not have `Clone` trait.
+    for i in &mut vec {
+        *i = None;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_slice_fill.rs b/src/tools/clippy/tests/ui/manual_slice_fill.rs
new file mode 100644
index 00000000000..c25127ca613
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_slice_fill.rs
@@ -0,0 +1,110 @@
+#![warn(clippy::manual_slice_fill)]
+#![allow(clippy::needless_range_loop)]
+
+macro_rules! assign_element {
+    ($slice:ident, $index:expr) => {
+        $slice[$index] = 0;
+    };
+}
+
+macro_rules! assign_element_2 {
+    ($i:expr) => {
+        $i = 0;
+    };
+}
+
+struct NoClone;
+
+fn num() -> usize {
+    5
+}
+
+fn should_lint() {
+    let mut some_slice = [1, 2, 3, 4, 5];
+
+    for i in 0..some_slice.len() {
+        some_slice[i] = 0;
+    }
+
+    let x = 5;
+    for i in 0..some_slice.len() {
+        some_slice[i] = x;
+    }
+
+    for i in &mut some_slice {
+        *i = 0;
+    }
+
+    // This should trigger `manual_slice_fill`, but the applicability is `MaybeIncorrect` since comments
+    // within the loop might be purely informational.
+    for i in 0..some_slice.len() {
+        some_slice[i] = 0;
+        // foo
+    }
+}
+
+fn should_not_lint() {
+    let mut some_slice = [1, 2, 3, 4, 5];
+
+    // Should not lint because we can't determine if the scope of the loop is intended to access all the
+    // elements of the slice.
+    for i in 0..5 {
+        some_slice[i] = 0;
+    }
+
+    // Should not lint, as using a function to assign values to elements might be
+    // intentional. For example, the contents of `num()` could be temporary and subject to change
+    // later.
+    for i in 0..some_slice.len() {
+        some_slice[i] = num();
+    }
+
+    // Should not lint because this loop isn't equivalent to `fill`.
+    for i in 0..some_slice.len() {
+        some_slice[i] = 0;
+        println!("foo");
+    }
+
+    // Should not lint because it may be intentional to use a macro to perform an operation equivalent
+    // to `fill`.
+    for i in 0..some_slice.len() {
+        assign_element!(some_slice, i);
+    }
+
+    let another_slice = [1, 2, 3];
+    // Should not lint because the range is not for `some_slice`.
+    for i in 0..another_slice.len() {
+        some_slice[i] = 0;
+    }
+
+    let mut vec: Vec<Option<NoClone>> = Vec::with_capacity(5);
+    // Should not lint because `NoClone` does not have `Clone` trait.
+    for i in 0..vec.len() {
+        vec[i] = None;
+    }
+
+    // Should not lint, as using a function to assign values to elements might be
+    // intentional. For example, the contents of `num()` could be temporary and subject to change
+    // later.
+    for i in &mut some_slice {
+        *i = num();
+    }
+
+    // Should not lint because this loop isn't equivalent to `fill`.
+    for i in &mut some_slice {
+        *i = 0;
+        println!("foo");
+    }
+
+    // Should not lint because it may be intentional to use a macro to perform an operation equivalent
+    // to `fill`.
+    for i in &mut some_slice {
+        assign_element_2!(*i);
+    }
+
+    let mut vec: Vec<Option<NoClone>> = Vec::with_capacity(5);
+    // Should not lint because `NoClone` does not have `Clone` trait.
+    for i in &mut vec {
+        *i = None;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_slice_fill.stderr b/src/tools/clippy/tests/ui/manual_slice_fill.stderr
new file mode 100644
index 00000000000..3aa980f6919
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_slice_fill.stderr
@@ -0,0 +1,38 @@
+error: manually filling a slice
+  --> tests/ui/manual_slice_fill.rs:25:5
+   |
+LL | /     for i in 0..some_slice.len() {
+LL | |         some_slice[i] = 0;
+LL | |     }
+   | |_____^ help: try: `some_slice.fill(0);`
+   |
+   = note: `-D clippy::manual-slice-fill` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_slice_fill)]`
+
+error: manually filling a slice
+  --> tests/ui/manual_slice_fill.rs:30:5
+   |
+LL | /     for i in 0..some_slice.len() {
+LL | |         some_slice[i] = x;
+LL | |     }
+   | |_____^ help: try: `some_slice.fill(x);`
+
+error: manually filling a slice
+  --> tests/ui/manual_slice_fill.rs:34:5
+   |
+LL | /     for i in &mut some_slice {
+LL | |         *i = 0;
+LL | |     }
+   | |_____^ help: try: `some_slice.fill(0);`
+
+error: manually filling a slice
+  --> tests/ui/manual_slice_fill.rs:40:5
+   |
+LL | /     for i in 0..some_slice.len() {
+LL | |         some_slice[i] = 0;
+LL | |         // foo
+LL | |     }
+   | |_____^ help: try: `some_slice.fill(0);`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.rs b/src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.rs
new file mode 100644
index 00000000000..acc54b52816
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.rs
@@ -0,0 +1,15 @@
+//@no-rustfix
+fn issue_12670() {
+    // no auto: type not found
+    #[allow(clippy::match_result_ok)]
+    let _ = if let Some(x) = "1".parse().ok() {
+        x
+    } else {
+        i32::default()
+    };
+    let _ = if let Some(x) = None { x } else { i32::default() };
+    // auto fix with unwrap_or_default
+    let a: Option<i32> = None;
+    let _ = if let Some(x) = a { x } else { i32::default() };
+    let _ = if let Some(x) = Some(99) { x } else { i32::default() };
+}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.stderr
new file mode 100644
index 00000000000..3849d33cf25
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default_unfixable.stderr
@@ -0,0 +1,34 @@
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default_unfixable.rs:5:13
+   |
+LL |       let _ = if let Some(x) = "1".parse().ok() {
+   |  _____________^
+LL | |         x
+LL | |     } else {
+LL | |         i32::default()
+LL | |     };
+   | |_____^ help: ascribe the type i32 and replace your expression with: `"1".parse().ok().unwrap_or_default()`
+   |
+   = note: `-D clippy::manual-unwrap-or-default` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or_default)]`
+
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default_unfixable.rs:10:13
+   |
+LL |     let _ = if let Some(x) = None { x } else { i32::default() };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `None::<i32>.unwrap_or_default()`
+
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default_unfixable.rs:13:13
+   |
+LL |     let _ = if let Some(x) = a { x } else { i32::default() };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.unwrap_or_default()`
+
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default_unfixable.rs:14:13
+   |
+LL |     let _ = if let Some(x) = Some(99) { x } else { i32::default() };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `Some(99).unwrap_or_default()`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_option_take.fixed b/src/tools/clippy/tests/ui/needless_option_take.fixed
new file mode 100644
index 00000000000..6514b67ef7a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_option_take.fixed
@@ -0,0 +1,58 @@
+struct MyStruct;
+
+impl MyStruct {
+    pub fn get_option() -> Option<Self> {
+        todo!()
+    }
+}
+
+fn return_option() -> Option<i32> {
+    todo!()
+}
+
+fn main() {
+    println!("Testing non erroneous option_take_on_temporary");
+    let mut option = Some(1);
+    let _ = Box::new(move || option.take().unwrap());
+
+    println!("Testing non erroneous option_take_on_temporary");
+    let x = Some(3);
+    x.as_ref();
+
+    let x = Some(3);
+    x.as_ref();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    println!("Testing non erroneous option_take_on_temporary");
+    let mut x = Some(3);
+    let y = x.as_mut();
+
+    let mut x = Some(3);
+    let y = x.as_mut();
+    //~^ ERROR: called `Option::take()` on a temporary value
+    let y = x.replace(289);
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let y = Some(3).as_mut();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let y = Option::as_mut(&mut x);
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let x = return_option();
+    let x = return_option();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let x = MyStruct::get_option();
+    let x = MyStruct::get_option();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let mut my_vec = vec![1, 2, 3];
+    my_vec.push(4);
+    let y = my_vec.first();
+    let y = my_vec.first();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let y = my_vec.first();
+    //~^ ERROR: called `Option::take()` on a temporary value
+}
diff --git a/src/tools/clippy/tests/ui/needless_option_take.stderr b/src/tools/clippy/tests/ui/needless_option_take.stderr
index e036bd53170..3fc339ed79e 100644
--- a/src/tools/clippy/tests/ui/needless_option_take.stderr
+++ b/src/tools/clippy/tests/ui/needless_option_take.stderr
@@ -2,7 +2,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:23:5
    |
 LL |     x.as_ref().take();
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^-------
+   |               |
+   |               help: remove
    |
    = note: `as_ref` creates a temporary value, so calling take() has no effect
    = note: `-D clippy::needless-option-take` implied by `-D warnings`
@@ -12,7 +14,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:31:13
    |
 LL |     let y = x.as_mut().take();
-   |             ^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^-------
+   |                       |
+   |                       help: remove
    |
    = note: `as_mut` creates a temporary value, so calling take() has no effect
 
@@ -20,7 +24,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:33:13
    |
 LL |     let y = x.replace(289).take();
-   |             ^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^-------
+   |                           |
+   |                           help: remove
    |
    = note: `replace` creates a temporary value, so calling take() has no effect
 
@@ -28,7 +34,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:36:13
    |
 LL |     let y = Some(3).as_mut().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^-------
+   |                             |
+   |                             help: remove
    |
    = note: `as_mut` creates a temporary value, so calling take() has no effect
 
@@ -36,7 +44,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:39:13
    |
 LL |     let y = Option::as_mut(&mut x).take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^-------
+   |                                   |
+   |                                   help: remove
    |
    = note: `as_mut` creates a temporary value, so calling take() has no effect
 
@@ -44,7 +54,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:43:13
    |
 LL |     let x = return_option().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^-------
+   |                            |
+   |                            help: remove
    |
    = note: `return_option` creates a temporary value, so calling take() has no effect
 
@@ -52,7 +64,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:47:13
    |
 LL |     let x = MyStruct::get_option().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^-------
+   |                                   |
+   |                                   help: remove
    |
    = note: `get_option` creates a temporary value, so calling take() has no effect
 
@@ -60,7 +74,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:53:13
    |
 LL |     let y = my_vec.first().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^-------
+   |                           |
+   |                           help: remove
    |
    = note: `first` creates a temporary value, so calling take() has no effect
 
@@ -68,7 +84,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:56:13
    |
 LL |     let y = my_vec.first().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^-------
+   |                           |
+   |                           help: remove
    |
    = note: `first` creates a temporary value, so calling take() has no effect
 
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.rs b/src/tools/clippy/tests/ui/needless_range_loop.rs
index 3f242195330..75f1896eded 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.rs
+++ b/src/tools/clippy/tests/ui/needless_range_loop.rs
@@ -2,7 +2,8 @@
 #![allow(
     clippy::uninlined_format_args,
     clippy::unnecessary_literal_unwrap,
-    clippy::useless_vec
+    clippy::useless_vec,
+    clippy::manual_slice_fill
 )]
 //@no-rustfix
 static STATIC: [usize; 4] = [0, 1, 8, 16];
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.stderr b/src/tools/clippy/tests/ui/needless_range_loop.stderr
index dc2cf437e02..503d796e5e8 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.stderr
+++ b/src/tools/clippy/tests/ui/needless_range_loop.stderr
@@ -1,5 +1,5 @@
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:15:14
+  --> tests/ui/needless_range_loop.rs:16:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     for <item> in &vec {
    |         ~~~~~~    ~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:26:14
+  --> tests/ui/needless_range_loop.rs:27:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     for <item> in &vec {
    |         ~~~~~~    ~~~~
 
 error: the loop variable `j` is only used to index `STATIC`
-  --> tests/ui/needless_range_loop.rs:32:14
+  --> tests/ui/needless_range_loop.rs:33:14
    |
 LL |     for j in 0..4 {
    |              ^^^^
@@ -34,7 +34,7 @@ LL |     for <item> in &STATIC {
    |         ~~~~~~    ~~~~~~~
 
 error: the loop variable `j` is only used to index `CONST`
-  --> tests/ui/needless_range_loop.rs:37:14
+  --> tests/ui/needless_range_loop.rs:38:14
    |
 LL |     for j in 0..4 {
    |              ^^^^
@@ -45,7 +45,7 @@ LL |     for <item> in &CONST {
    |         ~~~~~~    ~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> tests/ui/needless_range_loop.rs:42:14
+  --> tests/ui/needless_range_loop.rs:43:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     for (i, <item>) in vec.iter().enumerate() {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec2`
-  --> tests/ui/needless_range_loop.rs:51:14
+  --> tests/ui/needless_range_loop.rs:52:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
@@ -67,7 +67,7 @@ LL |     for <item> in vec2.iter().take(vec.len()) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:56:14
+  --> tests/ui/needless_range_loop.rs:57:14
    |
 LL |     for i in 5..vec.len() {
    |              ^^^^^^^^^^^^
@@ -78,7 +78,7 @@ LL |     for <item> in vec.iter().skip(5) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:61:14
+  --> tests/ui/needless_range_loop.rs:62:14
    |
 LL |     for i in 0..MAX_LEN {
    |              ^^^^^^^^^^
@@ -89,7 +89,7 @@ LL |     for <item> in vec.iter().take(MAX_LEN) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:66:14
+  --> tests/ui/needless_range_loop.rs:67:14
    |
 LL |     for i in 0..=MAX_LEN {
    |              ^^^^^^^^^^^
@@ -100,7 +100,7 @@ LL |     for <item> in vec.iter().take(MAX_LEN + 1) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:71:14
+  --> tests/ui/needless_range_loop.rs:72:14
    |
 LL |     for i in 5..10 {
    |              ^^^^^
@@ -111,7 +111,7 @@ LL |     for <item> in vec.iter().take(10).skip(5) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is only used to index `vec`
-  --> tests/ui/needless_range_loop.rs:76:14
+  --> tests/ui/needless_range_loop.rs:77:14
    |
 LL |     for i in 5..=10 {
    |              ^^^^^^
@@ -122,7 +122,7 @@ LL |     for <item> in vec.iter().take(10 + 1).skip(5) {
    |         ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> tests/ui/needless_range_loop.rs:81:14
+  --> tests/ui/needless_range_loop.rs:82:14
    |
 LL |     for i in 5..vec.len() {
    |              ^^^^^^^^^^^^
@@ -133,7 +133,7 @@ LL |     for (i, <item>) in vec.iter().enumerate().skip(5) {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> tests/ui/needless_range_loop.rs:86:14
+  --> tests/ui/needless_range_loop.rs:87:14
    |
 LL |     for i in 5..10 {
    |              ^^^^^
@@ -144,7 +144,7 @@ LL |     for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
    |         ~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: the loop variable `i` is used to index `vec`
-  --> tests/ui/needless_range_loop.rs:92:14
+  --> tests/ui/needless_range_loop.rs:93:14
    |
 LL |     for i in 0..vec.len() {
    |              ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/precedence.fixed b/src/tools/clippy/tests/ui/precedence.fixed
index 9864dd2550b..52144a18bac 100644
--- a/src/tools/clippy/tests/ui/precedence.fixed
+++ b/src/tools/clippy/tests/ui/precedence.fixed
@@ -20,10 +20,10 @@ fn main() {
     1 ^ (1 - 1);
     3 | (2 - 1);
     3 & (5 - 2);
-    0x0F00 & (0x00F0 << 4);
-    0x0F00 & (0xF000 >> 4);
-    (0x0F00 << 1) ^ 3;
-    (0x0F00 << 1) | 2;
+    0x0F00 & 0x00F0 << 4;
+    0x0F00 & 0xF000 >> 4;
+    0x0F00 << 1 ^ 3;
+    0x0F00 << 1 | 2;
 
     let b = 3;
     trip!(b * 8);
diff --git a/src/tools/clippy/tests/ui/precedence.stderr b/src/tools/clippy/tests/ui/precedence.stderr
index 329422cb8a6..68ad5cb4829 100644
--- a/src/tools/clippy/tests/ui/precedence.stderr
+++ b/src/tools/clippy/tests/ui/precedence.stderr
@@ -43,29 +43,5 @@ error: operator precedence might not be obvious
 LL |     3 & 5 - 2;
    |     ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)`
 
-error: operator precedence might not be obvious
-  --> tests/ui/precedence.rs:23:5
-   |
-LL |     0x0F00 & 0x00F0 << 4;
-   |     ^^^^^^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `0x0F00 & (0x00F0 << 4)`
-
-error: operator precedence might not be obvious
-  --> tests/ui/precedence.rs:24:5
-   |
-LL |     0x0F00 & 0xF000 >> 4;
-   |     ^^^^^^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `0x0F00 & (0xF000 >> 4)`
-
-error: operator precedence might not be obvious
-  --> tests/ui/precedence.rs:25:5
-   |
-LL |     0x0F00 << 1 ^ 3;
-   |     ^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(0x0F00 << 1) ^ 3`
-
-error: operator precedence might not be obvious
-  --> tests/ui/precedence.rs:26:5
-   |
-LL |     0x0F00 << 1 | 2;
-   |     ^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(0x0F00 << 1) | 2`
-
-error: aborting due to 11 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/precedence_bits.fixed b/src/tools/clippy/tests/ui/precedence_bits.fixed
new file mode 100644
index 00000000000..82fea0d14e4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/precedence_bits.fixed
@@ -0,0 +1,35 @@
+#![warn(clippy::precedence_bits)]
+#![allow(
+    unused_must_use,
+    clippy::no_effect,
+    clippy::unnecessary_operation,
+    clippy::precedence
+)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::eq_op)]
+
+macro_rules! trip {
+    ($a:expr) => {
+        match $a & 0b1111_1111u8 {
+            0 => println!("a is zero ({})", $a),
+            _ => println!("a is {}", $a),
+        }
+    };
+}
+
+fn main() {
+    1 << 2 + 3;
+    1 + 2 << 3;
+    4 >> 1 + 1;
+    1 + 3 >> 2;
+    1 ^ 1 - 1;
+    3 | 2 - 1;
+    3 & 5 - 2;
+    0x0F00 & (0x00F0 << 4);
+    0x0F00 & (0xF000 >> 4);
+    (0x0F00 << 1) ^ 3;
+    (0x0F00 << 1) | 2;
+
+    let b = 3;
+    trip!(b * 8);
+}
diff --git a/src/tools/clippy/tests/ui/precedence_bits.rs b/src/tools/clippy/tests/ui/precedence_bits.rs
new file mode 100644
index 00000000000..9b353308b6e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/precedence_bits.rs
@@ -0,0 +1,35 @@
+#![warn(clippy::precedence_bits)]
+#![allow(
+    unused_must_use,
+    clippy::no_effect,
+    clippy::unnecessary_operation,
+    clippy::precedence
+)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::eq_op)]
+
+macro_rules! trip {
+    ($a:expr) => {
+        match $a & 0b1111_1111u8 {
+            0 => println!("a is zero ({})", $a),
+            _ => println!("a is {}", $a),
+        }
+    };
+}
+
+fn main() {
+    1 << 2 + 3;
+    1 + 2 << 3;
+    4 >> 1 + 1;
+    1 + 3 >> 2;
+    1 ^ 1 - 1;
+    3 | 2 - 1;
+    3 & 5 - 2;
+    0x0F00 & 0x00F0 << 4;
+    0x0F00 & 0xF000 >> 4;
+    0x0F00 << 1 ^ 3;
+    0x0F00 << 1 | 2;
+
+    let b = 3;
+    trip!(b * 8);
+}
diff --git a/src/tools/clippy/tests/ui/precedence_bits.stderr b/src/tools/clippy/tests/ui/precedence_bits.stderr
new file mode 100644
index 00000000000..f468186b363
--- /dev/null
+++ b/src/tools/clippy/tests/ui/precedence_bits.stderr
@@ -0,0 +1,29 @@
+error: operator precedence might not be obvious
+  --> tests/ui/precedence_bits.rs:28:5
+   |
+LL |     0x0F00 & 0x00F0 << 4;
+   |     ^^^^^^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `0x0F00 & (0x00F0 << 4)`
+   |
+   = note: `-D clippy::precedence-bits` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::precedence_bits)]`
+
+error: operator precedence might not be obvious
+  --> tests/ui/precedence_bits.rs:29:5
+   |
+LL |     0x0F00 & 0xF000 >> 4;
+   |     ^^^^^^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `0x0F00 & (0xF000 >> 4)`
+
+error: operator precedence might not be obvious
+  --> tests/ui/precedence_bits.rs:30:5
+   |
+LL |     0x0F00 << 1 ^ 3;
+   |     ^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(0x0F00 << 1) ^ 3`
+
+error: operator precedence might not be obvious
+  --> tests/ui/precedence_bits.rs:31:5
+   |
+LL |     0x0F00 << 1 | 2;
+   |     ^^^^^^^^^^^^^^^ help: consider parenthesizing your expression: `(0x0F00 << 1) | 2`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/print_literal.fixed b/src/tools/clippy/tests/ui/print_literal.fixed
index 1705a7ff01b..328e9a9b999 100644
--- a/src/tools/clippy/tests/ui/print_literal.fixed
+++ b/src/tools/clippy/tests/ui/print_literal.fixed
@@ -66,3 +66,17 @@ fn main() {
 
     println!("mixed: {{hello}} {world}");
 }
+
+fn issue_13959() {
+    println!("\"");
+    println!(
+        "
+        foo
+        \\
+        \\\\
+        \"
+        \\\"
+        bar
+"
+    );
+}
diff --git a/src/tools/clippy/tests/ui/print_literal.rs b/src/tools/clippy/tests/ui/print_literal.rs
index d10b26b5887..3130d0b6998 100644
--- a/src/tools/clippy/tests/ui/print_literal.rs
+++ b/src/tools/clippy/tests/ui/print_literal.rs
@@ -66,3 +66,18 @@ fn main() {
 
     println!("mixed: {} {world}", "{hello}");
 }
+
+fn issue_13959() {
+    println!("{}", r#"""#);
+    println!(
+        "{}",
+        r#"
+        foo
+        \
+        \\
+        "
+        \"
+        bar
+"#
+    );
+}
diff --git a/src/tools/clippy/tests/ui/print_literal.stderr b/src/tools/clippy/tests/ui/print_literal.stderr
index c4cbb8bed70..d967b7c2407 100644
--- a/src/tools/clippy/tests/ui/print_literal.stderr
+++ b/src/tools/clippy/tests/ui/print_literal.stderr
@@ -192,5 +192,41 @@ LL -     println!("mixed: {} {world}", "{hello}");
 LL +     println!("mixed: {{hello}} {world}");
    |
 
-error: aborting due to 16 previous errors
+error: literal with an empty format string
+  --> tests/ui/print_literal.rs:71:20
+   |
+LL |     println!("{}", r#"""#);
+   |                    ^^^^^^
+   |
+help: try
+   |
+LL -     println!("{}", r#"""#);
+LL +     println!("\"");
+   |
+
+error: literal with an empty format string
+  --> tests/ui/print_literal.rs:74:9
+   |
+LL | /         r#"
+LL | |         foo
+LL | |         \
+LL | |         \\
+...  |
+LL | |         bar
+LL | | "#
+   | |__^
+   |
+help: try
+   |
+LL ~         "
+LL +         foo
+LL +         \\
+LL +         \\\\
+LL +         \"
+LL +         \\\"
+LL +         bar
+LL ~ "
+   |
+
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_else.fixed b/src/tools/clippy/tests/ui/redundant_else.fixed
new file mode 100644
index 00000000000..47aa79302d2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/redundant_else.fixed
@@ -0,0 +1,154 @@
+#![warn(clippy::redundant_else)]
+#![allow(clippy::needless_return, clippy::if_same_then_else, clippy::needless_late_init)]
+
+fn main() {
+    loop {
+        // break
+        if foo() {
+            println!("Love your neighbor;");
+            break;
+        }
+        //~^ ERROR: redundant else block
+        println!("yet don't pull down your hedge.");
+        // continue
+        if foo() {
+            println!("He that lies down with Dogs,");
+            continue;
+        }
+        //~^ ERROR: redundant else block
+        println!("shall rise up with fleas.");
+        // match block
+        if foo() {
+            match foo() {
+                1 => break,
+                _ => return,
+            }
+        }
+        //~^ ERROR: redundant else block
+        println!("You may delay, but time will not.");
+    }
+    // else if
+    if foo() {
+        return;
+    } else if foo() {
+        return;
+    }
+    //~^ ERROR: redundant else block
+    println!("A fat kitchen makes a lean will.");
+    // let binding outside of block
+    let _ = {
+        if foo() {
+            return;
+        }
+        //~^ ERROR: redundant else block
+        1
+    };
+    // else if with let binding outside of block
+    let _ = {
+        if foo() {
+            return;
+        } else if foo() {
+            return;
+        }
+        //~^ ERROR: redundant else block
+        2
+    };
+    // inside if let
+    let _ = if let Some(1) = foo() {
+        let _ = 1;
+        if foo() {
+            return;
+        }
+        //~^ ERROR: redundant else block
+        1
+    } else {
+        1
+    };
+
+    //
+    // non-lint cases
+    //
+
+    // sanity check
+    if foo() {
+        let _ = 1;
+    } else {
+        println!("Who is wise? He that learns from every one.");
+    }
+    // else if without else
+    if foo() {
+        return;
+    } else if foo() {
+        foo()
+    };
+    // nested if return
+    if foo() {
+        if foo() {
+            return;
+        }
+    } else {
+        foo()
+    };
+    // match with non-breaking branch
+    if foo() {
+        match foo() {
+            1 => foo(),
+            _ => return,
+        }
+    } else {
+        println!("Three may keep a secret, if two of them are dead.");
+    }
+    // let binding
+    let _ = if foo() {
+        return;
+    } else {
+        1
+    };
+    // assign
+    let mut a;
+    a = if foo() {
+        return;
+    } else {
+        1
+    };
+    // assign-op
+    a += if foo() {
+        return;
+    } else {
+        1
+    };
+    // if return else if else
+    if foo() {
+        return;
+    } else if foo() {
+        1
+    } else {
+        2
+    };
+    // if else if return else
+    if foo() {
+        1
+    } else if foo() {
+        return;
+    } else {
+        2
+    };
+    // else if with let binding
+    let _ = if foo() {
+        return;
+    } else if foo() {
+        return;
+    } else {
+        2
+    };
+    // inside function call
+    Box::new(if foo() {
+        return;
+    } else {
+        1
+    });
+}
+
+fn foo<T>() -> T {
+    unimplemented!("I'm not Santa Claus")
+}
diff --git a/src/tools/clippy/tests/ui/redundant_else.stderr b/src/tools/clippy/tests/ui/redundant_else.stderr
index b649a210b5f..ecc16f7cda5 100644
--- a/src/tools/clippy/tests/ui/redundant_else.stderr
+++ b/src/tools/clippy/tests/ui/redundant_else.stderr
@@ -1,88 +1,123 @@
 error: redundant else block
-  --> tests/ui/redundant_else.rs:10:16
+  --> tests/ui/redundant_else.rs:10:10
    |
 LL |           } else {
-   |  ________________^
+   |  __________^
 LL | |
 LL | |             println!("yet don't pull down your hedge.");
 LL | |         }
    | |_________^
    |
-   = help: remove the `else` block and move the contents out
    = note: `-D clippy::redundant-else` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::redundant_else)]`
+help: remove the `else` block and move the contents out
+   |
+LL ~         }
+LL +
+LL +         println!("yet don't pull down your hedge.");
+   |
 
 error: redundant else block
-  --> tests/ui/redundant_else.rs:18:16
+  --> tests/ui/redundant_else.rs:18:10
    |
 LL |           } else {
-   |  ________________^
+   |  __________^
 LL | |
 LL | |             println!("shall rise up with fleas.");
 LL | |         }
    | |_________^
    |
-   = help: remove the `else` block and move the contents out
+help: remove the `else` block and move the contents out
+   |
+LL ~         }
+LL +
+LL +         println!("shall rise up with fleas.");
+   |
 
 error: redundant else block
-  --> tests/ui/redundant_else.rs:28:16
+  --> tests/ui/redundant_else.rs:28:10
    |
 LL |           } else {
-   |  ________________^
+   |  __________^
 LL | |
 LL | |             println!("You may delay, but time will not.");
 LL | |         }
    | |_________^
    |
-   = help: remove the `else` block and move the contents out
+help: remove the `else` block and move the contents out
+   |
+LL ~         }
+LL +
+LL +         println!("You may delay, but time will not.");
+   |
 
 error: redundant else block
-  --> tests/ui/redundant_else.rs:38:12
+  --> tests/ui/redundant_else.rs:38:6
    |
 LL |       } else {
-   |  ____________^
+   |  ______^
 LL | |
 LL | |         println!("A fat kitchen makes a lean will.");
 LL | |     }
    | |_____^
    |
-   = help: remove the `else` block and move the contents out
+help: remove the `else` block and move the contents out
+   |
+LL ~     }
+LL +
+LL +     println!("A fat kitchen makes a lean will.");
+   |
 
 error: redundant else block
-  --> tests/ui/redundant_else.rs:46:16
+  --> tests/ui/redundant_else.rs:46:10
    |
 LL |           } else {
-   |  ________________^
+   |  __________^
 LL | |
 LL | |             1
 LL | |         }
    | |_________^
    |
-   = help: remove the `else` block and move the contents out
+help: remove the `else` block and move the contents out
+   |
+LL ~         }
+LL +
+LL +         1
+   |
 
 error: redundant else block
-  --> tests/ui/redundant_else.rs:57:16
+  --> tests/ui/redundant_else.rs:57:10
    |
 LL |           } else {
-   |  ________________^
+   |  __________^
 LL | |
 LL | |             2
 LL | |         }
    | |_________^
    |
-   = help: remove the `else` block and move the contents out
+help: remove the `else` block and move the contents out
+   |
+LL ~         }
+LL +
+LL +         2
+   |
 
 error: redundant else block
-  --> tests/ui/redundant_else.rs:67:16
+  --> tests/ui/redundant_else.rs:67:10
    |
 LL |           } else {
-   |  ________________^
+   |  __________^
 LL | |
 LL | |             1
 LL | |         }
    | |_________^
    |
-   = help: remove the `else` block and move the contents out
+help: remove the `else` block and move the contents out
+   |
+LL ~         }
+LL +
+LL +         1
+   |
 
 error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/return_and_then.fixed b/src/tools/clippy/tests/ui/return_and_then.fixed
new file mode 100644
index 00000000000..9736a51ac86
--- /dev/null
+++ b/src/tools/clippy/tests/ui/return_and_then.fixed
@@ -0,0 +1,67 @@
+#![warn(clippy::return_and_then)]
+
+fn main() {
+    fn test_opt_block(opt: Option<i32>) -> Option<i32> {
+        let n = opt?;
+        let mut ret = n + 1;
+        ret += n;
+        if n > 1 { Some(ret) } else { None }
+    }
+
+    fn test_opt_func(opt: Option<i32>) -> Option<i32> {
+        let n = opt?;
+        test_opt_block(Some(n))
+    }
+
+    fn test_call_chain() -> Option<i32> {
+        let n = gen_option(1)?;
+        test_opt_block(Some(n))
+    }
+
+    fn test_res_block(opt: Result<i32, i32>) -> Result<i32, i32> {
+        let n = opt?;
+        if n > 1 { Ok(n + 1) } else { Err(n) }
+    }
+
+    fn test_res_func(opt: Result<i32, i32>) -> Result<i32, i32> {
+        let n = opt?;
+        test_res_block(Ok(n))
+    }
+
+    fn test_ref_only() -> Option<i32> {
+        // ref: empty string
+        let x = Some("")?;
+        if x.len() > 2 { Some(3) } else { None }
+    }
+
+    fn test_tmp_only() -> Option<i32> {
+        // unused temporary: vec![1, 2, 4]
+        let x = Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
+            (a, _) if a.len() > 1 => a,
+            (_, b) => b,
+        })?;
+        if x.len() > 2 { Some(3) } else { None }
+    }
+
+    // should not lint
+    fn test_tmp_ref() -> Option<String> {
+        String::from("<BOOM>")
+            .strip_prefix("<")
+            .and_then(|s| s.strip_suffix(">").map(String::from))
+    }
+
+    // should not lint
+    fn test_unconsumed_tmp() -> Option<i32> {
+        [1, 2, 3]
+            .iter()
+            .map(|x| x + 1)
+            .collect::<Vec<_>>() // temporary Vec created here
+            .as_slice() // creates temporary slice
+            .first() // creates temporary reference
+            .and_then(|x| test_opt_block(Some(*x)))
+    }
+}
+
+fn gen_option(n: i32) -> Option<i32> {
+    Some(n)
+}
diff --git a/src/tools/clippy/tests/ui/return_and_then.rs b/src/tools/clippy/tests/ui/return_and_then.rs
new file mode 100644
index 00000000000..8bcbdfc3a63
--- /dev/null
+++ b/src/tools/clippy/tests/ui/return_and_then.rs
@@ -0,0 +1,63 @@
+#![warn(clippy::return_and_then)]
+
+fn main() {
+    fn test_opt_block(opt: Option<i32>) -> Option<i32> {
+        opt.and_then(|n| {
+            let mut ret = n + 1;
+            ret += n;
+            if n > 1 { Some(ret) } else { None }
+        })
+    }
+
+    fn test_opt_func(opt: Option<i32>) -> Option<i32> {
+        opt.and_then(|n| test_opt_block(Some(n)))
+    }
+
+    fn test_call_chain() -> Option<i32> {
+        gen_option(1).and_then(|n| test_opt_block(Some(n)))
+    }
+
+    fn test_res_block(opt: Result<i32, i32>) -> Result<i32, i32> {
+        opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) })
+    }
+
+    fn test_res_func(opt: Result<i32, i32>) -> Result<i32, i32> {
+        opt.and_then(|n| test_res_block(Ok(n)))
+    }
+
+    fn test_ref_only() -> Option<i32> {
+        // ref: empty string
+        Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None })
+    }
+
+    fn test_tmp_only() -> Option<i32> {
+        // unused temporary: vec![1, 2, 4]
+        Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
+            (a, _) if a.len() > 1 => a,
+            (_, b) => b,
+        })
+        .and_then(|x| if x.len() > 2 { Some(3) } else { None })
+    }
+
+    // should not lint
+    fn test_tmp_ref() -> Option<String> {
+        String::from("<BOOM>")
+            .strip_prefix("<")
+            .and_then(|s| s.strip_suffix(">").map(String::from))
+    }
+
+    // should not lint
+    fn test_unconsumed_tmp() -> Option<i32> {
+        [1, 2, 3]
+            .iter()
+            .map(|x| x + 1)
+            .collect::<Vec<_>>() // temporary Vec created here
+            .as_slice() // creates temporary slice
+            .first() // creates temporary reference
+            .and_then(|x| test_opt_block(Some(*x)))
+    }
+}
+
+fn gen_option(n: i32) -> Option<i32> {
+    Some(n)
+}
diff --git a/src/tools/clippy/tests/ui/return_and_then.stderr b/src/tools/clippy/tests/ui/return_and_then.stderr
new file mode 100644
index 00000000000..b2e8bf2ca45
--- /dev/null
+++ b/src/tools/clippy/tests/ui/return_and_then.stderr
@@ -0,0 +1,101 @@
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:5:9
+   |
+LL | /         opt.and_then(|n| {
+LL | |             let mut ret = n + 1;
+LL | |             ret += n;
+LL | |             if n > 1 { Some(ret) } else { None }
+LL | |         })
+   | |__________^
+   |
+   = note: `-D clippy::return-and-then` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::return_and_then)]`
+help: try
+   |
+LL ~         let n = opt?;
+LL +         let mut ret = n + 1;
+LL +         ret += n;
+LL +         if n > 1 { Some(ret) } else { None }
+   |
+
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:13:9
+   |
+LL |         opt.and_then(|n| test_opt_block(Some(n)))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~         let n = opt?;
+LL +         test_opt_block(Some(n))
+   |
+
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:17:9
+   |
+LL |         gen_option(1).and_then(|n| test_opt_block(Some(n)))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~         let n = gen_option(1)?;
+LL +         test_opt_block(Some(n))
+   |
+
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:21:9
+   |
+LL |         opt.and_then(|n| if n > 1 { Ok(n + 1) } else { Err(n) })
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~         let n = opt?;
+LL +         if n > 1 { Ok(n + 1) } else { Err(n) }
+   |
+
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:25:9
+   |
+LL |         opt.and_then(|n| test_res_block(Ok(n)))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~         let n = opt?;
+LL +         test_res_block(Ok(n))
+   |
+
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:30:9
+   |
+LL |         Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None })
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: try
+   |
+LL ~         let x = Some("")?;
+LL +         if x.len() > 2 { Some(3) } else { None }
+   |
+
+error: use the question mark operator instead of an `and_then` call
+  --> tests/ui/return_and_then.rs:35:9
+   |
+LL | /         Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
+LL | |             (a, _) if a.len() > 1 => a,
+LL | |             (_, b) => b,
+LL | |         })
+LL | |         .and_then(|x| if x.len() > 2 { Some(3) } else { None })
+   | |_______________________________________________________________^
+   |
+help: try
+   |
+LL ~         let x = Some(match (vec![1, 2, 3], vec![1, 2, 4]) {
+LL +             (a, _) if a.len() > 1 => a,
+LL +             (_, b) => b,
+LL +         })?;
+LL +         if x.len() > 2 { Some(3) } else { None }
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.rs b/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.rs
index 91b7ea3922c..f405ba200ac 100644
--- a/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.rs
+++ b/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.rs
@@ -8,11 +8,11 @@ fn main() {
     const SIZE: usize = 128;
     const HALF_SIZE: usize = SIZE / 2;
     const DOUBLE_SIZE: usize = SIZE * 2;
-    let mut x = [2u8; SIZE];
-    let mut y = [2u8; SIZE];
+    let mut x = [2u16; SIZE];
+    let mut y = [2u16; SIZE];
 
     // Count expression involving multiplication of size_of (Should trigger the lint)
-    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>() * SIZE) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
     // Count expression involving nested multiplications of size_of (Should trigger the lint)
@@ -20,22 +20,19 @@ fn main() {
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
     // Count expression involving divisions of size_of (Should trigger the lint)
-    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u16>() / 2) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
     // Count expression involving divisions by size_of (Should not trigger the lint)
-    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::<u8>()) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / size_of::<u16>()) };
 
     // Count expression involving divisions by multiple size_of (Should not trigger the lint)
-    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 * size_of::<u8>())) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 * size_of::<u16>())) };
 
     // Count expression involving recursive divisions by size_of (Should trigger the lint)
-    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u16>())) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
     // No size_of calls (Should not trigger the lint)
     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
-
-    // Different types for pointee and size_of (Should not trigger the lint)
-    unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u16>() / 2 * SIZE) };
 }
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr b/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr
index 6396afd7f39..74be0d7773d 100644
--- a/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr
+++ b/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr
@@ -1,8 +1,8 @@
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/expressions.rs:15:62
    |
-LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>() * SIZE) };
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
    = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
@@ -19,16 +19,16 @@ LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * si
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/expressions.rs:23:47
    |
-LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u16>() / 2) };
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/expressions.rs:33:47
    |
-LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u8>())) };
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / (2 / size_of::<u16>())) };
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count/functions.rs b/src/tools/clippy/tests/ui/size_of_in_element_count/functions.rs
index 3501cbdf81c..af18136a1db 100644
--- a/src/tools/clippy/tests/ui/size_of_in_element_count/functions.rs
+++ b/src/tools/clippy/tests/ui/size_of_in_element_count/functions.rs
@@ -11,57 +11,52 @@ fn main() {
     const SIZE: usize = 128;
     const HALF_SIZE: usize = SIZE / 2;
     const DOUBLE_SIZE: usize = SIZE * 2;
-    let mut x = [2u8; SIZE];
-    let mut y = [2u8; SIZE];
+    let mut x = [2u16; SIZE];
+    let mut y = [2u16; SIZE];
 
     // Count is size_of (Should trigger the lint)
-    unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { copy_nonoverlapping::<u16>(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
-    unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
-    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
-    unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
-    //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
-    //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-
-    unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u16>() * SIZE) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
-    slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
+    slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u16>() * SIZE);
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
+    slice_from_raw_parts(y.as_ptr(), size_of::<u16>() * SIZE);
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
-    unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u16>() * SIZE) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
+    unsafe { from_raw_parts(y.as_ptr(), size_of::<u16>() * SIZE) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 
-    unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().sub(size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    y.as_ptr().wrapping_sub(size_of::<u8>());
+    y.as_ptr().wrapping_sub(size_of::<u16>());
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { y.as_ptr().add(size_of::<u8>()) };
+    unsafe { y.as_ptr().add(size_of::<u16>()) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    y.as_mut_ptr().wrapping_add(size_of::<u8>());
+    y.as_mut_ptr().wrapping_add(size_of::<u16>());
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
+    unsafe { y.as_ptr().offset(size_of::<u16>() as isize) };
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
-    y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
+    y.as_mut_ptr().wrapping_offset(size_of::<u16>() as isize);
     //~^ ERROR: found a count of bytes instead of a count of elements of `T`
 }
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr b/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr
index abde7dc7cd2..de54789b225 100644
--- a/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr
+++ b/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr
@@ -1,8 +1,8 @@
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:18:68
+  --> tests/ui/size_of_in_element_count/functions.rs:18:69
    |
-LL |     unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
-   |                                                                    ^^^^^^^^^^^^^^^
+LL |     unsafe { copy_nonoverlapping::<u16>(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>()) };
+   |                                                                     ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
    = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
@@ -19,40 +19,40 @@ LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/functions.rs:23:49
    |
-LL |     unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
-   |                                                 ^^^^^^^^^^^^^^^
+LL |     unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u16>()) };
+   |                                                 ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/functions.rs:25:64
    |
-LL |     unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
-   |                                                                ^^^^^^^^^^^^^^^
+LL |     unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u16>()) };
+   |                                                                ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/functions.rs:27:51
    |
-LL |     unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
-   |                                                   ^^^^^^^^^^^^^^^
+LL |     unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u16>()) };
+   |                                                   ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/functions.rs:29:66
    |
-LL |     unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
-   |                                                                  ^^^^^^^^^^^^^^^
+LL |     unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u16>()) };
+   |                                                                  ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
   --> tests/ui/size_of_in_element_count/functions.rs:32:47
    |
-LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
-   |                                               ^^^^^^^^^^^^^^^
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u16>()) };
+   |                                               ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
@@ -65,108 +65,92 @@ LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:37:46
+  --> tests/ui/size_of_in_element_count/functions.rs:37:66
    |
-LL |     unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u16>() * SIZE) };
+   |                                                                  ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:39:47
+  --> tests/ui/size_of_in_element_count/functions.rs:40:46
    |
-LL |     unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
-   |                                               ^^^^^^^^^^^^^^^^^^^^^^
+LL |     slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u16>() * SIZE);
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:42:66
+  --> tests/ui/size_of_in_element_count/functions.rs:42:38
    |
-LL |     unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
-   |                                                                  ^^^^^^^^^^^^^^^^^^^^^^
+LL |     slice_from_raw_parts(y.as_ptr(), size_of::<u16>() * SIZE);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:45:46
+  --> tests/ui/size_of_in_element_count/functions.rs:45:49
    |
-LL |     slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u16>() * SIZE) };
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:47:38
+  --> tests/ui/size_of_in_element_count/functions.rs:47:41
    |
-LL |     slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
-   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { from_raw_parts(y.as_ptr(), size_of::<u16>() * SIZE) };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:50:49
+  --> tests/ui/size_of_in_element_count/functions.rs:50:33
    |
-LL |     unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { y.as_mut_ptr().sub(size_of::<u16>()) };
+   |                                 ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:52:41
+  --> tests/ui/size_of_in_element_count/functions.rs:52:29
    |
-LL |     unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^
+LL |     y.as_ptr().wrapping_sub(size_of::<u16>());
+   |                             ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:55:33
+  --> tests/ui/size_of_in_element_count/functions.rs:54:29
    |
-LL |     unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
-   |                                 ^^^^^^^^^^^^^^^
+LL |     unsafe { y.as_ptr().add(size_of::<u16>()) };
+   |                             ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:57:29
+  --> tests/ui/size_of_in_element_count/functions.rs:56:33
    |
-LL |     y.as_ptr().wrapping_sub(size_of::<u8>());
-   |                             ^^^^^^^^^^^^^^^
+LL |     y.as_mut_ptr().wrapping_add(size_of::<u16>());
+   |                                 ^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:59:29
+  --> tests/ui/size_of_in_element_count/functions.rs:58:32
    |
-LL |     unsafe { y.as_ptr().add(size_of::<u8>()) };
-   |                             ^^^^^^^^^^^^^^^
+LL |     unsafe { y.as_ptr().offset(size_of::<u16>() as isize) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
 error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:61:33
+  --> tests/ui/size_of_in_element_count/functions.rs:60:36
    |
-LL |     y.as_mut_ptr().wrapping_add(size_of::<u8>());
-   |                                 ^^^^^^^^^^^^^^^
+LL |     y.as_mut_ptr().wrapping_offset(size_of::<u16>() as isize);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
 
-error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:63:32
-   |
-LL |     unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
-
-error: found a count of bytes instead of a count of elements of `T`
-  --> tests/ui/size_of_in_element_count/functions.rs:65:36
-   |
-LL |     y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
-
-error: aborting due to 21 previous errors
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.stderr b/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.stderr
index fb8fb1a0090..26166e2fc8d 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.stderr
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg_non_rustfix.stderr
@@ -1,4 +1,4 @@
-error: `ref` directly on a function argument is ignored. Consider using a reference type instead
+error: `ref` directly on a function parameter does not prevent taking ownership of the passed argument. Consider using a reference type instead
   --> tests/ui/toplevel_ref_arg_non_rustfix.rs:9:15
    |
 LL | fn the_answer(ref mut x: u8) {
@@ -7,7 +7,7 @@ LL | fn the_answer(ref mut x: u8) {
    = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::toplevel_ref_arg)]`
 
-error: `ref` directly on a function argument is ignored. Consider using a reference type instead
+error: `ref` directly on a function parameter does not prevent taking ownership of the passed argument. Consider using a reference type instead
   --> tests/ui/toplevel_ref_arg_non_rustfix.rs:20:24
    |
 LL |         fn fun_example(ref _x: usize) {}
diff --git a/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2021.fixed b/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2021.fixed
index 7a3b79553de..343c88b9815 100644
--- a/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2021.fixed
@@ -55,3 +55,9 @@ fn no_borrow_issue(a: u32, b: u32) {
         None => {},
     }
 }
+
+fn issue14100() -> bool {
+    // Removing the `;` would make the block type be `()` instead of `!`, and this could no longer be
+    // cast into the `bool` function return type.
+    if return true {};
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2024.fixed b/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2024.fixed
index d186d5e7ebc..1cba5760eb0 100644
--- a/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2024.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_semicolon.edition2024.fixed
@@ -55,3 +55,9 @@ fn no_borrow_issue(a: u32, b: u32) {
         None => {},
     }
 }
+
+fn issue14100() -> bool {
+    // Removing the `;` would make the block type be `()` instead of `!`, and this could no longer be
+    // cast into the `bool` function return type.
+    if return true {};
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_semicolon.rs b/src/tools/clippy/tests/ui/unnecessary_semicolon.rs
index 3028c5b27b3..6abbbd79aaf 100644
--- a/src/tools/clippy/tests/ui/unnecessary_semicolon.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_semicolon.rs
@@ -55,3 +55,9 @@ fn no_borrow_issue(a: u32, b: u32) {
         None => {},
     };
 }
+
+fn issue14100() -> bool {
+    // Removing the `;` would make the block type be `()` instead of `!`, and this could no longer be
+    // cast into the `bool` function return type.
+    if return true {};
+}
diff --git a/src/tools/clippy/tests/ui/write_literal.fixed b/src/tools/clippy/tests/ui/write_literal.fixed
index 3d216b76cbf..f1def776e1b 100644
--- a/src/tools/clippy/tests/ui/write_literal.fixed
+++ b/src/tools/clippy/tests/ui/write_literal.fixed
@@ -62,3 +62,19 @@ fn main() {
     writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
     //~^ ERROR: literal with an empty format string
 }
+
+fn issue_13959() {
+    let mut v = Vec::new();
+    writeln!(v, "\"");
+    writeln!(
+        v,
+        "
+        foo
+        \\
+        \\\\
+        \"
+        \\\"
+        bar
+"
+    );
+}
diff --git a/src/tools/clippy/tests/ui/write_literal.rs b/src/tools/clippy/tests/ui/write_literal.rs
index 79d6daa2e3b..1b7df91b47e 100644
--- a/src/tools/clippy/tests/ui/write_literal.rs
+++ b/src/tools/clippy/tests/ui/write_literal.rs
@@ -62,3 +62,20 @@ fn main() {
     writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
     //~^ ERROR: literal with an empty format string
 }
+
+fn issue_13959() {
+    let mut v = Vec::new();
+    writeln!(v, "{}", r#"""#);
+    writeln!(
+        v,
+        "{}",
+        r#"
+        foo
+        \
+        \\
+        "
+        \"
+        bar
+"#
+    );
+}
diff --git a/src/tools/clippy/tests/ui/write_literal.stderr b/src/tools/clippy/tests/ui/write_literal.stderr
index 9f4cdfd91e8..35c93d567cd 100644
--- a/src/tools/clippy/tests/ui/write_literal.stderr
+++ b/src/tools/clippy/tests/ui/write_literal.stderr
@@ -144,5 +144,41 @@ LL -     writeln!(v, "{0} {1} {2}, {3} {4}", "hello", 2, 3, "world", 4);
 LL +     writeln!(v, "hello {0} {1}, world {2}", 2, 3, 4);
    |
 
-error: aborting due to 12 previous errors
+error: literal with an empty format string
+  --> tests/ui/write_literal.rs:68:23
+   |
+LL |     writeln!(v, "{}", r#"""#);
+   |                       ^^^^^^
+   |
+help: try
+   |
+LL -     writeln!(v, "{}", r#"""#);
+LL +     writeln!(v, "\"");
+   |
+
+error: literal with an empty format string
+  --> tests/ui/write_literal.rs:72:9
+   |
+LL | /         r#"
+LL | |         foo
+LL | |         \
+LL | |         \\
+...  |
+LL | |         bar
+LL | | "#
+   | |__^
+   |
+help: try
+   |
+LL ~         "
+LL +         foo
+LL +         \\
+LL +         \\\\
+LL +         \"
+LL +         \\\"
+LL +         bar
+LL ~ "
+   |
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html
index deb0ef0b499..a9b64628003 100644
--- a/src/tools/clippy/util/gh-pages/index_template.html
+++ b/src/tools/clippy/util/gh-pages/index_template.html
@@ -24,14 +24,16 @@ Otherwise, have a great day =^.^=
     <link id="styleNight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/tomorrow-night.css" disabled="true"> {# #}
     <link id="styleAyu" rel="stylesheet" href="https://rust-lang.github.io/mdBook/ayu-highlight.css" disabled="true"> {# #}
     <link rel="stylesheet" href="style.css"> {# #}
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js" defer></script> {# #}
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/rust.min.js" defer></script> {# #}
+    <script src="script.js" defer></script> {# #}
 </head> {# #}
 <body> {# #}
-    <script src="theme.js"></script> {# #}
     <div id="settings-dropdown"> {# #}
         <button class="settings-icon" tabindex="-1"></button> {# #}
         <div class="settings-menu" tabindex="-1"> {# #}
             <div class="setting-radio-name">Theme</div> {# #}
-            <select id="theme-choice" onchange="setTheme(this.value, true)"> {# #}
+            <select id="theme-choice"> {# #}
                 <option value="ayu">Ayu</option> {# #}
                 <option value="coal">Coal</option> {# #}
                 <option value="light">Light</option> {# #}
@@ -39,11 +41,12 @@ Otherwise, have a great day =^.^=
                 <option value="rust">Rust</option> {# #}
             </select> {# #}
             <label> {# #}
-                <input type="checkbox" id="disable-shortcuts" onchange="changeSetting(this)"> {#+ #}
+                <input type="checkbox" id="disable-shortcuts"> {#+ #}
                 <span>Disable keyboard shortcuts</span> {# #}
             </label> {# #}
         </div> {# #}
     </div> {# #}
+    <script src="theme.js"></script> {# #}
 
     <div class="container"> {# #}
         <div class="page-header"> {# #}
@@ -133,10 +136,10 @@ Otherwise, have a great day =^.^=
                         </div> {# #}
                     </div> {# #}
                     <div class="col-12 col-md-2 btn-group expansion-group"> {# #}
-                        <button title="Collapse All" class="btn btn-default expansion-control" type="button" onclick="toggleExpansion(false)"> {# #}
+                        <button title="Collapse All" class="btn btn-default expansion-control" type="button" id="collapse-all"> {# #}
                             <span class="glyphicon glyphicon-collapse-up"></span> {# #}
                         </button> {# #}
-                        <button title="Expand All" class="btn btn-default expansion-control" type="button" onclick="toggleExpansion(true)"> {# #}
+                        <button title="Expand All" class="btn btn-default expansion-control" type="button" id="expand-all"> {# #}
                             <span class="glyphicon glyphicon-collapse-down"></span> {# #}
                         </button> {# #}
                     </div> {# #}
@@ -145,13 +148,13 @@ Otherwise, have a great day =^.^=
             {% for lint in lints %}
                 <article class="panel panel-default" id="{{lint.id}}"> {# #}
                     <input id="label-{{lint.id}}" type="checkbox"> {# #}
-                    <label for="label-{{lint.id}}" onclick="highlightIfNeeded('{{lint.id}}')"> {# #}
+                    <label for="label-{{lint.id}}"> {# #}
                         <header class="panel-heading"> {# #}
                             <h2 class="panel-title"> {# #}
                                 <div class="panel-title-name" id="lint-{{lint.id}}"> {# #}
                                     <span>{{lint.id}}</span> {#+ #}
-                                    <a href="#{{lint.id}}" onclick="lintAnchor(event)" class="anchor label label-default">&para;</a> {#+ #}
-                                    <a href="" class="anchor label label-default" onclick="copyToClipboard(event)"> {# #}
+                                    <a href="#{{lint.id}}" class="lint-anchor anchor label label-default">&para;</a> {#+ #}
+                                    <a href="" class="copy-to-clipboard anchor label label-default"> {# #}
                                         &#128203; {# #}
                                     </a> {# #}
                                 </div> {# #}
@@ -227,9 +230,5 @@ Otherwise, have a great day =^.^=
             ></path> {# #}
         </svg> {# #}
     </a> {# #}
-
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script> {# #}
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/rust.min.js"></script> {# #}
-    <script src="script.js"></script> {# #}
 </body> {# #}
 </html> {# #}
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index 34d76ad642e..c942a6a05a1 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -1,3 +1,5 @@
+"use strict";
+
 window.searchState = {
     timeout: null,
     inputElem: document.getElementById("search-input"),
@@ -124,13 +126,6 @@ function toggleElements(filter, value) {
     }
 }
 
-function changeSetting(elem) {
-    if (elem.id === "disable-shortcuts") {
-        disableShortcuts = elem.checked;
-        storeValue(elem.id, elem.checked);
-    }
-}
-
 function onEachLazy(lazyArray, func) {
     const arr = Array.prototype.slice.call(lazyArray);
     for (const el of arr) {
@@ -138,17 +133,9 @@ function onEachLazy(lazyArray, func) {
     }
 }
 
-function highlightIfNeeded(lintId) {
-    onEachLazy(document.querySelectorAll(`#${lintId} pre > code:not(.hljs)`), el => {
-        hljs.highlightElement(el.parentElement)
-        el.classList.add("highlighted");
-    });
-}
-
 function expandLint(lintId) {
     const elem = document.querySelector(`#${lintId} > input[type="checkbox"]`);
     elem.checked = true;
-    highlightIfNeeded(lintId);
 }
 
 function lintAnchor(event) {
@@ -194,13 +181,9 @@ function handleBlur(event, elementId) {
 }
 
 function toggleExpansion(expand) {
-    onEachLazy(
-        document.querySelectorAll("article"),
-        expand ? el => {
-            el.classList.remove("collapsed");
-            highlightIfNeeded(el);
-        } : el => el.classList.add("collapsed"),
-    );
+    for (const checkbox of document.querySelectorAll("article input[type=checkbox]")) {
+        checkbox.checked = expand;
+    }
 }
 
 // Returns the current URL without any query parameter or hash.
@@ -535,7 +518,7 @@ function parseURLFilters() {
         for (const [corres_key, corres_value] of Object.entries(URL_PARAMS_CORRESPONDENCE)) {
             if (corres_value === key) {
                 if (key !== "versions") {
-                    const settings  = new Set(value.split(","));
+                    const settings = new Set(value.split(","));
                     onEachLazy(document.querySelectorAll(`#lint-${key} ul input`), elem => {
                         elem.checked = settings.has(elem.getAttribute("data-value"));
                         updateFilter(elem, corres_key, true);
@@ -555,12 +538,60 @@ function parseURLFilters() {
     }
 }
 
-document.getElementById(`theme-choice`).value = loadValue("theme");
-let disableShortcuts = loadValue('disable-shortcuts') === "true";
-document.getElementById("disable-shortcuts").checked = disableShortcuts;
+function addListeners() {
+    disableShortcutsButton.addEventListener("change", () => {
+        disableShortcuts = disableShortcutsButton.checked;
+        storeValue("disable-shortcuts", disableShortcuts);
+    });
+
+    document.getElementById("expand-all").addEventListener("click", () => toggleExpansion(true));
+    document.getElementById("collapse-all").addEventListener("click", () => toggleExpansion(false));
+
+    // A delegated listener to avoid the upfront cost of >1000 listeners
+    document.addEventListener("click", event => {
+        if (!event.target instanceof HTMLAnchorElement) {
+            return;
+        }
+
+        if (event.target.classList.contains("lint-anchor")) {
+            lintAnchor(event);
+        } else if (event.target.classList.contains("copy-to-clipboard")) {
+            copyToClipboard(event);
+        }
+    });
+
+    document.addEventListener("keypress", handleShortcut);
+    document.addEventListener("keydown", handleShortcut);
+}
+
+// Highlight code blocks only when they approach the viewport so that clicking the "Expand All"
+// button doesn't take a long time
+function highlightLazily() {
+    if (!'IntersectionObserver' in window) {
+        return;
+    }
+    const observer = new IntersectionObserver((entries) => {
+        for (const entry of entries) {
+            if (entry.isIntersecting) {
+                observer.unobserve(entry.target);
+                for (const code of entry.target.querySelectorAll("pre code")) {
+                    hljs.highlightElement(code);
+                }
+            }
+        }
+    });
+    for (const docs of document.querySelectorAll(".lint-docs")) {
+        observer.observe(docs);
+    }
+}
+
+let disableShortcuts = loadValue("disable-shortcuts") === "true";
+
+const disableShortcutsButton = document.getElementById("disable-shortcuts");
+disableShortcutsButton.checked = disableShortcuts;
 
-document.addEventListener("keypress", handleShortcut);
-document.addEventListener("keydown", handleShortcut);
+addListeners();
+highlightLazily();
 
 generateSettings();
 generateSearch();
diff --git a/src/tools/clippy/util/gh-pages/style.css b/src/tools/clippy/util/gh-pages/style.css
index 896f2fdac76..3cc7a919c23 100644
--- a/src/tools/clippy/util/gh-pages/style.css
+++ b/src/tools/clippy/util/gh-pages/style.css
@@ -1,9 +1,5 @@
 blockquote { font-size: 1em; }
 
-[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
-    display: none !important;
-}
-
 .dropdown-menu {
     color: var(--fg);
     background: var(--theme-popup-bg);
@@ -188,8 +184,8 @@ details {
     padding: .5em .5em 0;
 }
 
-code {
-    white-space: pre !important;
+pre {
+    padding: 0;
 }
 
 summary {
diff --git a/src/tools/clippy/util/gh-pages/theme.js b/src/tools/clippy/util/gh-pages/theme.js
index 90f57d4469d..a5dfeed9e8c 100644
--- a/src/tools/clippy/util/gh-pages/theme.js
+++ b/src/tools/clippy/util/gh-pages/theme.js
@@ -1,3 +1,5 @@
+"use strict";
+
 function storeValue(settingName, value) {
     try {
         localStorage.setItem(`clippy-lint-list-${settingName}`, value);
@@ -57,4 +59,11 @@ function setTheme(theme, store) {
     } else {
         setTheme(theme, false);
     }
+
+    const themeChoice = document.getElementById("theme-choice");
+
+    themeChoice.value = loadValue("theme");
+    document.getElementById("theme-choice").addEventListener("change", (e) => {
+        setTheme(themeChoice.value, true);
+    });
 })();
diff --git a/tests/crashes/132391.rs b/tests/crashes/132391.rs
deleted file mode 100644
index 6c8c2c3a878..00000000000
--- a/tests/crashes/132391.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ known-bug: #123291
-
-trait MyTrait {
-    #[repr(align)]
-    fn myfun();
-}
-
-pub fn main() {}
diff --git a/tests/mir-opt/pattern_types.main.PreCodegen.after.mir b/tests/mir-opt/pattern_types.main.PreCodegen.after.mir
index 8c99902f9b8..5ff90de9615 100644
--- a/tests/mir-opt/pattern_types.main.PreCodegen.after.mir
+++ b/tests/mir-opt/pattern_types.main.PreCodegen.after.mir
@@ -5,7 +5,7 @@ fn main() -> () {
     scope 1 {
         debug x => const 2_u32 is 1..=;
         scope 2 {
-            debug y => const 0_u32 is 1..=;
+            debug y => const {transmute(0x00000000): (u32) is 1..=};
         }
     }
 
diff --git a/tests/mir-opt/pattern_types.rs b/tests/mir-opt/pattern_types.rs
index 217c64b90cb..0369ccf9a9d 100644
--- a/tests/mir-opt/pattern_types.rs
+++ b/tests/mir-opt/pattern_types.rs
@@ -7,6 +7,6 @@ use std::pat::pattern_type;
 fn main() {
     // CHECK: debug x => const 2_u32 is 1..=
     let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(2) };
-    // CHECK: debug y => const 0_u32 is 1..=
+    // CHECK: debug y => const {transmute(0x00000000): (u32) is 1..=}
     let y: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) };
 }
diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
index aa8667a00ca..b25d8a34aca 100644
--- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
+++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
@@ -1,8 +1,5 @@
 //@ edition: 2021
 
-// Test doesn't fail until monomorphization time, unfortunately.
-//@ build-fail
-
 fn main() {
     let _ = async {
         A.first().await.second().await;
diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
index 8126c6e1394..4ca6ef89819 100644
--- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
+++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in an async fn requires boxing
-  --> $DIR/indirect-recursion-issue-112047.rs:34:5
+  --> $DIR/indirect-recursion-issue-112047.rs:31:5
    |
 LL |     async fn second(self) {
    |     ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic-width/binop.rs b/tests/ui/diagnostic-width/binop.rs
new file mode 100644
index 00000000000..60ba40b8047
--- /dev/null
+++ b/tests/ui/diagnostic-width/binop.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
+// The regex below normalizes the long type file name to make it suitable for compare-modes.
+//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'"
+type A = (i32, i32, i32, i32);
+type B = (A, A, A, A);
+type C = (B, B, B, B);
+type D = (C, C, C, C);
+
+fn foo(x: D) {
+    x + x; //~ ERROR cannot add `(...
+}
+
+fn bar(x: D) {
+    !x; //~ ERROR cannot apply unary operator `!` to type `(...
+}
+
+fn main() {}
diff --git a/tests/ui/diagnostic-width/binop.stderr b/tests/ui/diagnostic-width/binop.stderr
new file mode 100644
index 00000000000..fd69129c33e
--- /dev/null
+++ b/tests/ui/diagnostic-width/binop.stderr
@@ -0,0 +1,24 @@
+error[E0369]: cannot add `(..., ..., ..., ...)` to `(..., ..., ..., ...)`
+  --> $DIR/binop.rs:10:7
+   |
+LL |     x + x;
+   |     - ^ - (..., ..., ..., ...)
+   |     |
+   |     (..., ..., ..., ...)
+   |
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: consider using `--verbose` to print the full type name to the console
+
+error[E0600]: cannot apply unary operator `!` to type `(..., ..., ..., ...)`
+  --> $DIR/binop.rs:14:5
+   |
+LL |     !x;
+   |     ^^ cannot apply unary operator `!`
+   |
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt'
+   = note: consider using `--verbose` to print the full type name to the console
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0369, E0600.
+For more information about an error, try `rustc --explain E0369`.
diff --git a/tests/ui/feature-gates/feature-gate-fn_align.rs b/tests/ui/feature-gates/feature-gate-fn_align.rs
index ea873dba269..06784a45d76 100644
--- a/tests/ui/feature-gates/feature-gate-fn_align.rs
+++ b/tests/ui/feature-gates/feature-gate-fn_align.rs
@@ -2,3 +2,8 @@
 
 #[repr(align(16))] //~ ERROR `repr(align)` attributes on functions are unstable
 fn requires_alignment() {}
+
+trait MyTrait {
+    #[repr(align)] //~ ERROR `repr(align)` attributes on functions are unstable
+    fn myfun();
+}
diff --git a/tests/ui/feature-gates/feature-gate-fn_align.stderr b/tests/ui/feature-gates/feature-gate-fn_align.stderr
index eec332792b7..cd9900c6051 100644
--- a/tests/ui/feature-gates/feature-gate-fn_align.stderr
+++ b/tests/ui/feature-gates/feature-gate-fn_align.stderr
@@ -8,6 +8,16 @@ LL | #[repr(align(16))]
    = help: add `#![feature(fn_align)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 1 previous error
+error[E0658]: `repr(align)` attributes on functions are unstable
+  --> $DIR/feature-gate-fn_align.rs:7:12
+   |
+LL |     #[repr(align)]
+   |            ^^^^^
+   |
+   = note: see issue #82232 <https://github.com/rust-lang/rust/issues/82232> for more information
+   = help: add `#![feature(fn_align)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/force-inlining/deny-async.rs b/tests/ui/force-inlining/deny-async.rs
index bdf6271bd2a..7c95a53c26f 100644
--- a/tests/ui/force-inlining/deny-async.rs
+++ b/tests/ui/force-inlining/deny-async.rs
@@ -1,6 +1,6 @@
-//@ check-fail
 //@ compile-flags: --crate-type=lib
 //@ edition: 2021
+
 #![allow(internal_features)]
 #![feature(rustc_attrs)]
 
@@ -20,5 +20,7 @@ pub fn callee_justified() {
 
 async fn async_caller() {
     callee();
+    //~^ ERROR `callee` could not be inlined
     callee_justified();
+    //~^ ERROR `callee_justified` could not be inlined
 }
diff --git a/tests/ui/force-inlining/deny-async.stderr b/tests/ui/force-inlining/deny-async.stderr
index 302ca419071..d6516ed875c 100644
--- a/tests/ui/force-inlining/deny-async.stderr
+++ b/tests/ui/force-inlining/deny-async.stderr
@@ -20,5 +20,22 @@ LL | pub fn callee_justified() {
    |
    = note: incompatible due to: #[rustc_no_mir_inline]
 
-error: aborting due to 2 previous errors
+error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
+  --> $DIR/deny-async.rs:22:5
+   |
+LL |     callee();
+   |     ^^^^^^^^ ...`callee` called here
+   |
+   = note: could not be inlined due to: #[rustc_no_mir_inline]
+
+error: `callee_justified` could not be inlined into `async_caller::{closure#0}` but is required to be inlined
+  --> $DIR/deny-async.rs:24:5
+   |
+LL |     callee_justified();
+   |     ^^^^^^^^^^^^^^^^^^ ...`callee_justified` called here
+   |
+   = note: could not be inlined due to: #[rustc_no_mir_inline]
+   = note: `callee_justified` is required to be inlined to: the test requires it
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
index 9814187e179..7f3691123ee 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:11:18
+  --> $DIR/recursive-coroutine-indirect.rs:8:18
    |
 LL |     #[coroutine] move || {
    |                  ^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
index 9814187e179..7f3691123ee 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:11:18
+  --> $DIR/recursive-coroutine-indirect.rs:8:18
    |
 LL |     #[coroutine] move || {
    |                  ^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.rs b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
index cec2176049b..f0727ad3742 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
@@ -2,9 +2,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-//@[next] build-fail
-// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
-
 #![feature(coroutines)]
 #![allow(unconditional_recursion)]
 fn coroutine_hold() -> impl Sized {
diff --git a/tests/ui/pattern/overflowing-literals.rs b/tests/ui/pattern/overflowing-literals.rs
new file mode 100644
index 00000000000..13016d3f7d1
--- /dev/null
+++ b/tests/ui/pattern/overflowing-literals.rs
@@ -0,0 +1,21 @@
+//! Check that overflowing literals are in patterns are rejected
+
+#![feature(pattern_types)]
+#![feature(pattern_type_macro)]
+
+use std::pat::pattern_type;
+
+type TooBig = pattern_type!(u8 is 500..);
+//~^ ERROR:  literal out of range for `u8`
+type TooSmall = pattern_type!(i8 is -500..);
+//~^ ERROR:  literal out of range for `i8`
+type TooBigSigned = pattern_type!(i8 is 200..);
+//~^ ERROR:  literal out of range for `i8`
+
+fn main() {
+    match 5_u8 {
+        500 => {}
+        //~^ ERROR literal out of range for `u8`
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/overflowing-literals.stderr b/tests/ui/pattern/overflowing-literals.stderr
new file mode 100644
index 00000000000..8164b97fd47
--- /dev/null
+++ b/tests/ui/pattern/overflowing-literals.stderr
@@ -0,0 +1,37 @@
+error: literal out of range for `u8`
+  --> $DIR/overflowing-literals.rs:8:35
+   |
+LL | type TooBig = pattern_type!(u8 is 500..);
+   |                                   ^^^
+   |
+   = note: the literal `500` does not fit into the type `u8` whose range is `0..=255`
+   = note: `#[deny(overflowing_literals)]` on by default
+
+error: literal out of range for `i8`
+  --> $DIR/overflowing-literals.rs:10:37
+   |
+LL | type TooSmall = pattern_type!(i8 is -500..);
+   |                                     ^^^^
+   |
+   = note: the literal `-500` does not fit into the type `i8` whose range is `-128..=127`
+   = help: consider using the type `i16` instead
+
+error: literal out of range for `i8`
+  --> $DIR/overflowing-literals.rs:12:41
+   |
+LL | type TooBigSigned = pattern_type!(i8 is 200..);
+   |                                         ^^^
+   |
+   = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127`
+   = help: consider using the type `u8` instead
+
+error: literal out of range for `u8`
+  --> $DIR/overflowing-literals.rs:17:9
+   |
+LL |         500 => {}
+   |         ^^^
+   |
+   = note: the literal `500` does not fit into the type `u8` whose range is `0..=255`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs
index dc0d4f5be2e..d8515a12e05 100644
--- a/tests/ui/repr/attr-usage-repr.rs
+++ b/tests/ui/repr/attr-usage-repr.rs
@@ -16,18 +16,39 @@ struct SSimd([f64; 2]);
 struct SInt(f64, f64);
 
 #[repr(C)]
-enum EExtern { A, B }
+enum EExtern {
+    A,
+    B,
+}
 
 #[repr(align(8))]
-enum EAlign { A, B }
+enum EAlign {
+    A,
+    B,
+}
 
 #[repr(packed)] //~ ERROR: attribute should be applied to a struct
-enum EPacked { A, B }
+enum EPacked {
+    A,
+    B,
+}
 
 #[repr(simd)] //~ ERROR: attribute should be applied to a struct
-enum ESimd { A, B }
+enum ESimd {
+    A,
+    B,
+}
 
 #[repr(i8)]
-enum EInt { A, B }
+enum EInt {
+    A,
+    B,
+}
+
+#[repr()] //~ attribute should be applied to a struct, enum, function, associated function, or union [E0517]
+type SirThisIsAType = i32;
+
+#[repr()]
+struct EmptyReprArgumentList(i32);
 
 fn main() {}
diff --git a/tests/ui/repr/attr-usage-repr.stderr b/tests/ui/repr/attr-usage-repr.stderr
index 42f65625a46..a25e68c483f 100644
--- a/tests/ui/repr/attr-usage-repr.stderr
+++ b/tests/ui/repr/attr-usage-repr.stderr
@@ -15,21 +15,35 @@ LL | struct SInt(f64, f64);
    | ---------------------- not an enum
 
 error[E0517]: attribute should be applied to a struct or union
-  --> $DIR/attr-usage-repr.rs:24:8
+  --> $DIR/attr-usage-repr.rs:30:8
    |
-LL | #[repr(packed)]
-   |        ^^^^^^
-LL | enum EPacked { A, B }
-   | --------------------- not a struct or union
+LL |   #[repr(packed)]
+   |          ^^^^^^
+LL | / enum EPacked {
+LL | |     A,
+LL | |     B,
+LL | | }
+   | |_- not a struct or union
 
 error[E0517]: attribute should be applied to a struct
-  --> $DIR/attr-usage-repr.rs:27:8
+  --> $DIR/attr-usage-repr.rs:36:8
    |
-LL | #[repr(simd)]
-   |        ^^^^
-LL | enum ESimd { A, B }
-   | ------------------- not a struct
+LL |   #[repr(simd)]
+   |          ^^^^
+LL | / enum ESimd {
+LL | |     A,
+LL | |     B,
+LL | | }
+   | |_- not a struct
 
-error: aborting due to 4 previous errors
+error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union
+  --> $DIR/attr-usage-repr.rs:48:1
+   |
+LL | #[repr()]
+   | ^^^^^^^^^
+LL | type SirThisIsAType = i32;
+   | -------------------------- not a struct, enum, function, associated function, or union
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0517`.
diff --git a/tests/ui/traits/trait-upcasting/mono-impossible.rs b/tests/ui/traits/trait-upcasting/mono-impossible.rs
new file mode 100644
index 00000000000..88f19e1c95f
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/mono-impossible.rs
@@ -0,0 +1,26 @@
+//@ build-pass
+
+#![feature(trait_upcasting)]
+
+trait Supertrait<T> {
+    fn method(&self) {}
+}
+impl<T> Supertrait<T> for () {}
+
+trait WithAssoc {
+    type Assoc;
+}
+trait Trait<P: WithAssoc>: Supertrait<P::Assoc> + Supertrait<()> {}
+
+fn upcast<P>(x: &dyn Trait<P>) -> &dyn Supertrait<()> {
+    x
+}
+
+fn call<P>(x: &dyn Trait<P>) {
+    x.method();
+}
+
+fn main() {
+    println!("{:p}", upcast::<()> as *const ());
+    println!("{:p}", call::<()> as *const ());
+}
diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs
index 1aa64810d19..38dd6dd0af2 100644
--- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs
+++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs
@@ -1,5 +1,4 @@
 //@ edition: 2021
-//@ build-fail
 
 #![feature(impl_trait_in_assoc_type)]
 
diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
index 6cbffaaed4d..304ed12e944 100644
--- a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
+++ b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.stderr
@@ -1,11 +1,11 @@
 error[E0733]: recursion in an async block requires boxing
-  --> $DIR/indirect-recursion-issue-112047.rs:22:9
+  --> $DIR/indirect-recursion-issue-112047.rs:21:9
    |
 LL |         async move { recur(self).await; }
    |         ^^^^^^^^^^   ----------------- recursive call here
    |
 note: which leads to this async fn
-  --> $DIR/indirect-recursion-issue-112047.rs:14:1
+  --> $DIR/indirect-recursion-issue-112047.rs:13:1
    |
 LL | async fn recur(t: impl Recur) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^