diff --git a/Cargo.lock b/Cargo.lock
index 0b9eb88ec2b..e97d29d57ee 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -574,7 +574,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
 
 [[package]]
 name = "clippy"
-version = "0.1.78"
+version = "0.1.79"
 dependencies = [
  "anstream",
  "clippy_config",
@@ -602,7 +602,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_config"
-version = "0.1.78"
+version = "0.1.79"
 dependencies = [
  "rustc-semver",
  "serde",
@@ -625,7 +625,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.78"
+version = "0.1.79"
 dependencies = [
  "arrayvec",
  "cargo_metadata 0.18.1",
@@ -650,7 +650,7 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.78"
+version = "0.1.79"
 dependencies = [
  "arrayvec",
  "clippy_config",
@@ -971,7 +971,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
 
 [[package]]
 name = "declare_clippy_lint"
-version = "0.1.78"
+version = "0.1.79"
 dependencies = [
  "itertools 0.12.1",
  "quote",
@@ -2205,7 +2205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
 dependencies = [
  "cfg-if",
- "windows-targets 0.52.4",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d4d7833cb21..22cf50fce7f 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -597,9 +597,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 
     rustc_attr!(
-        rustc_never_type_mode, Normal, template!(NameValueStr: "fallback_to_unit|fallback_to_niko|fallback_to_never|no_fallback"), ErrorFollowing,
+        rustc_never_type_options,
+        Normal,
+        template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#),
+        ErrorFollowing,
         EncodeCrossCrate::No,
-        "`rustc_never_type_fallback` is used to experiment with never type fallback and work on \
+        "`rustc_never_type_options` is used to experiment with never type fallback and work on \
          never type stabilization, and will never be stable"
     ),
 
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 5118bf5c3b7..dbf86f5cf74 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -214,6 +214,7 @@ language_item_table! {
     FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
 
     Iterator,                sym::iterator,            iterator_trait,             Target::Trait,          GenericRequirement::Exact(0);
+    FusedIterator,           sym::fused_iterator,      fused_iterator_trait,       Target::Trait,          GenericRequirement::Exact(0);
     Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
     AsyncIterator,           sym::async_iterator,      async_iterator_trait,       Target::Trait,          GenericRequirement::Exact(0);
 
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index c16e941d4c5..140618e97cc 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -4,12 +4,11 @@ use rustc_data_structures::{
     graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
     unord::{UnordBag, UnordMap, UnordSet},
 };
-use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::ty::{self, Ty};
-use rustc_span::sym;
 
-enum DivergingFallbackBehavior {
+#[derive(Copy, Clone)]
+pub enum DivergingFallbackBehavior {
     /// Always fallback to `()` (aka "always spontaneous decay")
     FallbackToUnit,
     /// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
@@ -78,9 +77,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
             return false;
         }
 
-        let diverging_behavior = self.diverging_fallback_behavior();
-        let diverging_fallback =
-            self.calculate_diverging_fallback(&unresolved_variables, diverging_behavior);
+        let diverging_fallback = self
+            .calculate_diverging_fallback(&unresolved_variables, self.diverging_fallback_behavior);
 
         // We do fallback in two passes, to try to generate
         // better error messages.
@@ -94,32 +92,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         fallback_occurred
     }
 
-    fn diverging_fallback_behavior(&self) -> DivergingFallbackBehavior {
-        let Some((mode, span)) = self
-            .tcx
-            .get_attr(CRATE_DEF_ID, sym::rustc_never_type_mode)
-            .map(|attr| (attr.value_str().unwrap(), attr.span))
-        else {
-            if self.tcx.features().never_type_fallback {
-                return DivergingFallbackBehavior::FallbackToNiko;
-            }
-
-            return DivergingFallbackBehavior::FallbackToUnit;
-        };
-
-        match mode {
-            sym::fallback_to_unit => DivergingFallbackBehavior::FallbackToUnit,
-            sym::fallback_to_niko => DivergingFallbackBehavior::FallbackToNiko,
-            sym::fallback_to_never => DivergingFallbackBehavior::FallbackToNever,
-            sym::no_fallback => DivergingFallbackBehavior::NoFallback,
-            _ => {
-                self.tcx.dcx().span_err(span, format!("unknown never type mode: `{mode}` (supported: `fallback_to_unit`, `fallback_to_niko`, `fallback_to_never` and `no_fallback`)"));
-
-                DivergingFallbackBehavior::FallbackToUnit
-            }
-        }
-    }
-
     fn fallback_effects(&self) -> bool {
         let unsolved_effects = self.unsolved_effects();
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 5c56c6acd27..19f839b6240 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -45,6 +45,29 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
 use std::iter;
 use std::mem;
 
+#[derive(Clone, Copy, Default)]
+pub enum DivergingBlockBehavior {
+    /// This is the current stable behavior:
+    ///
+    /// ```rust
+    /// {
+    ///     return;
+    /// } // block has type = !, even though we are supposedly dropping it with `;`
+    /// ```
+    #[default]
+    Never,
+
+    /// Alternative behavior:
+    ///
+    /// ```ignore (very-unstable-new-attribute)
+    /// #![rustc_never_type_options(diverging_block_default = "unit")]
+    /// {
+    ///     return;
+    /// } // block has type = (), since we are dropping `!` from `return` with `;`
+    /// ```
+    Unit,
+}
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn check_casts(&mut self) {
         // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors
@@ -1710,7 +1733,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 //
                 // #41425 -- label the implicit `()` as being the
                 // "found type" here, rather than the "expected type".
-                if !self.diverges.get().is_always() {
+                if !self.diverges.get().is_always()
+                    || matches!(self.diverging_block_behavior, DivergingBlockBehavior::Unit)
+                {
                     // #50009 -- Do not point at the entire fn block span, point at the return type
                     // span, as it is the cause of the requirement, and
                     // `consider_hint_about_removing_semicolon` will point at the last expression
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 685b1af931e..1850463194d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -5,7 +5,10 @@ mod checks;
 mod suggestions;
 
 use crate::coercion::DynamicCoerceMany;
+use crate::fallback::DivergingFallbackBehavior;
+use crate::fn_ctxt::checks::DivergingBlockBehavior;
 use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited};
+use hir::def_id::CRATE_DEF_ID;
 use rustc_errors::{DiagCtxt, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -18,7 +21,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
-use rustc_span::{self, Span, DUMMY_SP};
+use rustc_span::{self, sym, Span, DUMMY_SP};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
 
 use std::cell::{Cell, RefCell};
@@ -108,6 +111,9 @@ pub struct FnCtxt<'a, 'tcx> {
     pub(super) inh: &'a Inherited<'tcx>,
 
     pub(super) fallback_has_occurred: Cell<bool>,
+
+    pub(super) diverging_fallback_behavior: DivergingFallbackBehavior,
+    pub(super) diverging_block_behavior: DivergingBlockBehavior,
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -116,6 +122,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         body_id: LocalDefId,
     ) -> FnCtxt<'a, 'tcx> {
+        let (diverging_fallback_behavior, diverging_block_behavior) =
+            parse_never_type_options_attr(inh.tcx);
         FnCtxt {
             body_id,
             param_env,
@@ -131,6 +139,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }),
             inh,
             fallback_has_occurred: Cell::new(false),
+            diverging_fallback_behavior,
+            diverging_block_behavior,
         }
     }
 
@@ -374,3 +384,64 @@ impl<'tcx> LoweredTy<'tcx> {
         LoweredTy { raw, normalized }
     }
 }
+
+fn parse_never_type_options_attr(
+    tcx: TyCtxt<'_>,
+) -> (DivergingFallbackBehavior, DivergingBlockBehavior) {
+    use DivergingFallbackBehavior::*;
+
+    // Error handling is dubious here (unwraps), but that's probably fine for an internal attribute.
+    // Just don't write incorrect attributes <3
+
+    let mut fallback = None;
+    let mut block = None;
+
+    let items = tcx
+        .get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
+        .map(|attr| attr.meta_item_list().unwrap())
+        .unwrap_or_default();
+
+    for item in items {
+        if item.has_name(sym::fallback) && fallback.is_none() {
+            let mode = item.value_str().unwrap();
+            match mode {
+                sym::unit => fallback = Some(FallbackToUnit),
+                sym::niko => fallback = Some(FallbackToNiko),
+                sym::never => fallback = Some(FallbackToNever),
+                sym::no => fallback = Some(NoFallback),
+                _ => {
+                    tcx.dcx().span_err(item.span(), format!("unknown never type fallback mode: `{mode}` (supported: `unit`, `niko`, `never` and `no`)"));
+                }
+            };
+            continue;
+        }
+
+        if item.has_name(sym::diverging_block_default) && fallback.is_none() {
+            let mode = item.value_str().unwrap();
+            match mode {
+                sym::unit => block = Some(DivergingBlockBehavior::Unit),
+                sym::never => block = Some(DivergingBlockBehavior::Never),
+                _ => {
+                    tcx.dcx().span_err(item.span(), format!("unknown diverging block default: `{mode}` (supported: `unit` and `never`)"));
+                }
+            };
+            continue;
+        }
+
+        tcx.dcx().span_err(
+            item.span(),
+            format!(
+                "unknown never type option: `{}` (supported: `fallback`)",
+                item.name_or_empty()
+            ),
+        );
+    }
+
+    let fallback = fallback.unwrap_or_else(|| {
+        if tcx.features().never_type_fallback { FallbackToNiko } else { FallbackToUnit }
+    });
+
+    let block = block.unwrap_or_default();
+
+    (fallback, block)
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8b35087a005..8530c6072c5 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -207,6 +207,7 @@ symbols! {
         FromResidual,
         FsOpenOptions,
         FsPermissions,
+        FusedIterator,
         Future,
         FutureOutput,
         GlobalAlloc,
@@ -690,6 +691,7 @@ symbols! {
         dispatch_from_dyn,
         div,
         div_assign,
+        diverging_block_default,
         do_not_recommend,
         doc,
         doc_alias,
@@ -815,9 +817,7 @@ symbols! {
         fadd_algebraic,
         fadd_fast,
         fake_variadic,
-        fallback_to_never,
-        fallback_to_niko,
-        fallback_to_unit,
+        fallback,
         fdiv_algebraic,
         fdiv_fast,
         feature,
@@ -886,6 +886,7 @@ symbols! {
         fsub_algebraic,
         fsub_fast,
         fundamental,
+        fused_iterator,
         future,
         future_trait,
         gdb_script_file,
@@ -1228,6 +1229,7 @@ symbols! {
         new_v1,
         new_v1_formatted,
         next,
+        niko,
         nll,
         no,
         no_builtins,
@@ -1236,7 +1238,6 @@ symbols! {
         no_crate_inject,
         no_debug,
         no_default_passes,
-        no_fallback,
         no_implicit_prelude,
         no_inline,
         no_link,
@@ -1554,7 +1555,7 @@ symbols! {
         rustc_mir,
         rustc_must_implement_one_of,
         rustc_never_returns_null_ptr,
-        rustc_never_type_mode,
+        rustc_never_type_options,
         rustc_no_mir_inline,
         rustc_nonnull_optimization_guaranteed,
         rustc_nounwind,
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 9f33dce2a6d..d92bae2528f 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -215,6 +215,13 @@ pub(super) trait GoalKind<'tcx>:
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
 
+    /// A coroutine (that comes from a `gen` desugaring) is known to implement
+    /// `FusedIterator`
+    fn consider_builtin_fused_iterator_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx>;
+
     fn consider_builtin_async_iterator_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
@@ -497,6 +504,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             G::consider_builtin_future_candidate(self, goal)
         } else if lang_items.iterator_trait() == Some(trait_def_id) {
             G::consider_builtin_iterator_candidate(self, goal)
+        } else if lang_items.fused_iterator_trait() == Some(trait_def_id) {
+            G::consider_builtin_fused_iterator_candidate(self, goal)
         } else if lang_items.async_iterator_trait() == Some(trait_def_id) {
             G::consider_builtin_async_iterator_candidate(self, goal)
         } else if lang_items.coroutine_trait() == Some(trait_def_id) {
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 85bb6338daf..66688893235 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -647,6 +647,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         )
     }
 
+    fn consider_builtin_fused_iterator_candidate(
+        _ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        bug!("`FusedIterator` does not have an associated type: {:?}", goal);
+    }
+
     fn consider_builtin_async_iterator_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index c252ad76dfe..184ba31f19d 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -456,6 +456,28 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 
+    fn consider_builtin_fused_iterator_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        if goal.predicate.polarity != ty::ImplPolarity::Positive {
+            return Err(NoSolution);
+        }
+
+        let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else {
+            return Err(NoSolution);
+        };
+
+        // Coroutines are not iterators unless they come from `gen` desugaring
+        let tcx = ecx.tcx();
+        if !tcx.coroutine_is_gen(def_id) {
+            return Err(NoSolution);
+        }
+
+        // Gen coroutines unconditionally implement `FusedIterator`
+        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+    }
+
     fn consider_builtin_async_iterator_candidate(
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 49091e53be7..9fb4577fb21 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -118,6 +118,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.assemble_future_candidates(obligation, &mut candidates);
                 } else if lang_items.iterator_trait() == Some(def_id) {
                     self.assemble_iterator_candidates(obligation, &mut candidates);
+                } else if lang_items.fused_iterator_trait() == Some(def_id) {
+                    self.assemble_fused_iterator_candidates(obligation, &mut candidates);
                 } else if lang_items.async_iterator_trait() == Some(def_id) {
                     self.assemble_async_iterator_candidates(obligation, &mut candidates);
                 } else if lang_items.async_fn_kind_helper() == Some(def_id) {
@@ -302,14 +304,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
         let self_ty = obligation.self_ty().skip_binder();
-        if let ty::Coroutine(did, ..) = self_ty.kind() {
-            // gen constructs get lowered to a special kind of coroutine that
-            // should directly `impl Iterator`.
-            if self.tcx().coroutine_is_gen(*did) {
-                debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
+        // gen constructs get lowered to a special kind of coroutine that
+        // should directly `impl Iterator`.
+        if let ty::Coroutine(did, ..) = self_ty.kind()
+            && self.tcx().coroutine_is_gen(*did)
+        {
+            debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
 
-                candidates.vec.push(IteratorCandidate);
-            }
+            candidates.vec.push(IteratorCandidate);
+        }
+    }
+
+    fn assemble_fused_iterator_candidates(
+        &mut self,
+        obligation: &PolyTraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        let self_ty = obligation.self_ty().skip_binder();
+        // gen constructs get lowered to a special kind of coroutine that
+        // should directly `impl FusedIterator`.
+        if let ty::Coroutine(did, ..) = self_ty.kind()
+            && self.tcx().coroutine_is_gen(*did)
+        {
+            debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
+
+            candidates.vec.push(BuiltinCandidate { has_nested: false });
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 557fc99a536..6f16194d44f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -267,6 +267,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 self.copy_clone_conditions(obligation)
             } else if Some(trait_def) == lang_items.clone_trait() {
                 self.copy_clone_conditions(obligation)
+            } else if Some(trait_def) == lang_items.fused_iterator_trait() {
+                self.fused_iterator_conditions(obligation)
             } else {
                 bug!("unexpected builtin trait {:?}", trait_def)
             };
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 53aadfb8a44..adbc7d12a64 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2259,6 +2259,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         }
     }
 
+    fn fused_iterator_conditions(
+        &mut self,
+        obligation: &PolyTraitObligation<'tcx>,
+    ) -> BuiltinImplConditions<'tcx> {
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        if let ty::Coroutine(did, ..) = *self_ty.kind()
+            && self.tcx().coroutine_is_gen(did)
+        {
+            BuiltinImplConditions::Where(ty::Binder::dummy(Vec::new()))
+        } else {
+            BuiltinImplConditions::None
+        }
+    }
+
     /// For default impls, we need to break apart a type into its
     /// "constituent types" -- meaning, the types that it contains.
     ///
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index e99c6220e20..3875f61efaf 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -72,7 +72,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 /// `BTreeMap` that observed the logic error and not result in undefined behavior. This could
 /// include panics, incorrect results, aborts, memory leaks, and non-termination.
 ///
-/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::values`], or
+/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or
 /// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
 /// amortized constant time per item returned.
 ///
@@ -415,7 +415,7 @@ impl<'a, K: 'a, V: 'a> Default for IterMut<'a, K, V> {
     }
 }
 
-/// An owning iterator over the entries of a `BTreeMap`.
+/// An owning iterator over the entries of a `BTreeMap`, sorted by key.
 ///
 /// This `struct` is created by the [`into_iter`] method on [`BTreeMap`]
 /// (provided by the [`IntoIterator`] trait). See its documentation for more.
@@ -1637,6 +1637,7 @@ impl<K, V, A: Allocator + Clone> IntoIterator for BTreeMap<K, V, A> {
     type Item = (K, V);
     type IntoIter = IntoIter<K, V, A>;
 
+    /// Gets an owning iterator over the entries of the map, sorted by key.
     fn into_iter(self) -> IntoIter<K, V, A> {
         let mut me = ManuallyDrop::new(self);
         if let Some(root) = me.root.take() {
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index ed91ae1a66e..7508ae468ae 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -27,7 +27,7 @@ use crate::alloc::{Allocator, Global};
 /// `BTreeSet` that observed the logic error and not result in undefined behavior. This could
 /// include panics, incorrect results, aborts, memory leaks, and non-termination.
 ///
-/// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case
+/// Iterators returned by [`BTreeSet::iter`] and [`BTreeSet::into_iter`] produce their items in order, and take worst-case
 /// logarithmic and amortized constant time per item returned.
 ///
 /// [`Cell`]: core::cell::Cell
@@ -140,7 +140,7 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
     }
 }
 
-/// An owning iterator over the items of a `BTreeSet`.
+/// An owning iterator over the items of a `BTreeSet` in ascending order.
 ///
 /// This `struct` is created by the [`into_iter`] method on [`BTreeSet`]
 /// (provided by the [`IntoIterator`] trait). See its documentation for more.
@@ -1237,7 +1237,7 @@ impl<T, A: Allocator + Clone> IntoIterator for BTreeSet<T, A> {
     type Item = T;
     type IntoIter = IntoIter<T, A>;
 
-    /// Gets an iterator for moving out the `BTreeSet`'s contents.
+    /// Gets an iterator for moving out the `BTreeSet`'s contents in ascending order.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs
index 8bdbca120d7..ad4d63d83b5 100644
--- a/library/core/src/iter/traits/marker.rs
+++ b/library/core/src/iter/traits/marker.rs
@@ -28,6 +28,7 @@ pub unsafe trait TrustedFused {}
 #[rustc_unsafe_specialization_marker]
 // FIXME: this should be a #[marker] and have another blanket impl for T: TrustedFused
 // but that ICEs iter::Fuse specializations.
+#[cfg_attr(not(bootstrap), lang = "fused_iterator")]
 pub trait FusedIterator: Iterator {}
 
 #[stable(feature = "fused", since = "1.26.0")]
diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs
index 33990d54caa..b7e0fdc0a9a 100644
--- a/library/std/src/os/freebsd/net.rs
+++ b/library/std/src/os/freebsd/net.rs
@@ -2,6 +2,7 @@
 
 #![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 
+use crate::ffi::CStr;
 use crate::io;
 use crate::os::unix::net;
 use crate::sealed::Sealed;
@@ -40,6 +41,15 @@ pub trait UnixSocketExt: Sealed {
     /// ```
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>;
+
+    /// Get a filter name if one had been set previously on the socket.
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn acceptfilter(&self) -> io::Result<&CStr>;
+
+    /// Set or disable a filter on the socket to filter incoming connections
+    /// to defer it before accept(2)
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()>;
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -51,6 +61,14 @@ impl UnixSocketExt for net::UnixDatagram {
     fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
         self.as_inner().set_local_creds_persistent(local_creds_persistent)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -62,4 +80,12 @@ impl UnixSocketExt for net::UnixStream {
     fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
         self.as_inner().set_local_creds_persistent(local_creds_persistent)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs
index 5c82f43077d..b9679c7b3af 100644
--- a/library/std/src/os/netbsd/net.rs
+++ b/library/std/src/os/netbsd/net.rs
@@ -2,6 +2,7 @@
 
 #![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 
+use crate::ffi::CStr;
 use crate::io;
 use crate::os::unix::net;
 use crate::sealed::Sealed;
@@ -40,6 +41,15 @@ pub trait UnixSocketExt: Sealed {
     /// ```
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     fn set_local_creds(&self, local_creds: bool) -> io::Result<()>;
+
+    /// Get a filter name if one had been set previously on the socket.
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn acceptfilter(&self) -> io::Result<&CStr>;
+
+    /// Set or disable a filter on the socket to filter incoming connections
+    /// to defer it before accept(2)
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()>;
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -51,6 +61,14 @@ impl UnixSocketExt for net::UnixDatagram {
     fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
         self.as_inner().set_local_creds(local_creds)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -62,4 +80,12 @@ impl UnixSocketExt for net::UnixStream {
     fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
         self.as_inner().set_local_creds(local_creds)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index 09750b6ffc8..1f140f7844f 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -453,6 +453,37 @@ impl Socket {
         Ok(raw as u32)
     }
 
+    #[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
+    pub fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        if !name.to_bytes().is_empty() {
+            const AF_NAME_MAX: usize = 16;
+            let mut buf = [0; AF_NAME_MAX];
+            for (src, dst) in name.to_bytes().iter().zip(&mut buf[..AF_NAME_MAX - 1]) {
+                *dst = *src as i8;
+            }
+            let mut arg: libc::accept_filter_arg = unsafe { mem::zeroed() };
+            arg.af_name = buf;
+            setsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER, &mut arg)
+        } else {
+            setsockopt(
+                self,
+                libc::SOL_SOCKET,
+                libc::SO_ACCEPTFILTER,
+                core::ptr::null_mut() as *mut c_void,
+            )
+        }
+    }
+
+    #[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
+    pub fn acceptfilter(&self) -> io::Result<&CStr> {
+        let arg: libc::accept_filter_arg =
+            getsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER)?;
+        let s: &[u8] =
+            unsafe { core::slice::from_raw_parts(arg.af_name.as_ptr() as *const u8, 16) };
+        let name = CStr::from_bytes_with_nul(s).unwrap();
+        Ok(name)
+    }
+
     #[cfg(any(target_os = "android", target_os = "linux",))]
     pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
         setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index f1edbb5ad8a..d8397ab51de 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -1009,15 +1009,23 @@ impl Build {
         let result = if !output.status.success() {
             if print_error {
                 println!(
-                    "\n\ncommand did not execute successfully: {:?}\n\
-                    expected success, got: {}\n\n\
-                    stdout ----\n{}\n\
-                    stderr ----\n{}\n\n",
-                    command.command,
+                    "\n\nCommand did not execute successfully.\
+                    \nExpected success, got: {}",
                     output.status,
-                    String::from_utf8_lossy(&output.stdout),
-                    String::from_utf8_lossy(&output.stderr)
                 );
+
+                if !self.is_verbose() {
+                    println!("Add `-v` to see more details.\n");
+                }
+
+                self.verbose(|| {
+                    println!(
+                        "\nSTDOUT ----\n{}\n\
+                        STDERR ----\n{}\n",
+                        String::from_utf8_lossy(&output.stdout),
+                        String::from_utf8_lossy(&output.stderr)
+                    )
+                });
             }
             Err(())
         } else {
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 603f91a910b..8179e3e65b5 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -26,6 +26,12 @@ env:
   NO_FMT_TEST: 1
   CARGO_INCREMENTAL: 0
 
+concurrency:
+  # For a given workflow, if we push to the same PR, cancel all previous builds on that PR.
+  # If the push is not attached to a PR, we will cancel all builds on the same branch.
+  group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}"
+  cancel-in-progress: true
+
 jobs:
   base:
     # NOTE: If you modify this job, make sure you copy the changes to clippy_bors.yml
@@ -33,10 +39,6 @@ jobs:
 
     steps:
     # Setup
-    - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
-      with:
-        github_token: "${{ secrets.github_token }}"
-
     - name: Checkout
       uses: actions/checkout@v4
 
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 0bc28c1f9d9..94515987eba 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -12,6 +12,11 @@ env:
   NO_FMT_TEST: 1
   CARGO_INCREMENTAL: 0
 
+concurrency:
+  # For a given workflow, if we push to the same branch, cancel all previous builds on that branch.
+  group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}"
+  cancel-in-progress: true
+
 defaults:
   run:
     shell: bash
@@ -21,10 +26,6 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-    - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
-      with:
-        github_token: "${{ secrets.github_token }}"
-
     - name: Checkout
       uses: actions/checkout@v4
       with:
@@ -67,10 +68,6 @@ jobs:
     # NOTE: If you modify this job, make sure you copy the changes to clippy.yml
     steps:
     # Setup
-    - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
-      with:
-        github_token: "${{ secrets.github_token }}"
-
     - name: Checkout
       uses: actions/checkout@v4
 
@@ -131,10 +128,6 @@ jobs:
 
     steps:
      # Setup
-    - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
-      with:
-        github_token: "${{ secrets.github_token }}"
-
     - name: Checkout
       uses: actions/checkout@v4
 
@@ -155,10 +148,6 @@ jobs:
 
     steps:
     # Setup
-    - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
-      with:
-        github_token: "${{ secrets.github_token }}"
-
     - name: Checkout
       uses: actions/checkout@v4
 
@@ -211,10 +200,6 @@ jobs:
 
     steps:
     # Setup
-    - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
-      with:
-        github_token: "${{ secrets.github_token }}"
-
     - name: Checkout
       uses: actions/checkout@v4
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index d3b2c0a7bf6..76ef84a48b8 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,65 @@ document.
 
 ## Unreleased / Beta / In Rust Nightly
 
-[a859e5cc...master](https://github.com/rust-lang/rust-clippy/compare/a859e5cc...master)
+[66c29b97...master](https://github.com/rust-lang/rust-clippy/compare/66c29b97...master)
+
+## Rust 1.77
+
+Current stable, released 2024-03-18
+
+[View all 93 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-12-16T18%3A20%3A00Z..2024-01-25T18%3A15%3A56Z+base%3Amaster)
+
+### New Lints
+
+* [`suspicious_open_options`]
+  [#11608](https://github.com/rust-lang/rust-clippy/pull/11608)
+* [`option_as_ref_cloned`]
+  [#12051](https://github.com/rust-lang/rust-clippy/pull/12051)
+* [`thread_local_initializer_can_be_made_const`]
+  [#12026](https://github.com/rust-lang/rust-clippy/pull/12026)
+* [`str_split_at_newline`]
+  [#11987](https://github.com/rust-lang/rust-clippy/pull/11987)
+* [`empty_enum_variants_with_brackets`]
+  [#12047](https://github.com/rust-lang/rust-clippy/pull/12047)
+* [`manual_is_variant_and`]
+  [#11865](https://github.com/rust-lang/rust-clippy/pull/11865)
+* [`pub_underscore_fields`]
+  [#10283](https://github.com/rust-lang/rust-clippy/pull/10283)
+* [`eager_transmute`]
+  [#11981](https://github.com/rust-lang/rust-clippy/pull/11981)
+* [`iter_filter_is_some`]
+  [#12004](https://github.com/rust-lang/rust/pull/12004)
+* [`iter_filter_is_ok`]
+  [#12004](https://github.com/rust-lang/rust/pull/12004)
+* [`result_filter_map`]
+  [#11869](https://github.com/rust-lang/rust-clippy/pull/11869)
+* [`unconditional_recursion`]
+  [#11938](https://github.com/rust-lang/rust-clippy/pull/11938)
+
+### Enhancements
+
+* [`multiple_crate_versions`]: Added the [`allowed-duplicate-crates`] configuration to allow specific crates
+  [#12179](https://github.com/rust-lang/rust-clippy/pull/12179)
+* [`single_call_fn`]: No longer ignores `#[allow]` attributes
+  [#12183](https://github.com/rust-lang/rust-clippy/pull/12183)
+* [`read_zero_byte_vec`]: Updated the heuristics used for linting
+  [#11766](https://github.com/rust-lang/rust-clippy/pull/11766)
+
+### ICE Fixes
+
+* [`unit_arg`]: No longer crashes when checking for const in nested bodies
+  [#11977](https://github.com/rust-lang/rust-clippy/pull/11977)
+* [`indexing_slicing`]: No longer crashes when the array index exceeds `usize`
+  [#12266](https://github.com/rust-lang/rust-clippy/pull/12266)
+
+### Others
+
+* Warnings about invalid fields inside `clippy.toml` files now include suggestions for existing fields
+  [#12180](https://github.com/rust-lang/rust-clippy/pull/12180)
 
 ## Rust 1.76
 
-Current stable, released 2024-02-08
+Released 2024-02-08
 
 [View all 85 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-11-02T20%3A23%3A40Z..2023-12-16T13%3A11%3A08Z+base%3Amaster)
 
@@ -5110,6 +5164,7 @@ Released 2018-09-13
 [`collection_is_never_read`]: https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read
 [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
 [`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
+[`const_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_is_empty
 [`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_static_lifetime
 [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
 [`crate_in_macro_def`]: https://rust-lang.github.io/rust-clippy/master/index.html#crate_in_macro_def
@@ -5156,6 +5211,7 @@ Released 2018-09-13
 [`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref
 [`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod
 [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument
+[`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes
 [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
 [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute
 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
@@ -5279,6 +5335,7 @@ Released 2018-09-13
 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
 [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic
 [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
+[`integer_division_remainder_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division_remainder_used
 [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
 [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
 [`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_without_iter
@@ -5376,6 +5433,7 @@ Released 2018-09-13
 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
 [`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold
 [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
+[`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default
 [`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some
 [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
 [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
@@ -5813,6 +5871,7 @@ Released 2018-09-13
 [`zero_divided_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_divided_by_zero
 [`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal
 [`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr
+[`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects
 [`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values
 [`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
 [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 5d1d0ce2c42..2b37b54c004 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.78"
+version = "0.1.79"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -24,7 +24,7 @@ path = "src/driver.rs"
 clippy_config = { path = "clippy_config" }
 clippy_lints = { path = "clippy_lints" }
 rustc_tools_util = "0.3.0"
-tempfile = { version = "3.2", optional = true }
+tempfile = { version = "3.3", optional = true }
 termize = "0.1"
 color-print = "0.3.4"
 anstream = "0.6.0"
@@ -32,18 +32,18 @@ anstream = "0.6.0"
 [dev-dependencies]
 ui_test = "0.22.2"
 tester = "0.9"
-regex = "1.5"
+regex = "1.5.5"
 toml = "0.7.3"
 walkdir = "2.3"
 # This is used by the `collect-metadata` alias.
-filetime = "0.2"
+filetime = "0.2.9"
 itertools = "0.12"
 
 # UI test dependencies
 clippy_utils = { path = "clippy_utils" }
 if_chain = "1.0"
-quote = "1.0"
-serde = { version = "1.0.125", features = ["derive"] }
+quote = "1.0.25"
+serde = { version = "1.0.145", features = ["derive"] }
 syn = { version = "2.0", features = ["full"] }
 futures = "0.3"
 parking_lot = "0.12"
diff --git a/src/tools/clippy/book/src/development/macro_expansions.md b/src/tools/clippy/book/src/development/macro_expansions.md
index aecca9ef72e..125b6c4bc5b 100644
--- a/src/tools/clippy/book/src/development/macro_expansions.md
+++ b/src/tools/clippy/book/src/development/macro_expansions.md
@@ -52,7 +52,7 @@ if expr.span.from_expansion() {
 
 ### `Span.ctxt` method
 
-The `span`'s context, given by the method [`ctxt`] and returning [SpanContext],
+The `span`'s context, given by the method [`ctxt`] and returning [SyntaxContext],
 represents if the span is from a macro expansion and, if it is, which
 macro call expanded this span.
 
@@ -155,4 +155,4 @@ if in_external_macro(cx.sess(), foo_span) {
 [`from_expansion`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion
 [`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html
 [Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html
-[SpanContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html
+[SyntaxContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index a985346b3c0..a9234899746 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -602,6 +602,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
 **Affected lints:**
 * [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
 * [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
+* [`assigning_clones`](https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones)
 * [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
 * [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
 * [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml
index 8c405ac6a4e..62ed55beb1f 100644
--- a/src/tools/clippy/clippy.toml
+++ b/src/tools/clippy/clippy.toml
@@ -1,7 +1,10 @@
 avoid-breaking-exported-api = false
 
-# use the various `span_lint_*` methods instead, which also add a link to the docs
-disallowed-methods = [
-    "rustc_lint::context::LintContext::span_lint",
-    "rustc_middle::ty::context::TyCtxt::node_span_lint"
-]
+[[disallowed-methods]]
+path = "rustc_lint::context::LintContext::span_lint"
+reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
+
+
+[[disallowed-methods]]
+path = "rustc_middle::ty::context::TyCtxt::node_span_lint"
+reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead"
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index 2edc5ed592c..8ba2ab56625 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.78"
+version = "0.1.79"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 673b6328b39..3218fe7f456 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -262,7 +262,7 @@ define_Conf! {
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS.
+    /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES.
     ///
     /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
     #[default_text = ""]
diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs
index a8a32f7ed20..bf4da5f14fe 100644
--- a/src/tools/clippy/clippy_config/src/msrvs.rs
+++ b/src/tools/clippy/clippy_config/src/msrvs.rs
@@ -23,6 +23,7 @@ msrv_aliases! {
     1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
+    1,63,0 { ASSIGNING_CLONES }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
     1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST }
     1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 2222abff7ad..76ae26dddf4 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -689,6 +689,8 @@ fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String {
 fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
     let mut seen_lints = HashSet::new();
     let mut res: String = GENERATED_FILE_COMMENT.into();
+
+    res.push_str("#![allow(clippy::duplicated_attributes)]\n");
     for lint in lints {
         if seen_lints.insert(&lint.new_name) {
             writeln!(res, "#![allow({})]", lint.new_name).unwrap();
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 6ae089b3e03..1d954607eee 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.78"
+version = "0.1.79"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index b1c552c7a8d..88d9f762a87 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -1,3 +1,4 @@
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::HirNode;
 use clippy_utils::sugg::Sugg;
@@ -6,7 +7,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{self as hir, Expr, ExprKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, Instance, Mutability};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::sym;
 use rustc_span::ExpnKind;
@@ -49,7 +50,19 @@ declare_clippy_lint! {
     perf,
     "assigning the result of cloning may be inefficient"
 }
-declare_lint_pass!(AssigningClones => [ASSIGNING_CLONES]);
+
+pub struct AssigningClones {
+    msrv: Msrv,
+}
+
+impl AssigningClones {
+    #[must_use]
+    pub fn new(msrv: Msrv) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]);
 
 impl<'tcx> LateLintPass<'tcx> for AssigningClones {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) {
@@ -68,10 +81,12 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
             return;
         };
 
-        if is_ok_to_suggest(cx, lhs, &call) {
+        if is_ok_to_suggest(cx, lhs, &call, &self.msrv) {
             suggest(cx, assign_expr, lhs, &call);
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 // Try to resolve the call to `Clone::clone` or `ToOwned::to_owned`.
@@ -135,7 +150,13 @@ fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<
 
 // Return true if we find that the called method has a custom implementation and isn't derived or
 // provided by default by the corresponding trait.
-fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) -> bool {
+fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>, msrv: &Msrv) -> bool {
+    // For calls to .to_owned we suggest using .clone_into(), which was only stablilized in 1.63.
+    // If the current MSRV is below that, don't suggest the lint.
+    if !msrv.meets(msrvs::ASSIGNING_CLONES) && matches!(call.target, TargetTrait::ToOwned) {
+        return false;
+    }
+
     // If the left-hand side is a local variable, it might be uninitialized at this point.
     // In that case we do not want to suggest the lint.
     if let Some(local) = path_to_local(lhs) {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
new file mode 100644
index 00000000000..3c5ac597fd5
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -0,0 +1,64 @@
+use super::DUPLICATED_ATTRIBUTES;
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_ast::{Attribute, MetaItem};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_lint::EarlyContext;
+use rustc_span::{sym, Span};
+use std::collections::hash_map::Entry;
+
+fn emit_if_duplicated(
+    cx: &EarlyContext<'_>,
+    attr: &MetaItem,
+    attr_paths: &mut FxHashMap<String, Span>,
+    complete_path: String,
+) {
+    match attr_paths.entry(complete_path) {
+        Entry::Vacant(v) => {
+            v.insert(attr.span);
+        },
+        Entry::Occupied(o) => {
+            span_lint_and_then(cx, DUPLICATED_ATTRIBUTES, attr.span, "duplicated attribute", |diag| {
+                diag.span_note(*o.get(), "first defined here");
+                diag.span_help(attr.span, "remove this attribute");
+            });
+        },
+    }
+}
+
+fn check_duplicated_attr(
+    cx: &EarlyContext<'_>,
+    attr: &MetaItem,
+    attr_paths: &mut FxHashMap<String, Span>,
+    parent: &mut Vec<String>,
+) {
+    let Some(ident) = attr.ident() else { return };
+    let name = ident.name;
+    if name == sym::doc || name == sym::cfg_attr {
+        // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
+        // conditions are the same.
+        return;
+    }
+    if let Some(value) = attr.value_str() {
+        emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}={value}", parent.join(":")));
+    } else if let Some(sub_attrs) = attr.meta_item_list() {
+        parent.push(name.as_str().to_string());
+        for sub_attr in sub_attrs {
+            if let Some(meta) = sub_attr.meta_item() {
+                check_duplicated_attr(cx, meta, attr_paths, parent);
+            }
+        }
+        parent.pop();
+    } else {
+        emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}", parent.join(":")));
+    }
+}
+
+pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
+    let mut attr_paths = FxHashMap::default();
+
+    for attr in attrs {
+        if let Some(meta) = attr.meta() {
+            check_duplicated_attr(cx, &meta, &mut attr_paths, &mut Vec::new());
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index c4c65d3248a..675c428948f 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -4,6 +4,7 @@ mod allow_attributes_without_reason;
 mod blanket_clippy_restriction_lints;
 mod deprecated_cfg_attr;
 mod deprecated_semver;
+mod duplicated_attributes;
 mod empty_line_after;
 mod inline_always;
 mod maybe_misused_cfg;
@@ -16,7 +17,7 @@ mod useless_attribute;
 mod utils;
 
 use clippy_config::msrvs::Msrv;
-use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
+use rustc_ast::{Attribute, Crate, MetaItemKind, NestedMetaItem};
 use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, impl_lint_pass};
@@ -489,6 +490,32 @@ declare_clippy_lint! {
     "item has both inner and outer attributes"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for attributes that appear two or more times.
+    ///
+    /// ### Why is this bad?
+    /// Repeating an attribute on the same item (or globally on the same crate)
+    /// is unnecessary and doesn't have an effect.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[allow(dead_code)]
+    /// #[allow(dead_code)]
+    /// fn foo() {}
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #[allow(dead_code)]
+    /// fn foo() {}
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub DUPLICATED_ATTRIBUTES,
+    suspicious,
+    "duplicated attribute"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -568,12 +595,18 @@ impl_lint_pass!(EarlyAttributes => [
     DEPRECATED_CLIPPY_CFG_ATTR,
     UNNECESSARY_CLIPPY_CFG,
     MIXED_ATTRIBUTES_STYLE,
+    DUPLICATED_ATTRIBUTES,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
+        duplicated_attributes::check(cx, &krate.attrs);
+    }
+
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
         empty_line_after::check(cx, item);
         mixed_attributes_style::check(cx, item);
+        duplicated_attributes::check(cx, &item.attrs);
     }
 
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index fe2455f4b23..86f4332d05a 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -1,12 +1,12 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::in_constant;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{snippet_opt, snippet_with_applicability};
 use clippy_utils::ty::is_isize_or_usize;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, QPath, TyKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_middle::ty::{self, FloatTy, Ty, UintTy};
 
 use super::{utils, CAST_LOSSLESS};
 
@@ -16,6 +16,7 @@ pub(super) fn check(
     cast_op: &Expr<'_>,
     cast_from: Ty<'_>,
     cast_to: Ty<'_>,
+    cast_to_hir: &rustc_hir::Ty<'_>,
     msrv: &Msrv,
 ) {
     if !should_lint(cx, expr, cast_from, cast_to, msrv) {
@@ -24,11 +25,11 @@ pub(super) fn check(
 
     // The suggestion is to use a function call, so if the original expression
     // has parens on the outside, they are no longer needed.
-    let mut applicability = Applicability::MachineApplicable;
+    let mut app = Applicability::MachineApplicable;
     let opt = snippet_opt(cx, cast_op.span.source_callsite());
     let sugg = opt.as_ref().map_or_else(
         || {
-            applicability = Applicability::HasPlaceholders;
+            app = Applicability::HasPlaceholders;
             ".."
         },
         |snip| {
@@ -40,10 +41,27 @@ pub(super) fn check(
         },
     );
 
-    let message = if cast_from.is_bool() {
-        format!("casting `{cast_from:}` to `{cast_to:}` is more cleanly stated with `{cast_to:}::from(_)`")
+    // Display the type alias instead of the aliased type. Fixes #11285
+    //
+    // FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead,
+    // this will allow us to display the right type with `cast_from` as well.
+    let cast_to_fmt = if let TyKind::Path(QPath::Resolved(None, path)) = cast_to_hir.kind
+        // It's a bit annoying but the turbofish is optional for types. A type in an `as` cast
+        // shouldn't have these if they're primitives, which are the only things we deal with.
+        //
+        // This could be removed for performance if this check is determined to have a pretty major
+        // effect.
+        && path.segments.iter().all(|segment| segment.args.is_none())
+    {
+        snippet_with_applicability(cx, cast_to_hir.span, "..", &mut app)
     } else {
-        format!("casting `{cast_from}` to `{cast_to}` may become silently lossy if you later change the type")
+        cast_to.to_string().into()
+    };
+
+    let message = if cast_from.is_bool() {
+        format!("casting `{cast_from}` to `{cast_to_fmt}` is more cleanly stated with `{cast_to_fmt}::from(_)`")
+    } else {
+        format!("casting `{cast_from}` to `{cast_to_fmt}` may become silently lossy if you later change the type")
     };
 
     span_lint_and_sugg(
@@ -52,14 +70,17 @@ pub(super) fn check(
         expr.span,
         &message,
         "try",
-        format!("{cast_to}::from({sugg})"),
-        applicability,
+        format!("{cast_to_fmt}::from({sugg})"),
+        app,
     );
 }
 
 fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool {
     // Do not suggest using From in consts/statics until it is valid to do so (see #2267).
-    if in_constant(cx, expr.hir_id) {
+    //
+    // If destination is u128, do not lint because source type cannot be larger
+    // If source is bool, still lint due to the lint message differing (refers to style)
+    if in_constant(cx, expr.hir_id) || (!cast_from.is_bool() && matches!(cast_to.kind(), ty::Uint(UintTy::U128))) {
         return false;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 14f2f4a7f59..063aab28238 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -791,7 +791,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
                     cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
                     cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to);
                 }
-                cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
+                cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir, &self.msrv);
                 cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index ec66556cebf..e2296767431 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -1,12 +1,14 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::root_macro_call_first_node;
+use clippy_utils::macros::{macro_backtrace, MacroCall};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_in_cfg_test, is_in_test_function};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, Node};
+use rustc_hir::{Expr, ExprKind, HirId, Node};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::sym;
+use rustc_span::{sym, Span, SyntaxContext};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -31,31 +33,38 @@ declare_clippy_lint! {
     "`dbg!` macro is intended as a debugging tool"
 }
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct DbgMacro {
     allow_dbg_in_tests: bool,
+    /// Tracks the `dbg!` macro callsites that are already checked.
+    checked_dbg_call_site: FxHashSet<Span>,
+    /// Tracks the previous `SyntaxContext`, to avoid walking the same context chain.
+    prev_ctxt: SyntaxContext,
 }
 
 impl_lint_pass!(DbgMacro => [DBG_MACRO]);
 
 impl DbgMacro {
     pub fn new(allow_dbg_in_tests: bool) -> Self {
-        DbgMacro { allow_dbg_in_tests }
+        DbgMacro {
+            allow_dbg_in_tests,
+            checked_dbg_call_site: FxHashSet::default(),
+            prev_ctxt: SyntaxContext::root(),
+        }
     }
 }
 
 impl LateLintPass<'_> for DbgMacro {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let Some(macro_call) = root_macro_call_first_node(cx, expr) else {
-            return;
-        };
-        if cx.tcx.is_diagnostic_item(sym::dbg_macro, macro_call.def_id) {
+        let cur_syntax_ctxt = expr.span.ctxt();
+
+        if cur_syntax_ctxt != self.prev_ctxt &&
+            let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) &&
+            !in_external_macro(cx.sess(), macro_call.span) &&
+            self.checked_dbg_call_site.insert(macro_call.span) &&
             // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
-            if self.allow_dbg_in_tests
-                && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id))
-            {
-                return;
-            }
+            !(self.allow_dbg_in_tests && is_in_test(cx, expr.hir_id))
+        {
             let mut applicability = Applicability::MachineApplicable;
 
             let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
@@ -101,6 +110,8 @@ impl LateLintPass<'_> for DbgMacro {
                 _ => return,
             };
 
+            self.prev_ctxt = cur_syntax_ctxt;
+
             span_lint_and_sugg(
                 cx,
                 DBG_MACRO,
@@ -112,4 +123,16 @@ impl LateLintPass<'_> for DbgMacro {
             );
         }
     }
+
+    fn check_crate_post(&mut self, _: &LateContext<'_>) {
+        self.checked_dbg_call_site = FxHashSet::default();
+    }
+}
+
+fn is_in_test(cx: &LateContext<'_>, hir_id: HirId) -> bool {
+    is_in_test_function(cx.tcx, hir_id) || is_in_cfg_test(cx.tcx, hir_id)
+}
+
+fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
+    macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
 }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 2b324f5f96e..c8e148598a2 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -54,6 +54,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::DEPRECATED_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
+    crate::attrs::DUPLICATED_ATTRIBUTES_INFO,
     crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
@@ -235,6 +236,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::instant_subtraction::MANUAL_INSTANT_ELAPSED_INFO,
     crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
     crate::int_plus_one::INT_PLUS_ONE_INFO,
+    crate::integer_division_remainder_used::INTEGER_DIVISION_REMAINDER_USED_INFO,
     crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
     crate::item_name_repetitions::ENUM_VARIANT_NAMES_INFO,
     crate::item_name_repetitions::MODULE_INCEPTION_INFO,
@@ -310,6 +312,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO,
     crate::manual_string_new::MANUAL_STRING_NEW_INFO,
     crate::manual_strip::MANUAL_STRIP_INFO,
+    crate::manual_unwrap_or_default::MANUAL_UNWRAP_OR_DEFAULT_INFO,
     crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO,
     crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO,
     crate::match_result_ok::MATCH_RESULT_OK_INFO,
@@ -353,6 +356,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::CLONE_ON_COPY_INFO,
     crate::methods::CLONE_ON_REF_PTR_INFO,
     crate::methods::COLLAPSIBLE_STR_REPLACE_INFO,
+    crate::methods::CONST_IS_EMPTY_INFO,
     crate::methods::DRAIN_COLLECT_INFO,
     crate::methods::ERR_EXPECT_INFO,
     crate::methods::EXPECT_FUN_CALL_INFO,
@@ -750,5 +754,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::write::WRITE_LITERAL_INFO,
     crate::write::WRITE_WITH_NEWLINE_INFO,
     crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO,
+    crate::zero_repeat_side_effects::ZERO_REPEAT_SIDE_EFFECTS_INFO,
     crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO,
 ];
diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
index d2f14756591..1add02af310 100644
--- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
@@ -8,7 +8,14 @@ use url::Url;
 
 use crate::doc::DOC_MARKDOWN;
 
-pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span, code_level: isize) {
+pub fn check(
+    cx: &LateContext<'_>,
+    valid_idents: &FxHashSet<String>,
+    text: &str,
+    span: Span,
+    code_level: isize,
+    blockquote_level: isize,
+) {
     for orig_word in text.split(|c: char| c.is_whitespace() || c == '\'') {
         // Trim punctuation as in `some comment (see foo::bar).`
         //                                                   ^^
@@ -46,11 +53,11 @@ pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str,
             span.parent(),
         );
 
-        check_word(cx, word, span, code_level);
+        check_word(cx, word, span, code_level, blockquote_level);
     }
 }
 
-fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) {
+fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, blockquote_level: isize) {
     /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
     /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
     /// letter (`NASA` is ok).
@@ -97,7 +104,9 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) {
     }
 
     // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
-    if code_level > 0 || (has_underscore(word) && has_hyphen(word)) {
+    //
+    // We also assume that backticks are not necessary if inside a quote. (Issue #10262)
+    if code_level > 0 || blockquote_level > 0 || (has_underscore(word) && has_hyphen(word)) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 003d26b7b89..b135e4e3577 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -7,14 +7,14 @@ use clippy_utils::{is_entrypoint_fn, method_chain_args};
 use pulldown_cmark::Event::{
     Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
 };
-use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
+use pulldown_cmark::Tag::{BlockQuote, CodeBlock, Heading, Item, Link, Paragraph};
 use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
 use rustc_ast::ast::Attribute;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AnonConst, Expr};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
@@ -538,7 +538,16 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
 
     suspicious_doc_comments::check(cx, attrs);
 
-    let (fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
+    let (fragments, _) = attrs_to_doc_fragments(
+        attrs.iter().filter_map(|attr| {
+            if in_external_macro(cx.sess(), attr.span) {
+                None
+            } else {
+                Some((attr, None))
+            }
+        }),
+        true,
+    );
     let mut doc = fragments.iter().fold(String::new(), |mut acc, fragment| {
         add_doc_fragment(&mut acc, fragment);
         acc
@@ -602,6 +611,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut text_to_check: Vec<(CowStr<'_>, Range<usize>, isize)> = Vec::new();
     let mut paragraph_range = 0..0;
     let mut code_level = 0;
+    let mut blockquote_level = 0;
 
     for (event, range) in events {
         match event {
@@ -610,8 +620,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     code_level += 1;
                 } else if tag.starts_with("</code") {
                     code_level -= 1;
+                } else if tag.starts_with("<blockquote") || tag.starts_with("<q") {
+                    blockquote_level += 1;
+                } else if tag.starts_with("</blockquote") || tag.starts_with("</q") {
+                    blockquote_level -= 1;
                 }
             },
+            Start(BlockQuote) => blockquote_level += 1,
+            End(BlockQuote) => blockquote_level -= 1,
             Start(CodeBlock(ref kind)) => {
                 in_code = true;
                 if let CodeBlockKind::Fenced(lang) = kind {
@@ -663,7 +679,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 } else {
                     for (text, range, assoc_code_level) in text_to_check {
                         if let Some(span) = fragments.span(cx, range) {
-                            markdown::check(cx, valid_idents, &text, span, assoc_code_level);
+                            markdown::check(cx, valid_idents, &text, span, assoc_code_level, blockquote_level);
                         }
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
index 47780cab9ed..a6ca7fe9e0b 100644
--- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
+++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
@@ -49,24 +49,22 @@ declare_clippy_lint! {
 declare_lint_pass!(ElseIfWithoutElse => [ELSE_IF_WITHOUT_ELSE]);
 
 impl EarlyLintPass for ElseIfWithoutElse {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
         if in_external_macro(cx.sess(), item.span) {
             return;
         }
 
-        while let ExprKind::If(_, _, Some(ref els)) = item.kind {
-            if let ExprKind::If(_, _, None) = els.kind {
-                span_lint_and_help(
-                    cx,
-                    ELSE_IF_WITHOUT_ELSE,
-                    els.span,
-                    "`if` expression with an `else if`, but without a final `else`",
-                    None,
-                    "add an `else` block here",
-                );
-            }
-
-            item = els;
+        if let ExprKind::If(_, _, Some(ref els)) = item.kind
+            && let ExprKind::If(_, _, None) = els.kind
+        {
+            span_lint_and_help(
+                cx,
+                ELSE_IF_WITHOUT_ELSE,
+                els.span,
+                "`if` expression with an `else if`, but without a final `else`",
+                None,
+                "add an `else` block here",
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index ebda2ad8387..dafbf6c8846 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -358,7 +358,7 @@ struct InsertSearcher<'cx, 'tcx> {
     can_use_entry: bool,
     /// Whether this expression is the final expression in this code path. This may be a statement.
     in_tail_pos: bool,
-    // Is this expression a single insert. A slightly better suggestion can be made in this case.
+    /// Is this expression a single insert. A slightly better suggestion can be made in this case.
     is_single_insert: bool,
     /// If the visitor has seen the map being used.
     is_map_used: bool,
@@ -431,6 +431,9 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                     self.is_single_insert = false;
                     self.visit_expr(e);
                 }
+                if let Some(els) = &l.els {
+                    self.visit_block(els);
+                }
             },
             StmtKind::Item(_) => {
                 self.allow_insert_closure &= !self.in_tail_pos;
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 96da2ec2a1a..9cc51fa8cd5 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -250,7 +250,7 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     /// A `Result` is at least as large as the `Err`-variant. While we
-    /// expect that variant to be seldomly used, the compiler needs to reserve
+    /// expect that variant to be seldom used, the compiler needs to reserve
     /// and move that much memory every single time.
     /// Furthermore, errors are often simply passed up the call-stack, making
     /// use of the `?`-operator and its type-conversion mechanics. If the
diff --git a/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs b/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs
new file mode 100644
index 00000000000..36dc45ca788
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/integer_division_remainder_used.rs
@@ -0,0 +1,50 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::BinOpKind;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self};
+use rustc_session::declare_lint_pass;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for the usage of division (/) and remainder (%) operations
+    /// when performed on any integer types using the default Div and Rem trait implementations.
+    ///
+    /// ### Why is this bad?
+    /// In cryptographic contexts, division can result in timing sidechannel vulnerabilities,
+    /// and needs to be replaced with constant-time code instead (e.g. Barrett reduction).
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let my_div = 10 / 2;
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let my_div = 10 >> 1;
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub INTEGER_DIVISION_REMAINDER_USED,
+    restriction,
+    "use of disallowed default division and remainder operations"
+}
+
+declare_lint_pass!(IntegerDivisionRemainderUsed => [INTEGER_DIVISION_REMAINDER_USED]);
+
+impl LateLintPass<'_> for IntegerDivisionRemainderUsed {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let ExprKind::Binary(op, lhs, rhs) = &expr.kind
+            && let BinOpKind::Div | BinOpKind::Rem = op.node
+            && let lhs_ty = cx.typeck_results().expr_ty(lhs)
+            && let rhs_ty = cx.typeck_results().expr_ty(rhs)
+            && let ty::Int(_) | ty::Uint(_) = lhs_ty.peel_refs().kind()
+            && let ty::Int(_) | ty::Uint(_) = rhs_ty.peel_refs().kind()
+        {
+            span_lint(
+                cx,
+                INTEGER_DIVISION_REMAINDER_USED,
+                expr.span.source_callsite(),
+                &format!("use of {} has been disallowed in this context", op.node.as_str()),
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index f084d89ccc2..d4ddf76fb8a 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::path_to_local_id;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::is_local_used;
@@ -122,9 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
                     value=snippet(cx, value.span, "<value>"),
                     default=snippet(cx, default.span, "<default>"),
                 );
-                span_lint_and_then(
+                span_lint_hir_and_then(
                     cx,
                     USELESS_LET_IF_SEQ,
+                    local.hir_id,
                     span,
                     "`if _ { .. } else { .. }` is an expression",
                     |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index b930175c4d8..57fac351042 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -172,6 +172,7 @@ mod init_numbered_fields;
 mod inline_fn_without_body;
 mod instant_subtraction;
 mod int_plus_one;
+mod integer_division_remainder_used;
 mod invalid_upcast_comparisons;
 mod item_name_repetitions;
 mod items_after_statements;
@@ -211,6 +212,7 @@ mod manual_retain;
 mod manual_slice_size_calculation;
 mod manual_string_new;
 mod manual_strip;
+mod manual_unwrap_or_default;
 mod map_unit_fn;
 mod match_result_ok;
 mod matches;
@@ -373,6 +375,7 @@ mod visibility;
 mod wildcard_imports;
 mod write;
 mod zero_div_zero;
+mod zero_repeat_side_effects;
 mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
@@ -1119,7 +1122,10 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv())));
     store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl));
     store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations));
-    store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones));
+    store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(msrv())));
+    store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects));
+    store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault));
+    store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 47dc3807e62..cf34c904dfe 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -273,7 +273,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
                     }
                     return false; // no need to walk further *on the variable*
                 },
-                Res::Def(DefKind::Static{..} | DefKind::Const, ..) => {
+                Res::Def(DefKind::Static { .. } | DefKind::Const, ..) => {
                     if index_used_directly {
                         self.indexed_directly.insert(
                             seqvar.segments[0].ident.name,
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 6cc79440f39..8aae7be4593 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -255,9 +255,7 @@ fn never_loop_expr<'tcx>(
             InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => {
                 NeverLoopResult::Normal
             },
-            InlineAsmOperand::Label { block } => {
-                never_loop_block(cx, block, local_labels, main_loop_id)
-            }
+            InlineAsmOperand::Label { block } => never_loop_block(cx, block, local_labels, main_loop_id),
         })),
         ExprKind::OffsetOf(_, _)
         | ExprKind::Yield(_, _)
diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs
index dd7fae79d9b..31f0f1cfeba 100644
--- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs
@@ -1,62 +1,41 @@
 use super::UNUSED_ENUMERATE_INDEX;
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
-use clippy_utils::{pat_is_wild, sugg};
+use clippy_utils::{match_def_path, pat_is_wild, sugg};
 use rustc_hir::def::DefKind;
 use rustc_hir::{Expr, ExprKind, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
 /// Checks for the `UNUSED_ENUMERATE_INDEX` lint.
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
-    let PatKind::Tuple([index, elem], _) = pat.kind else {
-        return;
-    };
-
-    let ExprKind::MethodCall(_method, self_arg, [], _) = arg.kind else {
-        return;
-    };
-
-    let ty = cx.typeck_results().expr_ty(arg);
-
-    if !pat_is_wild(cx, &index.kind, body) {
-        return;
+///
+/// The lint is also partially implemented in `clippy_lints/src/methods/unused_enumerate_index.rs`.
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, arg: &Expr<'_>, body: &'tcx Expr<'tcx>) {
+    if let PatKind::Tuple([index, elem], _) = pat.kind
+        && let ExprKind::MethodCall(_method, self_arg, [], _) = arg.kind
+        && let ty = cx.typeck_results().expr_ty(arg)
+        && pat_is_wild(cx, &index.kind, body)
+        && let ty::Adt(base, _) = *ty.kind()
+        && match_def_path(cx, base.did(), &clippy_utils::paths::CORE_ITER_ENUMERATE_STRUCT)
+        && let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id)
+        && match_def_path(cx, call_id, &clippy_utils::paths::CORE_ITER_ENUMERATE_METHOD)
+    {
+        span_lint_and_then(
+            cx,
+            UNUSED_ENUMERATE_INDEX,
+            arg.span,
+            "you seem to use `.enumerate()` and immediately discard the index",
+            |diag| {
+                let base_iter = sugg::Sugg::hir(cx, self_arg, "base iter");
+                multispan_sugg(
+                    diag,
+                    "remove the `.enumerate()` call",
+                    vec![
+                        (pat.span, snippet(cx, elem.span, "..").into_owned()),
+                        (arg.span, base_iter.to_string()),
+                    ],
+                );
+            },
+        );
     }
-
-    let name = match *ty.kind() {
-        ty::Adt(base, _substs) => cx.tcx.def_path_str(base.did()),
-        _ => return,
-    };
-
-    if name != "std::iter::Enumerate" && name != "core::iter::Enumerate" {
-        return;
-    }
-
-    let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id) else {
-        return;
-    };
-
-    let call_name = cx.tcx.def_path_str(call_id);
-
-    if call_name != "std::iter::Iterator::enumerate" && call_name != "core::iter::Iterator::enumerate" {
-        return;
-    }
-
-    span_lint_and_then(
-        cx,
-        UNUSED_ENUMERATE_INDEX,
-        arg.span,
-        "you seem to use `.enumerate()` and immediately discard the index",
-        |diag| {
-            let base_iter = sugg::Sugg::hir(cx, self_arg, "base iter");
-            multispan_sugg(
-                diag,
-                "remove the `.enumerate()` call",
-                vec![
-                    (pat.span, snippet(cx, elem.span, "..").into_owned()),
-                    (arg.span, base_iter.to_string()),
-                ],
-            );
-        },
-    );
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
index 3511d24e813..3dff826cb85 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
                 Res::Local(hir_id) => {
                     self.ids.insert(hir_id);
                 },
-                Res::Def(DefKind::Static{..}, def_id) => {
+                Res::Def(DefKind::Static { .. }, def_id) => {
                     let mutable = self.cx.tcx.is_mutable_static(def_id);
                     self.def_ids.insert(def_id, mutable);
                 },
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 6f15fca089e..3ddb06a1e08 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -2,7 +2,7 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq};
+use clippy_utils::{match_def_path, paths, SpanlessEq};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -69,17 +69,16 @@ impl_lint_pass!(ManualRetain => [MANUAL_RETAIN]);
 
 impl<'tcx> LateLintPass<'tcx> for ManualRetain {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        if let Some(parent_expr) = get_parent_expr(cx, expr)
-            && let Assign(left_expr, collect_expr, _) = &parent_expr.kind
+        if let Assign(left_expr, collect_expr, _) = &expr.kind
             && let hir::ExprKind::MethodCall(seg, ..) = &collect_expr.kind
             && seg.args.is_none()
             && let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind
             && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
             && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id)
         {
-            check_into_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv);
-            check_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv);
-            check_to_owned(cx, left_expr, target_expr, parent_expr.span, &self.msrv);
+            check_into_iter(cx, left_expr, target_expr, expr.span, &self.msrv);
+            check_iter(cx, left_expr, target_expr, expr.span, &self.msrv);
+            check_to_owned(cx, left_expr, target_expr, expr.span, &self.msrv);
         }
     }
 
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
new file mode 100644
index 00000000000..ddaf97c463a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
@@ -0,0 +1,181 @@
+use rustc_errors::Applicability;
+use rustc_hir::def::Res;
+use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::sym;
+
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_default_equivalent;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::implements_trait;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks if a `match` or `if let` expression can be simplified using
+    /// `.unwrap_or_default()`.
+    ///
+    /// ### Why is this bad?
+    /// It can be done in one call with `.unwrap_or_default()`.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let x: Option<String> = Some(String::new());
+    /// let y: String = match x {
+    ///     Some(v) => v,
+    ///     None => String::new(),
+    /// };
+    ///
+    /// let x: Option<Vec<String>> = Some(Vec::new());
+    /// let y: Vec<String> = if let Some(v) = x {
+    ///     v
+    /// } else {
+    ///     Vec::new()
+    /// };
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let x: Option<String> = Some(String::new());
+    /// let y: String = x.unwrap_or_default();
+    ///
+    /// let x: Option<Vec<String>> = Some(Vec::new());
+    /// let y: Vec<String> = x.unwrap_or_default();
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub MANUAL_UNWRAP_OR_DEFAULT,
+    suspicious,
+    "check if a `match` or `if let` can be simplified with `unwrap_or_default`"
+}
+
+declare_lint_pass!(ManualUnwrapOrDefault => [MANUAL_UNWRAP_OR_DEFAULT]);
+
+fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<HirId> {
+    if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind
+        && let Some(def_id) = path.res.opt_def_id()
+        // Since it comes from a pattern binding, we need to get the parent to actually match
+        // against it.
+        && let Some(def_id) = cx.tcx.opt_parent(def_id)
+        && cx.tcx.lang_items().get(LangItem::OptionSome) == Some(def_id)
+    {
+        let mut bindings = Vec::new();
+        pat.each_binding(|_, id, _, _| bindings.push(id));
+        if let &[id] = bindings.as_slice() {
+            Some(id)
+        } else {
+            None
+        }
+    } else {
+        None
+    }
+}
+
+fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+    if let PatKind::Path(QPath::Resolved(_, path)) = arm.pat.kind
+        && let Some(def_id) = path.res.opt_def_id()
+        // Since it comes from a pattern binding, we need to get the parent to actually match
+        // against it.
+        && let Some(def_id) = cx.tcx.opt_parent(def_id)
+        && cx.tcx.lang_items().get(LangItem::OptionNone) == Some(def_id)
+    {
+        Some(arm.body)
+    } else if let PatKind::Wild = arm.pat.kind {
+        // We consider that the `Some` check will filter it out if it's not right.
+        Some(arm.body)
+    } else {
+        None
+    }
+}
+
+fn get_some_and_none_bodies<'tcx>(
+    cx: &LateContext<'tcx>,
+    arm1: &'tcx Arm<'tcx>,
+    arm2: &'tcx Arm<'tcx>,
+) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> {
+    if let Some(binding_id) = get_some(cx, arm1.pat)
+        && let Some(body_none) = get_none(cx, arm2)
+    {
+        Some(((arm1.body, binding_id), body_none))
+    } else if let Some(binding_id) = get_some(cx, arm2.pat)
+        && let Some(body_none) = get_none(cx, arm1)
+    {
+        Some(((arm2.body, binding_id), body_none))
+    } else {
+        None
+    }
+}
+
+fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
+    let ExprKind::Match(match_expr, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) = expr.kind else {
+        return false;
+    };
+    // We don't want conditions on the arms to simplify things.
+    if arm1.guard.is_none()
+        && arm2.guard.is_none()
+        // We check that the returned type implements the `Default` trait.
+        && let match_ty = cx.typeck_results().expr_ty(expr)
+        && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
+        && implements_trait(cx, match_ty, default_trait_id, &[])
+        // We now get the bodies for both the `Some` and `None` arms.
+        && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
+        // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
+        && let ExprKind::Path(QPath::Resolved(_, path)) = body_some.peel_blocks().kind
+        && let Res::Local(local_id) = path.res
+        && local_id == binding_id
+        // We now check the `None` arm is calling a method equivalent to `Default::default`.
+        && let body_none = body_none.peel_blocks()
+        && is_default_equivalent(cx, body_none)
+        && let Some(match_expr_snippet) = snippet_opt(cx, match_expr.span)
+    {
+        span_lint_and_sugg(
+            cx,
+            MANUAL_UNWRAP_OR_DEFAULT,
+            expr.span,
+            "match can be simplified with `.unwrap_or_default()`",
+            "replace it with",
+            format!("{match_expr_snippet}.unwrap_or_default()"),
+            Applicability::MachineApplicable,
+        );
+    }
+    true
+}
+
+fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+    if let ExprKind::If(cond, if_block, Some(else_expr)) = expr.kind
+        && let ExprKind::Let(let_) = cond.kind
+        && let ExprKind::Block(_, _) = else_expr.kind
+        // We check that the returned type implements the `Default` trait.
+        && let match_ty = cx.typeck_results().expr_ty(expr)
+        && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
+        && implements_trait(cx, match_ty, default_trait_id, &[])
+        && let Some(binding_id) = get_some(cx, let_.pat)
+        // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
+        && let ExprKind::Path(QPath::Resolved(_, path)) = if_block.peel_blocks().kind
+        && let Res::Local(local_id) = path.res
+        && local_id == binding_id
+        // We now check the `None` arm is calling a method equivalent to `Default::default`.
+        && let body_else = else_expr.peel_blocks()
+        && is_default_equivalent(cx, body_else)
+        && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span)
+    {
+        span_lint_and_sugg(
+            cx,
+            MANUAL_UNWRAP_OR_DEFAULT,
+            expr.span,
+            "if let can be simplified with `.unwrap_or_default()`",
+            "replace it with",
+            format!("{if_let_expr_snippet}.unwrap_or_default()"),
+            Applicability::MachineApplicable,
+        );
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if expr.span.from_expansion() {
+            return;
+        }
+        if !handle_match(cx, expr) {
+            handle_if_let(cx, expr);
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 86c414dafcc..a0db8e2db1f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -55,23 +55,15 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
         };
 
         let ty = cx.typeck_results().expr_ty(ex);
-        if *ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) {
-            check_single_pattern(cx, ex, arms, expr, els);
-            check_opt_like(cx, ex, arms, expr, ty, els);
+        if (*ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id)) &&
+            (check_single_pattern(arms) || check_opt_like(cx, arms, ty)) {
+            report_single_pattern(cx, ex, arms, expr, els);
         }
     }
 }
 
-fn check_single_pattern(
-    cx: &LateContext<'_>,
-    ex: &Expr<'_>,
-    arms: &[Arm<'_>],
-    expr: &Expr<'_>,
-    els: Option<&Expr<'_>>,
-) {
-    if is_wild(arms[1].pat) {
-        report_single_pattern(cx, ex, arms, expr, els);
-    }
+fn check_single_pattern(arms: &[Arm<'_>]) -> bool {
+    is_wild(arms[1].pat)
 }
 
 fn report_single_pattern(
@@ -140,19 +132,10 @@ fn report_single_pattern(
     span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app);
 }
 
-fn check_opt_like<'a>(
-    cx: &LateContext<'a>,
-    ex: &Expr<'_>,
-    arms: &[Arm<'_>],
-    expr: &Expr<'_>,
-    ty: Ty<'a>,
-    els: Option<&Expr<'_>>,
-) {
+fn check_opt_like<'a>(cx: &LateContext<'a>, arms: &[Arm<'_>], ty: Ty<'a>) -> bool {
     // We don't want to lint if the second arm contains an enum which could
     // have more variants in the future.
-    if form_exhaustive_matches(cx, ty, arms[0].pat, arms[1].pat) {
-        report_single_pattern(cx, ex, arms, expr, els);
-    }
+    form_exhaustive_matches(cx, ty, arms[0].pat, arms[1].pat)
 }
 
 /// Returns `true` if all of the types in the pattern are enums which we know
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index e2c2997594a..4d8fb217f7f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -91,7 +91,7 @@ pub(super) fn check<'tcx>(
             },
             hir::ExprKind::Path(ref p) => matches!(
                 cx.qpath_res(p, arg.hir_id),
-                hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static{..}, _)
+                hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static { .. }, _)
             ),
             _ => false,
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
new file mode 100644
index 00000000000..7fe66062251
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -0,0 +1,49 @@
+use clippy_utils::consts::constant_is_empty;
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::{find_binding_init, path_to_local};
+use rustc_hir::{Expr, HirId};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_span::sym;
+
+use super::CONST_IS_EMPTY;
+
+/// Expression whose initialization depend on a constant conditioned by a `#[cfg(…)]` directive will
+/// not trigger the lint.
+pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_>) {
+    if in_external_macro(cx.sess(), expr.span) || !receiver.span.eq_ctxt(expr.span) {
+        return;
+    }
+    let init_expr = expr_or_init(cx, receiver);
+    if !receiver.span.eq_ctxt(init_expr.span) {
+        return;
+    }
+    if let Some(init_is_empty) = constant_is_empty(cx, init_expr) {
+        span_lint(
+            cx,
+            CONST_IS_EMPTY,
+            expr.span,
+            &format!("this expression always evaluates to {init_is_empty:?}"),
+        );
+    }
+}
+
+fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
+    cx.tcx
+        .hir()
+        .parent_id_iter(id)
+        .any(|id| cx.tcx.hir().attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
+}
+
+/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
+/// value depends on a `#[cfg(…)]` directive.
+fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
+    while let Some(init) = path_to_local(expr)
+        .and_then(|id| find_binding_init(cx, id))
+        .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
+        .filter(|init| !is_under_cfg(cx, init.hir_id))
+    {
+        expr = init;
+    }
+    expr
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
index 12104310405..5b0b70b4b96 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
@@ -1,10 +1,10 @@
-use super::utils::derefs_to_slice;
-use crate::methods::iter_nth_zero;
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::ty::get_type_diagnostic_name;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
+use rustc_span::Span;
 
 use super::ITER_NTH;
 
@@ -12,28 +12,33 @@ pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &hir::Expr<'_>,
     iter_recv: &'tcx hir::Expr<'tcx>,
-    nth_recv: &hir::Expr<'_>,
-    nth_arg: &hir::Expr<'_>,
-    is_mut: bool,
-) {
-    let mut_str = if is_mut { "_mut" } else { "" };
-    let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() {
-        "slice"
-    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::Vec) {
-        "`Vec`"
-    } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) {
-        "`VecDeque`"
-    } else {
-        iter_nth_zero::check(cx, expr, nth_recv, nth_arg);
-        return; // caller is not a type that we want to lint
+    iter_method: &str,
+    iter_span: Span,
+    nth_span: Span,
+) -> bool {
+    let caller_type = match get_type_diagnostic_name(cx, cx.typeck_results().expr_ty(iter_recv).peel_refs()) {
+        Some(sym::Vec) => "`Vec`",
+        Some(sym::VecDeque) => "`VecDeque`",
+        _ if cx.typeck_results().expr_ty_adjusted(iter_recv).peel_refs().is_slice() => "slice",
+        // caller is not a type that we want to lint
+        _ => return false,
     };
 
-    span_lint_and_help(
+    span_lint_and_then(
         cx,
         ITER_NTH,
         expr.span,
-        &format!("called `.iter{mut_str}().nth()` on a {caller_type}"),
-        None,
-        &format!("calling `.get{mut_str}()` is both faster and more readable"),
+        &format!("called `.{iter_method}().nth()` on a {caller_type}"),
+        |diag| {
+            let get_method = if iter_method == "iter_mut" { "get_mut" } else { "get" };
+            diag.span_suggestion_verbose(
+                iter_span.to(nth_span),
+                format!("`{get_method}` is equivalent but more concise"),
+                get_method,
+                Applicability::MachineApplicable,
+            );
+        },
     );
+
+    true
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 27e17b43b01..c3c7a3a0033 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -86,8 +86,11 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
                                     }
                                 }
                             },
-                            hir::ExprKind::Call(call, [_]) => {
-                                if let hir::ExprKind::Path(qpath) = call.kind {
+                            hir::ExprKind::Call(call, args) => {
+                                if let hir::ExprKind::Path(qpath) = call.kind
+                                    && let [arg] = args
+                                    && ident_eq(name, arg)
+                                {
                                     handle_path(cx, call, &qpath, e, recv);
                                 }
                             },
@@ -118,7 +121,9 @@ fn handle_path(
         if let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind()
             && let args = args.as_slice()
             && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type())
-            && ty.is_ref()
+            && let ty::Ref(_, ty, Mutability::Not) = ty.kind()
+            && let ty::FnDef(_, lst) = cx.typeck_results().expr_ty(arg).kind()
+            && lst.iter().all(|l| l.as_type() == Some(*ty))
         {
             lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs()));
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 8a24ccea3a1..b6c474212cd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -36,6 +36,7 @@ mod inefficient_to_string;
 mod inspect_for_each;
 mod into_iter_on_ref;
 mod is_digit_ascii_radix;
+mod is_empty;
 mod iter_cloned_collect;
 mod iter_count;
 mod iter_filter;
@@ -118,6 +119,7 @@ mod unnecessary_literal_unwrap;
 mod unnecessary_result_map_or_else;
 mod unnecessary_sort_by;
 mod unnecessary_to_owned;
+mod unused_enumerate_index;
 mod unwrap_expect_used;
 mod useless_asref;
 mod utils;
@@ -1235,12 +1237,11 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for usage of `.iter().nth()` (and the related
-    /// `.iter_mut().nth()`) on standard library types with *O*(1) element access.
+    /// Checks for usage of `.iter().nth()`/`.iter_mut().nth()` on standard library types that have
+    /// equivalent `.get()`/`.get_mut()` methods.
     ///
     /// ### Why is this bad?
-    /// `.get()` and `.get_mut()` are more efficient and more
-    /// readable.
+    /// `.get()` and `.get_mut()` are equivalent but more concise.
     ///
     /// ### Example
     /// ```no_run
@@ -1256,7 +1257,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "pre 1.29.0"]
     pub ITER_NTH,
-    perf,
+    style,
     "using `.iter().nth()` on a standard library type with O(1) element access"
 }
 
@@ -2848,7 +2849,7 @@ declare_clippy_lint! {
     /// the file is created from scratch, or ensure `truncate` is
     /// called so that the truncation behaviour is explicit. `truncate(true)`
     /// will ensure the file is entirely overwritten with new data, whereas
-    /// `truncate(false)` will explicitely keep the default behavior.
+    /// `truncate(false)` will explicitly keep the default behavior.
     ///
     /// ### Example
     /// ```rust,no_run
@@ -2862,7 +2863,7 @@ declare_clippy_lint! {
     ///
     /// OpenOptions::new().create(true).truncate(true);
     /// ```
-    #[clippy::version = "1.75.0"]
+    #[clippy::version = "1.77.0"]
     pub SUSPICIOUS_OPEN_OPTIONS,
     suspicious,
     "suspicious combination of options for opening a file"
@@ -3182,8 +3183,8 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     ///
-    /// Checks an argument of `seek` method of `Seek` trait
-    /// and if it start seek from `SeekFrom::Current(0)`, suggests `stream_position` instead.
+    /// Checks if the `seek` method of the `Seek` trait is called with `SeekFrom::Current(0)`,
+    /// and if it is, suggests using `stream_position` instead.
     ///
     /// ### Why is this bad?
     ///
@@ -3590,7 +3591,7 @@ declare_clippy_lint! {
     /// ```
     #[clippy::version = "1.73.0"]
     pub READONLY_WRITE_LOCK,
-    nursery,
+    perf,
     "acquiring a write lock when a read lock would work"
 }
 
@@ -3816,7 +3817,7 @@ declare_clippy_lint! {
     /// ```no_run
     /// let _ = std::iter::empty::<Result<i32, ()>>().flatten();
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub RESULT_FILTER_MAP,
     complexity,
     "filtering `Result` for `Ok` then force-unwrapping, which can be one type-safe operation"
@@ -3825,7 +3826,7 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for usage of `.filter(Option::is_some)` that may be replaced with a `.flatten()` call.
-    /// This lint will require additional changes to the follow-up calls as it appects the type.
+    /// This lint will require additional changes to the follow-up calls as it affects the type.
     ///
     /// ### Why is this bad?
     /// This pattern is often followed by manual unwrapping of the `Option`. The simplification
@@ -3842,7 +3843,7 @@ declare_clippy_lint! {
     /// // example code which does not raise clippy warning
     /// vec![Some(1)].into_iter().flatten();
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub ITER_FILTER_IS_SOME,
     pedantic,
     "filtering an iterator over `Option`s for `Some` can be achieved with `flatten`"
@@ -3851,7 +3852,7 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for usage of `.filter(Result::is_ok)` that may be replaced with a `.flatten()` call.
-    /// This lint will require additional changes to the follow-up calls as it appects the type.
+    /// This lint will require additional changes to the follow-up calls as it affects the type.
     ///
     /// ### Why is this bad?
     /// This pattern is often followed by manual unwrapping of `Result`. The simplification
@@ -3868,7 +3869,7 @@ declare_clippy_lint! {
     /// // example code which does not raise clippy warning
     /// vec![Ok::<i32, String>(1)].into_iter().flatten();
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub ITER_FILTER_IS_OK,
     pedantic,
     "filtering an iterator over `Result`s for `Ok` can be achieved with `flatten`"
@@ -3895,7 +3896,7 @@ declare_clippy_lint! {
     /// option.is_some_and(|a| a > 10);
     /// result.is_ok_and(|a| a > 10);
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub MANUAL_IS_VARIANT_AND,
     pedantic,
     "using `.map(f).unwrap_or_default()`, which is more succinctly expressed as `is_some_and(f)` or `is_ok_and(f)`"
@@ -3925,7 +3926,7 @@ declare_clippy_lint! {
     /// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is
     /// valid.
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub STR_SPLIT_AT_NEWLINE,
     pedantic,
     "splitting a trimmed string at hard-coded newlines"
@@ -4044,6 +4045,31 @@ declare_clippy_lint! {
     "calling `.get().is_some()` or `.get().is_none()` instead of `.contains()` or `.contains_key()`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// It identifies calls to `.is_empty()` on constant values.
+    ///
+    /// ### Why is this bad?
+    /// String literals and constant values are known at compile time. Checking if they
+    /// are empty will always return the same value. This might not be the intention of
+    /// the expression.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let value = "";
+    /// if value.is_empty() {
+    ///     println!("the string is empty");
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// println!("the string is empty");
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub CONST_IS_EMPTY,
+    suspicious,
+    "is_empty() called on strings known at compile time"
+}
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -4092,6 +4118,7 @@ impl_lint_pass!(Methods => [
     CLONE_ON_COPY,
     CLONE_ON_REF_PTR,
     COLLAPSIBLE_STR_REPLACE,
+    CONST_IS_EMPTY,
     ITER_OVEREAGER_CLONED,
     CLONED_INSTEAD_OF_COPIED,
     FLAT_MAP_OPTION,
@@ -4403,6 +4430,7 @@ impl Methods {
                     zst_offset::check(cx, expr, recv);
                 },
                 ("all", [arg]) => {
+                    unused_enumerate_index::check(cx, expr, recv, arg);
                     if let Some(("cloned", recv2, [], _, _)) = method_call(recv) {
                         iter_overeager_cloned::check(
                             cx,
@@ -4421,23 +4449,26 @@ impl Methods {
                         unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
                     }
                 },
-                ("any", [arg]) => match method_call(recv) {
-                    Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(
-                        cx,
-                        expr,
-                        recv,
-                        recv2,
-                        iter_overeager_cloned::Op::NeedlessMove(arg),
-                        false,
-                    ),
-                    Some(("chars", recv, _, _, _))
-                        if let ExprKind::Closure(arg) = arg.kind
-                            && let body = cx.tcx.hir().body(arg.body)
-                            && let [param] = body.params =>
-                    {
-                        string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
-                    },
-                    _ => {},
+                ("any", [arg]) => {
+                    unused_enumerate_index::check(cx, expr, recv, arg);
+                    match method_call(recv) {
+                        Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(
+                            cx,
+                            expr,
+                            recv,
+                            recv2,
+                            iter_overeager_cloned::Op::NeedlessMove(arg),
+                            false,
+                        ),
+                        Some(("chars", recv, _, _, _))
+                            if let ExprKind::Closure(arg) = arg.kind
+                                && let body = cx.tcx.hir().body(arg.body)
+                                && let [param] = body.params =>
+                        {
+                            string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), &self.msrv);
+                        },
+                        _ => {},
+                    }
                 },
                 ("arg", [arg]) => {
                     suspicious_command_arg_space::check(cx, recv, arg, span);
@@ -4445,7 +4476,7 @@ impl Methods {
                 ("as_deref" | "as_deref_mut", []) => {
                     needless_option_as_deref::check(cx, expr, recv, name);
                 },
-                ("as_bytes" | "is_empty", []) => {
+                ("as_bytes", []) => {
                     if let Some(("as_str", recv, [], as_str_span, _)) = method_call(recv) {
                         redundant_as_str::check(cx, expr, recv, as_str_span, span);
                     }
@@ -4570,14 +4601,17 @@ impl Methods {
                     }
                 },
                 ("filter_map", [arg]) => {
+                    unused_enumerate_index::check(cx, expr, recv, arg);
                     unnecessary_filter_map::check(cx, expr, arg, name);
                     filter_map_bool_then::check(cx, expr, arg, call_span);
                     filter_map_identity::check(cx, expr, arg, span);
                 },
                 ("find_map", [arg]) => {
+                    unused_enumerate_index::check(cx, expr, recv, arg);
                     unnecessary_filter_map::check(cx, expr, arg, name);
                 },
                 ("flat_map", [arg]) => {
+                    unused_enumerate_index::check(cx, expr, recv, arg);
                     flat_map_identity::check(cx, expr, arg, span);
                     flat_map_option::check(cx, expr, arg, span);
                 },
@@ -4599,17 +4633,20 @@ impl Methods {
                     manual_try_fold::check(cx, expr, init, acc, call_span, &self.msrv);
                     unnecessary_fold::check(cx, expr, init, acc, span);
                 },
-                ("for_each", [arg]) => match method_call(recv) {
-                    Some(("inspect", _, [_], span2, _)) => inspect_for_each::check(cx, expr, span2),
-                    Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(
-                        cx,
-                        expr,
-                        recv,
-                        recv2,
-                        iter_overeager_cloned::Op::NeedlessMove(arg),
-                        false,
-                    ),
-                    _ => {},
+                ("for_each", [arg]) => {
+                    unused_enumerate_index::check(cx, expr, recv, arg);
+                    match method_call(recv) {
+                        Some(("inspect", _, [_], span2, _)) => inspect_for_each::check(cx, expr, span2),
+                        Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(
+                            cx,
+                            expr,
+                            recv,
+                            recv2,
+                            iter_overeager_cloned::Op::NeedlessMove(arg),
+                            false,
+                        ),
+                        _ => {},
+                    }
                 },
                 ("get", [arg]) => {
                     get_first::check(cx, expr, recv, arg);
@@ -4619,6 +4656,12 @@ impl Methods {
                 ("hash", [arg]) => {
                     unit_hash::check(cx, expr, recv, arg);
                 },
+                ("is_empty", []) => {
+                    if let Some(("as_str", recv, [], as_str_span, _)) = method_call(recv) {
+                        redundant_as_str::check(cx, expr, recv, as_str_span, span);
+                    }
+                    is_empty::check(cx, expr, recv);
+                },
                 ("is_file", []) => filetype_is_file::check(cx, expr, recv),
                 ("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, &self.msrv),
                 ("is_none", []) => check_is_some_is_none(cx, expr, recv, call_span, false),
@@ -4650,6 +4693,7 @@ impl Methods {
                 },
                 (name @ ("map" | "map_err"), [m_arg]) => {
                     if name == "map" {
+                        unused_enumerate_index::check(cx, expr, recv, m_arg);
                         map_clone::check(cx, expr, recv, m_arg, &self.msrv);
                         match method_call(recv) {
                             Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => {
@@ -4723,8 +4767,11 @@ impl Methods {
                         iter_overeager_cloned::Op::LaterCloned,
                         false,
                     ),
-                    Some(("iter", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, false),
-                    Some(("iter_mut", recv2, [], _, _)) => iter_nth::check(cx, expr, recv2, recv, n_arg, true),
+                    Some((iter_method @ ("iter" | "iter_mut"), iter_recv, [], iter_span, _)) => {
+                        if !iter_nth::check(cx, expr, iter_recv, iter_method, iter_span, span) {
+                            iter_nth_zero::check(cx, expr, recv, n_arg);
+                        }
+                    },
                     _ => iter_nth_zero::check(cx, expr, recv, n_arg),
                 },
                 ("ok_or_else", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "ok_or"),
diff --git a/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs b/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs
index 81df32bdee2..a301a5f7d65 100644
--- a/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs
@@ -25,6 +25,7 @@ pub(super) fn check<'tcx>(
         && param1 == param2.as_str()
     {
         span_lint(cx, NO_EFFECT_REPLACE, expr.span, "replacing text with itself");
+        return;
     }
 
     if SpanlessEq::new(cx).eq_expr(arg1, arg2) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
new file mode 100644
index 00000000000..e5cc898612e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
@@ -0,0 +1,135 @@
+use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_hir_and_then};
+use clippy_utils::paths::{CORE_ITER_ENUMERATE_METHOD, CORE_ITER_ENUMERATE_STRUCT};
+use clippy_utils::source::{snippet, snippet_opt};
+use clippy_utils::{expr_or_init, is_trait_method, match_def_path, pat_is_wild};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::AdtDef;
+use rustc_span::{sym, Span};
+
+use crate::loops::UNUSED_ENUMERATE_INDEX;
+
+/// Check for the `UNUSED_ENUMERATE_INDEX` lint outside of loops.
+///
+/// The lint is declared in `clippy_lints/src/loops/mod.rs`. There, the following pattern is
+/// checked:
+/// ```ignore
+/// for (_, x) in some_iter.enumerate() {
+///     // Index is ignored
+/// }
+/// ```
+///
+/// This `check` function checks for chained method calls constructs where we can detect that the
+/// index is unused. Currently, this checks only for the following patterns:
+/// ```ignore
+/// some_iter.enumerate().map_function(|(_, x)| ..)
+/// let x = some_iter.enumerate();
+/// x.map_function(|(_, x)| ..)
+/// ```
+/// where `map_function` is one of `all`, `any`, `filter_map`, `find_map`, `flat_map`, `for_each` or
+/// `map`.
+///
+/// # Preconditions
+/// This function must be called not on the `enumerate` call expression itself, but on any of the
+/// map functions listed above. It will ensure that `recv` is a `std::iter::Enumerate` instance and
+/// that the method call is one of the `std::iter::Iterator` trait.
+///
+/// * `call_expr`: The map function call expression
+/// * `recv`: The receiver of the call
+/// * `closure_arg`: The argument to the map function call containing the closure/function to apply
+pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, closure_arg: &Expr<'_>) {
+    let recv_ty = cx.typeck_results().expr_ty(recv);
+    if let Some(recv_ty_defid) = recv_ty.ty_adt_def().map(AdtDef::did)
+        // If we call a method on a `std::iter::Enumerate` instance
+        && match_def_path(cx, recv_ty_defid, &CORE_ITER_ENUMERATE_STRUCT)
+        // If we are calling a method of the `Iterator` trait
+        && is_trait_method(cx, call_expr, sym::Iterator)
+        // And the map argument is a closure
+        && let ExprKind::Closure(closure) = closure_arg.kind
+        && let closure_body = cx.tcx.hir().body(closure.body)
+        // And that closure has one argument ...
+        && let [closure_param] = closure_body.params
+        // .. which is a tuple of 2 elements
+        && let PatKind::Tuple([index, elem], ..) = closure_param.pat.kind
+        // And that the first element (the index) is either `_` or unused in the body
+        && pat_is_wild(cx, &index.kind, closure_body)
+        // Try to find the initializer for `recv`. This is needed in case `recv` is a local_binding. In the
+        // first example below, `expr_or_init` would return `recv`.
+        // ```
+        // iter.enumerate().map(|(_, x)| x)
+        // ^^^^^^^^^^^^^^^^ `recv`, a call to `std::iter::Iterator::enumerate`
+        //
+        // let binding = iter.enumerate();
+        //               ^^^^^^^^^^^^^^^^ `recv_init_expr`
+        // binding.map(|(_, x)| x)
+        // ^^^^^^^ `recv`, not a call to `std::iter::Iterator::enumerate`
+        // ```
+        && let recv_init_expr = expr_or_init(cx, recv)
+        // Make sure the initializer is a method call. It may be that the `Enumerate` comes from something
+        // that we cannot control.
+        // This would for instance happen with:
+        // ```
+        // external_lib::some_function_returning_enumerate().map(|(_, x)| x)
+        // ```
+        && let ExprKind::MethodCall(_, enumerate_recv, _, enumerate_span) = recv_init_expr.kind
+        && let Some(enumerate_defid) = cx.typeck_results().type_dependent_def_id(recv_init_expr.hir_id)
+        // Make sure the method call is `std::iter::Iterator::enumerate`.
+        && match_def_path(cx, enumerate_defid, &CORE_ITER_ENUMERATE_METHOD)
+    {
+        // Check if the tuple type was explicit. It may be the type system _needs_ the type of the element
+        // that would be explicited in the closure.
+        let new_closure_param = match find_elem_explicit_type_span(closure.fn_decl) {
+            // We have an explicit type. Get its snippet, that of the binding name, and do `binding: ty`.
+            // Fallback to `..` if we fail getting either snippet.
+            Some(ty_span) => snippet_opt(cx, elem.span)
+                .and_then(|binding_name| snippet_opt(cx, ty_span).map(|ty_name| format!("{binding_name}: {ty_name}")))
+                .unwrap_or_else(|| "..".to_string()),
+            // Otherwise, we have no explicit type. We can replace with the binding name of the element.
+            None => snippet(cx, elem.span, "..").into_owned(),
+        };
+
+        // Suggest removing the tuple from the closure and the preceding call to `enumerate`, whose span we
+        // can get from the `MethodCall`.
+        span_lint_hir_and_then(
+            cx,
+            UNUSED_ENUMERATE_INDEX,
+            recv_init_expr.hir_id,
+            enumerate_span,
+            "you seem to use `.enumerate()` and immediately discard the index",
+            |diag| {
+                multispan_sugg_with_applicability(
+                    diag,
+                    "remove the `.enumerate()` call",
+                    Applicability::MachineApplicable,
+                    vec![
+                        (closure_param.span, new_closure_param),
+                        (
+                            enumerate_span.with_lo(enumerate_recv.span.source_callsite().hi()),
+                            String::new(),
+                        ),
+                    ],
+                );
+            },
+        );
+    }
+}
+
+/// Find the span of the explicit type of the element.
+///
+/// # Returns
+/// If the tuple argument:
+/// * Has no explicit type, returns `None`
+/// * Has an explicit tuple type with an implicit element type (`(usize, _)`), returns `None`
+/// * Has an explicit tuple type with an explicit element type (`(_, i32)`), returns the span for
+///   the element type.
+fn find_elem_explicit_type_span(fn_decl: &FnDecl<'_>) -> Option<Span> {
+    if let [tuple_ty] = fn_decl.inputs
+        && let TyKind::Tup([_idx_ty, elem_ty]) = tuple_ty.kind
+        && !matches!(elem_ty.kind, TyKind::Err(..) | TyKind::Infer)
+    {
+        Some(elem_ty.span)
+    } else {
+        None
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index bf4af7946f4..6878fb3349d 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -8,6 +8,7 @@
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
+use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -32,6 +33,13 @@ declare_clippy_lint! {
     "detects missing documentation for private members"
 }
 
+macro_rules! note_prev_span_then_ret {
+    ($prev_span:expr, $span:expr) => {{
+        $prev_span = Some($span);
+        return;
+    }};
+}
+
 pub struct MissingDoc {
     /// Whether to **only** check for missing documentation in items visible within the current
     /// crate. For example, `pub(crate)` items.
@@ -39,6 +47,8 @@ pub struct MissingDoc {
     /// Stack of whether #[doc(hidden)] is set
     /// at each level which has lint attributes.
     doc_hidden_stack: Vec<bool>,
+    /// Used to keep tracking of the previous item, field or variants etc, to get the search span.
+    prev_span: Option<Span>,
 }
 
 impl Default for MissingDoc {
@@ -54,6 +64,7 @@ impl MissingDoc {
         Self {
             crate_items_only,
             doc_hidden_stack: vec![false],
+            prev_span: None,
         }
     }
 
@@ -108,7 +119,8 @@ impl MissingDoc {
 
         let has_doc = attrs
             .iter()
-            .any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
+            .any(|a| a.doc_str().is_some() || Self::has_include(a.meta()))
+            || matches!(self.search_span(sp), Some(span) if span_to_snippet_contains_docs(cx, span));
 
         if !has_doc {
             span_lint(
@@ -119,6 +131,32 @@ impl MissingDoc {
             );
         }
     }
+
+    /// Return a span to search for doc comments manually.
+    ///
+    /// # Example
+    /// ```ignore
+    /// fn foo() { ... }
+    /// ^^^^^^^^^^^^^^^^ prev_span
+    ///                ↑
+    /// |  search_span |
+    /// ↓
+    /// fn bar() { ... }
+    /// ^^^^^^^^^^^^^^^^ cur_span
+    /// ```
+    fn search_span(&self, cur_span: Span) -> Option<Span> {
+        let prev_span = self.prev_span?;
+        let start_pos = if prev_span.contains(cur_span) {
+            // In case when the prev_span is an entire struct, or enum,
+            // and the current span is a field, or variant, we need to search from
+            // the starting pos of the previous span.
+            prev_span.lo()
+        } else {
+            prev_span.hi()
+        };
+        let search_span = cur_span.with_lo(start_pos).with_hi(cur_span.lo());
+        Some(search_span)
+    }
 }
 
 impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
@@ -138,6 +176,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
     }
 
+    fn check_crate_post(&mut self, _: &LateContext<'tcx>) {
+        self.prev_span = None;
+    }
+
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
         match it.kind {
             hir::ItemKind::Fn(..) => {
@@ -145,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
                 if it.ident.name == sym::main {
                     let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;
                     if at_root {
-                        return;
+                        note_prev_span_then_ret!(self.prev_span, it.span);
                     }
                 }
             },
@@ -164,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
             | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::Impl { .. }
-            | hir::ItemKind::Use(..) => return,
+            | hir::ItemKind::Use(..) => note_prev_span_then_ret!(self.prev_span, it.span),
         };
 
         let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
@@ -173,6 +215,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         if !is_from_proc_macro(cx, it) {
             self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
         }
+        self.prev_span = Some(it.span);
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
@@ -182,16 +225,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         if !is_from_proc_macro(cx, trait_item) {
             self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
         }
+        self.prev_span = Some(trait_item.span);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
         // If the method is an impl for a trait, don't doc.
         if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) {
             if cx.tcx.impl_trait_ref(cid).is_some() {
-                return;
+                note_prev_span_then_ret!(self.prev_span, impl_item.span);
             }
         } else {
-            return;
+            note_prev_span_then_ret!(self.prev_span, impl_item.span);
         }
 
         let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
@@ -199,6 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         if !is_from_proc_macro(cx, impl_item) {
             self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
         }
+        self.prev_span = Some(impl_item.span);
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
@@ -208,6 +253,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
                 self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
             }
         }
+        self.prev_span = Some(sf.span);
     }
 
     fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
@@ -215,5 +261,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         if !is_from_proc_macro(cx, v) {
             self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
         }
+        self.prev_span = Some(v.span);
     }
 }
+
+fn span_to_snippet_contains_docs(cx: &LateContext<'_>, search_span: Span) -> bool {
+    let Some(snippet) = snippet_opt(cx, search_span) else {
+        return false;
+    };
+    snippet.lines().rev().any(|line| line.trim().starts_with("///"))
+}
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 70fd07cd93c..648d780ac09 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
@@ -109,7 +109,14 @@ fn collect_unsafe_exprs<'tcx>(
             ExprKind::Path(QPath::Resolved(
                 _,
                 hir::Path {
-                    res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _),
+                    res:
+                        Res::Def(
+                            DefKind::Static {
+                                mutability: Mutability::Mut,
+                                ..
+                            },
+                            _,
+                        ),
                     ..
                 },
             )) => {
@@ -149,7 +156,13 @@ fn collect_unsafe_exprs<'tcx>(
                     ExprKind::Path(QPath::Resolved(
                         _,
                         hir::Path {
-                            res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _),
+                            res: Res::Def(
+                                DefKind::Static {
+                                    mutability: Mutability::Mut,
+                                    ..
+                                },
+                                _
+                            ),
                             ..
                         }
                     ))
diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs
index 72a2cca1e40..bc7b2c6b7c1 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::{span_lint, span_lint_hir};
 use clippy_utils::higher;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
@@ -35,9 +35,34 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
     }
 
     fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) {
-        use rustc_hir::intravisit::Visitor;
+        if in_external_macro(cx.sess(), ty.span) {
+            return;
+        }
 
-        MutVisitor { cx }.visit_ty(ty);
+        if let hir::TyKind::Ref(
+            _,
+            hir::MutTy {
+                ty: pty,
+                mutbl: hir::Mutability::Mut,
+            },
+        ) = ty.kind
+        {
+            if let hir::TyKind::Ref(
+                _,
+                hir::MutTy {
+                    mutbl: hir::Mutability::Mut,
+                    ..
+                },
+            ) = pty.kind
+            {
+                span_lint(
+                    cx,
+                    MUT_MUT,
+                    ty.span,
+                    "generally you want to avoid `&mut &mut _` if possible",
+                );
+            }
+        }
     }
 }
 
@@ -62,17 +87,19 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
             intravisit::walk_expr(self, body);
         } else if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e) = expr.kind {
             if let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) = e.kind {
-                span_lint(
+                span_lint_hir(
                     self.cx,
                     MUT_MUT,
+                    expr.hir_id,
                     expr.span,
                     "generally you want to avoid `&mut &mut _` if possible",
                 );
             } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() {
                 if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) {
-                    span_lint(
+                    span_lint_hir(
                         self.cx,
                         MUT_MUT,
+                        expr.hir_id,
                         expr.span,
                         "this expression mutably borrows a mutable reference. Consider reborrowing",
                     );
@@ -80,37 +107,4 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
             }
         }
     }
-
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
-        if in_external_macro(self.cx.sess(), ty.span) {
-            return;
-        }
-
-        if let hir::TyKind::Ref(
-            _,
-            hir::MutTy {
-                ty: pty,
-                mutbl: hir::Mutability::Mut,
-            },
-        ) = ty.kind
-        {
-            if let hir::TyKind::Ref(
-                _,
-                hir::MutTy {
-                    mutbl: hir::Mutability::Mut,
-                    ..
-                },
-            ) = pty.kind
-            {
-                span_lint(
-                    self.cx,
-                    MUT_MUT,
-                    ty.span,
-                    "generally you want to avoid `&mut &mut _` if possible",
-                );
-            }
-        }
-
-        intravisit::walk_ty(self, ty);
-    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index cebd2385656..6cb84bb78b6 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -290,14 +290,21 @@ impl NonCopyConst {
             promoted: None,
         };
         let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx);
-        let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP);
+        let result = cx
+            .tcx
+            .const_eval_global_id_for_typeck(param_env, cid, rustc_span::DUMMY_SP);
         self.is_value_unfrozen_raw(cx, result, ty)
     }
 
     fn is_value_unfrozen_expr<'tcx>(&self, cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
         let args = cx.typeck_results().node_args(hir_id);
 
-        let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), rustc_span::DUMMY_SP);
+        let result = Self::const_eval_resolve(
+            cx.tcx,
+            cx.param_env,
+            ty::UnevaluatedConst::new(def_id, args),
+            rustc_span::DUMMY_SP,
+        );
         self.is_value_unfrozen_raw(cx, result, ty)
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index d0b37cd92e0..0ebdb031d5a 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::get_enclosing_block;
 use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
 use clippy_utils::source::snippet;
@@ -77,36 +77,52 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                 if let Some(expr) = visitor.read_zero_expr {
                     let applicability = Applicability::MaybeIncorrect;
                     match vec_init_kind {
-                        VecInitKind::WithConstCapacity(len) => {
-                            span_lint_and_sugg(
-                                cx,
-                                READ_ZERO_BYTE_VEC,
-                                expr.span,
-                                "reading zero byte data to `Vec`",
-                                "try",
-                                format!("{}.resize({len}, 0); {}", ident.as_str(), snippet(cx, expr.span, "..")),
-                                applicability,
-                            );
-                        },
+                        VecInitKind::WithConstCapacity(len) => span_lint_hir_and_then(
+                            cx,
+                            READ_ZERO_BYTE_VEC,
+                            expr.hir_id,
+                            expr.span,
+                            "reading zero byte data to `Vec`",
+                            |diag| {
+                                diag.span_suggestion(
+                                    expr.span,
+                                    "try",
+                                    format!("{}.resize({len}, 0); {}", ident.as_str(), snippet(cx, expr.span, "..")),
+                                    applicability,
+                                );
+                            },
+                        ),
                         VecInitKind::WithExprCapacity(hir_id) => {
                             let e = cx.tcx.hir().expect_expr(hir_id);
-                            span_lint_and_sugg(
+                            span_lint_hir_and_then(
                                 cx,
                                 READ_ZERO_BYTE_VEC,
+                                expr.hir_id,
                                 expr.span,
                                 "reading zero byte data to `Vec`",
-                                "try",
-                                format!(
-                                    "{}.resize({}, 0); {}",
-                                    ident.as_str(),
-                                    snippet(cx, e.span, ".."),
-                                    snippet(cx, expr.span, "..")
-                                ),
-                                applicability,
+                                |diag| {
+                                    diag.span_suggestion(
+                                        expr.span,
+                                        "try",
+                                        format!(
+                                            "{}.resize({}, 0); {}",
+                                            ident.as_str(),
+                                            snippet(cx, e.span, ".."),
+                                            snippet(cx, expr.span, "..")
+                                        ),
+                                        applicability,
+                                    );
+                                },
                             );
                         },
                         _ => {
-                            span_lint(cx, READ_ZERO_BYTE_VEC, expr.span, "reading zero byte data to `Vec`");
+                            span_lint_hir(
+                                cx,
+                                READ_ZERO_BYTE_VEC,
+                                expr.hir_id,
+                                expr.span,
+                                "reading zero byte data to `Vec`",
+                            );
                         },
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index c2673bc409f..435899ddaa7 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -1,5 +1,5 @@
 use crate::rustc_lint::LintContext;
-use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir};
 use clippy_utils::get_parent_expr;
 use clippy_utils::sugg::Sugg;
 use hir::Param;
@@ -273,9 +273,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
                 && ident == path.segments[0].ident
                 && count_closure_usage(cx, block, path) == 1
             {
-                span_lint(
+                span_lint_hir(
                     cx,
                     REDUNDANT_CLOSURE_CALL,
+                    second.hir_id,
                     second.span,
                     "closure called just once immediately after it was declared",
                 );
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 19697527467..8bc24eda465 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
 use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
@@ -380,7 +380,7 @@ fn check_final_expr<'tcx>(
                 return;
             }
 
-            emit_return_lint(cx, ret_span, semi_spans, &replacement);
+            emit_return_lint(cx, ret_span, semi_spans, &replacement, expr.hir_id);
         },
         ExprKind::If(_, then, else_clause_opt) => {
             check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
@@ -415,18 +415,31 @@ fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool {
     contains_if(expr, false)
 }
 
-fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>, replacement: &RetReplacement<'_>) {
+fn emit_return_lint(
+    cx: &LateContext<'_>,
+    ret_span: Span,
+    semi_spans: Vec<Span>,
+    replacement: &RetReplacement<'_>,
+    at: HirId,
+) {
     if ret_span.from_expansion() {
         return;
     }
 
-    span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| {
-        let suggestions = std::iter::once((ret_span, replacement.to_string()))
-            .chain(semi_spans.into_iter().map(|span| (span, String::new())))
-            .collect();
+    span_lint_hir_and_then(
+        cx,
+        NEEDLESS_RETURN,
+        at,
+        ret_span,
+        "unneeded `return` statement",
+        |diag| {
+            let suggestions = std::iter::once((ret_span, replacement.to_string()))
+                .chain(semi_spans.into_iter().map(|span| (span, String::new())))
+                .collect();
 
-        diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability());
-    });
+            diag.multipart_suggestion_verbose(replacement.sugg_help(), suggestions, replacement.applicability());
+        },
+    );
 }
 
 fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
@@ -452,8 +465,8 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
 // Go backwards while encountering whitespace and extend the given Span to that point.
 fn extend_span_to_previous_non_ws(cx: &LateContext<'_>, sp: Span) -> Span {
     if let Ok(prev_source) = cx.sess().source_map().span_to_prev_source(sp) {
-        let ws = [' ', '\t', '\n'];
-        if let Some(non_ws_pos) = prev_source.rfind(|c| !ws.contains(&c)) {
+        let ws = [b' ', b'\t', b'\n'];
+        if let Some(non_ws_pos) = prev_source.bytes().rposition(|c| !ws.contains(&c)) {
             let len = prev_source.len() - non_ws_pos - 1;
             return sp.with_lo(sp.lo() - BytePos::from_usize(len));
         }
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index c0e4f3c368a..cf839941123 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -109,6 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     sym::core => (STD_INSTEAD_OF_CORE, "std", "core"),
                     sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"),
                     _ => {
+                        self.prev_span = first_segment.ident.span;
                         return;
                     },
                 },
@@ -116,6 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     if cx.tcx.crate_name(def_id.krate) == sym::core {
                         (ALLOC_INSTEAD_OF_CORE, "alloc", "core")
                     } else {
+                        self.prev_span = first_segment.ident.span;
                         return;
                     }
                 },
diff --git a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
index 1af3733ebfa..f8bdb866ca3 100644
--- a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
+++ b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
@@ -37,7 +37,7 @@ declare_clippy_lint! {
     ///     static BUF: String = const { String::new() };
     /// }
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST,
     perf,
     "suggest using `const` in `thread_local!` macro"
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index e47b14bf63b..3c11b481310 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -514,7 +514,7 @@ declare_clippy_lint! {
     ///              ^^^^ ^^ `bool::then` only executes the closure if the condition is true!
     /// }
     /// ```
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub EAGER_TRANSMUTE,
     correctness,
     "eager evaluation of `transmute`"
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index bdef82e9c5e..2ad15ac8312 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -392,6 +392,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) {
+        if field.span.from_expansion() {
+            return;
+        }
+
         let is_exported = cx.effective_visibilities.is_exported(field.def_id);
 
         self.check_ty(
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 224ec475c51..d638af2b78b 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{expr_or_init, get_trait_def_id, path_def_id};
+use clippy_utils::{expr_or_init, fn_def_id_with_node_args, path_def_id};
 use rustc_ast::BinOpKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
@@ -19,11 +19,11 @@ use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks that there isn't an infinite recursion in `PartialEq` trait
-    /// implementation.
+    /// Checks that there isn't an infinite recursion in trait
+    /// implementations.
     ///
     /// ### Why is this bad?
-    /// This is a hard to find infinite recursion which will crashing any code
+    /// This is a hard to find infinite recursion that will crash any code.
     /// using it.
     ///
     /// ### Example
@@ -42,7 +42,7 @@ declare_clippy_lint! {
     /// Use instead:
     ///
     /// In such cases, either use `#[derive(PartialEq)]` or don't implement it.
-    #[clippy::version = "1.76.0"]
+    #[clippy::version = "1.77.0"]
     pub UNCONDITIONAL_RECURSION,
     suspicious,
     "detect unconditional recursion in some traits implementation"
@@ -201,7 +201,6 @@ fn check_partial_eq(cx: &LateContext<'_>, method_span: Span, method_def_id: Loca
     }
 }
 
-#[allow(clippy::unnecessary_def_path)]
 fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, name: Ident, expr: &Expr<'_>) {
     let args = cx
         .tcx
@@ -224,7 +223,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local
         && let Some(trait_) = impl_.of_trait
         && let Some(trait_def_id) = trait_.trait_def_id()
         // The trait is `ToString`.
-        && Some(trait_def_id) == get_trait_def_id(cx, &["alloc", "string", "ToString"])
+        && cx.tcx.is_diagnostic_item(sym::ToString, trait_def_id)
     {
         let is_bad = match expr.kind {
             ExprKind::MethodCall(segment, _receiver, &[_arg], _) if segment.ident.name == name.name => {
@@ -291,7 +290,6 @@ where
         self.map
     }
 
-    #[allow(clippy::unnecessary_def_path)]
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         if self.found_default_call {
             return;
@@ -303,7 +301,7 @@ where
             && is_default_method_on_current_ty(self.cx.tcx, qpath, self.implemented_ty_id)
             && let Some(method_def_id) = path_def_id(self.cx, f)
             && let Some(trait_def_id) = self.cx.tcx.trait_of_item(method_def_id)
-            && Some(trait_def_id) == get_trait_def_id(self.cx, &["core", "default", "Default"])
+            && self.cx.tcx.is_diagnostic_item(sym::Default, trait_def_id)
         {
             self.found_default_call = true;
             span_error(self.cx, self.method_span, expr);
@@ -312,10 +310,9 @@ where
 }
 
 impl UnconditionalRecursion {
-    #[allow(clippy::unnecessary_def_path)]
     fn init_default_impl_for_type_if_needed(&mut self, cx: &LateContext<'_>) {
         if self.default_impl_for_type.is_empty()
-            && let Some(default_trait_id) = get_trait_def_id(cx, &["core", "default", "Default"])
+            && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
         {
             let impls = cx.tcx.trait_impls_of(default_trait_id);
             for (ty, impl_def_ids) in impls.non_blanket_impls() {
@@ -394,6 +391,34 @@ impl UnconditionalRecursion {
     }
 }
 
+fn check_from(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, expr: &Expr<'_>) {
+    let Some(sig) = cx
+        .typeck_results()
+        .liberated_fn_sigs()
+        .get(cx.tcx.local_def_id_to_hir_id(method_def_id))
+    else {
+        return;
+    };
+
+    // Check if we are calling `Into::into` where the node args match with our `From::from` signature:
+    // From::from signature: fn(S1) -> S2
+    // <S1 as Into<S2>>::into(s1), node_args=[S1, S2]
+    // If they do match, then it must mean that it is the blanket impl,
+    // which calls back into our `From::from` again (`Into` is not specializable).
+    // rustc's unconditional_recursion already catches calling `From::from` directly
+    if let Some((fn_def_id, node_args)) = fn_def_id_with_node_args(cx, expr)
+        && let [s1, s2] = **node_args
+        && let (Some(s1), Some(s2)) = (s1.as_type(), s2.as_type())
+        && let Some(trait_def_id) = cx.tcx.trait_of_item(fn_def_id)
+        && cx.tcx.is_diagnostic_item(sym::Into, trait_def_id)
+        && get_impl_trait_def_id(cx, method_def_id) == cx.tcx.get_diagnostic_item(sym::From)
+        && s1 == sig.inputs()[0]
+        && s2 == sig.output()
+    {
+        span_error(cx, method_span, expr);
+    }
+}
+
 impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion {
     fn check_fn(
         &mut self,
@@ -410,10 +435,11 @@ impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion {
             // Doesn't have a conditional return.
             && !has_conditional_return(body, expr)
         {
-            if name.name == sym::eq || name.name == sym::ne {
-                check_partial_eq(cx, method_span, method_def_id, name, expr);
-            } else if name.name == sym::to_string {
-                check_to_string(cx, method_span, method_def_id, name, expr);
+            match name.name {
+                sym::eq | sym::ne => check_partial_eq(cx, method_span, method_def_id, name, expr),
+                sym::to_string => check_to_string(cx, method_span, method_def_id, name, expr),
+                sym::from => check_from(cx, method_span, method_def_id, expr),
+                _ => {},
             }
             self.check_default_new(cx, decl, body, method_span, method_def_id);
         }
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index 1497d883dfc..d8c5f1b7382 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -1,7 +1,7 @@
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths, peel_blocks};
-use hir::{ExprKind, PatKind};
+use hir::{ExprKind, HirId, PatKind};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -135,22 +135,22 @@ fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
                 && is_ok_wild_or_dotdot_pattern(cx, pat)
                 && let Some(op) = should_lint(cx, init) =>
         {
-            emit_lint(cx, cond.span, op, &[pat.span]);
+            emit_lint(cx, cond.span, cond.hir_id, op, &[pat.span]);
         },
         // we will capture only the case where the match is Ok( ) or Err( )
         // prefer to match the minimum possible, and expand later if needed
         // to avoid false positives on something as used as this
         hir::ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => {
             if non_consuming_ok_arm(cx, arm1) && non_consuming_err_arm(cx, arm2) {
-                emit_lint(cx, expr.span, op, &[arm1.pat.span]);
+                emit_lint(cx, expr.span, expr.hir_id, op, &[arm1.pat.span]);
             }
             if non_consuming_ok_arm(cx, arm2) && non_consuming_err_arm(cx, arm1) {
-                emit_lint(cx, expr.span, op, &[arm2.pat.span]);
+                emit_lint(cx, expr.span, expr.hir_id, op, &[arm2.pat.span]);
             }
         },
         hir::ExprKind::Match(_, _, hir::MatchSource::Normal) => {},
         _ if let Some(op) = should_lint(cx, expr) => {
-            emit_lint(cx, expr.span, op, &[]);
+            emit_lint(cx, expr.span, expr.hir_id, op, &[]);
         },
         _ => {},
     };
@@ -279,7 +279,7 @@ fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option<IoOp> {
     }
 }
 
-fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) {
+fn emit_lint(cx: &LateContext<'_>, span: Span, at: HirId, op: IoOp, wild_cards: &[Span]) {
     let (msg, help) = match op {
         IoOp::AsyncRead(false) => (
             "read amount is not handled",
@@ -301,7 +301,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) {
         IoOp::SyncWrite(true) | IoOp::AsyncWrite(true) => ("written amount is not handled", None),
     };
 
-    span_lint_and_then(cx, UNUSED_IO_AMOUNT, span, msg, |diag| {
+    span_lint_hir_and_then(cx, UNUSED_IO_AMOUNT, at, span, msg, |diag| {
         if let Some(help_str) = help {
             diag.help(help_str);
         }
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index f1d0c22b1ae..3f4ab3e31cf 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
 use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators};
 use rustc_ast::Mutability;
@@ -79,13 +79,15 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable {
                 }
 
                 if !vis.found_peek_call {
-                    span_lint_and_help(
+                    span_lint_hir_and_then(
                         cx,
                         UNUSED_PEEKABLE,
+                        local.hir_id,
                         ident.span,
                         "`peek` never called on `Peekable` iterator",
-                        None,
-                        "consider removing the call to `peekable`",
+                        |diag| {
+                            diag.help("consider removing the call to `peekable`");
+                        },
                     );
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index a1b08d105b9..b28037db112 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -8,11 +8,12 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{walk_inf, walk_ty, Visitor};
 use rustc_hir::{
-    self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind,
-    HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
+    self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl,
+    ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
 };
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty as MiddleTy;
 use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
@@ -95,10 +96,9 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
         let stack_item = if let ItemKind::Impl(Impl { self_ty, generics, .. }) = item.kind
             && let TyKind::Path(QPath::Resolved(_, item_path)) = self_ty.kind
             && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args
-            && parameters.as_ref().map_or(true, |params| {
-                params.parenthesized == GenericArgsParentheses::No
-                    && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
-            })
+            && parameters
+                .as_ref()
+                .map_or(true, |params| params.parenthesized == GenericArgsParentheses::No)
             && !item.span.from_expansion()
             && !is_from_proc_macro(cx, item)
         // expensive, should be last check
@@ -226,7 +226,12 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             } else {
                 hir_ty_to_ty(cx.tcx, hir_ty)
             }
-            && same_type_and_consts(ty, cx.tcx.type_of(impl_id).instantiate_identity())
+            && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity()
+            && same_type_and_consts(ty, impl_ty)
+            // Ensure the type we encounter and the one from the impl have the same lifetime parameters. It may be that
+            // the lifetime parameters of `ty` are ellided (`impl<'a> Foo<'a> { fn new() -> Self { Foo{..} } }`, in
+            // which case we must still trigger the lint.
+            && (has_no_lifetime(ty) || same_lifetimes(ty, impl_ty))
         {
             span_lint(cx, hir_ty.span);
         }
@@ -318,3 +323,37 @@ fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) {
         span_lint(cx, span);
     }
 }
+
+/// Returns `true` if types `a` and `b` have the same lifetime parameters, otherwise returns
+/// `false`.
+///
+/// This function does not check that types `a` and `b` are the same types.
+fn same_lifetimes<'tcx>(a: MiddleTy<'tcx>, b: MiddleTy<'tcx>) -> bool {
+    use rustc_middle::ty::{Adt, GenericArgKind};
+    match (&a.kind(), &b.kind()) {
+        (&Adt(_, args_a), &Adt(_, args_b)) => {
+            args_a
+                .iter()
+                .zip(args_b.iter())
+                .all(|(arg_a, arg_b)| match (arg_a.unpack(), arg_b.unpack()) {
+                    // TODO: Handle inferred lifetimes
+                    (GenericArgKind::Lifetime(inner_a), GenericArgKind::Lifetime(inner_b)) => inner_a == inner_b,
+                    (GenericArgKind::Type(type_a), GenericArgKind::Type(type_b)) => same_lifetimes(type_a, type_b),
+                    _ => true,
+                })
+        },
+        _ => a == b,
+    }
+}
+
+/// Returns `true` if `ty` has no lifetime parameter, otherwise returns `false`.
+fn has_no_lifetime(ty: MiddleTy<'_>) -> bool {
+    use rustc_middle::ty::{Adt, GenericArgKind};
+    match ty.kind() {
+        &Adt(_, args) => !args
+            .iter()
+            // TODO: Handle inferred lifetimes
+            .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(..))),
+        _ => true,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 97b509a84f9..1ebe1d6a2c4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -925,7 +925,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
             && let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr))
             && match_type(self.cx, expr_ty, &paths::LINT)
         {
-            if let hir::def::Res::Def(DefKind::Static(..), _) = path.res {
+            if let hir::def::Res::Def(DefKind::Static { .. }, _) = path.res {
                 let lint_name = last_path_segment(qpath).ident.name;
                 self.lints.push(sym_to_string(lint_name).to_ascii_lowercase());
             } else if let Some(local) = get_parent_local(self.cx, expr) {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 38c832931fc..f4e277fd0c4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -223,7 +223,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
                     None
                 }
             },
-            Res::Def(DefKind::Static(_), def_id) => read_mir_alloc_def_path(
+            Res::Def(DefKind::Static { .. }, def_id) => read_mir_alloc_def_path(
                 cx,
                 cx.tcx.eval_static_initializer(def_id).ok()?.inner(),
                 cx.tcx.type_of(def_id).instantiate_identity(),
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 5410e8ac117..436f0cb79fb 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -213,7 +213,7 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool {
 // Allow skipping imports containing user configured segments,
 // i.e. "...::utils::...::*" if user put `allowed-wildcard-imports = ["utils"]` in `Clippy.toml`
 fn is_allowed_via_config(segments: &[PathSegment<'_>], allowed_segments: &FxHashSet<String>) -> bool {
-    // segment matching need to be exact instead of using 'contains', in case user unintentionaly put
+    // segment matching need to be exact instead of using 'contains', in case user unintentionally put
     // a single character in the config thus skipping most of the warnings.
     segments.iter().any(|seg| allowed_segments.contains(seg.ident.as_str()))
 }
diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
new file mode 100644
index 00000000000..852d04cd21b
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs
@@ -0,0 +1,154 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::higher::VecArgs;
+use clippy_utils::source::snippet;
+use clippy_utils::visitors::for_each_expr;
+use rustc_ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir::{ExprKind, Node};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, ConstKind, Ty};
+use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for array or vec initializations which call a function or method,
+    /// but which have a repeat count of zero.
+    ///
+    /// ### Why is this bad?
+    /// Such an initialization, despite having a repeat length of 0, will still call the inner function.
+    /// This may not be obvious and as such there may be unintended side effects in code.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// fn side_effect() -> i32 {
+    ///     println!("side effect");
+    ///     10
+    /// }
+    /// let a = [side_effect(); 0];
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// fn side_effect() -> i32 {
+    ///     println!("side effect");
+    ///     10
+    /// }
+    /// side_effect();
+    /// let a: [i32; 0] = [];
+    /// ```
+    #[clippy::version = "1.75.0"]
+    pub ZERO_REPEAT_SIDE_EFFECTS,
+    suspicious,
+    "usage of zero-sized initializations of arrays or vecs causing side effects"
+}
+
+declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
+
+impl LateLintPass<'_> for ZeroRepeatSideEffects {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
+        if let Some(args) = VecArgs::hir(cx, expr)
+            && let VecArgs::Repeat(inner_expr, len) = args
+            && let ExprKind::Lit(l) = len.kind
+            && let LitKind::Int(i, _) = l.node
+            && i.0 == 0
+        {
+            inner_check(cx, expr, inner_expr, true);
+        } else if let ExprKind::Repeat(inner_expr, _) = expr.kind
+            && let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind()
+            && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
+            && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
+            && element_count == 0
+        {
+            inner_check(cx, expr, inner_expr, false);
+        }
+    }
+}
+
+fn inner_check(cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>, inner_expr: &'_ rustc_hir::Expr<'_>, is_vec: bool) {
+    // check if expr is a call or has a call inside it
+    if for_each_expr(inner_expr, |x| {
+        if let ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _) = x.kind {
+            std::ops::ControlFlow::Break(())
+        } else {
+            std::ops::ControlFlow::Continue(())
+        }
+    })
+    .is_some()
+    {
+        let parent_hir_node = cx.tcx.parent_hir_node(expr.hir_id);
+        let return_type = cx.typeck_results().expr_ty(expr);
+
+        if let Node::Local(l) = parent_hir_node {
+            array_span_lint(
+                cx,
+                l.span,
+                inner_expr.span,
+                l.pat.span,
+                Some(return_type),
+                is_vec,
+                false,
+            );
+        } else if let Node::Expr(x) = parent_hir_node
+            && let ExprKind::Assign(l, _, _) = x.kind
+        {
+            array_span_lint(cx, x.span, inner_expr.span, l.span, Some(return_type), is_vec, true);
+        } else {
+            span_lint_and_sugg(
+                cx,
+                ZERO_REPEAT_SIDE_EFFECTS,
+                expr.span.source_callsite(),
+                "function or method calls as the initial value in zero-sized array initializers may cause side effects",
+                "consider using",
+                format!(
+                    "{{ {}; {}[] as {return_type} }}",
+                    snippet(cx, inner_expr.span.source_callsite(), ".."),
+                    if is_vec { "vec!" } else { "" },
+                ),
+                Applicability::Unspecified,
+            );
+        }
+    }
+}
+
+fn array_span_lint(
+    cx: &LateContext<'_>,
+    expr_span: Span,
+    func_call_span: Span,
+    variable_name_span: Span,
+    expr_ty: Option<Ty<'_>>,
+    is_vec: bool,
+    is_assign: bool,
+) {
+    let has_ty = expr_ty.is_some();
+
+    span_lint_and_sugg(
+        cx,
+        ZERO_REPEAT_SIDE_EFFECTS,
+        expr_span.source_callsite(),
+        "function or method calls as the initial value in zero-sized array initializers may cause side effects",
+        "consider using",
+        format!(
+            "{}; {}{}{} = {}[]{}{}",
+            snippet(cx, func_call_span.source_callsite(), ".."),
+            if has_ty && !is_assign { "let " } else { "" },
+            snippet(cx, variable_name_span.source_callsite(), ".."),
+            if let Some(ty) = expr_ty
+                && !is_assign
+            {
+                format!(": {ty}")
+            } else {
+                String::new()
+            },
+            if is_vec { "vec!" } else { "" },
+            if let Some(ty) = expr_ty
+                && is_assign
+            {
+                format!(" as {ty}")
+            } else {
+                String::new()
+            },
+            if is_assign { "" } else { ";" }
+        ),
+        Applicability::Unspecified,
+    );
+}
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index bf55040ddbc..d2bb719a517 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.78"
+version = "0.1.79"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index e75d5953fae..046087d3298 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -10,8 +10,10 @@ use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{alloc_range, Scalar};
+use rustc_middle::mir::ConstValue;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy};
 use rustc_middle::{bug, mir, span_bug};
+use rustc_span::def_id::DefId;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::SyntaxContext;
 use rustc_target::abi::Size;
@@ -307,6 +309,12 @@ impl ConstantSource {
     }
 }
 
+/// Attempts to check whether the expression is a constant representing an empty slice, str, array,
+/// etc…
+pub fn constant_is_empty(lcx: &LateContext<'_>, e: &Expr<'_>) -> Option<bool> {
+    ConstEvalLateContext::new(lcx, lcx.typeck_results()).expr_is_empty(e)
+}
+
 /// Attempts to evaluate the expression as a constant.
 pub fn constant<'tcx>(
     lcx: &LateContext<'tcx>,
@@ -406,7 +414,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         match e.kind {
             ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value),
             ExprKind::DropTemps(e) => self.expr(e),
-            ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
+            ExprKind::Path(ref qpath) => {
+                self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
+                    let result = mir_to_const(this.lcx, result)?;
+                    this.source = ConstantSource::Constant;
+                    Some(result)
+                })
+            },
             ExprKind::Block(block, _) => self.block(block),
             ExprKind::Lit(lit) => {
                 if is_direct_expn_of(e.span, "cfg").is_some() {
@@ -472,6 +486,49 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
+    /// Simple constant folding to determine if an expression is an empty slice, str, array, …
+    /// `None` will be returned if the constness cannot be determined, or if the resolution
+    /// leaves the local crate.
+    pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
+        match e.kind {
+            ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value),
+            ExprKind::DropTemps(e) => self.expr_is_empty(e),
+            ExprKind::Path(ref qpath) => {
+                if !self
+                    .typeck_results
+                    .qpath_res(qpath, e.hir_id)
+                    .opt_def_id()
+                    .is_some_and(DefId::is_local)
+                {
+                    return None;
+                }
+                self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
+                    mir_is_empty(this.lcx, result)
+                })
+            },
+            ExprKind::Lit(lit) => {
+                if is_direct_expn_of(e.span, "cfg").is_some() {
+                    None
+                } else {
+                    match &lit.node {
+                        LitKind::Str(is, _) => Some(is.is_empty()),
+                        LitKind::ByteStr(s, _) | LitKind::CStr(s, _) => Some(s.is_empty()),
+                        _ => None,
+                    }
+                }
+            },
+            ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()),
+            ExprKind::Repeat(..) => {
+                if let ty::Array(_, n) = self.typeck_results.expr_ty(e).kind() {
+                    Some(n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)? == 0)
+                } else {
+                    span_bug!(e.span, "typeck error");
+                }
+            },
+            _ => None,
+        }
+    }
+
     #[expect(clippy::cast_possible_wrap)]
     fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
         use self::Constant::{Bool, Int};
@@ -519,8 +576,11 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         vec.iter().map(|elem| self.expr(elem)).collect::<Option<_>>()
     }
 
-    /// Lookup a possibly constant expression from an `ExprKind::Path`.
-    fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<Constant<'tcx>> {
+    /// Lookup a possibly constant expression from an `ExprKind::Path` and apply a function on it.
+    fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option<T>
+    where
+        F: FnOnce(&mut Self, rustc_middle::mir::Const<'tcx>) -> Option<T>,
+    {
         let res = self.typeck_results.qpath_res(qpath, id);
         match res {
             Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => {
@@ -553,9 +613,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
                     .ok()
                     .map(|val| rustc_middle::mir::Const::from_value(val, ty))?;
-                let result = mir_to_const(self.lcx, result)?;
-                self.source = ConstantSource::Constant;
-                Some(result)
+                f(self, result)
             },
             _ => None,
         }
@@ -746,7 +804,6 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
 }
 
 pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
-    use rustc_middle::mir::ConstValue;
     let mir::Const::Val(val, _) = result else {
         // We only work on evaluated consts.
         return None;
@@ -794,6 +851,42 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
     }
 }
 
+fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<bool> {
+    let mir::Const::Val(val, _) = result else {
+        // We only work on evaluated consts.
+        return None;
+    };
+    match (val, result.ty().kind()) {
+        (_, ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
+            ty::Str | ty::Slice(_) => {
+                if let ConstValue::Indirect { alloc_id, offset } = val {
+                    // Get the length from the slice, using the same formula as
+                    // [`ConstValue::try_get_slice_bytes_for_diagnostics`].
+                    let a = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
+                    let ptr_size = lcx.tcx.data_layout.pointer_size;
+                    if a.size() < offset + 2 * ptr_size {
+                        // (partially) dangling reference
+                        return None;
+                    }
+                    let len = a
+                        .read_scalar(&lcx.tcx, alloc_range(offset + ptr_size, ptr_size), false)
+                        .ok()?
+                        .to_target_usize(&lcx.tcx)
+                        .ok()?;
+                    Some(len == 0)
+                } else {
+                    None
+                }
+            },
+            ty::Array(_, len) => Some(len.try_to_target_usize(lcx.tcx)? == 0),
+            _ => None,
+        },
+        (ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(lcx.tcx)? == 0),
+        (ConstValue::ZeroSized, _) => Some(true),
+        _ => None,
+    }
+}
+
 fn field_of_struct<'tcx>(
     adt_def: ty::AdtDef<'tcx>,
     lcx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 6ed46e5dde0..0352696f93e 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -36,6 +36,20 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
 /// Usually it's nicer to provide more context for lint messages.
 /// Be sure the output is understandable when you use this method.
 ///
+/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
+/// the lint level.
+/// For the `span_lint` function, the node that was passed into the `LintPass::check_*` function is
+/// used.
+///
+/// If you're emitting the lint at the span of a different node than the one provided by the
+/// `LintPass::check_*` function, consider using [`span_lint_hir`] instead.
+/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
+/// highlighted in the displayed warning.
+///
+/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
+/// where you would expect it to.
+/// If it doesn't, you likely need to use [`span_lint_hir`] instead.
+///
 /// # Example
 ///
 /// ```ignore
@@ -61,6 +75,20 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
 ///
 /// If you change the signature, remember to update the internal lint `CollapsibleCalls`
 ///
+/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
+/// the lint level.
+/// For the `span_lint_and_help` function, the node that was passed into the `LintPass::check_*`
+/// function is used.
+///
+/// If you're emitting the lint at the span of a different node than the one provided by the
+/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
+/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
+/// highlighted in the displayed warning.
+///
+/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
+/// where you would expect it to.
+/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
+///
 /// # Example
 ///
 /// ```text
@@ -99,6 +127,20 @@ pub fn span_lint_and_help<T: LintContext>(
 ///
 /// If you change the signature, remember to update the internal lint `CollapsibleCalls`
 ///
+/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
+/// the lint level.
+/// For the `span_lint_and_note` function, the node that was passed into the `LintPass::check_*`
+/// function is used.
+///
+/// If you're emitting the lint at the span of a different node than the one provided by the
+/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
+/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
+/// highlighted in the displayed warning.
+///
+/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
+/// where you would expect it to.
+/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
+///
 /// # Example
 ///
 /// ```text
@@ -139,6 +181,20 @@ pub fn span_lint_and_note<T: LintContext>(
 ///
 /// If you need to customize your lint output a lot, use this function.
 /// If you change the signature, remember to update the internal lint `CollapsibleCalls`
+///
+/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
+/// the lint level.
+/// For the `span_lint_and_then` function, the node that was passed into the `LintPass::check_*`
+/// function is used.
+///
+/// If you're emitting the lint at the span of a different node than the one provided by the
+/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
+/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
+/// highlighted in the displayed warning.
+///
+/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
+/// where you would expect it to.
+/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
 pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F)
 where
     C: LintContext,
@@ -152,6 +208,30 @@ where
     });
 }
 
+/// Like [`span_lint`], but emits the lint at the node identified by the given `HirId`.
+///
+/// This is in contrast to [`span_lint`], which always emits the lint at the node that was last
+/// passed to the `LintPass::check_*` function.
+///
+/// The `HirId` is used for checking lint level attributes and to fulfill lint expectations defined
+/// via the `#[expect]` attribute.
+///
+/// For example:
+/// ```ignore
+/// fn f() { /* <node_1> */
+///
+///     #[allow(clippy::some_lint)]
+///     let _x = /* <expr_1> */;
+/// }
+/// ```
+/// If `some_lint` does its analysis in `LintPass::check_fn` (at `<node_1>`) and emits a lint at
+/// `<expr_1>` using [`span_lint`], then allowing the lint at `<expr_1>` as attempted in the snippet
+/// will not work!
+/// Even though that is where the warning points at, which would be confusing to users.
+///
+/// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
+/// the compiler check lint level attributes at the place of the expression and
+/// the `#[allow]` will work.
 pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
     #[expect(clippy::disallowed_methods)]
     cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
@@ -159,6 +239,30 @@ pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, s
     });
 }
 
+/// Like [`span_lint_and_then`], but emits the lint at the node identified by the given `HirId`.
+///
+/// This is in contrast to [`span_lint_and_then`], which always emits the lint at the node that was
+/// last passed to the `LintPass::check_*` function.
+///
+/// The `HirId` is used for checking lint level attributes and to fulfill lint expectations defined
+/// via the `#[expect]` attribute.
+///
+/// For example:
+/// ```ignore
+/// fn f() { /* <node_1> */
+///
+///     #[allow(clippy::some_lint)]
+///     let _x = /* <expr_1> */;
+/// }
+/// ```
+/// If `some_lint` does its analysis in `LintPass::check_fn` (at `<node_1>`) and emits a lint at
+/// `<expr_1>` using [`span_lint`], then allowing the lint at `<expr_1>` as attempted in the snippet
+/// will not work!
+/// Even though that is where the warning points at, which would be confusing to users.
+///
+/// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
+/// the compiler check lint level attributes at the place of the expression and
+/// the `#[allow]` will work.
 pub fn span_lint_hir_and_then(
     cx: &LateContext<'_>,
     lint: &'static Lint,
@@ -182,6 +286,20 @@ pub fn span_lint_hir_and_then(
 ///
 /// If you change the signature, remember to update the internal lint `CollapsibleCalls`
 ///
+/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
+/// the lint level.
+/// For the `span_lint_and_sugg` function, the node that was passed into the `LintPass::check_*`
+/// function is used.
+///
+/// If you're emitting the lint at the span of a different node than the one provided by the
+/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
+/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
+/// highlighted in the displayed warning.
+///
+/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
+/// where you would expect it to.
+/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
+///
 /// # Example
 ///
 /// ```text
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index b4cc747e0e6..11b56ed47de 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2246,8 +2246,21 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
 
 /// Returns the `DefId` of the callee if the given expression is a function or method call.
 pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
+    fn_def_id_with_node_args(cx, expr).map(|(did, _)| did)
+}
+
+/// Returns the `DefId` of the callee if the given expression is a function or method call,
+/// as well as its node args.
+pub fn fn_def_id_with_node_args<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'_>,
+) -> Option<(DefId, rustc_ty::GenericArgsRef<'tcx>)> {
+    let typeck = cx.typeck_results();
     match &expr.kind {
-        ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
+        ExprKind::MethodCall(..) => Some((
+            typeck.type_dependent_def_id(expr.hir_id)?,
+            typeck.node_args(expr.hir_id),
+        )),
         ExprKind::Call(
             Expr {
                 kind: ExprKind::Path(qpath),
@@ -2259,9 +2272,9 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
             // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or
             // deref to fn pointers, dyn Fn, impl Fn - #8850
             if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) =
-                cx.typeck_results().qpath_res(qpath, *path_hir_id)
+                typeck.qpath_res(qpath, *path_hir_id)
             {
-                Some(id)
+                Some((id, typeck.node_args(*path_hir_id)))
             } else {
                 None
             }
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 987f28192a8..456b8019e95 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -19,6 +19,8 @@ pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "B
 pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
 pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
 pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
+pub const CORE_ITER_ENUMERATE_METHOD: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "enumerate"];
+pub const CORE_ITER_ENUMERATE_STRUCT: [&str; 5] = ["core", "iter", "adapters", "enumerate", "Enumerate"];
 pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
 pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 296eb8dd340..9a3a41e1d1e 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "declare_clippy_lint"
-version = "0.1.78"
+version = "0.1.79"
 edition = "2021"
 publish = false
 
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 070b62887d5..a63e66f3214 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-03-07"
+channel = "nightly-2024-03-21"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
index ae5d6843406..cfc590bed36 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -4,6 +4,7 @@ error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
 LL |     cx.span_lint(lint, span, msg, |_| {});
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead (from clippy.toml)
    = note: `-D clippy::disallowed-methods` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
 
@@ -12,6 +13,8 @@ error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_
    |
 LL |     tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead (from clippy.toml)
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.fixed
new file mode 100644
index 00000000000..d42b29ba21a
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.fixed
@@ -0,0 +1,38 @@
+//@compile-flags: --test
+#![warn(clippy::dbg_macro)]
+#![allow(clippy::unnecessary_operation, clippy::no_effect)]
+
+fn foo(n: u32) -> u32 {
+    if let Some(n) = n.checked_sub(4) { n } else { n }
+}
+
+fn factorial(n: u32) -> u32 {
+    if n <= 1 {
+        1
+    } else {
+        n * factorial(n - 1)
+    }
+}
+
+fn main() {
+    42;
+    foo(3) + factorial(4);
+    (1, 2, 3, 4, 5);
+}
+
+#[test]
+pub fn issue8481() {
+    dbg!(1);
+}
+
+#[cfg(test)]
+fn foo2() {
+    dbg!(1);
+}
+
+#[cfg(test)]
+mod mod1 {
+    fn func() {
+        dbg!(1);
+    }
+}
diff --git a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs
index 67129e62477..bd189b1576f 100644
--- a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.rs
@@ -1,6 +1,7 @@
 //@compile-flags: --test
 #![warn(clippy::dbg_macro)]
-//@no-rustfix
+#![allow(clippy::unnecessary_operation, clippy::no_effect)]
+
 fn foo(n: u32) -> u32 {
     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
 }
@@ -15,9 +16,7 @@ fn factorial(n: u32) -> u32 {
 
 fn main() {
     dbg!(42);
-    dbg!(dbg!(dbg!(42)));
     foo(3) + dbg!(factorial(4));
-    dbg!(1, 2, dbg!(3, 4));
     dbg!(1, 2, 3, 4, 5);
 }
 
diff --git a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
index 8ffc426be2d..129fab5ff97 100644
--- a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
@@ -1,5 +1,5 @@
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:5:22
+  --> tests/ui-toml/dbg_macro/dbg_macro.rs:6:22
    |
 LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
    |                      ^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:9:8
+  --> tests/ui-toml/dbg_macro/dbg_macro.rs:10:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     if n <= 1 {
    |        ~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:10:9
+  --> tests/ui-toml/dbg_macro/dbg_macro.rs:11:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -34,7 +34,7 @@ LL |         1
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:12:9
+  --> tests/ui-toml/dbg_macro/dbg_macro.rs:13:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |         n * factorial(n - 1)
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:17:5
+  --> tests/ui-toml/dbg_macro/dbg_macro.rs:18:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -55,17 +55,6 @@ help: remove the invocation before committing it to a version control system
 LL |     42;
    |     ~~
 
-error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:18:5
-   |
-LL |     dbg!(dbg!(dbg!(42)));
-   |     ^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the invocation before committing it to a version control system
-   |
-LL |     dbg!(dbg!(42));
-   |     ~~~~~~~~~~~~~~
-
 error: the `dbg!` macro is intended as a debugging tool
   --> tests/ui-toml/dbg_macro/dbg_macro.rs:19:14
    |
@@ -80,17 +69,6 @@ LL |     foo(3) + factorial(4);
 error: the `dbg!` macro is intended as a debugging tool
   --> tests/ui-toml/dbg_macro/dbg_macro.rs:20:5
    |
-LL |     dbg!(1, 2, dbg!(3, 4));
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the invocation before committing it to a version control system
-   |
-LL |     (1, 2, dbg!(3, 4));
-   |     ~~~~~~~~~~~~~~~~~~
-
-error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui-toml/dbg_macro/dbg_macro.rs:21:5
-   |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
    |
@@ -99,5 +77,5 @@ help: remove the invocation before committing it to a version control system
 LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
 
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
index 663c2eb2c37..523148d6586 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
@@ -1,7 +1,7 @@
 //@aux-build:proc_macros.rs
 #![feature(lint_reasons)]
 #![deny(clippy::allow_attributes_without_reason)]
-#![allow(unfulfilled_lint_expectations)]
+#![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)]
 
 extern crate proc_macros;
 use proc_macros::{external, with_span};
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
index 3c81233bf77..770a771ec3d 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
@@ -1,8 +1,8 @@
 error: `allow` attribute without specifying a reason
   --> tests/ui/allow_attributes_without_reason.rs:4:1
    |
-LL | #![allow(unfulfilled_lint_expectations)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a reason at the end with `, reason = ".."`
 note: the lint level is defined here
diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed
index c66e0c1f602..160f3b94663 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.fixed
+++ b/src/tools/clippy/tests/ui/assigning_clones.fixed
@@ -128,6 +128,19 @@ fn ignore_generic_clone<T: Clone>(a: &mut T, b: &T) {
     *a = b.clone();
 }
 
+#[clippy::msrv = "1.62"]
+fn msrv_1_62(mut a: String, b: String, c: &str) {
+    a.clone_from(&b);
+    // Should not be linted, as clone_into wasn't stabilized until 1.63
+    a = c.to_owned();
+}
+
+#[clippy::msrv = "1.63"]
+fn msrv_1_63(mut a: String, b: String, c: &str) {
+    a.clone_from(&b);
+    c.clone_into(&mut a);
+}
+
 macro_rules! clone_inside {
     ($a:expr, $b: expr) => {
         $a = $b.clone();
diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs
index b9f994d3e03..14ba1d4db9a 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.rs
+++ b/src/tools/clippy/tests/ui/assigning_clones.rs
@@ -128,6 +128,19 @@ fn ignore_generic_clone<T: Clone>(a: &mut T, b: &T) {
     *a = b.clone();
 }
 
+#[clippy::msrv = "1.62"]
+fn msrv_1_62(mut a: String, b: String, c: &str) {
+    a = b.clone();
+    // Should not be linted, as clone_into wasn't stabilized until 1.63
+    a = c.to_owned();
+}
+
+#[clippy::msrv = "1.63"]
+fn msrv_1_63(mut a: String, b: String, c: &str) {
+    a = b.clone();
+    a = c.to_owned();
+}
+
 macro_rules! clone_inside {
     ($a:expr, $b: expr) => {
         $a = $b.clone();
diff --git a/src/tools/clippy/tests/ui/assigning_clones.stderr b/src/tools/clippy/tests/ui/assigning_clones.stderr
index b76323f3606..ba59f067431 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.stderr
+++ b/src/tools/clippy/tests/ui/assigning_clones.stderr
@@ -67,41 +67,59 @@ error: assigning the result of `Clone::clone()` may be inefficient
 LL |         a = b.clone();
    |         ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
 
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:133:5
+   |
+LL |     a = b.clone();
+   |     ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:140:5
+   |
+LL |     a = b.clone();
+   |     ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
+
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:145:5
+  --> tests/ui/assigning_clones.rs:141:5
+   |
+LL |     a = c.to_owned();
+   |     ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:158:5
    |
 LL |     *mut_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:149:5
+  --> tests/ui/assigning_clones.rs:162:5
    |
 LL |     mut_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:170:5
+  --> tests/ui/assigning_clones.rs:183:5
    |
 LL |     **mut_box_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:174:5
+  --> tests/ui/assigning_clones.rs:187:5
    |
 LL |     **mut_box_string = ref_str.to_owned();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:178:5
+  --> tests/ui/assigning_clones.rs:191:5
    |
 LL |     *mut_thing = ToOwned::to_owned(ref_str);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
 
 error: assigning the result of `ToOwned::to_owned()` may be inefficient
-  --> tests/ui/assigning_clones.rs:182:5
+  --> tests/ui/assigning_clones.rs:195:5
    |
 LL |     mut_thing = ToOwned::to_owned(ref_str);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`
 
-error: aborting due to 17 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index 75f7a20f961..a6f3b164c9b 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -11,8 +11,8 @@ use quote::{quote, quote_spanned};
 use syn::spanned::Spanned;
 use syn::token::Star;
 use syn::{
-    parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType,
-    Signature, TraitItem, Type,
+    parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent,
+    PatType, Signature, TraitItem, Type, Visibility,
 };
 
 #[proc_macro_attribute]
@@ -101,9 +101,7 @@ pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
     let mut item = parse_macro_input!(item as ItemFn);
     let span = item.block.brace_token.span;
 
-    if item.sig.asyncness.is_some() {
-        item.sig.asyncness = None;
-    }
+    item.sig.asyncness = None;
 
     let crate_name = quote! { fake_crate };
     let block = item.block;
@@ -128,7 +126,7 @@ pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
 
 #[proc_macro_attribute]
 pub fn fake_desugar_await(_args: TokenStream, input: TokenStream) -> TokenStream {
-    let mut async_fn = syn::parse_macro_input!(input as syn::ItemFn);
+    let mut async_fn = parse_macro_input!(input as syn::ItemFn);
 
     for stmt in &mut async_fn.block.stmts {
         if let syn::Stmt::Expr(syn::Expr::Match(syn::ExprMatch { expr: scrutinee, .. }), _) = stmt {
@@ -145,3 +143,36 @@ pub fn fake_desugar_await(_args: TokenStream, input: TokenStream) -> TokenStream
 
     quote!(#async_fn).into()
 }
+
+#[proc_macro_attribute]
+pub fn rewrite_struct(_args: TokenStream, input: TokenStream) -> TokenStream {
+    let mut item_struct = parse_macro_input!(input as syn::ItemStruct);
+    // remove struct attributes including doc comments.
+    item_struct.attrs = vec![];
+    if let Visibility::Public(token) = item_struct.vis {
+        // set vis to `pub(crate)` to trigger `missing_docs_in_private_items` lint.
+        let new_vis: Visibility = syn::parse_quote_spanned!(token.span() => pub(crate));
+        item_struct.vis = new_vis;
+    }
+    if let syn::Fields::Named(fields) = &mut item_struct.fields {
+        for field in &mut fields.named {
+            // remove all attributes from fields as well.
+            field.attrs = vec![];
+        }
+    }
+
+    quote!(#item_struct).into()
+}
+
+#[proc_macro_attribute]
+pub fn with_empty_docs(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    let item = parse_macro_input!(input as syn::Item);
+    let attrs: Vec<syn::Attribute> = vec![];
+    let doc_comment = "";
+    quote! {
+        #(#attrs)*
+        #[doc = #doc_comment]
+        #item
+    }
+    .into()
+}
diff --git a/src/tools/clippy/tests/ui/await_holding_lock.rs b/src/tools/clippy/tests/ui/await_holding_lock.rs
index 27b57b64813..8e5510e6cd0 100644
--- a/src/tools/clippy/tests/ui/await_holding_lock.rs
+++ b/src/tools/clippy/tests/ui/await_holding_lock.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::await_holding_lock)]
+#![allow(clippy::readonly_write_lock)]
 
 // When adding or modifying a test, please do the same for parking_lot::Mutex.
 mod std_mutex {
diff --git a/src/tools/clippy/tests/ui/await_holding_lock.stderr b/src/tools/clippy/tests/ui/await_holding_lock.stderr
index e58436345b5..0af48a36acc 100644
--- a/src/tools/clippy/tests/ui/await_holding_lock.stderr
+++ b/src/tools/clippy/tests/ui/await_holding_lock.stderr
@@ -1,12 +1,12 @@
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:9:13
+  --> tests/ui/await_holding_lock.rs:10:13
    |
 LL |         let guard = x.lock().unwrap();
    |             ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:11:15
+  --> tests/ui/await_holding_lock.rs:12:15
    |
 LL |         baz().await
    |               ^^^^^
@@ -14,40 +14,40 @@ LL |         baz().await
    = help: to override `-D warnings` add `#[allow(clippy::await_holding_lock)]`
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:25:13
+  --> tests/ui/await_holding_lock.rs:26:13
    |
 LL |         let guard = x.read().unwrap();
    |             ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:27:15
+  --> tests/ui/await_holding_lock.rs:28:15
    |
 LL |         baz().await
    |               ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:31:13
+  --> tests/ui/await_holding_lock.rs:32:13
    |
 LL |         let mut guard = x.write().unwrap();
    |             ^^^^^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:33:15
+  --> tests/ui/await_holding_lock.rs:34:15
    |
 LL |         baz().await
    |               ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:53:13
+  --> tests/ui/await_holding_lock.rs:54:13
    |
 LL |         let guard = x.lock().unwrap();
    |             ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:56:28
+  --> tests/ui/await_holding_lock.rs:57:28
    |
 LL |         let second = baz().await;
    |                            ^^^^^
@@ -56,79 +56,79 @@ LL |         let third = baz().await;
    |                           ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:67:17
+  --> tests/ui/await_holding_lock.rs:68:17
    |
 LL |             let guard = x.lock().unwrap();
    |                 ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:69:19
+  --> tests/ui/await_holding_lock.rs:70:19
    |
 LL |             baz().await
    |                   ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:80:17
+  --> tests/ui/await_holding_lock.rs:81:17
    |
 LL |             let guard = x.lock().unwrap();
    |                 ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:82:19
+  --> tests/ui/await_holding_lock.rs:83:19
    |
 LL |             baz().await
    |                   ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:93:13
+  --> tests/ui/await_holding_lock.rs:94:13
    |
 LL |         let guard = x.lock();
    |             ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:95:15
+  --> tests/ui/await_holding_lock.rs:96:15
    |
 LL |         baz().await
    |               ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:109:13
+  --> tests/ui/await_holding_lock.rs:110:13
    |
 LL |         let guard = x.read();
    |             ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:111:15
+  --> tests/ui/await_holding_lock.rs:112:15
    |
 LL |         baz().await
    |               ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:115:13
+  --> tests/ui/await_holding_lock.rs:116:13
    |
 LL |         let mut guard = x.write();
    |             ^^^^^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:117:15
+  --> tests/ui/await_holding_lock.rs:118:15
    |
 LL |         baz().await
    |               ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:137:13
+  --> tests/ui/await_holding_lock.rs:138:13
    |
 LL |         let guard = x.lock();
    |             ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:140:28
+  --> tests/ui/await_holding_lock.rs:141:28
    |
 LL |         let second = baz().await;
    |                            ^^^^^
@@ -137,40 +137,40 @@ LL |         let third = baz().await;
    |                           ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:151:17
+  --> tests/ui/await_holding_lock.rs:152:17
    |
 LL |             let guard = x.lock();
    |                 ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:153:19
+  --> tests/ui/await_holding_lock.rs:154:19
    |
 LL |             baz().await
    |                   ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:164:17
+  --> tests/ui/await_holding_lock.rs:165:17
    |
 LL |             let guard = x.lock();
    |                 ^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:166:19
+  --> tests/ui/await_holding_lock.rs:167:19
    |
 LL |             baz().await
    |                   ^^^^^
 
 error: this `MutexGuard` is held across an `await` point
-  --> tests/ui/await_holding_lock.rs:185:9
+  --> tests/ui/await_holding_lock.rs:186:9
    |
 LL |     let mut guard = x.lock().unwrap();
    |         ^^^^^^^^^
    |
    = help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
 note: these are all the `await` points this lock is held through
-  --> tests/ui/await_holding_lock.rs:189:11
+  --> tests/ui/await_holding_lock.rs:190:11
    |
 LL |     baz().await;
    |           ^^^^^
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
index 63b8e27e1c6..b05166a055e 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
@@ -1,4 +1,4 @@
-#![allow(unused, clippy::assertions_on_constants)]
+#![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)]
 #![warn(clippy::bool_assert_comparison)]
 
 use std::ops::Not;
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
index 58f81fedb79..dc51fcf1d36 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
@@ -1,4 +1,4 @@
-#![allow(unused, clippy::assertions_on_constants)]
+#![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)]
 #![warn(clippy::bool_assert_comparison)]
 
 use std::ops::Not;
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.fixed b/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
index a4ce1c6f928..51a38a60cf6 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
@@ -1,6 +1,8 @@
 #![allow(dead_code)]
 #![warn(clippy::cast_lossless)]
 
+type U8 = u8;
+
 fn main() {
     // Test clippy::cast_lossless with casts to integer types
     let _ = u8::from(true);
@@ -19,6 +21,8 @@ fn main() {
 
     // Test with an expression wrapped in parens
     let _ = u16::from(true | false);
+
+    let _ = U8::from(true);
 }
 
 // The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.rs b/src/tools/clippy/tests/ui/cast_lossless_bool.rs
index e5b1c30c103..cb307bd68e4 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.rs
@@ -1,6 +1,8 @@
 #![allow(dead_code)]
 #![warn(clippy::cast_lossless)]
 
+type U8 = u8;
+
 fn main() {
     // Test clippy::cast_lossless with casts to integer types
     let _ = true as u8;
@@ -19,6 +21,8 @@ fn main() {
 
     // Test with an expression wrapped in parens
     let _ = (true | false) as u16;
+
+    let _ = true as U8;
 }
 
 // The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.stderr b/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
index 792b30b7a38..b47b35461f6 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
@@ -1,5 +1,5 @@
 error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:6:13
+  --> tests/ui/cast_lossless_bool.rs:8:13
    |
 LL |     let _ = true as u8;
    |             ^^^^^^^^^^ help: try: `u8::from(true)`
@@ -8,82 +8,88 @@ LL |     let _ = true as u8;
    = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
 
 error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:7:13
+  --> tests/ui/cast_lossless_bool.rs:9:13
    |
 LL |     let _ = true as u16;
    |             ^^^^^^^^^^^ help: try: `u16::from(true)`
 
 error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:8:13
+  --> tests/ui/cast_lossless_bool.rs:10:13
    |
 LL |     let _ = true as u32;
    |             ^^^^^^^^^^^ help: try: `u32::from(true)`
 
 error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:9:13
+  --> tests/ui/cast_lossless_bool.rs:11:13
    |
 LL |     let _ = true as u64;
    |             ^^^^^^^^^^^ help: try: `u64::from(true)`
 
 error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:10:13
+  --> tests/ui/cast_lossless_bool.rs:12:13
    |
 LL |     let _ = true as u128;
    |             ^^^^^^^^^^^^ help: try: `u128::from(true)`
 
 error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:11:13
+  --> tests/ui/cast_lossless_bool.rs:13:13
    |
 LL |     let _ = true as usize;
    |             ^^^^^^^^^^^^^ help: try: `usize::from(true)`
 
 error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:13:13
+  --> tests/ui/cast_lossless_bool.rs:15:13
    |
 LL |     let _ = true as i8;
    |             ^^^^^^^^^^ help: try: `i8::from(true)`
 
 error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:14:13
+  --> tests/ui/cast_lossless_bool.rs:16:13
    |
 LL |     let _ = true as i16;
    |             ^^^^^^^^^^^ help: try: `i16::from(true)`
 
 error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:15:13
+  --> tests/ui/cast_lossless_bool.rs:17:13
    |
 LL |     let _ = true as i32;
    |             ^^^^^^^^^^^ help: try: `i32::from(true)`
 
 error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:16:13
+  --> tests/ui/cast_lossless_bool.rs:18:13
    |
 LL |     let _ = true as i64;
    |             ^^^^^^^^^^^ help: try: `i64::from(true)`
 
 error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:17:13
+  --> tests/ui/cast_lossless_bool.rs:19:13
    |
 LL |     let _ = true as i128;
    |             ^^^^^^^^^^^^ help: try: `i128::from(true)`
 
 error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:18:13
+  --> tests/ui/cast_lossless_bool.rs:20:13
    |
 LL |     let _ = true as isize;
    |             ^^^^^^^^^^^^^ help: try: `isize::from(true)`
 
 error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:21:13
+  --> tests/ui/cast_lossless_bool.rs:23:13
    |
 LL |     let _ = (true | false) as u16;
    |             ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
 
+error: casting `bool` to `U8` is more cleanly stated with `U8::from(_)`
+  --> tests/ui/cast_lossless_bool.rs:25:13
+   |
+LL |     let _ = true as U8;
+   |             ^^^^^^^^^^ help: try: `U8::from(true)`
+
 error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
-  --> tests/ui/cast_lossless_bool.rs:49:13
+  --> tests/ui/cast_lossless_bool.rs:53:13
    |
 LL |     let _ = true as u8;
    |             ^^^^^^^^^^ help: try: `u8::from(true)`
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cast_lossless_float.fixed b/src/tools/clippy/tests/ui/cast_lossless_float.fixed
index f4f2e4773a5..96a67b1945c 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_float.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_float.fixed
@@ -1,11 +1,16 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
 #![warn(clippy::cast_lossless)]
 
+type F32 = f32;
+type F64 = f64;
+
 fn main() {
     // Test clippy::cast_lossless with casts to floating-point types
     let x0 = 1i8;
     let _ = f32::from(x0);
     let _ = f64::from(x0);
+    let _ = F32::from(x0);
+    let _ = F64::from(x0);
     let x1 = 1u8;
     let _ = f32::from(x1);
     let _ = f64::from(x1);
diff --git a/src/tools/clippy/tests/ui/cast_lossless_float.rs b/src/tools/clippy/tests/ui/cast_lossless_float.rs
index fdd88ed36fc..d37b2c1d920 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_float.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_float.rs
@@ -1,11 +1,16 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
 #![warn(clippy::cast_lossless)]
 
+type F32 = f32;
+type F64 = f64;
+
 fn main() {
     // Test clippy::cast_lossless with casts to floating-point types
     let x0 = 1i8;
     let _ = x0 as f32;
     let _ = x0 as f64;
+    let _ = x0 as F32;
+    let _ = x0 as F64;
     let x1 = 1u8;
     let _ = x1 as f32;
     let _ = x1 as f64;
diff --git a/src/tools/clippy/tests/ui/cast_lossless_float.stderr b/src/tools/clippy/tests/ui/cast_lossless_float.stderr
index e70f81eb91f..ad7de760adf 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_float.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_float.stderr
@@ -1,5 +1,5 @@
 error: casting `i8` to `f32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:7:13
+  --> tests/ui/cast_lossless_float.rs:10:13
    |
 LL |     let _ = x0 as f32;
    |             ^^^^^^^^^ help: try: `f32::from(x0)`
@@ -8,64 +8,76 @@ LL |     let _ = x0 as f32;
    = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
 
 error: casting `i8` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:8:13
+  --> tests/ui/cast_lossless_float.rs:11:13
    |
 LL |     let _ = x0 as f64;
    |             ^^^^^^^^^ help: try: `f64::from(x0)`
 
+error: casting `i8` to `F32` may become silently lossy if you later change the type
+  --> tests/ui/cast_lossless_float.rs:12:13
+   |
+LL |     let _ = x0 as F32;
+   |             ^^^^^^^^^ help: try: `F32::from(x0)`
+
+error: casting `i8` to `F64` may become silently lossy if you later change the type
+  --> tests/ui/cast_lossless_float.rs:13:13
+   |
+LL |     let _ = x0 as F64;
+   |             ^^^^^^^^^ help: try: `F64::from(x0)`
+
 error: casting `u8` to `f32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:10:13
+  --> tests/ui/cast_lossless_float.rs:15:13
    |
 LL |     let _ = x1 as f32;
    |             ^^^^^^^^^ help: try: `f32::from(x1)`
 
 error: casting `u8` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:11:13
+  --> tests/ui/cast_lossless_float.rs:16:13
    |
 LL |     let _ = x1 as f64;
    |             ^^^^^^^^^ help: try: `f64::from(x1)`
 
 error: casting `i16` to `f32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:13:13
+  --> tests/ui/cast_lossless_float.rs:18:13
    |
 LL |     let _ = x2 as f32;
    |             ^^^^^^^^^ help: try: `f32::from(x2)`
 
 error: casting `i16` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:14:13
+  --> tests/ui/cast_lossless_float.rs:19:13
    |
 LL |     let _ = x2 as f64;
    |             ^^^^^^^^^ help: try: `f64::from(x2)`
 
 error: casting `u16` to `f32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:16:13
+  --> tests/ui/cast_lossless_float.rs:21:13
    |
 LL |     let _ = x3 as f32;
    |             ^^^^^^^^^ help: try: `f32::from(x3)`
 
 error: casting `u16` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:17:13
+  --> tests/ui/cast_lossless_float.rs:22:13
    |
 LL |     let _ = x3 as f64;
    |             ^^^^^^^^^ help: try: `f64::from(x3)`
 
 error: casting `i32` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:19:13
+  --> tests/ui/cast_lossless_float.rs:24:13
    |
 LL |     let _ = x4 as f64;
    |             ^^^^^^^^^ help: try: `f64::from(x4)`
 
 error: casting `u32` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:21:13
+  --> tests/ui/cast_lossless_float.rs:26:13
    |
 LL |     let _ = x5 as f64;
    |             ^^^^^^^^^ help: try: `f64::from(x5)`
 
 error: casting `f32` to `f64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_float.rs:24:13
+  --> tests/ui/cast_lossless_float.rs:29:13
    |
 LL |     let _ = 1.0f32 as f64;
    |             ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)`
 
-error: aborting due to 11 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
index 5e7e545e764..291556a9774 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
@@ -1,6 +1,9 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
 #![warn(clippy::cast_lossless)]
 
+type I64 = i64;
+type U128 = u128;
+
 fn main() {
     // Test clippy::cast_lossless with casts to integer types
     let _ = i16::from(1i8);
@@ -24,6 +27,13 @@ fn main() {
 
     // Test with an expression wrapped in parens
     let _ = u16::from(1u8 + 1u8);
+
+    let _ = I64::from(1i8);
+
+    // Do not lint if destination type is u128
+    // see https://github.com/rust-lang/rust-clippy/issues/12492
+    let _ = 1u8 as u128;
+    let _ = 1u8 as U128;
 }
 
 // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.rs b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
index 0d69ddbd586..a917c7a371d 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
@@ -1,6 +1,9 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
 #![warn(clippy::cast_lossless)]
 
+type I64 = i64;
+type U128 = u128;
+
 fn main() {
     // Test clippy::cast_lossless with casts to integer types
     let _ = 1i8 as i16;
@@ -24,6 +27,13 @@ fn main() {
 
     // Test with an expression wrapped in parens
     let _ = (1u8 + 1u8) as u16;
+
+    let _ = 1i8 as I64;
+
+    // Do not lint if destination type is u128
+    // see https://github.com/rust-lang/rust-clippy/issues/12492
+    let _ = 1u8 as u128;
+    let _ = 1u8 as U128;
 }
 
 // The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr
index 43d4ce3ce91..aaece939285 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr
@@ -1,5 +1,5 @@
 error: casting `i8` to `i16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:6:13
+  --> tests/ui/cast_lossless_integer.rs:9:13
    |
 LL |     let _ = 1i8 as i16;
    |             ^^^^^^^^^^ help: try: `i16::from(1i8)`
@@ -8,124 +8,130 @@ LL |     let _ = 1i8 as i16;
    = help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
 
 error: casting `i8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:7:13
+  --> tests/ui/cast_lossless_integer.rs:10:13
    |
 LL |     let _ = 1i8 as i32;
    |             ^^^^^^^^^^ help: try: `i32::from(1i8)`
 
 error: casting `i8` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:8:13
+  --> tests/ui/cast_lossless_integer.rs:11:13
    |
 LL |     let _ = 1i8 as i64;
    |             ^^^^^^^^^^ help: try: `i64::from(1i8)`
 
 error: casting `u8` to `i16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:9:13
+  --> tests/ui/cast_lossless_integer.rs:12:13
    |
 LL |     let _ = 1u8 as i16;
    |             ^^^^^^^^^^ help: try: `i16::from(1u8)`
 
 error: casting `u8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:10:13
+  --> tests/ui/cast_lossless_integer.rs:13:13
    |
 LL |     let _ = 1u8 as i32;
    |             ^^^^^^^^^^ help: try: `i32::from(1u8)`
 
 error: casting `u8` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:11:13
+  --> tests/ui/cast_lossless_integer.rs:14:13
    |
 LL |     let _ = 1u8 as i64;
    |             ^^^^^^^^^^ help: try: `i64::from(1u8)`
 
 error: casting `u8` to `u16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:12:13
+  --> tests/ui/cast_lossless_integer.rs:15:13
    |
 LL |     let _ = 1u8 as u16;
    |             ^^^^^^^^^^ help: try: `u16::from(1u8)`
 
 error: casting `u8` to `u32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:13:13
+  --> tests/ui/cast_lossless_integer.rs:16:13
    |
 LL |     let _ = 1u8 as u32;
    |             ^^^^^^^^^^ help: try: `u32::from(1u8)`
 
 error: casting `u8` to `u64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:14:13
+  --> tests/ui/cast_lossless_integer.rs:17:13
    |
 LL |     let _ = 1u8 as u64;
    |             ^^^^^^^^^^ help: try: `u64::from(1u8)`
 
 error: casting `i16` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:15:13
+  --> tests/ui/cast_lossless_integer.rs:18:13
    |
 LL |     let _ = 1i16 as i32;
    |             ^^^^^^^^^^^ help: try: `i32::from(1i16)`
 
 error: casting `i16` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:16:13
+  --> tests/ui/cast_lossless_integer.rs:19:13
    |
 LL |     let _ = 1i16 as i64;
    |             ^^^^^^^^^^^ help: try: `i64::from(1i16)`
 
 error: casting `u16` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:17:13
+  --> tests/ui/cast_lossless_integer.rs:20:13
    |
 LL |     let _ = 1u16 as i32;
    |             ^^^^^^^^^^^ help: try: `i32::from(1u16)`
 
 error: casting `u16` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:18:13
+  --> tests/ui/cast_lossless_integer.rs:21:13
    |
 LL |     let _ = 1u16 as i64;
    |             ^^^^^^^^^^^ help: try: `i64::from(1u16)`
 
 error: casting `u16` to `u32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:19:13
+  --> tests/ui/cast_lossless_integer.rs:22:13
    |
 LL |     let _ = 1u16 as u32;
    |             ^^^^^^^^^^^ help: try: `u32::from(1u16)`
 
 error: casting `u16` to `u64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:20:13
+  --> tests/ui/cast_lossless_integer.rs:23:13
    |
 LL |     let _ = 1u16 as u64;
    |             ^^^^^^^^^^^ help: try: `u64::from(1u16)`
 
 error: casting `i32` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:21:13
+  --> tests/ui/cast_lossless_integer.rs:24:13
    |
 LL |     let _ = 1i32 as i64;
    |             ^^^^^^^^^^^ help: try: `i64::from(1i32)`
 
 error: casting `u32` to `i64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:22:13
+  --> tests/ui/cast_lossless_integer.rs:25:13
    |
 LL |     let _ = 1u32 as i64;
    |             ^^^^^^^^^^^ help: try: `i64::from(1u32)`
 
 error: casting `u32` to `u64` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:23:13
+  --> tests/ui/cast_lossless_integer.rs:26:13
    |
 LL |     let _ = 1u32 as u64;
    |             ^^^^^^^^^^^ help: try: `u64::from(1u32)`
 
 error: casting `u8` to `u16` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:26:13
+  --> tests/ui/cast_lossless_integer.rs:29:13
    |
 LL |     let _ = (1u8 + 1u8) as u16;
    |             ^^^^^^^^^^^^^^^^^^ help: try: `u16::from(1u8 + 1u8)`
 
+error: casting `i8` to `I64` may become silently lossy if you later change the type
+  --> tests/ui/cast_lossless_integer.rs:31:13
+   |
+LL |     let _ = 1i8 as I64;
+   |             ^^^^^^^^^^ help: try: `I64::from(1i8)`
+
 error: casting `i8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:60:13
+  --> tests/ui/cast_lossless_integer.rs:70:13
    |
 LL |     let _ = sign_cast!(x, u8, i8) as i32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8))`
 
 error: casting `i8` to `i32` may become silently lossy if you later change the type
-  --> tests/ui/cast_lossless_integer.rs:61:13
+  --> tests/ui/cast_lossless_integer.rs:71:13
    |
 LL |     let _ = (sign_cast!(x, u8, i8) + 1) as i32;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::from(sign_cast!(x, u8, i8) + 1)`
 
-error: aborting due to 21 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/const_is_empty.rs b/src/tools/clippy/tests/ui/const_is_empty.rs
new file mode 100644
index 00000000000..ae37a82e4f9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/const_is_empty.rs
@@ -0,0 +1,174 @@
+#![feature(inline_const)]
+#![warn(clippy::const_is_empty)]
+#![allow(clippy::needless_late_init, unused_must_use)]
+
+fn test_literal() {
+    if "".is_empty() {
+        //~^ERROR: this expression always evaluates to true
+    }
+    if "foobar".is_empty() {
+        //~^ERROR: this expression always evaluates to false
+    }
+}
+
+fn test_byte_literal() {
+    if b"".is_empty() {
+        //~^ERROR: this expression always evaluates to true
+    }
+    if b"foobar".is_empty() {
+        //~^ERROR: this expression always evaluates to false
+    }
+}
+
+fn test_no_mut() {
+    let mut empty = "";
+    if empty.is_empty() {
+        // No lint because it is mutable
+    }
+}
+
+fn test_propagated() {
+    let empty = "";
+    let non_empty = "foobar";
+    let empty2 = empty;
+    let non_empty2 = non_empty;
+    if empty2.is_empty() {
+        //~^ERROR: this expression always evaluates to true
+    }
+    if non_empty2.is_empty() {
+        //~^ERROR: this expression always evaluates to false
+    }
+}
+
+const EMPTY_STR: &str = "";
+const NON_EMPTY_STR: &str = "foo";
+const EMPTY_BSTR: &[u8] = b"";
+const NON_EMPTY_BSTR: &[u8] = b"foo";
+const EMPTY_U8_SLICE: &[u8] = &[];
+const NON_EMPTY_U8_SLICE: &[u8] = &[1, 2];
+const EMPTY_SLICE: &[u32] = &[];
+const NON_EMPTY_SLICE: &[u32] = &[1, 2];
+const NON_EMPTY_SLICE_REPEAT: &[u32] = &[1; 2];
+const EMPTY_ARRAY: [u32; 0] = [];
+const EMPTY_ARRAY_REPEAT: [u32; 0] = [1; 0];
+const NON_EMPTY_ARRAY: [u32; 2] = [1, 2];
+const NON_EMPTY_ARRAY_REPEAT: [u32; 2] = [1; 2];
+const EMPTY_REF_ARRAY: &[u32; 0] = &[];
+const NON_EMPTY_REF_ARRAY: &[u32; 3] = &[1, 2, 3];
+
+fn test_from_const() {
+    let _ = EMPTY_STR.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = NON_EMPTY_STR.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = EMPTY_BSTR.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = NON_EMPTY_BSTR.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = EMPTY_ARRAY.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = EMPTY_ARRAY_REPEAT.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = EMPTY_U8_SLICE.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = NON_EMPTY_U8_SLICE.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = NON_EMPTY_ARRAY.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = NON_EMPTY_ARRAY_REPEAT.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = EMPTY_REF_ARRAY.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = NON_EMPTY_REF_ARRAY.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = EMPTY_SLICE.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = NON_EMPTY_SLICE.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = NON_EMPTY_SLICE_REPEAT.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+}
+
+fn main() {
+    let value = "foobar";
+    let _ = value.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let x = value;
+    let _ = x.is_empty();
+    //~^ ERROR: this expression always evaluates to false
+    let _ = "".is_empty();
+    //~^ ERROR: this expression always evaluates to true
+    let _ = b"".is_empty();
+    //~^ ERROR: this expression always evaluates to true
+}
+
+fn str_from_arg(var: &str) {
+    var.is_empty();
+    // Do not lint, we know nothiny about var
+}
+
+fn update_str() {
+    let mut value = "duck";
+    value = "penguin";
+
+    let _ = value.is_empty();
+    // Do not lint since value is mutable
+}
+
+fn macros() {
+    // Content from Macro
+    let file = include_str!("const_is_empty.rs");
+    let _ = file.is_empty();
+    // No lint because initializer comes from a macro result
+
+    let var = env!("PATH");
+    let _ = var.is_empty();
+    // No lint because initializer comes from a macro result
+}
+
+fn conditional_value() {
+    let value;
+
+    if true {
+        value = "hey";
+    } else {
+        value = "hej";
+    }
+
+    let _ = value.is_empty();
+    // Do not lint, current constant folding is too simple to detect this
+}
+
+fn cfg_conditioned() {
+    #[cfg(test)]
+    let val = "";
+    #[cfg(not(test))]
+    let val = "foo";
+
+    let _ = val.is_empty();
+    // Do not lint, value depend on a #[cfg(…)] directive
+}
+
+fn not_cfg_conditioned() {
+    let val = "";
+    #[cfg(not(target_os = "inexistent"))]
+    let _ = val.is_empty();
+    //~^ ERROR: this expression always evaluates to true
+}
+
+const fn const_rand() -> &'static str {
+    "17"
+}
+
+fn const_expressions() {
+    let _ = const { if true { "1" } else { "2" } }.is_empty();
+    // Do not lint, we do not recurse into boolean expressions
+
+    let _ = const_rand().is_empty();
+    // Do not lint, we do not recurse into functions
+}
+
+fn constant_from_external_crate() {
+    let _ = std::env::consts::EXE_EXTENSION.is_empty();
+    // Do not lint, `exe_ext` comes from the `std` crate
+}
diff --git a/src/tools/clippy/tests/ui/const_is_empty.stderr b/src/tools/clippy/tests/ui/const_is_empty.stderr
new file mode 100644
index 00000000000..0e09da77bb4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/const_is_empty.stderr
@@ -0,0 +1,161 @@
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:6:8
+   |
+LL |     if "".is_empty() {
+   |        ^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::const-is-empty` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::const_is_empty)]`
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:9:8
+   |
+LL |     if "foobar".is_empty() {
+   |        ^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:15:8
+   |
+LL |     if b"".is_empty() {
+   |        ^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:18:8
+   |
+LL |     if b"foobar".is_empty() {
+   |        ^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:35:8
+   |
+LL |     if empty2.is_empty() {
+   |        ^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:38:8
+   |
+LL |     if non_empty2.is_empty() {
+   |        ^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:60:13
+   |
+LL |     let _ = EMPTY_STR.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:62:13
+   |
+LL |     let _ = NON_EMPTY_STR.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:64:13
+   |
+LL |     let _ = EMPTY_BSTR.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:66:13
+   |
+LL |     let _ = NON_EMPTY_BSTR.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:68:13
+   |
+LL |     let _ = EMPTY_ARRAY.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:70:13
+   |
+LL |     let _ = EMPTY_ARRAY_REPEAT.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:72:13
+   |
+LL |     let _ = EMPTY_U8_SLICE.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:74:13
+   |
+LL |     let _ = NON_EMPTY_U8_SLICE.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:76:13
+   |
+LL |     let _ = NON_EMPTY_ARRAY.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:78:13
+   |
+LL |     let _ = NON_EMPTY_ARRAY_REPEAT.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:80:13
+   |
+LL |     let _ = EMPTY_REF_ARRAY.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:82:13
+   |
+LL |     let _ = NON_EMPTY_REF_ARRAY.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:84:13
+   |
+LL |     let _ = EMPTY_SLICE.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:86:13
+   |
+LL |     let _ = NON_EMPTY_SLICE.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:88:13
+   |
+LL |     let _ = NON_EMPTY_SLICE_REPEAT.is_empty();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:94:13
+   |
+LL |     let _ = value.is_empty();
+   |             ^^^^^^^^^^^^^^^^
+
+error: this expression always evaluates to false
+  --> tests/ui/const_is_empty.rs:97:13
+   |
+LL |     let _ = x.is_empty();
+   |             ^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:99:13
+   |
+LL |     let _ = "".is_empty();
+   |             ^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:101:13
+   |
+LL |     let _ = b"".is_empty();
+   |             ^^^^^^^^^^^^^^
+
+error: this expression always evaluates to true
+  --> tests/ui/const_is_empty.rs:155:13
+   |
+LL |     let _ = val.is_empty();
+   |             ^^^^^^^^^^^^^^
+
+error: aborting due to 26 previous errors
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-12491.fixed b/src/tools/clippy/tests/ui/crashes/ice-12491.fixed
new file mode 100644
index 00000000000..4ea480b0663
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-12491.fixed
@@ -0,0 +1,7 @@
+#![warn(clippy::needless_return)]
+
+fn main() {
+    if (true) {
+        // anything一些中文
+    }
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-12491.rs b/src/tools/clippy/tests/ui/crashes/ice-12491.rs
new file mode 100644
index 00000000000..60add6afa2c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-12491.rs
@@ -0,0 +1,8 @@
+#![warn(clippy::needless_return)]
+
+fn main() {
+    if (true) {
+        // anything一些中文
+        return;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-12491.stderr b/src/tools/clippy/tests/ui/crashes/ice-12491.stderr
new file mode 100644
index 00000000000..7cc418898e8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-12491.stderr
@@ -0,0 +1,19 @@
+error: unneeded `return` statement
+  --> tests/ui/crashes/ice-12491.rs:5:24
+   |
+LL |           // anything一些中文
+   |  ____________________________^
+LL | |         return;
+   | |______________^
+   |
+   = note: `-D clippy::needless-return` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::needless_return)]`
+help: remove `return`
+   |
+LL -         // anything一些中文
+LL -         return;
+LL +         // anything一些中文
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
new file mode 100644
index 00000000000..e3525191423
--- /dev/null
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed
@@ -0,0 +1,111 @@
+#![warn(clippy::dbg_macro)]
+#![allow(clippy::unnecessary_operation, clippy::no_effect)]
+
+fn foo(n: u32) -> u32 {
+    if let Some(n) = n.checked_sub(4) { n } else { n }
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+}
+fn bar(_: ()) {}
+
+fn factorial(n: u32) -> u32 {
+    if n <= 1 {
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+        1
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    } else {
+        n * factorial(n - 1)
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    }
+}
+
+fn main() {
+    42;
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    foo(3) + factorial(4);
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    (1, 2, 3, 4, 5);
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+}
+
+fn issue9914() {
+    macro_rules! foo {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! foo2 {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! expand_to_dbg {
+        () => {
+            
+            //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+        };
+    }
+
+    
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    #[allow(clippy::let_unit_value)]
+    let _ = ();
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    bar(());
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    foo!(());
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    foo2!(foo!(()));
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    expand_to_dbg!();
+}
+
+mod issue7274 {
+    trait Thing<'b> {
+        fn foo(&self);
+    }
+
+    macro_rules! define_thing {
+        ($thing:ident, $body:expr) => {
+            impl<'a> Thing<'a> for $thing {
+                fn foo<'b>(&self) {
+                    $body
+                }
+            }
+        };
+    }
+
+    struct MyThing;
+    define_thing!(MyThing, {
+        2;
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    });
+}
+
+#[test]
+pub fn issue8481() {
+    1;
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+}
+
+#[cfg(test)]
+fn foo2() {
+    1;
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+}
+
+#[cfg(test)]
+mod mod1 {
+    fn func() {
+        1;
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    }
+}
+
+mod issue12131 {
+    fn dbg_in_print(s: &str) {
+        println!("dbg: {:?}", s);
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+        print!("{}", s);
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    }
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
index 3f4770c63d0..80606c2db05 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs
@@ -1,9 +1,5 @@
-//@no-rustfix
-
 #![warn(clippy::dbg_macro)]
-
-#[path = "auxiliary/submodule.rs"]
-mod submodule;
+#![allow(clippy::unnecessary_operation, clippy::no_effect)]
 
 fn foo(n: u32) -> u32 {
     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
@@ -25,12 +21,8 @@ fn factorial(n: u32) -> u32 {
 fn main() {
     dbg!(42);
     //~^ ERROR: the `dbg!` macro is intended as a debugging tool
-    dbg!(dbg!(dbg!(42)));
-    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
     foo(3) + dbg!(factorial(4));
     //~^ ERROR: the `dbg!` macro is intended as a debugging tool
-    dbg!(1, 2, dbg!(3, 4));
-    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
     dbg!(1, 2, 3, 4, 5);
     //~^ ERROR: the `dbg!` macro is intended as a debugging tool
 }
@@ -49,6 +41,7 @@ fn issue9914() {
     macro_rules! expand_to_dbg {
         () => {
             dbg!();
+            //~^ ERROR: the `dbg!` macro is intended as a debugging tool
         };
     }
 
@@ -107,3 +100,12 @@ mod mod1 {
         //~^ ERROR: the `dbg!` macro is intended as a debugging tool
     }
 }
+
+mod issue12131 {
+    fn dbg_in_print(s: &str) {
+        println!("dbg: {:?}", dbg!(s));
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+        print!("{}", dbg!(s));
+        //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    }
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
index 5ad0bbfed94..86667701da0 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
@@ -1,30 +1,18 @@
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/auxiliary/submodule.rs:2:5
-   |
-LL |     dbg!();
-   |     ^^^^^^^
-   |
-   = note: `-D clippy::dbg-macro` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]`
-help: remove the invocation before committing it to a version control system
-   |
-LL -     dbg!();
-LL +     
-   |
-
-error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:9:22
+  --> tests/ui/dbg_macro/dbg_macro.rs:5:22
    |
 LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
    |                      ^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `-D clippy::dbg-macro` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]`
 help: remove the invocation before committing it to a version control system
    |
 LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:15:8
+  --> tests/ui/dbg_macro/dbg_macro.rs:11:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -35,7 +23,7 @@ LL |     if n <= 1 {
    |        ~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:17:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:13:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -46,7 +34,7 @@ LL |         1
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:20:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:16:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +45,7 @@ LL |         n * factorial(n - 1)
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:26:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:22:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -68,18 +56,7 @@ LL |     42;
    |     ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:28:5
-   |
-LL |     dbg!(dbg!(dbg!(42)));
-   |     ^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the invocation before committing it to a version control system
-   |
-LL |     dbg!(dbg!(42));
-   |     ~~~~~~~~~~~~~~
-
-error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:30:14
+  --> tests/ui/dbg_macro/dbg_macro.rs:24:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
@@ -90,18 +67,7 @@ LL |     foo(3) + factorial(4);
    |              ~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:32:5
-   |
-LL |     dbg!(1, 2, dbg!(3, 4));
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: remove the invocation before committing it to a version control system
-   |
-LL |     (1, 2, dbg!(3, 4));
-   |     ~~~~~~~~~~~~~~~~~~
-
-error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:34:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:26:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -112,7 +78,7 @@ LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:55:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:48:5
    |
 LL |     dbg!();
    |     ^^^^^^^
@@ -124,7 +90,7 @@ LL +
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:58:13
+  --> tests/ui/dbg_macro/dbg_macro.rs:51:13
    |
 LL |     let _ = dbg!();
    |             ^^^^^^
@@ -135,7 +101,7 @@ LL |     let _ = ();
    |             ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:60:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:53:9
    |
 LL |     bar(dbg!());
    |         ^^^^^^
@@ -146,7 +112,7 @@ LL |     bar(());
    |         ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:62:10
+  --> tests/ui/dbg_macro/dbg_macro.rs:55:10
    |
 LL |     foo!(dbg!());
    |          ^^^^^^
@@ -157,7 +123,7 @@ LL |     foo!(());
    |          ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:64:16
+  --> tests/ui/dbg_macro/dbg_macro.rs:57:16
    |
 LL |     foo2!(foo!(dbg!()));
    |                ^^^^^^
@@ -168,7 +134,23 @@ LL |     foo2!(foo!(()));
    |                ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:86:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:43:13
+   |
+LL |             dbg!();
+   |             ^^^^^^^
+...
+LL |     expand_to_dbg!();
+   |     ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `expand_to_dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: remove the invocation before committing it to a version control system
+   |
+LL -             dbg!();
+LL +             
+   |
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro.rs:79:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
@@ -179,7 +161,7 @@ LL |         2;
    |         ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:93:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:86:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -190,7 +172,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:99:5
+  --> tests/ui/dbg_macro/dbg_macro.rs:92:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -201,7 +183,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> tests/ui/dbg_macro/dbg_macro.rs:106:9
+  --> tests/ui/dbg_macro/dbg_macro.rs:99:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
@@ -211,5 +193,27 @@ help: remove the invocation before committing it to a version control system
 LL |         1;
    |         ~
 
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro.rs:106:31
+   |
+LL |         println!("dbg: {:?}", dbg!(s));
+   |                               ^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |         println!("dbg: {:?}", s);
+   |                               ~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro.rs:108:22
+   |
+LL |         print!("{}", dbg!(s));
+   |                      ^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |         print!("{}", s);
+   |                      ~
+
 error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.rs
new file mode 100644
index 00000000000..0e83766ccae
--- /dev/null
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.rs
@@ -0,0 +1,12 @@
+//@no-rustfix
+#![warn(clippy::dbg_macro)]
+
+#[path = "auxiliary/submodule.rs"]
+mod submodule;
+
+fn main() {
+    dbg!(dbg!(dbg!(42)));
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+    dbg!(1, 2, dbg!(3, 4));
+    //~^ ERROR: the `dbg!` macro is intended as a debugging tool
+}
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr
new file mode 100644
index 00000000000..d21595c2fcd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr
@@ -0,0 +1,71 @@
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/auxiliary/submodule.rs:2:5
+   |
+LL |     dbg!();
+   |     ^^^^^^^
+   |
+   = note: `-D clippy::dbg-macro` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]`
+help: remove the invocation before committing it to a version control system
+   |
+LL -     dbg!();
+LL +     
+   |
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:5
+   |
+LL |     dbg!(dbg!(dbg!(42)));
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     dbg!(dbg!(42));
+   |     ~~~~~~~~~~~~~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:10
+   |
+LL |     dbg!(dbg!(dbg!(42)));
+   |          ^^^^^^^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     dbg!(dbg!(42));
+   |          ~~~~~~~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:8:15
+   |
+LL |     dbg!(dbg!(dbg!(42)));
+   |               ^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     dbg!(dbg!(42));
+   |               ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:10:5
+   |
+LL |     dbg!(1, 2, dbg!(3, 4));
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     (1, 2, dbg!(3, 4));
+   |     ~~~~~~~~~~~~~~~~~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> tests/ui/dbg_macro/dbg_macro_unfixable.rs:10:16
+   |
+LL |     dbg!(1, 2, dbg!(3, 4));
+   |                ^^^^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     dbg!(1, 2, (3, 4));
+   |                ~~~~~~
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/doc/issue_10262.fixed b/src/tools/clippy/tests/ui/doc/issue_10262.fixed
new file mode 100644
index 00000000000..5d067736d55
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_10262.fixed
@@ -0,0 +1,12 @@
+#![warn(clippy::doc_markdown)]
+
+// Should only warn for the first line!
+/// `AviSynth` documentation:
+//~^ ERROR: item in documentation is missing backticks
+///
+/// > AvisynthPluginInit3 may be called more than once with different IScriptEnvironments.
+///
+/// <blockquote>bla AvisynthPluginInit3 bla</blockquote>
+///
+/// <q>bla AvisynthPluginInit3 bla</q>
+pub struct Foo;
diff --git a/src/tools/clippy/tests/ui/doc/issue_10262.rs b/src/tools/clippy/tests/ui/doc/issue_10262.rs
new file mode 100644
index 00000000000..e2cbd938d5d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_10262.rs
@@ -0,0 +1,12 @@
+#![warn(clippy::doc_markdown)]
+
+// Should only warn for the first line!
+/// AviSynth documentation:
+//~^ ERROR: item in documentation is missing backticks
+///
+/// > AvisynthPluginInit3 may be called more than once with different IScriptEnvironments.
+///
+/// <blockquote>bla AvisynthPluginInit3 bla</blockquote>
+///
+/// <q>bla AvisynthPluginInit3 bla</q>
+pub struct Foo;
diff --git a/src/tools/clippy/tests/ui/doc/issue_10262.stderr b/src/tools/clippy/tests/ui/doc/issue_10262.stderr
new file mode 100644
index 00000000000..f43d9551e94
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_10262.stderr
@@ -0,0 +1,15 @@
+error: item in documentation is missing backticks
+  --> tests/ui/doc/issue_10262.rs:4:5
+   |
+LL | /// AviSynth documentation:
+   |     ^^^^^^^^
+   |
+   = note: `-D clippy::doc-markdown` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]`
+help: try
+   |
+LL | /// `AviSynth` documentation:
+   |     ~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.rs b/src/tools/clippy/tests/ui/duplicated_attributes.rs
new file mode 100644
index 00000000000..0f036c684c1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/duplicated_attributes.rs
@@ -0,0 +1,17 @@
+#![warn(clippy::duplicated_attributes)]
+#![cfg(any(unix, windows))]
+#![allow(dead_code)]
+#![allow(dead_code)] //~ ERROR: duplicated attribute
+#![cfg(any(unix, windows))]
+//~^ ERROR: duplicated attribute
+//~| ERROR: duplicated attribute
+
+#[cfg(any(unix, windows, target_os = "linux"))]
+#[allow(dead_code)]
+#[allow(dead_code)] //~ ERROR: duplicated attribute
+#[cfg(any(unix, windows, target_os = "linux"))]
+//~^ ERROR: duplicated attribute
+//~| ERROR: duplicated attribute
+fn foo() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.stderr b/src/tools/clippy/tests/ui/duplicated_attributes.stderr
new file mode 100644
index 00000000000..1c6578dbb43
--- /dev/null
+++ b/src/tools/clippy/tests/ui/duplicated_attributes.stderr
@@ -0,0 +1,123 @@
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:4:10
+   |
+LL | #![allow(dead_code)]
+   |          ^^^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:3:10
+   |
+LL | #![allow(dead_code)]
+   |          ^^^^^^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:4:10
+   |
+LL | #![allow(dead_code)]
+   |          ^^^^^^^^^
+   = note: `-D clippy::duplicated-attributes` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]`
+
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:5:12
+   |
+LL | #![cfg(any(unix, windows))]
+   |            ^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:2:12
+   |
+LL | #![cfg(any(unix, windows))]
+   |            ^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:5:12
+   |
+LL | #![cfg(any(unix, windows))]
+   |            ^^^^
+
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:5:18
+   |
+LL | #![cfg(any(unix, windows))]
+   |                  ^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:2:18
+   |
+LL | #![cfg(any(unix, windows))]
+   |                  ^^^^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:5:18
+   |
+LL | #![cfg(any(unix, windows))]
+   |                  ^^^^^^^
+
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:11:9
+   |
+LL | #[allow(dead_code)]
+   |         ^^^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:10:9
+   |
+LL | #[allow(dead_code)]
+   |         ^^^^^^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:11:9
+   |
+LL | #[allow(dead_code)]
+   |         ^^^^^^^^^
+
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:12:11
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |           ^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:9:11
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |           ^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:12:11
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |           ^^^^
+
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:12:17
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |                 ^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:9:17
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |                 ^^^^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:12:17
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |                 ^^^^^^^
+
+error: duplicated attribute
+  --> tests/ui/duplicated_attributes.rs:12:26
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |                          ^^^^^^^^^^^^^^^^^^^
+   |
+note: first defined here
+  --> tests/ui/duplicated_attributes.rs:9:26
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |                          ^^^^^^^^^^^^^^^^^^^
+help: remove this attribute
+  --> tests/ui/duplicated_attributes.rs:12:26
+   |
+LL | #[cfg(any(unix, windows, target_os = "linux"))]
+   |                          ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.rs b/src/tools/clippy/tests/ui/else_if_without_else.rs
index e7786f7dd27..b04c22fa2ae 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.rs
+++ b/src/tools/clippy/tests/ui/else_if_without_else.rs
@@ -1,7 +1,5 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
-#![warn(clippy::all)]
 #![warn(clippy::else_if_without_else)]
+#![allow(clippy::collapsible_else_if)]
 
 fn bla1() -> bool {
     unimplemented!()
@@ -12,6 +10,12 @@ fn bla2() -> bool {
 fn bla3() -> bool {
     unimplemented!()
 }
+fn bla4() -> bool {
+    unimplemented!()
+}
+fn bla5() -> bool {
+    unimplemented!()
+}
 
 fn main() {
     if bla1() {
@@ -57,4 +61,62 @@ fn main() {
         //~^ ERROR: `if` expression with an `else if`, but without a final `else`
         println!("else if 2");
     }
+
+    if bla1() {
+        println!("if");
+    } else if bla2() {
+        println!("else if 1");
+    } else if bla3() {
+        println!("else if 2");
+    } else if bla4() {
+        println!("else if 3");
+    } else if bla5() {
+        println!("else if 4");
+    } else {
+        println!("else");
+    }
+
+    if bla1() {
+        println!("if");
+    } else if bla2() {
+        println!("else if 1");
+    } else if bla3() {
+        println!("else if 2");
+    } else if bla4() {
+        println!("else if 3");
+    } else if bla5() {
+        //~^ ERROR: `if` expression with an `else if`, but without a final `else`
+        println!("else if 4");
+    }
+
+    if bla1() {
+        println!("if");
+    } else if bla2() {
+        println!("else if 1");
+    } else {
+        if bla3() {
+            println!("else if 2");
+        } else if bla4() {
+            println!("else if 3");
+        } else if bla5() {
+            println!("else if 4");
+        } else {
+            println!("else");
+        }
+    }
+
+    if bla1() {
+        println!("if");
+    } else if bla2() {
+        println!("else if 1");
+    } else {
+        if bla3() {
+            println!("else if 2");
+        } else if bla4() {
+            println!("else if 3");
+        } else if bla5() {
+            //~^ ERROR: `if` expression with an `else if`, but without a final `else`
+            println!("else if 4");
+        }
+    }
 }
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.stderr b/src/tools/clippy/tests/ui/else_if_without_else.stderr
index 3bb840f39e7..bc717485229 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.stderr
+++ b/src/tools/clippy/tests/ui/else_if_without_else.stderr
@@ -1,5 +1,5 @@
 error: `if` expression with an `else if`, but without a final `else`
-  --> tests/ui/else_if_without_else.rs:47:12
+  --> tests/ui/else_if_without_else.rs:51:12
    |
 LL |       } else if bla2() {
    |  ____________^
@@ -13,7 +13,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::else_if_without_else)]`
 
 error: `if` expression with an `else if`, but without a final `else`
-  --> tests/ui/else_if_without_else.rs:56:12
+  --> tests/ui/else_if_without_else.rs:60:12
    |
 LL |       } else if bla3() {
    |  ____________^
@@ -24,5 +24,29 @@ LL | |     }
    |
    = help: add an `else` block here
 
-error: aborting due to 2 previous errors
+error: `if` expression with an `else if`, but without a final `else`
+  --> tests/ui/else_if_without_else.rs:87:12
+   |
+LL |       } else if bla5() {
+   |  ____________^
+LL | |
+LL | |         println!("else if 4");
+LL | |     }
+   | |_____^
+   |
+   = help: add an `else` block here
+
+error: `if` expression with an `else if`, but without a final `else`
+  --> tests/ui/else_if_without_else.rs:117:16
+   |
+LL |           } else if bla5() {
+   |  ________________^
+LL | |
+LL | |             println!("else if 4");
+LL | |         }
+   | |_________^
+   |
+   = help: add an `else` block here
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/empty_docs.rs b/src/tools/clippy/tests/ui/empty_docs.rs
index 272fab7d5ca..00e64eebc5f 100644
--- a/src/tools/clippy/tests/ui/empty_docs.rs
+++ b/src/tools/clippy/tests/ui/empty_docs.rs
@@ -1,6 +1,9 @@
+//@aux-build:proc_macro_attr.rs
+
 #![allow(unused)]
 #![warn(clippy::empty_docs)]
 #![allow(clippy::mixed_attributes_style)]
+#![feature(extern_types)]
 
 mod outer {
     //!
@@ -67,3 +70,17 @@ mod outer {
         y: i32,
     }
 }
+
+mod issue_12377 {
+    use proc_macro_attr::with_empty_docs;
+
+    #[with_empty_docs]
+    extern "C" {
+        type Test;
+    }
+
+    #[with_empty_docs]
+    struct Foo {
+        a: u8,
+    }
+}
diff --git a/src/tools/clippy/tests/ui/empty_docs.stderr b/src/tools/clippy/tests/ui/empty_docs.stderr
index f12aead6aa7..28ebea22c5d 100644
--- a/src/tools/clippy/tests/ui/empty_docs.stderr
+++ b/src/tools/clippy/tests/ui/empty_docs.stderr
@@ -1,5 +1,5 @@
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:6:5
+  --> tests/ui/empty_docs.rs:9:5
    |
 LL |     //!
    |     ^^^
@@ -9,7 +9,7 @@ LL |     //!
    = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]`
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:14:5
+  --> tests/ui/empty_docs.rs:17:5
    |
 LL |     ///
    |     ^^^
@@ -17,7 +17,7 @@ LL |     ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:16:9
+  --> tests/ui/empty_docs.rs:19:9
    |
 LL |         ///
    |         ^^^
@@ -25,7 +25,7 @@ LL |         ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:27:5
+  --> tests/ui/empty_docs.rs:30:5
    |
 LL |     #[doc = ""]
    |     ^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     #[doc = ""]
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:30:5
+  --> tests/ui/empty_docs.rs:33:5
    |
 LL | /     #[doc = ""]
 LL | |     #[doc = ""]
@@ -42,7 +42,7 @@ LL | |     #[doc = ""]
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:37:5
+  --> tests/ui/empty_docs.rs:40:5
    |
 LL |     ///
    |     ^^^
@@ -50,7 +50,7 @@ LL |     ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:50:13
+  --> tests/ui/empty_docs.rs:53:13
    |
 LL |             /*! */
    |             ^^^^^^
@@ -58,7 +58,7 @@ LL |             /*! */
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:58:13
+  --> tests/ui/empty_docs.rs:61:13
    |
 LL |             ///
    |             ^^^
@@ -66,7 +66,7 @@ LL |             ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:66:9
+  --> tests/ui/empty_docs.rs:69:9
    |
 LL |         ///
    |         ^^^
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
index e843770f578..dd78491749c 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macro_attr.rs
 #![warn(clippy::empty_line_after_doc_comments)]
-#![allow(clippy::assertions_on_constants)]
+#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)]
 #![feature(custom_inner_attributes)]
 #![rustfmt::skip]
 
diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
index 269e66ea0a8..f147cf2cd5d 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
@@ -1,6 +1,6 @@
 //@aux-build:proc_macro_attr.rs
 #![warn(clippy::empty_line_after_outer_attr)]
-#![allow(clippy::assertions_on_constants)]
+#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)]
 #![feature(custom_inner_attributes)]
 #![rustfmt::skip]
 
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index 71ec13f4610..abdfae2a3e1 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -176,4 +176,14 @@ pub fn issue_11935() {
     }
 }
 
+fn issue12489(map: &mut HashMap<u64, u64>) -> Option<()> {
+    if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) {
+        let Some(1) = Some(2) else {
+            return None;
+        };
+        e.insert(42);
+    }
+    Some(())
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index 86092b7c055..7774f99a2a2 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -180,4 +180,14 @@ pub fn issue_11935() {
     }
 }
 
+fn issue12489(map: &mut HashMap<u64, u64>) -> Option<()> {
+    if !map.contains_key(&1) {
+        let Some(1) = Some(2) else {
+            return None;
+        };
+        map.insert(1, 42);
+    }
+    Some(())
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr
index ef4c36bcf54..fb467676606 100644
--- a/src/tools/clippy/tests/ui/entry.stderr
+++ b/src/tools/clippy/tests/ui/entry.stderr
@@ -214,5 +214,26 @@ LL +         v
 LL +     });
    |
 
-error: aborting due to 10 previous errors
+error: usage of `contains_key` followed by `insert` on a `HashMap`
+  --> tests/ui/entry.rs:184:5
+   |
+LL | /     if !map.contains_key(&1) {
+LL | |         let Some(1) = Some(2) else {
+LL | |             return None;
+LL | |         };
+LL | |         map.insert(1, 42);
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     if let std::collections::hash_map::Entry::Vacant(e) = map.entry(1) {
+LL +         let Some(1) = Some(2) else {
+LL +             return None;
+LL +         };
+LL +         e.insert(42);
+LL +     }
+   |
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/integer_division_remainder_used.rs b/src/tools/clippy/tests/ui/integer_division_remainder_used.rs
new file mode 100644
index 00000000000..5d1b02095d1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/integer_division_remainder_used.rs
@@ -0,0 +1,41 @@
+#![warn(clippy::integer_division_remainder_used)]
+#![allow(unused_variables)]
+#![allow(clippy::op_ref)]
+
+struct CustomOps(pub i32);
+impl std::ops::Div for CustomOps {
+    type Output = Self;
+
+    fn div(self, rhs: Self) -> Self::Output {
+        Self(self.0 / rhs.0)
+    }
+}
+impl std::ops::Rem for CustomOps {
+    type Output = Self;
+
+    fn rem(self, rhs: Self) -> Self::Output {
+        Self(self.0 % rhs.0)
+    }
+}
+
+fn main() {
+    // should trigger
+    let a = 10;
+    let b = 5;
+    let c = a / b;
+    let d = a % b;
+    let e = &a / b;
+    let f = a % &b;
+    let g = &a / &b;
+    let h = &10 % b;
+    let i = a / &4;
+
+    // should not trigger on custom Div and Rem
+    let w = CustomOps(3);
+    let x = CustomOps(4);
+    let y = w / x;
+
+    let w = CustomOps(3);
+    let x = CustomOps(4);
+    let z = w % x;
+}
diff --git a/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr b/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr
new file mode 100644
index 00000000000..8adfda28893
--- /dev/null
+++ b/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr
@@ -0,0 +1,59 @@
+error: use of / has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:10:14
+   |
+LL |         Self(self.0 / rhs.0)
+   |              ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::integer-division-remainder-used` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::integer_division_remainder_used)]`
+
+error: use of % has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:17:14
+   |
+LL |         Self(self.0 % rhs.0)
+   |              ^^^^^^^^^^^^^^
+
+error: use of / has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:25:13
+   |
+LL |     let c = a / b;
+   |             ^^^^^
+
+error: use of % has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:26:13
+   |
+LL |     let d = a % b;
+   |             ^^^^^
+
+error: use of / has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:27:13
+   |
+LL |     let e = &a / b;
+   |             ^^^^^^
+
+error: use of % has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:28:13
+   |
+LL |     let f = a % &b;
+   |             ^^^^^^
+
+error: use of / has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:29:13
+   |
+LL |     let g = &a / &b;
+   |             ^^^^^^^
+
+error: use of % has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:30:13
+   |
+LL |     let h = &10 % b;
+   |             ^^^^^^^
+
+error: use of / has been disallowed in this context
+  --> tests/ui/integer_division_remainder_used.rs:31:13
+   |
+LL |     let i = a / &4;
+   |             ^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/iter_nth.fixed b/src/tools/clippy/tests/ui/iter_nth.fixed
new file mode 100644
index 00000000000..aff3731a883
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_nth.fixed
@@ -0,0 +1,60 @@
+//@aux-build:option_helpers.rs
+
+#![warn(clippy::iter_nth)]
+#![allow(clippy::useless_vec)]
+
+#[macro_use]
+extern crate option_helpers;
+
+use option_helpers::IteratorFalsePositives;
+use std::collections::VecDeque;
+
+/// Struct to generate false positives for things with `.iter()`.
+#[derive(Copy, Clone)]
+struct HasIter;
+
+impl HasIter {
+    fn iter(self) -> IteratorFalsePositives {
+        IteratorFalsePositives { foo: 0 }
+    }
+
+    fn iter_mut(self) -> IteratorFalsePositives {
+        IteratorFalsePositives { foo: 0 }
+    }
+}
+
+/// Checks implementation of `ITER_NTH` lint.
+fn iter_nth() {
+    let mut some_vec = vec![0, 1, 2, 3];
+    let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
+    let mut some_vec_deque: VecDeque<_> = some_vec.iter().cloned().collect();
+
+    {
+        // Make sure we lint `.iter()` for relevant types.
+        let bad_vec = some_vec.get(3);
+        let bad_slice = &some_vec[..].get(3);
+        let bad_boxed_slice = boxed_slice.get(3);
+        let bad_vec_deque = some_vec_deque.get(3);
+    }
+
+    {
+        // Make sure we lint `.iter_mut()` for relevant types.
+        let bad_vec = some_vec.get_mut(3);
+    }
+    {
+        let bad_slice = &some_vec[..].get_mut(3);
+    }
+    {
+        let bad_vec_deque = some_vec_deque.get_mut(3);
+    }
+
+    let vec_ref = &Vec::<String>::new();
+    vec_ref.get(3);
+
+    // Make sure we don't lint for non-relevant types.
+    let false_positive = HasIter;
+    let ok = false_positive.iter().nth(3);
+    let ok_mut = false_positive.iter_mut().nth(3);
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/iter_nth.rs b/src/tools/clippy/tests/ui/iter_nth.rs
index 7c567bb81d8..89d68044ddd 100644
--- a/src/tools/clippy/tests/ui/iter_nth.rs
+++ b/src/tools/clippy/tests/ui/iter_nth.rs
@@ -48,6 +48,9 @@ fn iter_nth() {
         let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
     }
 
+    let vec_ref = &Vec::<String>::new();
+    vec_ref.iter().nth(3);
+
     // Make sure we don't lint for non-relevant types.
     let false_positive = HasIter;
     let ok = false_positive.iter().nth(3);
diff --git a/src/tools/clippy/tests/ui/iter_nth.stderr b/src/tools/clippy/tests/ui/iter_nth.stderr
index c5dd0c99727..178463f5347 100644
--- a/src/tools/clippy/tests/ui/iter_nth.stderr
+++ b/src/tools/clippy/tests/ui/iter_nth.stderr
@@ -4,9 +4,12 @@ error: called `.iter().nth()` on a `Vec`
 LL |         let bad_vec = some_vec.iter().nth(3);
    |                       ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get()` is both faster and more readable
    = note: `-D clippy::iter-nth` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::iter_nth)]`
+help: `get` is equivalent but more concise
+   |
+LL |         let bad_vec = some_vec.get(3);
+   |                                ~~~
 
 error: called `.iter().nth()` on a slice
   --> tests/ui/iter_nth.rs:35:26
@@ -14,7 +17,10 @@ error: called `.iter().nth()` on a slice
 LL |         let bad_slice = &some_vec[..].iter().nth(3);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get()` is both faster and more readable
+help: `get` is equivalent but more concise
+   |
+LL |         let bad_slice = &some_vec[..].get(3);
+   |                                       ~~~
 
 error: called `.iter().nth()` on a slice
   --> tests/ui/iter_nth.rs:36:31
@@ -22,7 +28,10 @@ error: called `.iter().nth()` on a slice
 LL |         let bad_boxed_slice = boxed_slice.iter().nth(3);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get()` is both faster and more readable
+help: `get` is equivalent but more concise
+   |
+LL |         let bad_boxed_slice = boxed_slice.get(3);
+   |                                           ~~~
 
 error: called `.iter().nth()` on a `VecDeque`
   --> tests/ui/iter_nth.rs:37:29
@@ -30,7 +39,10 @@ error: called `.iter().nth()` on a `VecDeque`
 LL |         let bad_vec_deque = some_vec_deque.iter().nth(3);
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get()` is both faster and more readable
+help: `get` is equivalent but more concise
+   |
+LL |         let bad_vec_deque = some_vec_deque.get(3);
+   |                                            ~~~
 
 error: called `.iter_mut().nth()` on a `Vec`
   --> tests/ui/iter_nth.rs:42:23
@@ -38,7 +50,10 @@ error: called `.iter_mut().nth()` on a `Vec`
 LL |         let bad_vec = some_vec.iter_mut().nth(3);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get_mut()` is both faster and more readable
+help: `get_mut` is equivalent but more concise
+   |
+LL |         let bad_vec = some_vec.get_mut(3);
+   |                                ~~~~~~~
 
 error: called `.iter_mut().nth()` on a slice
   --> tests/ui/iter_nth.rs:45:26
@@ -46,7 +61,10 @@ error: called `.iter_mut().nth()` on a slice
 LL |         let bad_slice = &some_vec[..].iter_mut().nth(3);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get_mut()` is both faster and more readable
+help: `get_mut` is equivalent but more concise
+   |
+LL |         let bad_slice = &some_vec[..].get_mut(3);
+   |                                       ~~~~~~~
 
 error: called `.iter_mut().nth()` on a `VecDeque`
   --> tests/ui/iter_nth.rs:48:29
@@ -54,7 +72,21 @@ error: called `.iter_mut().nth()` on a `VecDeque`
 LL |         let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: calling `.get_mut()` is both faster and more readable
+help: `get_mut` is equivalent but more concise
+   |
+LL |         let bad_vec_deque = some_vec_deque.get_mut(3);
+   |                                            ~~~~~~~
 
-error: aborting due to 7 previous errors
+error: called `.iter().nth()` on a `Vec`
+  --> tests/ui/iter_nth.rs:52:5
+   |
+LL |     vec_ref.iter().nth(3);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: `get` is equivalent but more concise
+   |
+LL |     vec_ref.get(3);
+   |             ~~~
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/len_zero.fixed b/src/tools/clippy/tests/ui/len_zero.fixed
index 745fc7e1a8b..c16d7a26616 100644
--- a/src/tools/clippy/tests/ui/len_zero.fixed
+++ b/src/tools/clippy/tests/ui/len_zero.fixed
@@ -1,5 +1,11 @@
 #![warn(clippy::len_zero)]
-#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)]
+#![allow(
+    dead_code,
+    unused,
+    clippy::needless_if,
+    clippy::len_without_is_empty,
+    clippy::const_is_empty
+)]
 
 extern crate core;
 use core::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/len_zero.rs b/src/tools/clippy/tests/ui/len_zero.rs
index 048ad2f4fd3..5c49a5abf81 100644
--- a/src/tools/clippy/tests/ui/len_zero.rs
+++ b/src/tools/clippy/tests/ui/len_zero.rs
@@ -1,5 +1,11 @@
 #![warn(clippy::len_zero)]
-#![allow(dead_code, unused, clippy::needless_if, clippy::len_without_is_empty)]
+#![allow(
+    dead_code,
+    unused,
+    clippy::needless_if,
+    clippy::len_without_is_empty,
+    clippy::const_is_empty
+)]
 
 extern crate core;
 use core::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/len_zero.stderr b/src/tools/clippy/tests/ui/len_zero.stderr
index b1f04c94de6..dd07a85d62c 100644
--- a/src/tools/clippy/tests/ui/len_zero.stderr
+++ b/src/tools/clippy/tests/ui/len_zero.stderr
@@ -1,5 +1,5 @@
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:82:8
+  --> tests/ui/len_zero.rs:88:8
    |
 LL |     if x.len() == 0 {
    |        ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()`
@@ -8,13 +8,13 @@ LL |     if x.len() == 0 {
    = help: to override `-D warnings` add `#[allow(clippy::len_zero)]`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:86:8
+  --> tests/ui/len_zero.rs:92:8
    |
 LL |     if "".len() == 0 {}
    |        ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:95:20
+  --> tests/ui/len_zero.rs:101:20
    |
 LL |     println!("{}", *s1 == "");
    |                    ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s1.is_empty()`
@@ -23,121 +23,121 @@ LL |     println!("{}", *s1 == "");
    = help: to override `-D warnings` add `#[allow(clippy::comparison_to_empty)]`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:96:20
+  --> tests/ui/len_zero.rs:102:20
    |
 LL |     println!("{}", **s2 == "");
    |                    ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s2.is_empty()`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:97:20
+  --> tests/ui/len_zero.rs:103:20
    |
 LL |     println!("{}", ***s3 == "");
    |                    ^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s3.is_empty()`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:98:20
+  --> tests/ui/len_zero.rs:104:20
    |
 LL |     println!("{}", ****s4 == "");
    |                    ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s4.is_empty()`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:99:20
+  --> tests/ui/len_zero.rs:105:20
    |
 LL |     println!("{}", *****s5 == "");
    |                    ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s5.is_empty()`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:100:20
+  --> tests/ui/len_zero.rs:106:20
    |
 LL |     println!("{}", ******(s6) == "");
    |                    ^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(s6).is_empty()`
 
 error: comparison to empty slice
-  --> tests/ui/len_zero.rs:103:20
+  --> tests/ui/len_zero.rs:109:20
    |
 LL |     println!("{}", &**d2s == "");
    |                    ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(**d2s).is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:118:8
+  --> tests/ui/len_zero.rs:124:8
    |
 LL |     if has_is_empty.len() == 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:121:8
+  --> tests/ui/len_zero.rs:127:8
    |
 LL |     if has_is_empty.len() != 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:124:8
+  --> tests/ui/len_zero.rs:130:8
    |
 LL |     if has_is_empty.len() > 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> tests/ui/len_zero.rs:127:8
+  --> tests/ui/len_zero.rs:133:8
    |
 LL |     if has_is_empty.len() < 1 {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> tests/ui/len_zero.rs:130:8
+  --> tests/ui/len_zero.rs:136:8
    |
 LL |     if has_is_empty.len() >= 1 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:141:8
+  --> tests/ui/len_zero.rs:147:8
    |
 LL |     if 0 == has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:144:8
+  --> tests/ui/len_zero.rs:150:8
    |
 LL |     if 0 != has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:147:8
+  --> tests/ui/len_zero.rs:153:8
    |
 LL |     if 0 < has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> tests/ui/len_zero.rs:150:8
+  --> tests/ui/len_zero.rs:156:8
    |
 LL |     if 1 <= has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to one
-  --> tests/ui/len_zero.rs:153:8
+  --> tests/ui/len_zero.rs:159:8
    |
 LL |     if 1 > has_is_empty.len() {
    |        ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:167:8
+  --> tests/ui/len_zero.rs:173:8
    |
 LL |     if with_is_empty.len() == 0 {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:179:6
+  --> tests/ui/len_zero.rs:185:6
    |
 LL |     (has_is_empty.len() > 0).then(|| println!("This can happen."));
    |      ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:180:6
+  --> tests/ui/len_zero.rs:186:6
    |
 LL |     (has_is_empty.len() == 0).then(|| println!("Or this!"));
    |      ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
 
 error: length comparison to zero
-  --> tests/ui/len_zero.rs:184:8
+  --> tests/ui/len_zero.rs:190:8
    |
 LL |     if b.len() != 0 {}
    |        ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()`
diff --git a/src/tools/clippy/tests/ui/let_if_seq.rs b/src/tools/clippy/tests/ui/let_if_seq.rs
index 9869d945299..a29d35880b8 100644
--- a/src/tools/clippy/tests/ui/let_if_seq.rs
+++ b/src/tools/clippy/tests/ui/let_if_seq.rs
@@ -57,6 +57,17 @@ fn early_return() -> u8 {
     foo
 }
 
+fn allow_works() -> i32 {
+    #[allow(clippy::useless_let_if_seq)]
+    let x;
+    if true {
+        x = 1;
+    } else {
+        x = 2;
+    }
+    x
+}
+
 fn main() {
     early_return();
     issue975();
diff --git a/src/tools/clippy/tests/ui/let_if_seq.stderr b/src/tools/clippy/tests/ui/let_if_seq.stderr
index 87ad20dc27e..41930108fb1 100644
--- a/src/tools/clippy/tests/ui/let_if_seq.stderr
+++ b/src/tools/clippy/tests/ui/let_if_seq.stderr
@@ -1,5 +1,5 @@
 error: `if _ { .. } else { .. }` is an expression
-  --> tests/ui/let_if_seq.rs:66:5
+  --> tests/ui/let_if_seq.rs:77:5
    |
 LL | /     let mut foo = 0;
 LL | |
@@ -14,7 +14,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::useless_let_if_seq)]`
 
 error: `if _ { .. } else { .. }` is an expression
-  --> tests/ui/let_if_seq.rs:73:5
+  --> tests/ui/let_if_seq.rs:84:5
    |
 LL | /     let mut bar = 0;
 LL | |
@@ -28,7 +28,7 @@ LL | |     }
    = note: you might not need `mut` at all
 
 error: `if _ { .. } else { .. }` is an expression
-  --> tests/ui/let_if_seq.rs:83:5
+  --> tests/ui/let_if_seq.rs:94:5
    |
 LL | /     let quz;
 LL | |
@@ -40,7 +40,7 @@ LL | |     }
    | |_____^ help: it is more idiomatic to write: `let quz = if f() { 42 } else { 0 };`
 
 error: `if _ { .. } else { .. }` is an expression
-  --> tests/ui/let_if_seq.rs:113:5
+  --> tests/ui/let_if_seq.rs:124:5
    |
 LL | /     let mut baz = 0;
 LL | |
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index 1fb252e3f97..2b36c3f3c2f 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -8,7 +8,8 @@
     clippy::never_loop,
     clippy::needless_if,
     clippy::diverging_sub_expression,
-    clippy::single_match
+    clippy::single_match,
+    clippy::manual_unwrap_or_default
 )]
 #![warn(clippy::manual_let_else)]
 //@no-rustfix
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 7012c6b8891..55a410982ad 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,5 +1,5 @@
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:28:5
+  --> tests/ui/manual_let_else.rs:29:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
@@ -8,7 +8,7 @@ LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:31:5
+  --> tests/ui/manual_let_else.rs:32:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -26,7 +26,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:38:5
+  --> tests/ui/manual_let_else.rs:39:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |
@@ -47,25 +47,25 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:50:9
+  --> tests/ui/manual_let_else.rs:51:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:52:9
+  --> tests/ui/manual_let_else.rs:53:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:57:5
+  --> tests/ui/manual_let_else.rs:58:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:61:5
+  --> tests/ui/manual_let_else.rs:62:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -83,7 +83,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:69:5
+  --> tests/ui/manual_let_else.rs:70:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -101,7 +101,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:77:5
+  --> tests/ui/manual_let_else.rs:78:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -121,7 +121,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:86:5
+  --> tests/ui/manual_let_else.rs:87:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -141,7 +141,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:95:5
+  --> tests/ui/manual_let_else.rs:96:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -168,7 +168,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:111:5
+  --> tests/ui/manual_let_else.rs:112:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -190,7 +190,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:122:5
+  --> tests/ui/manual_let_else.rs:123:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -217,7 +217,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:138:5
+  --> tests/ui/manual_let_else.rs:139:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -239,7 +239,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:149:5
+  --> tests/ui/manual_let_else.rs:150:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -257,7 +257,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:157:5
+  --> tests/ui/manual_let_else.rs:158:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -278,7 +278,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:167:5
+  --> tests/ui/manual_let_else.rs:168:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -299,7 +299,7 @@ LL +     } };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:177:5
+  --> tests/ui/manual_let_else.rs:178:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -328,7 +328,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:195:5
+  --> tests/ui/manual_let_else.rs:196:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |
@@ -346,7 +346,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:203:5
+  --> tests/ui/manual_let_else.rs:204:5
    |
 LL | /     let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
 LL | |
@@ -364,7 +364,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:213:13
+  --> tests/ui/manual_let_else.rs:214:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
@@ -375,19 +375,19 @@ LL |     create_binding_if_some!(w, g());
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:222:5
+  --> tests/ui/manual_let_else.rs:223:5
    |
 LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:226:5
+  --> tests/ui/manual_let_else.rs:227:5
    |
 LL |     let mut v = if let Variant::B(b) = e() { b } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:231:5
+  --> tests/ui/manual_let_else.rs:232:5
    |
 LL | /     let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
 LL | |
@@ -405,19 +405,19 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:238:5
+  --> tests/ui/manual_let_else.rs:239:5
    |
 LL |     let v = if let Variant::A(.., a) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:242:5
+  --> tests/ui/manual_let_else.rs:243:5
    |
 LL |     let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:246:5
+  --> tests/ui/manual_let_else.rs:247:5
    |
 LL | /     let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
 LL | |
@@ -435,7 +435,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:254:5
+  --> tests/ui/manual_let_else.rs:255:5
    |
 LL | /     let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
 LL | |
@@ -453,7 +453,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:262:5
+  --> tests/ui/manual_let_else.rs:263:5
    |
 LL | /     let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
 LL | |
@@ -471,7 +471,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:379:5
+  --> tests/ui/manual_let_else.rs:380:5
    |
 LL | /     let _ = match ff {
 LL | |
@@ -481,7 +481,7 @@ LL | |     };
    | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:456:9
+  --> tests/ui/manual_let_else.rs:457:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { return };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed
index e359dfbb98c..5540029bf6b 100644
--- a/src/tools/clippy/tests/ui/manual_retain.fixed
+++ b/src/tools/clippy/tests/ui/manual_retain.fixed
@@ -1,5 +1,3 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![warn(clippy::manual_retain)]
 #![allow(unused, clippy::redundant_clone)]
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs
index 931814f08b7..cee641d9d65 100644
--- a/src/tools/clippy/tests/ui/manual_retain.rs
+++ b/src/tools/clippy/tests/ui/manual_retain.rs
@@ -1,5 +1,3 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![warn(clippy::manual_retain)]
 #![allow(unused, clippy::redundant_clone)]
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
diff --git a/src/tools/clippy/tests/ui/manual_retain.stderr b/src/tools/clippy/tests/ui/manual_retain.stderr
index fdbbc53e4df..c25c804df75 100644
--- a/src/tools/clippy/tests/ui/manual_retain.stderr
+++ b/src/tools/clippy/tests/ui/manual_retain.stderr
@@ -1,5 +1,5 @@
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:27:5
+  --> tests/ui/manual_retain.rs:25:5
    |
 LL |     binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
@@ -8,43 +8,43 @@ LL |     binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
    = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:28:5
+  --> tests/ui/manual_retain.rs:26:5
    |
 LL |     binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:29:5
+  --> tests/ui/manual_retain.rs:27:5
    |
 LL |     binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:33:5
+  --> tests/ui/manual_retain.rs:31:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:34:5
+  --> tests/ui/manual_retain.rs:32:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:64:5
+  --> tests/ui/manual_retain.rs:62:5
    |
 LL |     btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:65:5
+  --> tests/ui/manual_retain.rs:63:5
    |
 LL |     btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:66:5
+  --> tests/ui/manual_retain.rs:64:5
    |
 LL | /     btree_map = btree_map
 LL | |         .into_iter()
@@ -53,49 +53,49 @@ LL | |         .collect();
    | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:91:5
+  --> tests/ui/manual_retain.rs:89:5
    |
 LL |     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:92:5
+  --> tests/ui/manual_retain.rs:90:5
    |
 LL |     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:93:5
+  --> tests/ui/manual_retain.rs:91:5
    |
 LL |     btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:97:5
+  --> tests/ui/manual_retain.rs:95:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:98:5
+  --> tests/ui/manual_retain.rs:96:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:128:5
+  --> tests/ui/manual_retain.rs:126:5
    |
 LL |     hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:129:5
+  --> tests/ui/manual_retain.rs:127:5
    |
 LL |     hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:130:5
+  --> tests/ui/manual_retain.rs:128:5
    |
 LL | /     hash_map = hash_map
 LL | |         .into_iter()
@@ -104,133 +104,133 @@ LL | |         .collect();
    | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:154:5
+  --> tests/ui/manual_retain.rs:152:5
    |
 LL |     hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:155:5
+  --> tests/ui/manual_retain.rs:153:5
    |
 LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:156:5
+  --> tests/ui/manual_retain.rs:154:5
    |
 LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:160:5
+  --> tests/ui/manual_retain.rs:158:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:161:5
+  --> tests/ui/manual_retain.rs:159:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:190:5
+  --> tests/ui/manual_retain.rs:188:5
    |
 LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:202:5
+  --> tests/ui/manual_retain.rs:200:5
    |
 LL |     vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:203:5
+  --> tests/ui/manual_retain.rs:201:5
    |
 LL |     vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:204:5
+  --> tests/ui/manual_retain.rs:202:5
    |
 LL |     vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:208:5
+  --> tests/ui/manual_retain.rs:206:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:209:5
+  --> tests/ui/manual_retain.rs:207:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:231:5
+  --> tests/ui/manual_retain.rs:229:5
    |
 LL |     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:232:5
+  --> tests/ui/manual_retain.rs:230:5
    |
 LL |     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:233:5
+  --> tests/ui/manual_retain.rs:231:5
    |
 LL |     vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:290:5
+  --> tests/ui/manual_retain.rs:288:5
    |
 LL |     vec = vec.into_iter().filter(|(x, y)| *x == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:294:5
+  --> tests/ui/manual_retain.rs:292:5
    |
 LL |     tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:311:5
+  --> tests/ui/manual_retain.rs:309:5
    |
 LL |     vec = vec.iter().filter(|&&x| x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:312:5
+  --> tests/ui/manual_retain.rs:310:5
    |
 LL |     vec = vec.iter().filter(|&&x| x == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:313:5
+  --> tests/ui/manual_retain.rs:311:5
    |
 LL |     vec = vec.into_iter().filter(|&x| x == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:316:5
+  --> tests/ui/manual_retain.rs:314:5
    |
 LL |     vec = vec.iter().filter(|&x| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:317:5
+  --> tests/ui/manual_retain.rs:315:5
    |
 LL |     vec = vec.iter().filter(|&x| *x == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:318:5
+  --> tests/ui/manual_retain.rs:316:5
    |
 LL |     vec = vec.into_iter().filter(|x| *x == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
index 737d4c90dca..dffd44b6a7c 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.fixed
@@ -1,5 +1,10 @@
 #![allow(dead_code)]
-#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)]
+#![allow(
+    unused_variables,
+    clippy::unnecessary_wraps,
+    clippy::unnecessary_literal_unwrap,
+    clippy::manual_unwrap_or_default
+)]
 
 fn option_unwrap_or() {
     // int case
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.rs b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
index f59fb87529f..67427132c1a 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.rs
@@ -1,5 +1,10 @@
 #![allow(dead_code)]
-#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)]
+#![allow(
+    unused_variables,
+    clippy::unnecessary_wraps,
+    clippy::unnecessary_literal_unwrap,
+    clippy::manual_unwrap_or_default
+)]
 
 fn option_unwrap_or() {
     // int case
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
index 511b79881ac..33a099680ce 100644
--- a/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or.stderr
@@ -1,5 +1,5 @@
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:6:5
+  --> tests/ui/manual_unwrap_or.rs:11:5
    |
 LL | /     match Some(1) {
 LL | |         Some(i) => i,
@@ -11,7 +11,7 @@ LL | |     };
    = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or)]`
 
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:12:5
+  --> tests/ui/manual_unwrap_or.rs:17:5
    |
 LL | /     match Some(1) {
 LL | |         None => 42,
@@ -20,7 +20,7 @@ LL | |     };
    | |_____^ help: replace with: `Some(1).unwrap_or(42)`
 
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:18:5
+  --> tests/ui/manual_unwrap_or.rs:23:5
    |
 LL | /     match Some(1) {
 LL | |         Some(i) => i,
@@ -29,7 +29,7 @@ LL | |     };
    | |_____^ help: replace with: `Some(1).unwrap_or(1 + 42)`
 
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:25:5
+  --> tests/ui/manual_unwrap_or.rs:30:5
    |
 LL | /     match Some(1) {
 LL | |         Some(i) => i,
@@ -50,7 +50,7 @@ LL ~     });
    |
 
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:35:5
+  --> tests/ui/manual_unwrap_or.rs:40:5
    |
 LL | /     match Some("Bob") {
 LL | |         Some(i) => i,
@@ -59,7 +59,7 @@ LL | |     };
    | |_____^ help: replace with: `Some("Bob").unwrap_or("Alice")`
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:85:5
+  --> tests/ui/manual_unwrap_or.rs:90:5
    |
 LL | /     match Ok::<i32, &str>(1) {
 LL | |         Ok(i) => i,
@@ -68,7 +68,7 @@ LL | |     };
    | |_____^ help: replace with: `Ok::<i32, &str>(1).unwrap_or(42)`
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:92:5
+  --> tests/ui/manual_unwrap_or.rs:97:5
    |
 LL | /     match a {
 LL | |         Ok(i) => i,
@@ -77,7 +77,7 @@ LL | |     };
    | |_____^ help: replace with: `a.unwrap_or(42)`
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:98:5
+  --> tests/ui/manual_unwrap_or.rs:103:5
    |
 LL | /     match Ok(1) as Result<i32, &str> {
 LL | |         Ok(i) => i,
@@ -86,7 +86,7 @@ LL | |     };
    | |_____^ help: replace with: `(Ok(1) as Result<i32, &str>).unwrap_or(42)`
 
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:111:5
+  --> tests/ui/manual_unwrap_or.rs:116:5
    |
 LL | /     match s.method() {
 LL | |         Some(i) => i,
@@ -95,7 +95,7 @@ LL | |     };
    | |_____^ help: replace with: `s.method().unwrap_or(42)`
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:117:5
+  --> tests/ui/manual_unwrap_or.rs:122:5
    |
 LL | /     match Ok::<i32, &str>(1) {
 LL | |         Err(_) => 42,
@@ -104,7 +104,7 @@ LL | |     };
    | |_____^ help: replace with: `Ok::<i32, &str>(1).unwrap_or(42)`
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:123:5
+  --> tests/ui/manual_unwrap_or.rs:128:5
    |
 LL | /     match Ok::<i32, &str>(1) {
 LL | |         Ok(i) => i,
@@ -113,7 +113,7 @@ LL | |     };
    | |_____^ help: replace with: `Ok::<i32, &str>(1).unwrap_or(1 + 42)`
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:130:5
+  --> tests/ui/manual_unwrap_or.rs:135:5
    |
 LL | /     match Ok::<i32, &str>(1) {
 LL | |         Ok(i) => i,
@@ -134,7 +134,7 @@ LL ~     });
    |
 
 error: this pattern reimplements `Result::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:140:5
+  --> tests/ui/manual_unwrap_or.rs:145:5
    |
 LL | /     match Ok::<&str, &str>("Bob") {
 LL | |         Ok(i) => i,
@@ -143,7 +143,7 @@ LL | |     };
    | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")`
 
 error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:200:17
+  --> tests/ui/manual_unwrap_or.rs:205:17
    |
 LL |           let _ = match some_macro!() {
    |  _________________^
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
new file mode 100644
index 00000000000..c8456805ee6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.fixed
@@ -0,0 +1,19 @@
+#![warn(clippy::manual_unwrap_or_default)]
+#![allow(clippy::unnecessary_literal_unwrap)]
+
+fn main() {
+    let x: Option<Vec<String>> = None;
+    x.unwrap_or_default();
+
+    let x: Option<Vec<String>> = None;
+    x.unwrap_or_default();
+
+    let x: Option<String> = None;
+    x.unwrap_or_default();
+
+    let x: Option<Vec<String>> = None;
+    x.unwrap_or_default();
+
+    let x: Option<Vec<String>> = None;
+    x.unwrap_or_default();
+}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
new file mode 100644
index 00000000000..820717be53a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.rs
@@ -0,0 +1,40 @@
+#![warn(clippy::manual_unwrap_or_default)]
+#![allow(clippy::unnecessary_literal_unwrap)]
+
+fn main() {
+    let x: Option<Vec<String>> = None;
+    match x {
+        //~^ ERROR: match can be simplified with `.unwrap_or_default()`
+        Some(v) => v,
+        None => Vec::default(),
+    };
+
+    let x: Option<Vec<String>> = None;
+    match x {
+        //~^ ERROR: match can be simplified with `.unwrap_or_default()`
+        Some(v) => v,
+        _ => Vec::default(),
+    };
+
+    let x: Option<String> = None;
+    match x {
+        //~^ ERROR: match can be simplified with `.unwrap_or_default()`
+        Some(v) => v,
+        None => String::new(),
+    };
+
+    let x: Option<Vec<String>> = None;
+    match x {
+        //~^ ERROR: match can be simplified with `.unwrap_or_default()`
+        None => Vec::default(),
+        Some(v) => v,
+    };
+
+    let x: Option<Vec<String>> = None;
+    if let Some(v) = x {
+        //~^ ERROR: if let can be simplified with `.unwrap_or_default()`
+        v
+    } else {
+        Vec::default()
+    };
+}
diff --git a/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr b/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
new file mode 100644
index 00000000000..f4eb6583588
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_unwrap_or_default.stderr
@@ -0,0 +1,56 @@
+error: match can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:6:5
+   |
+LL | /     match x {
+LL | |
+LL | |         Some(v) => v,
+LL | |         None => Vec::default(),
+LL | |     };
+   | |_____^ help: replace it with: `x.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: match can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:13:5
+   |
+LL | /     match x {
+LL | |
+LL | |         Some(v) => v,
+LL | |         _ => Vec::default(),
+LL | |     };
+   | |_____^ help: replace it with: `x.unwrap_or_default()`
+
+error: match can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:20:5
+   |
+LL | /     match x {
+LL | |
+LL | |         Some(v) => v,
+LL | |         None => String::new(),
+LL | |     };
+   | |_____^ help: replace it with: `x.unwrap_or_default()`
+
+error: match can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:27:5
+   |
+LL | /     match x {
+LL | |
+LL | |         None => Vec::default(),
+LL | |         Some(v) => v,
+LL | |     };
+   | |_____^ help: replace it with: `x.unwrap_or_default()`
+
+error: if let can be simplified with `.unwrap_or_default()`
+  --> tests/ui/manual_unwrap_or_default.rs:34:5
+   |
+LL | /     if let Some(v) = x {
+LL | |
+LL | |         v
+LL | |     } else {
+LL | |         Vec::default()
+LL | |     };
+   | |_____^ help: replace it with: `x.unwrap_or_default()`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/map_clone.fixed b/src/tools/clippy/tests/ui/map_clone.fixed
index 395eea69294..e58b6b2f19e 100644
--- a/src/tools/clippy/tests/ui/map_clone.fixed
+++ b/src/tools/clippy/tests/ui/map_clone.fixed
@@ -6,7 +6,8 @@
     clippy::redundant_clone,
     clippy::redundant_closure,
     clippy::useless_asref,
-    clippy::useless_vec
+    clippy::useless_vec,
+    clippy::empty_loop
 )]
 
 fn main() {
@@ -117,4 +118,17 @@ fn main() {
     let y = x.as_ref().map(|x| String::clone(x));
     let x: Result<String, ()> = Ok(String::new());
     let y = x.as_ref().map(|x| String::clone(x));
+
+    // Issue #12271
+    {
+        // Don't lint these
+        let x: Option<&u8> = None;
+        let y = x.map(|x| String::clone(loop {}));
+        let x: Option<&u8> = None;
+        let y = x.map(|x| u8::clone(loop {}));
+        let x: Vec<&u8> = vec![];
+        let y = x.into_iter().map(|x| String::clone(loop {}));
+        let x: Vec<&u8> = vec![];
+        let y = x.into_iter().map(|x| u8::clone(loop {}));
+    }
 }
diff --git a/src/tools/clippy/tests/ui/map_clone.rs b/src/tools/clippy/tests/ui/map_clone.rs
index 82a103edf5a..e642e4046f8 100644
--- a/src/tools/clippy/tests/ui/map_clone.rs
+++ b/src/tools/clippy/tests/ui/map_clone.rs
@@ -6,7 +6,8 @@
     clippy::redundant_clone,
     clippy::redundant_closure,
     clippy::useless_asref,
-    clippy::useless_vec
+    clippy::useless_vec,
+    clippy::empty_loop
 )]
 
 fn main() {
@@ -117,4 +118,17 @@ fn main() {
     let y = x.as_ref().map(|x| String::clone(x));
     let x: Result<String, ()> = Ok(String::new());
     let y = x.as_ref().map(|x| String::clone(x));
+
+    // Issue #12271
+    {
+        // Don't lint these
+        let x: Option<&u8> = None;
+        let y = x.map(|x| String::clone(loop {}));
+        let x: Option<&u8> = None;
+        let y = x.map(|x| u8::clone(loop {}));
+        let x: Vec<&u8> = vec![];
+        let y = x.into_iter().map(|x| String::clone(loop {}));
+        let x: Vec<&u8> = vec![];
+        let y = x.into_iter().map(|x| u8::clone(loop {}));
+    }
 }
diff --git a/src/tools/clippy/tests/ui/map_clone.stderr b/src/tools/clippy/tests/ui/map_clone.stderr
index 1a26a26a4ca..d9e025de4ab 100644
--- a/src/tools/clippy/tests/ui/map_clone.stderr
+++ b/src/tools/clippy/tests/ui/map_clone.stderr
@@ -1,5 +1,5 @@
 error: you are using an explicit closure for copying elements
-  --> tests/ui/map_clone.rs:13:22
+  --> tests/ui/map_clone.rs:14:22
    |
 LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()`
@@ -8,85 +8,85 @@ LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    = help: to override `-D warnings` add `#[allow(clippy::map_clone)]`
 
 error: you are using an explicit closure for cloning elements
-  --> tests/ui/map_clone.rs:14:26
+  --> tests/ui/map_clone.rs:15:26
    |
 LL |     let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()`
 
 error: you are using an explicit closure for copying elements
-  --> tests/ui/map_clone.rs:15:23
+  --> tests/ui/map_clone.rs:16:23
    |
 LL |     let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect();
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()`
 
 error: you are using an explicit closure for copying elements
-  --> tests/ui/map_clone.rs:17:26
+  --> tests/ui/map_clone.rs:18:26
    |
 LL |     let _: Option<u64> = Some(&16).map(|b| *b);
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()`
 
 error: you are using an explicit closure for copying elements
-  --> tests/ui/map_clone.rs:18:25
+  --> tests/ui/map_clone.rs:19:25
    |
 LL |     let _: Option<u8> = Some(&1).map(|x| x.clone());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()`
 
 error: you are needlessly cloning iterator elements
-  --> tests/ui/map_clone.rs:29:29
+  --> tests/ui/map_clone.rs:30:29
    |
 LL |     let _ = std::env::args().map(|v| v.clone());
    |                             ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:68:13
+  --> tests/ui/map_clone.rs:69:13
    |
 LL |     let y = x.map(|x| String::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:70:13
+  --> tests/ui/map_clone.rs:71:13
    |
 LL |     let y = x.map(Clone::clone);
    |             ^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:73:13
+  --> tests/ui/map_clone.rs:74:13
    |
 LL |     let y = x.map(String::clone);
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:79:13
+  --> tests/ui/map_clone.rs:80:13
    |
 LL |     let y = x.map(|x| u32::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:82:13
+  --> tests/ui/map_clone.rs:83:13
    |
 LL |     let y = x.map(|x| Clone::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:94:13
+  --> tests/ui/map_clone.rs:95:13
    |
 LL |     let y = x.map(|x| String::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:97:13
+  --> tests/ui/map_clone.rs:98:13
    |
 LL |     let y = x.map(|x| Clone::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:103:13
+  --> tests/ui/map_clone.rs:104:13
    |
 LL |     let y = x.map(|x| u32::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
 
 error: you are explicitly cloning with `.map()`
-  --> tests/ui/map_clone.rs:106:13
+  --> tests/ui/map_clone.rs:107:13
    |
 LL |     let y = x.map(|x| Clone::clone(x));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
diff --git a/src/tools/clippy/tests/ui/match_result_ok.fixed b/src/tools/clippy/tests/ui/match_result_ok.fixed
index 8d7cddc0ad7..76b26f5e438 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.fixed
+++ b/src/tools/clippy/tests/ui/match_result_ok.fixed
@@ -1,6 +1,6 @@
 #![warn(clippy::match_result_ok)]
 #![allow(dead_code)]
-#![allow(clippy::boxed_local, clippy::uninlined_format_args)]
+#![allow(clippy::boxed_local, clippy::uninlined_format_args, clippy::manual_unwrap_or_default)]
 
 // Checking `if` cases
 
diff --git a/src/tools/clippy/tests/ui/match_result_ok.rs b/src/tools/clippy/tests/ui/match_result_ok.rs
index 9a18b813aca..d6f2475ba79 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.rs
+++ b/src/tools/clippy/tests/ui/match_result_ok.rs
@@ -1,6 +1,6 @@
 #![warn(clippy::match_result_ok)]
 #![allow(dead_code)]
-#![allow(clippy::boxed_local, clippy::uninlined_format_args)]
+#![allow(clippy::boxed_local, clippy::uninlined_format_args, clippy::manual_unwrap_or_default)]
 
 // Checking `if` cases
 
diff --git a/src/tools/clippy/tests/ui/missing_doc.rs b/src/tools/clippy/tests/ui/missing_doc.rs
index 9bfad3b96cf..9c936d7fa23 100644
--- a/src/tools/clippy/tests/ui/missing_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_doc.rs
@@ -1,5 +1,6 @@
 //@needs-asm-support
 //@aux-build: proc_macros.rs
+//@aux-build: proc_macro_attr.rs
 
 #![warn(clippy::missing_docs_in_private_items)]
 // When denying at the crate level, be sure to not get random warnings from the
@@ -8,6 +9,8 @@
 //! Some garbage docs for the crate here
 #![doc = "More garbage"]
 
+#[macro_use]
+extern crate proc_macro_attr;
 extern crate proc_macros;
 
 use proc_macros::with_span;
@@ -112,3 +115,12 @@ with_span!(span pub enum FooPm3 { A, B(u32), C { field: u32 }});
 with_span!(span pub fn foo_pm() {});
 with_span!(span pub static FOO_PM: u32 = 0;);
 with_span!(span pub const FOO2_PM: u32 = 0;);
+
+// issue #12197
+// Undocumented field originated inside of spanned proc-macro attribute
+/// Some dox for struct.
+#[rewrite_struct]
+pub struct Test {
+    /// Dox
+    a: u8,
+}
diff --git a/src/tools/clippy/tests/ui/missing_doc.stderr b/src/tools/clippy/tests/ui/missing_doc.stderr
index 7e66e2097e9..ef0f96a5b71 100644
--- a/src/tools/clippy/tests/ui/missing_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_doc.stderr
@@ -1,5 +1,5 @@
 error: missing documentation for a type alias
-  --> tests/ui/missing_doc.rs:16:1
+  --> tests/ui/missing_doc.rs:19:1
    |
 LL | type Typedef = String;
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -8,19 +8,19 @@ LL | type Typedef = String;
    = help: to override `-D warnings` add `#[allow(clippy::missing_docs_in_private_items)]`
 
 error: missing documentation for a module
-  --> tests/ui/missing_doc.rs:19:1
+  --> tests/ui/missing_doc.rs:22:1
    |
 LL | mod module_no_dox {}
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> tests/ui/missing_doc.rs:25:1
+  --> tests/ui/missing_doc.rs:28:1
    |
 LL | fn foo3() {}
    | ^^^^^^^^^^^^
 
 error: missing documentation for an enum
-  --> tests/ui/missing_doc.rs:39:1
+  --> tests/ui/missing_doc.rs:42:1
    |
 LL | / enum Baz {
 LL | |     BazA { a: isize, b: isize },
@@ -29,43 +29,43 @@ LL | | }
    | |_^
 
 error: missing documentation for a variant
-  --> tests/ui/missing_doc.rs:40:5
+  --> tests/ui/missing_doc.rs:43:5
    |
 LL |     BazA { a: isize, b: isize },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> tests/ui/missing_doc.rs:40:12
+  --> tests/ui/missing_doc.rs:43:12
    |
 LL |     BazA { a: isize, b: isize },
    |            ^^^^^^^^
 
 error: missing documentation for a struct field
-  --> tests/ui/missing_doc.rs:40:22
+  --> tests/ui/missing_doc.rs:43:22
    |
 LL |     BazA { a: isize, b: isize },
    |                      ^^^^^^^^
 
 error: missing documentation for a variant
-  --> tests/ui/missing_doc.rs:41:5
+  --> tests/ui/missing_doc.rs:44:5
    |
 LL |     BarB,
    |     ^^^^
 
 error: missing documentation for a constant
-  --> tests/ui/missing_doc.rs:65:1
+  --> tests/ui/missing_doc.rs:68:1
    |
 LL | const FOO: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a static
-  --> tests/ui/missing_doc.rs:74:1
+  --> tests/ui/missing_doc.rs:77:1
    |
 LL | static BAR: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a module
-  --> tests/ui/missing_doc.rs:83:1
+  --> tests/ui/missing_doc.rs:86:1
    |
 LL | / mod internal_impl {
 LL | |     /// dox
@@ -77,13 +77,13 @@ LL | | }
    | |_^
 
 error: missing documentation for a function
-  --> tests/ui/missing_doc.rs:88:5
+  --> tests/ui/missing_doc.rs:91:5
    |
 LL |     fn undocumented3() {}
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> tests/ui/missing_doc.rs:94:9
+  --> tests/ui/missing_doc.rs:97:9
    |
 LL |         fn also_undocumented2() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.rs b/src/tools/clippy/tests/ui/mixed_attributes_style.rs
index ad93e3019fa..4f89aa8a5e5 100644
--- a/src/tools/clippy/tests/ui/mixed_attributes_style.rs
+++ b/src/tools/clippy/tests/ui/mixed_attributes_style.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::mixed_attributes_style)]
+#![allow(clippy::duplicated_attributes)]
 
 #[allow(unused)] //~ ERROR: item has both inner and outer attributes
 fn foo1() {
diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.stderr b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
index d1d5cd3f47f..ed798073cb7 100644
--- a/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
+++ b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
@@ -1,5 +1,5 @@
 error: item has both inner and outer attributes
-  --> tests/ui/mixed_attributes_style.rs:3:1
+  --> tests/ui/mixed_attributes_style.rs:4:1
    |
 LL | / #[allow(unused)]
 LL | | fn foo1() {
@@ -10,7 +10,7 @@ LL | |     #![allow(unused)]
    = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]`
 
 error: item has both inner and outer attributes
-  --> tests/ui/mixed_attributes_style.rs:17:1
+  --> tests/ui/mixed_attributes_style.rs:18:1
    |
 LL | / /// linux
 LL | |
@@ -19,7 +19,7 @@ LL | |     //! windows
    | |_______________^
 
 error: item has both inner and outer attributes
-  --> tests/ui/mixed_attributes_style.rs:32:1
+  --> tests/ui/mixed_attributes_style.rs:33:1
    |
 LL | / #[allow(unused)]
 LL | | mod bar {
diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs
index 288b003405d..4c45bc98026 100644
--- a/src/tools/clippy/tests/ui/mut_mut.rs
+++ b/src/tools/clippy/tests/ui/mut_mut.rs
@@ -1,5 +1,4 @@
 //@aux-build:proc_macros.rs
-//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::mut_mut)]
 #![allow(unused)]
@@ -82,3 +81,8 @@ mod issue9035 {
 
     fn bar(_: &mut impl Display) {}
 }
+
+fn allow_works() {
+    #[allow(clippy::mut_mut)]
+    let _ = &mut &mut 1;
+}
diff --git a/src/tools/clippy/tests/ui/mut_mut.stderr b/src/tools/clippy/tests/ui/mut_mut.stderr
index 73f2410a252..42853fdc008 100644
--- a/src/tools/clippy/tests/ui/mut_mut.stderr
+++ b/src/tools/clippy/tests/ui/mut_mut.stderr
@@ -1,5 +1,5 @@
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:16:11
+  --> tests/ui/mut_mut.rs:15:11
    |
 LL | fn fun(x: &mut &mut u32) -> bool {
    |           ^^^^^^^^^^^^^
@@ -8,13 +8,13 @@ LL | fn fun(x: &mut &mut u32) -> bool {
    = help: to override `-D warnings` add `#[allow(clippy::mut_mut)]`
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:33:17
+  --> tests/ui/mut_mut.rs:32:17
    |
 LL |     let mut x = &mut &mut 1u32;
    |                 ^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:48:25
+  --> tests/ui/mut_mut.rs:47:25
    |
 LL |     let mut z = inline!(&mut $(&mut 3u32));
    |                         ^
@@ -22,37 +22,37 @@ LL |     let mut z = inline!(&mut $(&mut 3u32));
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this expression mutably borrows a mutable reference. Consider reborrowing
-  --> tests/ui/mut_mut.rs:35:21
+  --> tests/ui/mut_mut.rs:34:21
    |
 LL |         let mut y = &mut x;
    |                     ^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:39:32
+  --> tests/ui/mut_mut.rs:38:32
    |
 LL |         let y: &mut &mut u32 = &mut &mut 2;
    |                                ^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:39:16
+  --> tests/ui/mut_mut.rs:38:16
    |
 LL |         let y: &mut &mut u32 = &mut &mut 2;
    |                ^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:44:37
+  --> tests/ui/mut_mut.rs:43:37
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                                     ^^^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:44:16
+  --> tests/ui/mut_mut.rs:43:16
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                ^^^^^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:44:21
+  --> tests/ui/mut_mut.rs:43:21
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                     ^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed b/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed
index 201f8a4c19d..a8176618c1f 100644
--- a/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed
+++ b/src/tools/clippy/tests/ui/needless_bitwise_bool.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::needless_bitwise_bool)]
+#![allow(clippy::const_is_empty)]
 
 fn returns_bool() -> bool {
     true
diff --git a/src/tools/clippy/tests/ui/needless_bitwise_bool.rs b/src/tools/clippy/tests/ui/needless_bitwise_bool.rs
index b0e5014b74b..f190eb2b76e 100644
--- a/src/tools/clippy/tests/ui/needless_bitwise_bool.rs
+++ b/src/tools/clippy/tests/ui/needless_bitwise_bool.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::needless_bitwise_bool)]
+#![allow(clippy::const_is_empty)]
 
 fn returns_bool() -> bool {
     true
diff --git a/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr b/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr
index f29d4492540..9f14646c3e5 100644
--- a/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr
+++ b/src/tools/clippy/tests/ui/needless_bitwise_bool.stderr
@@ -1,5 +1,5 @@
 error: use of bitwise operator instead of lazy operator between booleans
-  --> tests/ui/needless_bitwise_bool.rs:22:8
+  --> tests/ui/needless_bitwise_bool.rs:23:8
    |
 LL |     if y & !x {
    |        ^^^^^^ help: try: `y && !x`
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index f9eb39d4938..2575f2449e1 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -316,4 +316,11 @@ fn test_match_as_stmt() {
     };
 }
 
+fn allow_works() -> i32 {
+    #[allow(clippy::needless_return, clippy::match_single_binding)]
+    match () {
+        () => return 42,
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 4dd2e22ea9f..04f21834d88 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -326,4 +326,11 @@ fn test_match_as_stmt() {
     };
 }
 
+fn allow_works() -> i32 {
+    #[allow(clippy::needless_return, clippy::match_single_binding)]
+    match () {
+        () => return 42,
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/no_effect_replace.rs b/src/tools/clippy/tests/ui/no_effect_replace.rs
index 2a940d87fb9..e4fd5caae2a 100644
--- a/src/tools/clippy/tests/ui/no_effect_replace.rs
+++ b/src/tools/clippy/tests/ui/no_effect_replace.rs
@@ -1,5 +1,3 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![warn(clippy::no_effect_replace)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/no_effect_replace.stderr b/src/tools/clippy/tests/ui/no_effect_replace.stderr
index ad2dcd2cc9b..ded86c5c5b8 100644
--- a/src/tools/clippy/tests/ui/no_effect_replace.stderr
+++ b/src/tools/clippy/tests/ui/no_effect_replace.stderr
@@ -1,5 +1,5 @@
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:6:13
+  --> tests/ui/no_effect_replace.rs:4:13
    |
 LL |     let _ = "12345".replace('1', "1");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,43 +8,43 @@ LL |     let _ = "12345".replace('1', "1");
    = help: to override `-D warnings` add `#[allow(clippy::no_effect_replace)]`
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:9:13
+  --> tests/ui/no_effect_replace.rs:7:13
    |
 LL |     let _ = "12345".replace("12", "12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:11:13
+  --> tests/ui/no_effect_replace.rs:9:13
    |
 LL |     let _ = String::new().replace("12", "12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:14:13
+  --> tests/ui/no_effect_replace.rs:12:13
    |
 LL |     let _ = "12345".replacen('1', "1", 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:16:13
+  --> tests/ui/no_effect_replace.rs:14:13
    |
 LL |     let _ = "12345".replacen("12", "12", 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:18:13
+  --> tests/ui/no_effect_replace.rs:16:13
    |
 LL |     let _ = String::new().replacen("12", "12", 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:25:13
+  --> tests/ui/no_effect_replace.rs:23:13
    |
 LL |     let _ = "hello".replace(&x.f(), &x.f());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:29:13
+  --> tests/ui/no_effect_replace.rs:27:13
    |
 LL |     let _ = "hello".replace(&y(), &y());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index d443334bb05..eeab801b7da 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -3,7 +3,8 @@
     clippy::ref_option_ref,
     clippy::equatable_if_let,
     clippy::let_unit_value,
-    clippy::redundant_locals
+    clippy::redundant_locals,
+    clippy::manual_unwrap_or_default
 )]
 
 fn bad1(string: Option<&str>) -> (bool, &str) {
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 317c35bf842..3e5b96d7c31 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -3,7 +3,8 @@
     clippy::ref_option_ref,
     clippy::equatable_if_let,
     clippy::let_unit_value,
-    clippy::redundant_locals
+    clippy::redundant_locals,
+    clippy::manual_unwrap_or_default
 )]
 
 fn bad1(string: Option<&str>) -> (bool, &str) {
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index a794dca762f..f5359a0c34f 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -1,5 +1,5 @@
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:10:5
+  --> tests/ui/option_if_let_else.rs:11:5
    |
 LL | /     if let Some(x) = string {
 LL | |         (true, x)
@@ -12,19 +12,19 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:28:13
+  --> tests/ui/option_if_let_else.rs:29:13
    |
 LL |     let _ = if let Some(s) = *string { s.len() } else { 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:29:13
+  --> tests/ui/option_if_let_else.rs:30:13
    |
 LL |     let _ = if let Some(s) = &num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:30:13
+  --> tests/ui/option_if_let_else.rs:31:13
    |
 LL |       let _ = if let Some(s) = &mut num {
    |  _____________^
@@ -44,13 +44,13 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:36:13
+  --> tests/ui/option_if_let_else.rs:37:13
    |
 LL |     let _ = if let Some(ref s) = num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:37:13
+  --> tests/ui/option_if_let_else.rs:38:13
    |
 LL |       let _ = if let Some(mut s) = num {
    |  _____________^
@@ -70,7 +70,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:43:13
+  --> tests/ui/option_if_let_else.rs:44:13
    |
 LL |       let _ = if let Some(ref mut s) = num {
    |  _____________^
@@ -90,7 +90,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:52:5
+  --> tests/ui/option_if_let_else.rs:53:5
    |
 LL | /     if let Some(x) = arg {
 LL | |         let y = x * x;
@@ -109,7 +109,7 @@ LL +     })
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:65:13
+  --> tests/ui/option_if_let_else.rs:66:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -121,7 +121,7 @@ LL | |     };
    | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)`
 
 error: use Option::map_or_else instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:74:13
+  --> tests/ui/option_if_let_else.rs:75:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -144,7 +144,7 @@ LL ~     }, |x| x * x * x * x);
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:107:13
+  --> tests/ui/option_if_let_else.rs:108:13
    |
 LL | /             if let Some(idx) = s.find('.') {
 LL | |                 vec![s[..idx].to_string(), s[idx..].to_string()]
@@ -154,7 +154,7 @@ LL | |             }
    | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
 
 error: use Option::map_or_else instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:118:5
+  --> tests/ui/option_if_let_else.rs:119:5
    |
 LL | /     if let Ok(binding) = variable {
 LL | |         println!("Ok {binding}");
@@ -177,13 +177,13 @@ LL +     })
    |
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:142:13
+  --> tests/ui/option_if_let_else.rs:143:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:152:13
+  --> tests/ui/option_if_let_else.rs:153:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -205,13 +205,13 @@ LL ~         });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:180:13
+  --> tests/ui/option_if_let_else.rs:181:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:184:13
+  --> tests/ui/option_if_let_else.rs:185:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -231,7 +231,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:223:13
+  --> tests/ui/option_if_let_else.rs:224:13
    |
 LL |       let _ = match s {
    |  _____________^
@@ -241,7 +241,7 @@ LL | |     };
    | |_____^ help: try: `s.map_or(1, |string| string.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:227:13
+  --> tests/ui/option_if_let_else.rs:228:13
    |
 LL |       let _ = match Some(10) {
    |  _____________^
@@ -251,7 +251,7 @@ LL | |     };
    | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:233:13
+  --> tests/ui/option_if_let_else.rs:234:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -261,7 +261,7 @@ LL | |     };
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:237:13
+  --> tests/ui/option_if_let_else.rs:238:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -271,13 +271,13 @@ LL | |     };
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:241:13
+  --> tests/ui/option_if_let_else.rs:242:13
    |
 LL |     let _ = if let Ok(a) = res { a + 1 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:258:17
+  --> tests/ui/option_if_let_else.rs:259:17
    |
 LL |           let _ = match initial {
    |  _________________^
@@ -287,7 +287,7 @@ LL | |         };
    | |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))`
 
 error: use Option::map_or instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:265:17
+  --> tests/ui/option_if_let_else.rs:266:17
    |
 LL |           let _ = match initial {
    |  _________________^
@@ -297,7 +297,7 @@ LL | |         };
    | |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))`
 
 error: use Option::map_or_else instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:288:24
+  --> tests/ui/option_if_let_else.rs:289:24
    |
 LL |       let mut _hashmap = if let Some(hm) = &opt {
    |  ________________________^
@@ -308,7 +308,7 @@ LL | |     };
    | |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())`
 
 error: use Option::map_or_else instead of an if let/else
-  --> tests/ui/option_if_let_else.rs:294:19
+  --> tests/ui/option_if_let_else.rs:295:19
    |
 LL |     let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() };
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())`
diff --git a/src/tools/clippy/tests/ui/option_option.rs b/src/tools/clippy/tests/ui/option_option.rs
index 2f6e4d76145..42f03aae7bb 100644
--- a/src/tools/clippy/tests/ui/option_option.rs
+++ b/src/tools/clippy/tests/ui/option_option.rs
@@ -1,7 +1,5 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![deny(clippy::option_option)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::unnecessary_wraps, clippy::manual_unwrap_or_default)]
 
 const C: Option<Option<i32>> = None;
 //~^ ERROR: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if
diff --git a/src/tools/clippy/tests/ui/option_option.stderr b/src/tools/clippy/tests/ui/option_option.stderr
index 76cb9ae944c..0cd048e400e 100644
--- a/src/tools/clippy/tests/ui/option_option.stderr
+++ b/src/tools/clippy/tests/ui/option_option.stderr
@@ -1,77 +1,77 @@
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:6:10
+  --> tests/ui/option_option.rs:4:10
    |
 LL | const C: Option<Option<i32>> = None;
    |          ^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> tests/ui/option_option.rs:3:9
+  --> tests/ui/option_option.rs:1:9
    |
 LL | #![deny(clippy::option_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:8:11
+  --> tests/ui/option_option.rs:6:11
    |
 LL | static S: Option<Option<i32>> = None;
    |           ^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:11:13
+  --> tests/ui/option_option.rs:9:13
    |
 LL | fn input(_: Option<Option<u8>>) {}
    |             ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:14:16
+  --> tests/ui/option_option.rs:12:16
    |
 LL | fn output() -> Option<Option<u8>> {
    |                ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:19:27
+  --> tests/ui/option_option.rs:17:27
    |
 LL | fn output_nested() -> Vec<Option<Option<u8>>> {
    |                           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:25:30
+  --> tests/ui/option_option.rs:23:30
    |
 LL | fn output_nested_nested() -> Option<Option<Option<u8>>> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:31:8
+  --> tests/ui/option_option.rs:29:8
    |
 LL |     x: Option<Option<u8>>,
    |        ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:36:23
+  --> tests/ui/option_option.rs:34:23
    |
 LL |     fn struct_fn() -> Option<Option<u8>> {
    |                       ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:43:22
+  --> tests/ui/option_option.rs:41:22
    |
 LL |     fn trait_fn() -> Option<Option<u8>>;
    |                      ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:48:11
+  --> tests/ui/option_option.rs:46:11
    |
 LL |     Tuple(Option<Option<u8>>),
    |           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:50:17
+  --> tests/ui/option_option.rs:48:17
    |
 LL |     Struct { x: Option<Option<u8>> },
    |                 ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:92:14
+  --> tests/ui/option_option.rs:90:14
    |
 LL |         foo: Option<Option<Cow<'a, str>>>,
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/read_zero_byte_vec.rs b/src/tools/clippy/tests/ui/read_zero_byte_vec.rs
index fd5a88a37a6..68acf433469 100644
--- a/src/tools/clippy/tests/ui/read_zero_byte_vec.rs
+++ b/src/tools/clippy/tests/ui/read_zero_byte_vec.rs
@@ -112,4 +112,10 @@ async fn test_tokio<R: TokioAsyncRead + Unpin>(r: &mut R) {
     //~^ ERROR: reading zero byte data to `Vec`
 }
 
+fn allow_works<F: std::io::Read>(mut f: F) {
+    let mut data = Vec::with_capacity(100);
+    #[allow(clippy::read_zero_byte_vec)]
+    f.read(&mut data).unwrap();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_as_str.fixed b/src/tools/clippy/tests/ui/redundant_as_str.fixed
index 4185b402226..708a1cc9150 100644
--- a/src/tools/clippy/tests/ui/redundant_as_str.fixed
+++ b/src/tools/clippy/tests/ui/redundant_as_str.fixed
@@ -1,4 +1,5 @@
 #![warn(clippy::redundant_as_str)]
+#![allow(clippy::const_is_empty)]
 
 fn main() {
     let string = "Hello, world!".to_owned();
diff --git a/src/tools/clippy/tests/ui/redundant_as_str.rs b/src/tools/clippy/tests/ui/redundant_as_str.rs
index 7a74d8a55de..257af591cef 100644
--- a/src/tools/clippy/tests/ui/redundant_as_str.rs
+++ b/src/tools/clippy/tests/ui/redundant_as_str.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::redundant_as_str)]
+#![allow(clippy::const_is_empty)]
 
 fn main() {
     let string = "Hello, world!".to_owned();
diff --git a/src/tools/clippy/tests/ui/redundant_as_str.stderr b/src/tools/clippy/tests/ui/redundant_as_str.stderr
index f086de5fede..f5379d701db 100644
--- a/src/tools/clippy/tests/ui/redundant_as_str.stderr
+++ b/src/tools/clippy/tests/ui/redundant_as_str.stderr
@@ -1,5 +1,5 @@
 error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too
-  --> tests/ui/redundant_as_str.rs:7:29
+  --> tests/ui/redundant_as_str.rs:8:29
    |
 LL |     let _redundant = string.as_str().as_bytes();
    |                             ^^^^^^^^^^^^^^^^^ help: try: `as_bytes`
@@ -8,7 +8,7 @@ LL |     let _redundant = string.as_str().as_bytes();
    = help: to override `-D warnings` add `#[allow(clippy::redundant_as_str)]`
 
 error: this `as_str` is redundant and can be removed as the method immediately following exists on `String` too
-  --> tests/ui/redundant_as_str.rs:8:29
+  --> tests/ui/redundant_as_str.rs:9:29
    |
 LL |     let _redundant = string.as_str().is_empty();
    |                             ^^^^^^^^^^^^^^^^^ help: try: `is_empty`
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index f4ff0f0b88b..24d0f797542 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -2,6 +2,7 @@
 // Use that command to update this file and do not edit by hand.
 // Manual edits will be overwritten.
 
+#![allow(clippy::duplicated_attributes)]
 #![allow(clippy::almost_complete_range)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::blocks_in_conditions)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 0df1098f5fb..be8da2fa1a3 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -2,6 +2,7 @@
 // Use that command to update this file and do not edit by hand.
 // Manual edits will be overwritten.
 
+#![allow(clippy::duplicated_attributes)]
 #![allow(clippy::almost_complete_range)]
 #![allow(clippy::disallowed_names)]
 #![allow(clippy::blocks_in_conditions)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index e6659b109e5..777ac20153d 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> tests/ui/rename.rs:55:9
+  --> tests/ui/rename.rs:56:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,343 +8,343 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> tests/ui/rename.rs:56:9
+  --> tests/ui/rename.rs:57:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:57:9
+  --> tests/ui/rename.rs:58:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:58:9
+  --> tests/ui/rename.rs:59:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
-  --> tests/ui/rename.rs:59:9
+  --> tests/ui/rename.rs:60:9
    |
 LL | #![warn(clippy::blocks_in_if_conditions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> tests/ui/rename.rs:60:9
+  --> tests/ui/rename.rs:61:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> tests/ui/rename.rs:61:9
+  --> tests/ui/rename.rs:62:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> tests/ui/rename.rs:62:9
+  --> tests/ui/rename.rs:63:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> tests/ui/rename.rs:63:9
+  --> tests/ui/rename.rs:64:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> tests/ui/rename.rs:64:9
+  --> tests/ui/rename.rs:65:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> tests/ui/rename.rs:65:9
+  --> tests/ui/rename.rs:66:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> tests/ui/rename.rs:66:9
+  --> tests/ui/rename.rs:67:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> tests/ui/rename.rs:67:9
+  --> tests/ui/rename.rs:68:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> tests/ui/rename.rs:68:9
+  --> tests/ui/rename.rs:69:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
-  --> tests/ui/rename.rs:69:9
+  --> tests/ui/rename.rs:70:9
    |
 LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
 
 error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
-  --> tests/ui/rename.rs:70:9
+  --> tests/ui/rename.rs:71:9
    |
 LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> tests/ui/rename.rs:71:9
+  --> tests/ui/rename.rs:72:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> tests/ui/rename.rs:72:9
+  --> tests/ui/rename.rs:73:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> tests/ui/rename.rs:73:9
+  --> tests/ui/rename.rs:74:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> tests/ui/rename.rs:74:9
+  --> tests/ui/rename.rs:75:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:75:9
+  --> tests/ui/rename.rs:76:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:76:9
+  --> tests/ui/rename.rs:77:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:77:9
+  --> tests/ui/rename.rs:78:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:78:9
+  --> tests/ui/rename.rs:79:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> tests/ui/rename.rs:79:9
+  --> tests/ui/rename.rs:80:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> tests/ui/rename.rs:80:9
+  --> tests/ui/rename.rs:81:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> tests/ui/rename.rs:81:9
+  --> tests/ui/rename.rs:82:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> tests/ui/rename.rs:82:9
+  --> tests/ui/rename.rs:83:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> tests/ui/rename.rs:83:9
+  --> tests/ui/rename.rs:84:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> tests/ui/rename.rs:84:9
+  --> tests/ui/rename.rs:85:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> tests/ui/rename.rs:85:9
+  --> tests/ui/rename.rs:86:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> tests/ui/rename.rs:86:9
+  --> tests/ui/rename.rs:87:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> tests/ui/rename.rs:87:9
+  --> tests/ui/rename.rs:88:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> tests/ui/rename.rs:88:9
+  --> tests/ui/rename.rs:89:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> tests/ui/rename.rs:89:9
+  --> tests/ui/rename.rs:90:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> tests/ui/rename.rs:90:9
+  --> tests/ui/rename.rs:91:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> tests/ui/rename.rs:91:9
+  --> tests/ui/rename.rs:92:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> tests/ui/rename.rs:92:9
+  --> tests/ui/rename.rs:93:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> tests/ui/rename.rs:93:9
+  --> tests/ui/rename.rs:94:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> tests/ui/rename.rs:94:9
+  --> tests/ui/rename.rs:95:9
    |
 LL | #![warn(clippy::fn_null_check)]
    |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:95:9
+  --> tests/ui/rename.rs:96:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:96:9
+  --> tests/ui/rename.rs:97:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> tests/ui/rename.rs:97:9
+  --> tests/ui/rename.rs:98:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> tests/ui/rename.rs:98:9
+  --> tests/ui/rename.rs:99:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> tests/ui/rename.rs:99:9
+  --> tests/ui/rename.rs:100:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> tests/ui/rename.rs:100:9
+  --> tests/ui/rename.rs:101:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> tests/ui/rename.rs:101:9
+  --> tests/ui/rename.rs:102:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> tests/ui/rename.rs:102:9
+  --> tests/ui/rename.rs:103:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> tests/ui/rename.rs:103:9
+  --> tests/ui/rename.rs:104:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> tests/ui/rename.rs:104:9
+  --> tests/ui/rename.rs:105:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> tests/ui/rename.rs:105:9
+  --> tests/ui/rename.rs:106:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> tests/ui/rename.rs:106:9
+  --> tests/ui/rename.rs:107:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> tests/ui/rename.rs:107:9
+  --> tests/ui/rename.rs:108:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> tests/ui/rename.rs:108:9
+  --> tests/ui/rename.rs:109:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> tests/ui/rename.rs:109:9
+  --> tests/ui/rename.rs:110:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> tests/ui/rename.rs:110:9
+  --> tests/ui/rename.rs:111:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> tests/ui/rename.rs:111:9
+  --> tests/ui/rename.rs:112:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
 error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
-  --> tests/ui/rename.rs:112:9
+  --> tests/ui/rename.rs:113:9
    |
 LL | #![warn(clippy::vtable_address_comparisons)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed
index 6df64eb4053..acd70416d8b 100644
--- a/src/tools/clippy/tests/ui/single_match.fixed
+++ b/src/tools/clippy/tests/ui/single_match.fixed
@@ -1,12 +1,11 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![warn(clippy::single_match)]
 #![allow(
     unused,
     clippy::uninlined_format_args,
     clippy::needless_if,
     clippy::redundant_guards,
-    clippy::redundant_pattern_matching
+    clippy::redundant_pattern_matching,
+    clippy::manual_unwrap_or_default
 )]
 fn dummy() {}
 
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index 4f005f4e04f..bde78199810 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -1,12 +1,11 @@
-//@compile-flags: -Zdeduplicate-diagnostics=yes
-
 #![warn(clippy::single_match)]
 #![allow(
     unused,
     clippy::uninlined_format_args,
     clippy::needless_if,
     clippy::redundant_guards,
-    clippy::redundant_pattern_matching
+    clippy::redundant_pattern_matching,
+    clippy::manual_unwrap_or_default
 )]
 fn dummy() {}
 
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index 651d0b4911d..a249c120ee4 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:16:5
+  --> tests/ui/single_match.rs:15:5
    |
 LL | /     match x {
 LL | |         Some(y) => {
@@ -19,7 +19,7 @@ LL ~     };
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:24:5
+  --> tests/ui/single_match.rs:23:5
    |
 LL | /     match x {
 LL | |         // Note the missing block braces.
@@ -31,7 +31,7 @@ LL | |     }
    | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:33:5
+  --> tests/ui/single_match.rs:32:5
    |
 LL | /     match z {
 LL | |         (2..=3, 7..=9) => dummy(),
@@ -40,7 +40,7 @@ LL | |     };
    | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:62:5
+  --> tests/ui/single_match.rs:61:5
    |
 LL | /     match x {
 LL | |         Some(y) => dummy(),
@@ -49,7 +49,7 @@ LL | |     };
    | |_____^ help: try: `if let Some(y) = x { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:67:5
+  --> tests/ui/single_match.rs:66:5
    |
 LL | /     match y {
 LL | |         Ok(y) => dummy(),
@@ -58,7 +58,7 @@ LL | |     };
    | |_____^ help: try: `if let Ok(y) = y { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:74:5
+  --> tests/ui/single_match.rs:73:5
    |
 LL | /     match c {
 LL | |         Cow::Borrowed(..) => dummy(),
@@ -67,7 +67,7 @@ LL | |     };
    | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:95:5
+  --> tests/ui/single_match.rs:94:5
    |
 LL | /     match x {
 LL | |         "test" => println!(),
@@ -76,7 +76,7 @@ LL | |     }
    | |_____^ help: try: `if x == "test" { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:108:5
+  --> tests/ui/single_match.rs:107:5
    |
 LL | /     match x {
 LL | |         Foo::A => println!(),
@@ -85,7 +85,7 @@ LL | |     }
    | |_____^ help: try: `if x == Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:114:5
+  --> tests/ui/single_match.rs:113:5
    |
 LL | /     match x {
 LL | |         FOO_C => println!(),
@@ -94,7 +94,7 @@ LL | |     }
    | |_____^ help: try: `if x == FOO_C { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:119:5
+  --> tests/ui/single_match.rs:118:5
    |
 LL | /     match &&x {
 LL | |         Foo::A => println!(),
@@ -103,7 +103,7 @@ LL | |     }
    | |_____^ help: try: `if x == Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:125:5
+  --> tests/ui/single_match.rs:124:5
    |
 LL | /     match &x {
 LL | |         Foo::A => println!(),
@@ -112,7 +112,7 @@ LL | |     }
    | |_____^ help: try: `if x == &Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:142:5
+  --> tests/ui/single_match.rs:141:5
    |
 LL | /     match x {
 LL | |         Bar::A => println!(),
@@ -121,7 +121,7 @@ LL | |     }
    | |_____^ help: try: `if let Bar::A = x { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:150:5
+  --> tests/ui/single_match.rs:149:5
    |
 LL | /     match x {
 LL | |         None => println!(),
@@ -130,7 +130,7 @@ LL | |     };
    | |_____^ help: try: `if let None = x { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:172:5
+  --> tests/ui/single_match.rs:171:5
    |
 LL | /     match x {
 LL | |         (Some(_), _) => {},
@@ -139,7 +139,7 @@ LL | |     }
    | |_____^ help: try: `if let (Some(_), _) = x {}`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:178:5
+  --> tests/ui/single_match.rs:177:5
    |
 LL | /     match x {
 LL | |         (Some(E::V), _) => todo!(),
@@ -148,7 +148,7 @@ LL | |     }
    | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:184:5
+  --> tests/ui/single_match.rs:183:5
    |
 LL | /     match (Some(42), Some(E::V), Some(42)) {
 LL | |         (.., Some(E::V), _) => {},
@@ -157,7 +157,7 @@ LL | |     }
    | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:256:5
+  --> tests/ui/single_match.rs:255:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -177,7 +177,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:264:5
+  --> tests/ui/single_match.rs:263:5
    |
 LL | /     match bar {
 LL | |         #[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed
index 2970f5485fa..e840adf0fa3 100644
--- a/src/tools/clippy/tests/ui/single_match_else.fixed
+++ b/src/tools/clippy/tests/ui/single_match_else.fixed
@@ -1,5 +1,4 @@
 //@aux-build: proc_macros.rs
-//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index 26974b2a48a..430c4da20f1 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -1,5 +1,4 @@
 //@aux-build: proc_macros.rs
-//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr
index 48c74c0caea..f8f88379d6d 100644
--- a/src/tools/clippy/tests/ui/single_match_else.stderr
+++ b/src/tools/clippy/tests/ui/single_match_else.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:18:13
+  --> tests/ui/single_match_else.rs:17:13
    |
 LL |       let _ = match ExprNode::Butterflies {
    |  _____________^
@@ -22,7 +22,7 @@ LL ~     };
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:83:5
+  --> tests/ui/single_match_else.rs:82:5
    |
 LL | /     match Some(1) {
 LL | |         Some(a) => println!("${:?}", a),
@@ -42,7 +42,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:92:5
+  --> tests/ui/single_match_else.rs:91:5
    |
 LL | /     match Some(1) {
 LL | |         Some(a) => println!("${:?}", a),
@@ -62,7 +62,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:102:5
+  --> tests/ui/single_match_else.rs:101:5
    |
 LL | /     match Result::<i32, Infallible>::Ok(1) {
 LL | |         Ok(a) => println!("${:?}", a),
@@ -82,7 +82,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:111:5
+  --> tests/ui/single_match_else.rs:110:5
    |
 LL | /     match Cow::from("moo") {
 LL | |         Cow::Owned(a) => println!("${:?}", a),
@@ -102,7 +102,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:121:5
+  --> tests/ui/single_match_else.rs:120:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -125,7 +125,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:132:5
+  --> tests/ui/single_match_else.rs:131:5
    |
 LL | /     match bar {
 LL | |         Some(v) => {
@@ -149,7 +149,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:144:5
+  --> tests/ui/single_match_else.rs:143:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -173,7 +173,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:156:5
+  --> tests/ui/single_match_else.rs:155:5
    |
 LL | /     match bar {
 LL | |         #[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
index 0a734a65d29..ec4ae2ea13c 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
@@ -17,7 +17,7 @@ fn std_instead_of_core() {
     use ::core::hash::Hash;
     //~^ ERROR: used import from `std` instead of `core`
     // Don't lint on `env` macro
-    use core::env;
+    use std::env;
 
     // Multiple imports
     use core::fmt::{Debug, Result};
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
index ee42b474a32..8f920511cc5 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
@@ -13,12 +13,6 @@ error: used import from `std` instead of `core`
 LL |     use ::std::hash::Hash;
    |           ^^^ help: consider importing the item from `core`: `core`
 
-error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:20:9
-   |
-LL |     use std::env;
-   |         ^^^ help: consider importing the item from `core`: `core`
-
 error: used import from `std` instead of `core`
   --> tests/ui/std_instead_of_core.rs:23:9
    |
@@ -85,5 +79,5 @@ LL |     use alloc::slice::from_ref;
    = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]`
 
-error: aborting due to 13 previous errors
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.rs b/src/tools/clippy/tests/ui/unconditional_recursion.rs
index 35275e81ded..70b390b00e2 100644
--- a/src/tools/clippy/tests/ui/unconditional_recursion.rs
+++ b/src/tools/clippy/tests/ui/unconditional_recursion.rs
@@ -1,7 +1,11 @@
 //@no-rustfix
 
 #![warn(clippy::unconditional_recursion)]
-#![allow(clippy::partialeq_ne_impl, clippy::default_constructed_unit_structs)]
+#![allow(
+    clippy::partialeq_ne_impl,
+    clippy::default_constructed_unit_structs,
+    clippy::only_used_in_recursion
+)]
 
 enum Foo {
     A,
@@ -350,4 +354,48 @@ mod issue12154 {
     }
 }
 
+// From::from -> Into::into -> From::from
+struct BadFromTy1<'a>(&'a ());
+struct BadIntoTy1<'b>(&'b ());
+impl<'a> From<BadFromTy1<'a>> for BadIntoTy1<'static> {
+    fn from(f: BadFromTy1<'a>) -> Self {
+        f.into()
+    }
+}
+
+// Using UFCS syntax
+struct BadFromTy2<'a>(&'a ());
+struct BadIntoTy2<'b>(&'b ());
+impl<'a> From<BadFromTy2<'a>> for BadIntoTy2<'static> {
+    fn from(f: BadFromTy2<'a>) -> Self {
+        Into::into(f)
+    }
+}
+
+// Different Into impl (<i16 as Into<i32>>), so no infinite recursion
+struct BadFromTy3;
+impl From<BadFromTy3> for i32 {
+    fn from(f: BadFromTy3) -> Self {
+        Into::into(1i16)
+    }
+}
+
+// A conditional return that ends the recursion
+struct BadFromTy4;
+impl From<BadFromTy4> for i32 {
+    fn from(f: BadFromTy4) -> Self {
+        if true {
+            return 42;
+        }
+        f.into()
+    }
+}
+
+// Types differ in refs, don't lint
+impl From<&BadFromTy4> for i32 {
+    fn from(f: &BadFromTy4) -> Self {
+        BadFromTy4.into()
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.stderr b/src/tools/clippy/tests/ui/unconditional_recursion.stderr
index 3fd6c91000e..03c27bd8ed8 100644
--- a/src/tools/clippy/tests/ui/unconditional_recursion.stderr
+++ b/src/tools/clippy/tests/ui/unconditional_recursion.stderr
@@ -1,5 +1,5 @@
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:42:5
+  --> tests/ui/unconditional_recursion.rs:46:5
    |
 LL |     fn ne(&self, other: &Self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -12,7 +12,7 @@ LL |         self.ne(other)
    = help: to override `-D warnings` add `#[allow(unconditional_recursion)]`
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:46:5
+  --> tests/ui/unconditional_recursion.rs:50:5
    |
 LL |     fn eq(&self, other: &Self) -> bool {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -23,7 +23,7 @@ LL |         self.eq(other)
    = help: a `loop` may express intention better if this is on purpose
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:211:5
+  --> tests/ui/unconditional_recursion.rs:215:5
    |
 LL |     fn to_string(&self) -> String {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -34,7 +34,7 @@ LL |         self.to_string()
    = help: a `loop` may express intention better if this is on purpose
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:221:5
+  --> tests/ui/unconditional_recursion.rs:225:5
    |
 LL |     fn to_string(&self) -> String {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -45,7 +45,7 @@ LL |         x.to_string()
    = help: a `loop` may express intention better if this is on purpose
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:232:5
+  --> tests/ui/unconditional_recursion.rs:236:5
    |
 LL |     fn to_string(&self) -> String {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
@@ -56,7 +56,7 @@ LL |         (self as &Self).to_string()
    = help: a `loop` may express intention better if this is on purpose
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:12:5
+  --> tests/ui/unconditional_recursion.rs:16:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
 LL | |
@@ -65,7 +65,7 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:14:9
+  --> tests/ui/unconditional_recursion.rs:18:9
    |
 LL |         self != other
    |         ^^^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL |         self != other
    = help: to override `-D warnings` add `#[allow(clippy::unconditional_recursion)]`
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:16:5
+  --> tests/ui/unconditional_recursion.rs:20:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -82,13 +82,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:18:9
+  --> tests/ui/unconditional_recursion.rs:22:9
    |
 LL |         self == other
    |         ^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:28:5
+  --> tests/ui/unconditional_recursion.rs:32:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
 LL | |         self != &Foo2::B // no error here
@@ -96,13 +96,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:29:9
+  --> tests/ui/unconditional_recursion.rs:33:9
    |
 LL |         self != &Foo2::B // no error here
    |         ^^^^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:31:5
+  --> tests/ui/unconditional_recursion.rs:35:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |         self == &Foo2::B // no error here
@@ -110,13 +110,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:32:9
+  --> tests/ui/unconditional_recursion.rs:36:9
    |
 LL |         self == &Foo2::B // no error here
    |         ^^^^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:42:5
+  --> tests/ui/unconditional_recursion.rs:46:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
 LL | |
@@ -125,27 +125,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:44:9
+  --> tests/ui/unconditional_recursion.rs:48:9
    |
 LL |         self.ne(other)
    |         ^^^^^^^^^^^^^^
 
-error: parameter is only used in recursion
-  --> tests/ui/unconditional_recursion.rs:42:18
-   |
-LL |     fn ne(&self, other: &Self) -> bool {
-   |                  ^^^^^ help: if this is intentional, prefix it with an underscore: `_other`
-   |
-note: parameter used here
-  --> tests/ui/unconditional_recursion.rs:44:17
-   |
-LL |         self.ne(other)
-   |                 ^^^^^
-   = note: `-D clippy::only-used-in-recursion` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::only_used_in_recursion)]`
-
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:46:5
+  --> tests/ui/unconditional_recursion.rs:50:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -154,25 +140,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:48:9
+  --> tests/ui/unconditional_recursion.rs:52:9
    |
 LL |         self.eq(other)
    |         ^^^^^^^^^^^^^^
 
-error: parameter is only used in recursion
-  --> tests/ui/unconditional_recursion.rs:46:18
-   |
-LL |     fn eq(&self, other: &Self) -> bool {
-   |                  ^^^^^ help: if this is intentional, prefix it with an underscore: `_other`
-   |
-note: parameter used here
-  --> tests/ui/unconditional_recursion.rs:48:17
-   |
-LL |         self.eq(other)
-   |                 ^^^^^
-
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:90:5
+  --> tests/ui/unconditional_recursion.rs:94:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
 LL | |
@@ -181,13 +155,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:92:9
+  --> tests/ui/unconditional_recursion.rs:96:9
    |
 LL |         other != self
    |         ^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:94:5
+  --> tests/ui/unconditional_recursion.rs:98:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -196,13 +170,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:96:9
+  --> tests/ui/unconditional_recursion.rs:100:9
    |
 LL |         other == self
    |         ^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:104:5
+  --> tests/ui/unconditional_recursion.rs:108:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
 LL | |
@@ -211,13 +185,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:106:9
+  --> tests/ui/unconditional_recursion.rs:110:9
    |
 LL |         other != other
    |         ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> tests/ui/unconditional_recursion.rs:106:9
+  --> tests/ui/unconditional_recursion.rs:110:9
    |
 LL |         other != other
    |         ^^^^^^^^^^^^^^
@@ -225,7 +199,7 @@ LL |         other != other
    = note: `#[deny(clippy::eq_op)]` on by default
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:108:5
+  --> tests/ui/unconditional_recursion.rs:112:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -234,19 +208,19 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:110:9
+  --> tests/ui/unconditional_recursion.rs:114:9
    |
 LL |         other == other
    |         ^^^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> tests/ui/unconditional_recursion.rs:110:9
+  --> tests/ui/unconditional_recursion.rs:114:9
    |
 LL |         other == other
    |         ^^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:117:5
+  --> tests/ui/unconditional_recursion.rs:121:5
    |
 LL | /     fn ne(&self, _other: &Self) -> bool {
 LL | |
@@ -255,19 +229,19 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:119:9
+  --> tests/ui/unconditional_recursion.rs:123:9
    |
 LL |         self != self
    |         ^^^^^^^^^^^^
 
 error: equal expressions as operands to `!=`
-  --> tests/ui/unconditional_recursion.rs:119:9
+  --> tests/ui/unconditional_recursion.rs:123:9
    |
 LL |         self != self
    |         ^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:121:5
+  --> tests/ui/unconditional_recursion.rs:125:5
    |
 LL | /     fn eq(&self, _other: &Self) -> bool {
 LL | |
@@ -276,19 +250,19 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:123:9
+  --> tests/ui/unconditional_recursion.rs:127:9
    |
 LL |         self == self
    |         ^^^^^^^^^^^^
 
 error: equal expressions as operands to `==`
-  --> tests/ui/unconditional_recursion.rs:123:9
+  --> tests/ui/unconditional_recursion.rs:127:9
    |
 LL |         self == self
    |         ^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:149:13
+  --> tests/ui/unconditional_recursion.rs:153:13
    |
 LL | /             fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -300,7 +274,7 @@ LL |   impl_partial_eq!(S5);
    |   -------------------- in this macro invocation
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:151:17
+  --> tests/ui/unconditional_recursion.rs:155:17
    |
 LL |                 self == other
    |                 ^^^^^^^^^^^^^
@@ -310,7 +284,7 @@ LL | impl_partial_eq!(S5);
    = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:178:5
+  --> tests/ui/unconditional_recursion.rs:182:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -321,13 +295,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:182:9
+  --> tests/ui/unconditional_recursion.rs:186:9
    |
 LL |         mine == theirs
    |         ^^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:247:5
+  --> tests/ui/unconditional_recursion.rs:251:5
    |
 LL | /     fn new() -> Self {
 LL | |
@@ -336,13 +310,13 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:249:9
+  --> tests/ui/unconditional_recursion.rs:253:9
    |
 LL |         Self::default()
    |         ^^^^^^^^^^^^^^^
 
 error: function cannot return without recursing
-  --> tests/ui/unconditional_recursion.rs:286:5
+  --> tests/ui/unconditional_recursion.rs:290:5
    |
 LL | /     fn eq(&self, other: &Self) -> bool {
 LL | |
@@ -353,10 +327,38 @@ LL | |     }
    | |_____^
    |
 note: recursive call site
-  --> tests/ui/unconditional_recursion.rs:290:9
+  --> tests/ui/unconditional_recursion.rs:294:9
    |
 LL |         mine.eq(theirs)
    |         ^^^^^^^^^^^^^^^
 
+error: function cannot return without recursing
+  --> tests/ui/unconditional_recursion.rs:361:5
+   |
+LL | /     fn from(f: BadFromTy1<'a>) -> Self {
+LL | |         f.into()
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> tests/ui/unconditional_recursion.rs:362:9
+   |
+LL |         f.into()
+   |         ^^^^^^^^
+
+error: function cannot return without recursing
+  --> tests/ui/unconditional_recursion.rs:370:5
+   |
+LL | /     fn from(f: BadFromTy2<'a>) -> Self {
+LL | |         Into::into(f)
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> tests/ui/unconditional_recursion.rs:371:9
+   |
+LL |         Into::into(f)
+   |         ^^^^^^^^^^^^^
+
 error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_enumerate_index.fixed b/src/tools/clippy/tests/ui/unused_enumerate_index.fixed
index d079807ab58..cffd02b0acc 100644
--- a/src/tools/clippy/tests/ui/unused_enumerate_index.fixed
+++ b/src/tools/clippy/tests/ui/unused_enumerate_index.fixed
@@ -1,8 +1,12 @@
-#![allow(unused)]
+#![allow(unused, clippy::map_identity)]
 #![warn(clippy::unused_enumerate_index)]
 
 use std::iter::Enumerate;
 
+fn get_enumerate() -> Enumerate<std::vec::IntoIter<i32>> {
+    vec![1].into_iter().enumerate()
+}
+
 fn main() {
     let v = [1, 2, 3];
     for x in v.iter() {
@@ -55,4 +59,48 @@ fn main() {
     for x in dummy {
         println!("{x}");
     }
+
+    let _ = vec![1, 2, 3].into_iter().map(|x| println!("{x}"));
+
+    let p = vec![1, 2, 3].into_iter();
+    p.map(|x| println!("{x}"));
+
+    // This shouldn't trigger the lint. `get_enumerate` may come from an external library on which we
+    // have no control.
+    let p = get_enumerate();
+    p.map(|(_, x)| println!("{x}"));
+
+    // This shouldn't trigger the lint. The `enumerate` call is in a different context.
+    macro_rules! mac {
+        () => {
+            [1].iter().enumerate()
+        };
+    }
+    _ = mac!().map(|(_, v)| v);
+
+    macro_rules! mac2 {
+        () => {
+            [1].iter()
+        };
+    }
+    _ = mac2!().map(|_v| {});
+
+    // This shouldn't trigger the lint because of the `allow`.
+    #[allow(clippy::unused_enumerate_index)]
+    let v = [1].iter().enumerate();
+    v.map(|(_, _x)| {});
+
+    // This should keep the explicit type of `x`.
+    let v = [1, 2, 3].iter().copied();
+    let x = v.map(|x: i32| x).sum::<i32>();
+    assert_eq!(x, 6);
+
+    // This should keep the explicit type of `x`.
+    let v = [1, 2, 3].iter().copied();
+    let x = v.map(|x: i32| x).sum::<i32>();
+    assert_eq!(x, 6);
+
+    let v = [1, 2, 3].iter().copied();
+    let x = v.map(|x| x).sum::<i32>();
+    assert_eq!(x, 6);
 }
diff --git a/src/tools/clippy/tests/ui/unused_enumerate_index.rs b/src/tools/clippy/tests/ui/unused_enumerate_index.rs
index 2d524da7632..f2b5f8b9124 100644
--- a/src/tools/clippy/tests/ui/unused_enumerate_index.rs
+++ b/src/tools/clippy/tests/ui/unused_enumerate_index.rs
@@ -1,8 +1,12 @@
-#![allow(unused)]
+#![allow(unused, clippy::map_identity)]
 #![warn(clippy::unused_enumerate_index)]
 
 use std::iter::Enumerate;
 
+fn get_enumerate() -> Enumerate<std::vec::IntoIter<i32>> {
+    vec![1].into_iter().enumerate()
+}
+
 fn main() {
     let v = [1, 2, 3];
     for (_, x) in v.iter().enumerate() {
@@ -55,4 +59,48 @@ fn main() {
     for (_, x) in dummy.enumerate() {
         println!("{x}");
     }
+
+    let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}"));
+
+    let p = vec![1, 2, 3].into_iter().enumerate();
+    p.map(|(_, x)| println!("{x}"));
+
+    // This shouldn't trigger the lint. `get_enumerate` may come from an external library on which we
+    // have no control.
+    let p = get_enumerate();
+    p.map(|(_, x)| println!("{x}"));
+
+    // This shouldn't trigger the lint. The `enumerate` call is in a different context.
+    macro_rules! mac {
+        () => {
+            [1].iter().enumerate()
+        };
+    }
+    _ = mac!().map(|(_, v)| v);
+
+    macro_rules! mac2 {
+        () => {
+            [1].iter()
+        };
+    }
+    _ = mac2!().enumerate().map(|(_, _v)| {});
+
+    // This shouldn't trigger the lint because of the `allow`.
+    #[allow(clippy::unused_enumerate_index)]
+    let v = [1].iter().enumerate();
+    v.map(|(_, _x)| {});
+
+    // This should keep the explicit type of `x`.
+    let v = [1, 2, 3].iter().copied().enumerate();
+    let x = v.map(|(_, x): (usize, i32)| x).sum::<i32>();
+    assert_eq!(x, 6);
+
+    // This should keep the explicit type of `x`.
+    let v = [1, 2, 3].iter().copied().enumerate();
+    let x = v.map(|(_, x): (_, i32)| x).sum::<i32>();
+    assert_eq!(x, 6);
+
+    let v = [1, 2, 3].iter().copied().enumerate();
+    let x = v.map(|(_, x)| x).sum::<i32>();
+    assert_eq!(x, 6);
 }
diff --git a/src/tools/clippy/tests/ui/unused_enumerate_index.stderr b/src/tools/clippy/tests/ui/unused_enumerate_index.stderr
index 7bd7d29117e..6ec07dcbff0 100644
--- a/src/tools/clippy/tests/ui/unused_enumerate_index.stderr
+++ b/src/tools/clippy/tests/ui/unused_enumerate_index.stderr
@@ -1,5 +1,5 @@
 error: you seem to use `.enumerate()` and immediately discard the index
-  --> tests/ui/unused_enumerate_index.rs:8:19
+  --> tests/ui/unused_enumerate_index.rs:12:19
    |
 LL |     for (_, x) in v.iter().enumerate() {
    |                   ^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     for x in v.iter() {
    |         ~    ~~~~~~~~
 
 error: you seem to use `.enumerate()` and immediately discard the index
-  --> tests/ui/unused_enumerate_index.rs:55:19
+  --> tests/ui/unused_enumerate_index.rs:59:19
    |
 LL |     for (_, x) in dummy.enumerate() {
    |                   ^^^^^^^^^^^^^^^^^
@@ -22,5 +22,77 @@ help: remove the `.enumerate()` call
 LL |     for x in dummy {
    |         ~    ~~~~~
 
-error: aborting due to 2 previous errors
+error: you seem to use `.enumerate()` and immediately discard the index
+  --> tests/ui/unused_enumerate_index.rs:63:39
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}"));
+   |                                       ^^^^^^^^^^^
+   |
+help: remove the `.enumerate()` call
+   |
+LL -     let _ = vec![1, 2, 3].into_iter().enumerate().map(|(_, x)| println!("{x}"));
+LL +     let _ = vec![1, 2, 3].into_iter().map(|x| println!("{x}"));
+   |
+
+error: you seem to use `.enumerate()` and immediately discard the index
+  --> tests/ui/unused_enumerate_index.rs:65:39
+   |
+LL |     let p = vec![1, 2, 3].into_iter().enumerate();
+   |                                       ^^^^^^^^^^^
+   |
+help: remove the `.enumerate()` call
+   |
+LL ~     let p = vec![1, 2, 3].into_iter();
+LL ~     p.map(|x| println!("{x}"));
+   |
+
+error: you seem to use `.enumerate()` and immediately discard the index
+  --> tests/ui/unused_enumerate_index.rs:86:17
+   |
+LL |     _ = mac2!().enumerate().map(|(_, _v)| {});
+   |                 ^^^^^^^^^^^
+   |
+help: remove the `.enumerate()` call
+   |
+LL -     _ = mac2!().enumerate().map(|(_, _v)| {});
+LL +     _ = mac2!().map(|_v| {});
+   |
+
+error: you seem to use `.enumerate()` and immediately discard the index
+  --> tests/ui/unused_enumerate_index.rs:94:39
+   |
+LL |     let v = [1, 2, 3].iter().copied().enumerate();
+   |                                       ^^^^^^^^^^^
+   |
+help: remove the `.enumerate()` call
+   |
+LL ~     let v = [1, 2, 3].iter().copied();
+LL ~     let x = v.map(|x: i32| x).sum::<i32>();
+   |
+
+error: you seem to use `.enumerate()` and immediately discard the index
+  --> tests/ui/unused_enumerate_index.rs:99:39
+   |
+LL |     let v = [1, 2, 3].iter().copied().enumerate();
+   |                                       ^^^^^^^^^^^
+   |
+help: remove the `.enumerate()` call
+   |
+LL ~     let v = [1, 2, 3].iter().copied();
+LL ~     let x = v.map(|x: i32| x).sum::<i32>();
+   |
+
+error: you seem to use `.enumerate()` and immediately discard the index
+  --> tests/ui/unused_enumerate_index.rs:103:39
+   |
+LL |     let v = [1, 2, 3].iter().copied().enumerate();
+   |                                       ^^^^^^^^^^^
+   |
+help: remove the `.enumerate()` call
+   |
+LL ~     let v = [1, 2, 3].iter().copied();
+LL ~     let x = v.map(|x| x).sum::<i32>();
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs
index 7e5a10c911b..f5b200d5ffe 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.rs
+++ b/src/tools/clippy/tests/ui/unused_io_amount.rs
@@ -271,5 +271,10 @@ pub fn wildcards(rdr: &mut dyn std::io::Read) {
         }
     }
 }
+fn allow_works<F: std::io::Read>(mut f: F) {
+    let mut data = Vec::with_capacity(100);
+    #[allow(clippy::unused_io_amount)]
+    f.read(&mut data).unwrap();
+}
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unused_peekable.rs b/src/tools/clippy/tests/ui/unused_peekable.rs
index 131b51e01b6..5865bba4350 100644
--- a/src/tools/clippy/tests/ui/unused_peekable.rs
+++ b/src/tools/clippy/tests/ui/unused_peekable.rs
@@ -174,3 +174,9 @@ fn valid() {
     let mut peekable = std::iter::empty::<u32>().peekable();
     takes_dyn(&mut peekable);
 }
+
+fn allow_works() {
+    #[allow(clippy::unused_peekable)]
+    let iter = [1, 2, 3].iter().peekable();
+    iter;
+}
diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed
index 787dd3ec7e6..6ea7857a238 100644
--- a/src/tools/clippy/tests/ui/use_self.fixed
+++ b/src/tools/clippy/tests/ui/use_self.fixed
@@ -6,7 +6,8 @@
     clippy::should_implement_trait,
     clippy::upper_case_acronyms,
     clippy::from_over_into,
-    clippy::self_named_constructors
+    clippy::self_named_constructors,
+    clippy::needless_lifetimes
 )]
 
 #[macro_use]
@@ -53,6 +54,7 @@ mod better {
 }
 
 mod lifetimes {
+    #[derive(Clone, Copy)]
     struct Foo<'a> {
         foo_str: &'a str,
     }
@@ -68,11 +70,19 @@ mod lifetimes {
             Foo { foo_str: "foo" }
         }
 
-        // FIXME: the lint does not handle lifetimed struct
-        // `Self` should be applicable here
-        fn clone(&self) -> Foo<'a> {
+        fn clone(&self) -> Self {
             Foo { foo_str: self.foo_str }
         }
+
+        // Cannot replace with `Self` because the lifetime is not `'a`.
+        fn eq<'b>(&self, other: Foo<'b>) -> bool {
+            let x: Foo<'_> = other;
+            self.foo_str == other.foo_str
+        }
+
+        fn f(&self) -> Foo<'_> {
+            *self
+        }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs
index 39e182faea6..338cc00e45a 100644
--- a/src/tools/clippy/tests/ui/use_self.rs
+++ b/src/tools/clippy/tests/ui/use_self.rs
@@ -6,7 +6,8 @@
     clippy::should_implement_trait,
     clippy::upper_case_acronyms,
     clippy::from_over_into,
-    clippy::self_named_constructors
+    clippy::self_named_constructors,
+    clippy::needless_lifetimes
 )]
 
 #[macro_use]
@@ -53,6 +54,7 @@ mod better {
 }
 
 mod lifetimes {
+    #[derive(Clone, Copy)]
     struct Foo<'a> {
         foo_str: &'a str,
     }
@@ -68,11 +70,19 @@ mod lifetimes {
             Foo { foo_str: "foo" }
         }
 
-        // FIXME: the lint does not handle lifetimed struct
-        // `Self` should be applicable here
         fn clone(&self) -> Foo<'a> {
             Foo { foo_str: self.foo_str }
         }
+
+        // Cannot replace with `Self` because the lifetime is not `'a`.
+        fn eq<'b>(&self, other: Foo<'b>) -> bool {
+            let x: Foo<'_> = other;
+            self.foo_str == other.foo_str
+        }
+
+        fn f(&self) -> Foo<'_> {
+            *self
+        }
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/use_self.stderr b/src/tools/clippy/tests/ui/use_self.stderr
index 8d045f05ed2..d7aa8410a47 100644
--- a/src/tools/clippy/tests/ui/use_self.stderr
+++ b/src/tools/clippy/tests/ui/use_self.stderr
@@ -1,5 +1,5 @@
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:21:21
+  --> tests/ui/use_self.rs:22:21
    |
 LL |         fn new() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
@@ -8,250 +8,256 @@ LL |         fn new() -> Foo {
    = help: to override `-D warnings` add `#[allow(clippy::use_self)]`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:22:13
+  --> tests/ui/use_self.rs:23:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:24:22
+  --> tests/ui/use_self.rs:25:22
    |
 LL |         fn test() -> Foo {
    |                      ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:25:13
+  --> tests/ui/use_self.rs:26:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:30:25
+  --> tests/ui/use_self.rs:31:25
    |
 LL |         fn default() -> Foo {
    |                         ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:31:13
+  --> tests/ui/use_self.rs:32:13
    |
 LL |             Foo::new()
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:96:24
+  --> tests/ui/use_self.rs:73:28
+   |
+LL |         fn clone(&self) -> Foo<'a> {
+   |                            ^^^^^^^ help: use the applicable keyword: `Self`
+
+error: unnecessary structure name repetition
+  --> tests/ui/use_self.rs:106:24
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                        ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:96:55
+  --> tests/ui/use_self.rs:106:55
    |
 LL |         fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
    |                                                       ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:111:13
+  --> tests/ui/use_self.rs:121:13
    |
 LL |             TS(0)
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:146:29
+  --> tests/ui/use_self.rs:156:29
    |
 LL |                 fn bar() -> Bar {
    |                             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:147:21
+  --> tests/ui/use_self.rs:157:21
    |
 LL |                     Bar { foo: Foo {} }
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:158:21
+  --> tests/ui/use_self.rs:168:21
    |
 LL |         fn baz() -> Foo {
    |                     ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:159:13
+  --> tests/ui/use_self.rs:169:13
    |
 LL |             Foo {}
    |             ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:176:21
+  --> tests/ui/use_self.rs:186:21
    |
 LL |             let _ = Enum::B(42);
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:177:21
+  --> tests/ui/use_self.rs:187:21
    |
 LL |             let _ = Enum::C { field: true };
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:178:21
+  --> tests/ui/use_self.rs:188:21
    |
 LL |             let _ = Enum::A;
    |                     ^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:220:13
+  --> tests/ui/use_self.rs:230:13
    |
 LL |             nested::A::fun_1();
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:221:13
+  --> tests/ui/use_self.rs:231:13
    |
 LL |             nested::A::A;
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:223:13
+  --> tests/ui/use_self.rs:233:13
    |
 LL |             nested::A {};
    |             ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:242:13
+  --> tests/ui/use_self.rs:252:13
    |
 LL |             TestStruct::from_something()
    |             ^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:256:25
+  --> tests/ui/use_self.rs:266:25
    |
 LL |         async fn g() -> S {
    |                         ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:257:13
+  --> tests/ui/use_self.rs:267:13
    |
 LL |             S {}
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:261:16
+  --> tests/ui/use_self.rs:271:16
    |
 LL |             &p[S::A..S::B]
    |                ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:261:22
+  --> tests/ui/use_self.rs:271:22
    |
 LL |             &p[S::A..S::B]
    |                      ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:284:29
+  --> tests/ui/use_self.rs:294:29
    |
 LL |         fn foo(value: T) -> Foo<T> {
    |                             ^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:285:13
+  --> tests/ui/use_self.rs:295:13
    |
 LL |             Foo::<T> { value }
    |             ^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:457:13
+  --> tests/ui/use_self.rs:467:13
    |
 LL |             A::new::<submod::B>(submod::B {})
    |             ^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:494:13
+  --> tests/ui/use_self.rs:504:13
    |
 LL |             S2::new()
    |             ^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:531:17
+  --> tests/ui/use_self.rs:541:17
    |
 LL |                 Foo::Bar => unimplemented!(),
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:532:17
+  --> tests/ui/use_self.rs:542:17
    |
 LL |                 Foo::Baz => unimplemented!(),
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:538:20
+  --> tests/ui/use_self.rs:548:20
    |
 LL |             if let Foo::Bar = self {
    |                    ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:562:17
+  --> tests/ui/use_self.rs:572:17
    |
 LL |                 Something::Num(n) => *n,
    |                 ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:563:17
+  --> tests/ui/use_self.rs:573:17
    |
 LL |                 Something::TupleNums(n, _m) => *n,
    |                 ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:564:17
+  --> tests/ui/use_self.rs:574:17
    |
 LL |                 Something::StructNums { one, two: _ } => *one,
    |                 ^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:570:17
+  --> tests/ui/use_self.rs:580:17
    |
 LL |                 crate::issue8845::Something::Num(n) => *n,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:571:17
+  --> tests/ui/use_self.rs:581:17
    |
 LL |                 crate::issue8845::Something::TupleNums(n, _m) => *n,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:572:17
+  --> tests/ui/use_self.rs:582:17
    |
 LL |                 crate::issue8845::Something::StructNums { one, two: _ } => *one,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:588:17
+  --> tests/ui/use_self.rs:598:17
    |
 LL |             let Foo(x) = self;
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:593:17
+  --> tests/ui/use_self.rs:603:17
    |
 LL |             let crate::issue8845::Foo(x) = self;
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:600:17
+  --> tests/ui/use_self.rs:610:17
    |
 LL |             let Bar { x, .. } = self;
    |                 ^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:605:17
+  --> tests/ui/use_self.rs:615:17
    |
 LL |             let crate::issue8845::Bar { x, .. } = self;
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
 
 error: unnecessary structure name repetition
-  --> tests/ui/use_self.rs:644:17
+  --> tests/ui/use_self.rs:654:17
    |
 LL |                 E::A => {},
    |                 ^ help: use the applicable keyword: `Self`
 
-error: aborting due to 42 previous errors
+error: aborting due to 43 previous errors
 
diff --git a/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed b/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed
new file mode 100644
index 00000000000..6f132521926
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zero_repeat_side_effects.fixed
@@ -0,0 +1,60 @@
+#![warn(clippy::zero_repeat_side_effects)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::useless_vec)]
+#![allow(clippy::needless_late_init)]
+
+fn f() -> i32 {
+    println!("side effect");
+    10
+}
+
+fn main() {
+    const N: usize = 0;
+    const M: usize = 1;
+
+    // should trigger
+
+    // on arrays
+    f(); let a: [i32; 0] = [];
+    f(); let a: [i32; 0] = [];
+    let mut b;
+    f(); b = [] as [i32; 0];
+    f(); b = [] as [i32; 0];
+
+    // on vecs
+    // vecs dont support infering value of consts
+    f(); let c: std::vec::Vec<i32> = vec![];
+    let d;
+    f(); d = vec![] as std::vec::Vec<i32>;
+
+    // for macros
+    println!("side effect"); let e: [(); 0] = [];
+
+    // for nested calls
+    { f() }; let g: [i32; 0] = [];
+
+    // as function param
+    drop({ f(); vec![] as std::vec::Vec<i32> });
+
+    // when singled out/not part of assignment/local
+    { f(); vec![] as std::vec::Vec<i32> };
+    { f(); [] as [i32; 0] };
+    { f(); [] as [i32; 0] };
+
+    // should not trigger
+
+    // on arrays with > 0 repeat
+    let a = [f(); 1];
+    let a = [f(); M];
+    let mut b;
+    b = [f(); 1];
+    b = [f(); M];
+
+    // on vecs with > 0 repeat
+    let c = vec![f(); 1];
+    let d;
+    d = vec![f(); 1];
+
+    // as function param
+    drop(vec![f(); 1]);
+}
diff --git a/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs b/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs
new file mode 100644
index 00000000000..9d9c367375a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zero_repeat_side_effects.rs
@@ -0,0 +1,60 @@
+#![warn(clippy::zero_repeat_side_effects)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::useless_vec)]
+#![allow(clippy::needless_late_init)]
+
+fn f() -> i32 {
+    println!("side effect");
+    10
+}
+
+fn main() {
+    const N: usize = 0;
+    const M: usize = 1;
+
+    // should trigger
+
+    // on arrays
+    let a = [f(); 0];
+    let a = [f(); N];
+    let mut b;
+    b = [f(); 0];
+    b = [f(); N];
+
+    // on vecs
+    // vecs dont support infering value of consts
+    let c = vec![f(); 0];
+    let d;
+    d = vec![f(); 0];
+
+    // for macros
+    let e = [println!("side effect"); 0];
+
+    // for nested calls
+    let g = [{ f() }; 0];
+
+    // as function param
+    drop(vec![f(); 0]);
+
+    // when singled out/not part of assignment/local
+    vec![f(); 0];
+    [f(); 0];
+    [f(); N];
+
+    // should not trigger
+
+    // on arrays with > 0 repeat
+    let a = [f(); 1];
+    let a = [f(); M];
+    let mut b;
+    b = [f(); 1];
+    b = [f(); M];
+
+    // on vecs with > 0 repeat
+    let c = vec![f(); 1];
+    let d;
+    d = vec![f(); 1];
+
+    // as function param
+    drop(vec![f(); 1]);
+}
diff --git a/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr b/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr
new file mode 100644
index 00000000000..afdc6054253
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zero_repeat_side_effects.stderr
@@ -0,0 +1,77 @@
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:18:5
+   |
+LL |     let a = [f(); 0];
+   |     ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];`
+   |
+   = note: `-D clippy::zero-repeat-side-effects` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:19:5
+   |
+LL |     let a = [f(); N];
+   |     ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:21:5
+   |
+LL |     b = [f(); 0];
+   |     ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:22:5
+   |
+LL |     b = [f(); N];
+   |     ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:26:5
+   |
+LL |     let c = vec![f(); 0];
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec<i32> = vec![];`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:28:5
+   |
+LL |     d = vec![f(); 0];
+   |     ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec<i32>`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:31:5
+   |
+LL |     let e = [println!("side effect"); 0];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:34:5
+   |
+LL |     let g = [{ f() }; 0];
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:37:10
+   |
+LL |     drop(vec![f(); 0]);
+   |          ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:40:5
+   |
+LL |     vec![f(); 0];
+   |     ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:41:5
+   |
+LL |     [f(); 0];
+   |     ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
+
+error: function or method calls as the initial value in zero-sized array initializers may cause side effects
+  --> tests/ui/zero_repeat_side_effects.rs:42:5
+   |
+LL |     [f(); N];
+   |     ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
+
+error: aborting due to 12 previous errors
+
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 1a81394af10..d455d967e30 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -19,7 +19,7 @@ new_pr = true
 
 [assign]
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
-users_on_vacation = ["xFrednet"]
+users_on_vacation = []
 
 [assign.owners]
 "/.github" = ["@flip1995"]
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 22927cffd1b..fa24447f699 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -183,9 +183,10 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) {
         }
     });
 
-    // if an excluded file is renamed, it must be removed from this list
+    // if there are any file names remaining, they were moved on the fs.
+    // our data must remain up to date, so it must be removed from issues.txt
     // do this automatically on bless, otherwise issue a tidy error
-    if bless {
+    if bless && !remaining_issue_names.is_empty() {
         let issues_txt_header = r#"
 /*
 ============================================================
diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.rs b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.rs
new file mode 100644
index 00000000000..1768b006622
--- /dev/null
+++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.rs
@@ -0,0 +1,18 @@
+trait Id {
+    type This: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type This = T;
+}
+
+trait Trait {
+    type Assoc: Id<This: Copy>;
+}
+
+// We can't see use the `T::Assoc::This: Copy` bound to prove `T::Assoc: Copy`
+fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc) {
+    (x, x)
+    //~^ ERROR use of moved value
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.stderr b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.stderr
new file mode 100644
index 00000000000..cd0e026905c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid-2.stderr
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/cant-see-copy-bound-from-child-rigid-2.rs:14:9
+   |
+LL | fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc) {
+   |                  - move occurs because `x` has type `<T as Trait>::Assoc`, which does not implement the `Copy` trait
+LL |     (x, x)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs
new file mode 100644
index 00000000000..6b3fd7e898d
--- /dev/null
+++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs
@@ -0,0 +1,18 @@
+trait Id {
+    type This: ?Sized;
+}
+
+trait Trait {
+    type Assoc: Id<This: Copy>;
+}
+
+// We can't see use the `T::Assoc::This: Copy` bound to prove `T::Assoc: Copy`
+fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc)
+where
+    T::Assoc: Id<This = T::Assoc>,
+{
+    (x, x)
+    //~^ ERROR use of moved value
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.stderr b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.stderr
new file mode 100644
index 00000000000..3ed73918de3
--- /dev/null
+++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.stderr
@@ -0,0 +1,14 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/cant-see-copy-bound-from-child-rigid.rs:14:9
+   |
+LL | fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc)
+   |                  - move occurs because `x` has type `<T as Trait>::Assoc`, which does not implement the `Copy` trait
+...
+LL |     (x, x)
+   |      -  ^ value used here after move
+   |      |
+   |      value moved here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/borrowck/ice-mutability-error-slicing-121807.rs b/tests/ui/borrowck/ice-mutability-error-slicing-121807.rs
new file mode 100644
index 00000000000..bbdd895d763
--- /dev/null
+++ b/tests/ui/borrowck/ice-mutability-error-slicing-121807.rs
@@ -0,0 +1,27 @@
+//@ edition:2015
+// test for ICE #121807 begin <= end (12 <= 11) when slicing 'Self::Assoc<'_>'
+// fixed by #122749
+
+trait MemoryUnit { // ERROR: not all trait items implemented, missing: `read_word`
+    extern "C" fn read_word(&mut self) -> u8;
+    extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
+    //~^ WARN anonymous parameters are deprecated and will be removed in the next edition
+    //~^^ WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+    //~^^^ ERROR associated type `Assoc` not found for `Self`
+}
+
+struct ROM {}
+
+impl MemoryUnit for ROM {
+//~^ ERROR not all trait items implemented, missing: `read_word`
+    extern "C" fn read_dword(&'s self) -> u16 {
+    //~^ ERROR use of undeclared lifetime name `'s`
+    //~^^ ERROR method `read_dword` has a `&self` declaration in the impl, but not in the trait
+        let a16 = self.read_word() as u16;
+        let b16 = self.read_word() as u16;
+
+        (b16 << 8) | a16
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr b/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr
new file mode 100644
index 00000000000..3a6b8008fce
--- /dev/null
+++ b/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr
@@ -0,0 +1,53 @@
+error[E0261]: use of undeclared lifetime name `'s`
+  --> $DIR/ice-mutability-error-slicing-121807.rs:17:31
+   |
+LL |     extern "C" fn read_dword(&'s self) -> u16 {
+   |                               ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'s` here
+   |
+LL |     extern "C" fn read_dword<'s>(&'s self) -> u16 {
+   |                             ++++
+help: consider introducing lifetime `'s` here
+   |
+LL | impl<'s> MemoryUnit for ROM {
+   |     ++++
+
+warning: anonymous parameters are deprecated and will be removed in the next edition
+  --> $DIR/ice-mutability-error-slicing-121807.rs:7:30
+   |
+LL |     extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
+   |                              ^^^^^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: Self::Assoc<'_>`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+   = note: `#[warn(anonymous_parameters)]` on by default
+
+error[E0220]: associated type `Assoc` not found for `Self`
+  --> $DIR/ice-mutability-error-slicing-121807.rs:7:36
+   |
+LL |     extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
+   |                                    ^^^^^ associated type `Assoc` not found
+
+error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait
+  --> $DIR/ice-mutability-error-slicing-121807.rs:17:5
+   |
+LL |     extern "C" fn read_dword(Self::Assoc<'_>) -> u16;
+   |     ------------------------------------------------- trait method declared without `&self`
+...
+LL |     extern "C" fn read_dword(&'s self) -> u16 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl
+
+error[E0046]: not all trait items implemented, missing: `read_word`
+  --> $DIR/ice-mutability-error-slicing-121807.rs:15:1
+   |
+LL |     extern "C" fn read_word(&mut self) -> u8;
+   |     ----------------------------------------- `read_word` from trait
+...
+LL | impl MemoryUnit for ROM {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0046, E0185, E0220, E0261.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/const-generics/ice-unexpected-inference-var-122549.rs b/tests/ui/const-generics/ice-unexpected-inference-var-122549.rs
new file mode 100644
index 00000000000..126ea667290
--- /dev/null
+++ b/tests/ui/const-generics/ice-unexpected-inference-var-122549.rs
@@ -0,0 +1,29 @@
+// Regression test for https://github.com/rust-lang/rust/issues/122549
+// was fixed by https://github.com/rust-lang/rust/pull/122749
+
+trait ConstChunksExactTrait<T> {
+    fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'a, T, { N }>;
+    //~^ ERROR undeclared lifetime
+}
+
+impl<T> ConstChunksExactTrait<T> for [T] {}
+//~^ ERROR not all trait items implemented, missing: `const_chunks_exact`
+struct ConstChunksExact<'rem, T: 'a, const N: usize> {}
+//~^ ERROR use of undeclared lifetime name `'a`
+//~^^ ERROR lifetime parameter
+//~^^^ ERROR type parameter
+impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}> {
+//~^ ERROR the const parameter `N` is not constrained by the impl trait, self type, or predicates
+//~^^ ERROR mismatched types
+    type Item = &'a [T; N];
+}
+
+fn main() {
+    let slice = &[1i32, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+    let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].iter();
+
+    for a in slice.const_chunks_exact::<3>() {
+        assert_eq!(a, iter.next().unwrap());
+    }
+}
diff --git a/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr b/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr
new file mode 100644
index 00000000000..afad3388145
--- /dev/null
+++ b/tests/ui/const-generics/ice-unexpected-inference-var-122549.stderr
@@ -0,0 +1,67 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ice-unexpected-inference-var-122549.rs:5:70
+   |
+LL |     fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'a, T, { N }>;
+   |                                                                      ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn const_chunks_exact<'a, const N: usize>(&self) -> ConstChunksExact<'a, T, { N }>;
+   |                           +++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait ConstChunksExactTrait<'a, T> {
+   |                             +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ice-unexpected-inference-var-122549.rs:11:34
+   |
+LL | struct ConstChunksExact<'rem, T: 'a, const N: usize> {}
+   |                         -        ^^ undeclared lifetime
+   |                         |
+   |                         help: consider introducing lifetime `'a` here: `'a,`
+
+error[E0046]: not all trait items implemented, missing: `const_chunks_exact`
+  --> $DIR/ice-unexpected-inference-var-122549.rs:9:1
+   |
+LL |     fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'a, T, { N }>;
+   |     ------------------------------------------------------------------------------- `const_chunks_exact` from trait
+...
+LL | impl<T> ConstChunksExactTrait<T> for [T] {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `const_chunks_exact` in implementation
+
+error[E0392]: lifetime parameter `'rem` is never used
+  --> $DIR/ice-unexpected-inference-var-122549.rs:11:25
+   |
+LL | struct ConstChunksExact<'rem, T: 'a, const N: usize> {}
+   |                         ^^^^ unused lifetime parameter
+   |
+   = help: consider removing `'rem`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/ice-unexpected-inference-var-122549.rs:11:31
+   |
+LL | struct ConstChunksExact<'rem, T: 'a, const N: usize> {}
+   |                               ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/ice-unexpected-inference-var-122549.rs:15:13
+   |
+LL | impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}> {
+   |             ^^^^^^^^^^^^^^ unconstrained const parameter
+   |
+   = note: expressions using a const parameter must map each value to a distinct output value
+   = note: proving the result of expressions other than the parameter are unique is not supported
+
+error[E0308]: mismatched types
+  --> $DIR/ice-unexpected-inference-var-122549.rs:15:66
+   |
+LL | impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}> {
+   |                                                                  ^^ expected `usize`, found `()`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0046, E0207, E0261, E0308, E0392.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/coroutine/gen_block_is_fused_iter.rs b/tests/ui/coroutine/gen_block_is_fused_iter.rs
new file mode 100644
index 00000000000..f3e19a7f54f
--- /dev/null
+++ b/tests/ui/coroutine/gen_block_is_fused_iter.rs
@@ -0,0 +1,21 @@
+//@ revisions: next old
+//@compile-flags: --edition 2024 -Zunstable-options
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+#![feature(gen_blocks)]
+
+use std::iter::FusedIterator;
+
+fn foo() -> impl FusedIterator {
+    gen { yield 42 }
+}
+
+fn bar() -> impl FusedIterator<Item = u16> {
+    gen { yield 42 }
+}
+
+fn baz() -> impl FusedIterator + Iterator<Item = i64> {
+    gen { yield 42 }
+}
+
+fn main() {}
diff --git a/tests/ui/inference/ice-cannot-relate-region-109178.rs b/tests/ui/inference/ice-cannot-relate-region-109178.rs
new file mode 100644
index 00000000000..3282f95a992
--- /dev/null
+++ b/tests/ui/inference/ice-cannot-relate-region-109178.rs
@@ -0,0 +1,14 @@
+// test for ice #109178  cannot relate region: LUB(ReErased, ReError)
+
+#![allow(incomplete_features)]
+#![crate_type = "lib"]
+#![feature(adt_const_params, generic_const_exprs)]
+
+struct Changes<const CHANGES: &[&'static str]>
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+where
+    [(); CHANGES.len()]:, {}
+
+impl<const CHANGES: &[&str]> Changes<CHANGES> where [(); CHANGES.len()]: {}
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//~^^ ERROR `&` without an explicit lifetime name cannot be used here
diff --git a/tests/ui/inference/ice-cannot-relate-region-109178.stderr b/tests/ui/inference/ice-cannot-relate-region-109178.stderr
new file mode 100644
index 00000000000..0ac924452c0
--- /dev/null
+++ b/tests/ui/inference/ice-cannot-relate-region-109178.stderr
@@ -0,0 +1,21 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/ice-cannot-relate-region-109178.rs:7:31
+   |
+LL | struct Changes<const CHANGES: &[&'static str]>
+   |                               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/ice-cannot-relate-region-109178.rs:12:21
+   |
+LL | impl<const CHANGES: &[&str]> Changes<CHANGES> where [(); CHANGES.len()]: {}
+   |                     ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/ice-cannot-relate-region-109178.rs:12:23
+   |
+LL | impl<const CHANGES: &[&str]> Changes<CHANGES> where [(); CHANGES.len()]: {}
+   |                       ^ explicit lifetime name needed here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/tests/ui/inference/ice-ifer-var-leaked-out-of-rollback-122098.rs b/tests/ui/inference/ice-ifer-var-leaked-out-of-rollback-122098.rs
new file mode 100644
index 00000000000..3c2aa176c0f
--- /dev/null
+++ b/tests/ui/inference/ice-ifer-var-leaked-out-of-rollback-122098.rs
@@ -0,0 +1,25 @@
+// test for #122098 ICE snapshot_vec.rs: index out of bounds: the len is 4 but the index is 4
+
+trait LendingIterator {
+    type Item<'q>: 'a;
+    //~^ ERROR use of undeclared lifetime name `'a`
+
+    fn for_each(mut self, mut f: Box<dyn FnMut(Self::Item<'_>) + 'static>) {}
+    //~^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+struct Query<'q> {}
+//~^ ERROR lifetime parameter `'q` is never used
+
+impl<'static> Query<'q> {
+//~^ ERROR invalid lifetime parameter name: `'static`
+//~^^ ERROR use of undeclared lifetime name `'q`
+    pub fn new() -> Self {}
+}
+
+fn data() {
+    LendingIterator::for_each(Query::new(&data), Box::new);
+    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+}
+
+pub fn main() {}
diff --git a/tests/ui/inference/ice-ifer-var-leaked-out-of-rollback-122098.stderr b/tests/ui/inference/ice-ifer-var-leaked-out-of-rollback-122098.stderr
new file mode 100644
index 00000000000..e2ddf474c4a
--- /dev/null
+++ b/tests/ui/inference/ice-ifer-var-leaked-out-of-rollback-122098.stderr
@@ -0,0 +1,72 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:4:20
+   |
+LL |     type Item<'q>: 'a;
+   |                    ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     type Item<'a, 'q>: 'a;
+   |               +++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait LendingIterator<'a> {
+   |                      ++++
+
+error[E0262]: invalid lifetime parameter name: `'static`
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:14:6
+   |
+LL | impl<'static> Query<'q> {
+   |      ^^^^^^^ 'static is a reserved lifetime name
+
+error[E0261]: use of undeclared lifetime name `'q`
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:14:21
+   |
+LL | impl<'static> Query<'q> {
+   |      -              ^^ undeclared lifetime
+   |      |
+   |      help: consider introducing lifetime `'q` here: `'q,`
+
+error[E0392]: lifetime parameter `'q` is never used
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:11:14
+   |
+LL | struct Query<'q> {}
+   |              ^^ unused lifetime parameter
+   |
+   = help: consider removing `'q`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:7:17
+   |
+LL |     fn for_each(mut self, mut f: Box<dyn FnMut(Self::Item<'_>) + 'static>) {}
+   |                 ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: unsized fn params are gated as an unstable feature
+help: consider further restricting `Self`
+   |
+LL |     fn for_each(mut self, mut f: Box<dyn FnMut(Self::Item<'_>) + 'static>) where Self: Sized {}
+   |                                                                            +++++++++++++++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     fn for_each(mut &self, mut f: Box<dyn FnMut(Self::Item<'_>) + 'static>) {}
+   |                     +
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:21:31
+   |
+LL |     LendingIterator::for_each(Query::new(&data), Box::new);
+   |                               ^^^^^^^^^^ -----
+   |                                          |
+   |                                          unexpected argument of type `&fn() {data}`
+   |                                          help: remove the extra argument
+   |
+note: associated function defined here
+  --> $DIR/ice-ifer-var-leaked-out-of-rollback-122098.rs:17:12
+   |
+LL |     pub fn new() -> Self {}
+   |            ^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0061, E0261, E0262, E0277, E0392.
+For more information about an error, try `rustc --explain E0061`.