about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--book/src/lint_configuration.md23
-rw-r--r--clippy_dev/src/fmt.rs1
-rw-r--r--clippy_dev/src/lib.rs6
-rw-r--r--clippy_dev/src/new_lint.rs1
-rw-r--r--clippy_lints/src/casts/unnecessary_cast.rs71
-rw-r--r--clippy_lints/src/declared_lints.rs4
-rw-r--r--clippy_lints/src/derivable_impls.rs39
-rw-r--r--clippy_lints/src/doc.rs11
-rw-r--r--clippy_lints/src/enum_clike.rs2
-rw-r--r--clippy_lints/src/float_literal.rs11
-rw-r--r--clippy_lints/src/floating_point_arithmetic.rs2
-rw-r--r--clippy_lints/src/from_over_into.rs3
-rw-r--r--clippy_lints/src/incorrect_impls.rs124
-rw-r--r--clippy_lints/src/items_after_test_module.rs3
-rw-r--r--clippy_lints/src/lib.rs58
-rw-r--r--clippy_lints/src/lifetimes.rs15
-rw-r--r--clippy_lints/src/matches/match_same_arms.rs29
-rw-r--r--clippy_lints/src/matches/mod.rs8
-rw-r--r--clippy_lints/src/matches/overlapping_arms.rs4
-rw-r--r--clippy_lints/src/matches/single_match.rs24
-rw-r--r--clippy_lints/src/methods/drain_collect.rs85
-rw-r--r--clippy_lints/src/methods/mod.rs41
-rw-r--r--clippy_lints/src/methods/option_map_unwrap_or.rs87
-rw-r--r--clippy_lints/src/methods/unnecessary_fold.rs211
-rw-r--r--clippy_lints/src/minmax.rs8
-rw-r--r--clippy_lints/src/module_style.rs10
-rw-r--r--clippy_lints/src/no_effect.rs47
-rw-r--r--clippy_lints/src/operators/float_cmp.rs2
-rw-r--r--clippy_lints/src/ranges.rs6
-rw-r--r--clippy_lints/src/redundant_clone.rs15
-rw-r--r--clippy_lints/src/redundant_closure_call.rs163
-rw-r--r--clippy_lints/src/single_call_fn.rs133
-rw-r--r--clippy_lints/src/single_range_in_vec_init.rs147
-rw-r--r--clippy_lints/src/undocumented_unsafe_blocks.rs126
-rw-r--r--clippy_lints/src/utils/conf.rs11
-rw-r--r--clippy_utils/src/consts.rs143
-rw-r--r--clippy_utils/src/lib.rs4
-rw-r--r--clippy_utils/src/macros.rs14
-rw-r--r--clippy_utils/src/qualify_min_const_fn.rs7
-rw-r--r--src/main.rs4
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr4
-rw-r--r--tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs18
-rw-r--r--tests/ui-toml/undocumented_unsafe_blocks/clippy.toml2
-rw-r--r--tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs567
-rw-r--r--tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr314
-rw-r--r--tests/ui/arithmetic_side_effects.rs15
-rw-r--r--tests/ui/auxiliary/extern_fake_libc.rs10
-rw-r--r--tests/ui/auxiliary/macro_rules.rs7
-rw-r--r--tests/ui/clone_on_copy_impl.rs2
-rw-r--r--tests/ui/crashes/ice-2774.stderr4
-rw-r--r--tests/ui/crashes/needless_lifetimes_impl_trait.stderr4
-rw-r--r--tests/ui/derivable_impls.fixed21
-rw-r--r--tests/ui/derivable_impls.rs21
-rw-r--r--tests/ui/derive.rs2
-rw-r--r--tests/ui/doc/doc-fixable.fixed1
-rw-r--r--tests/ui/doc/doc-fixable.rs1
-rw-r--r--tests/ui/doc/doc-fixable.stderr32
-rw-r--r--tests/ui/doc/needless_doctest_main.rs20
-rw-r--r--tests/ui/drain_collect.fixed77
-rw-r--r--tests/ui/drain_collect.rs77
-rw-r--r--tests/ui/drain_collect.stderr68
-rw-r--r--tests/ui/excessive_precision.fixed15
-rw-r--r--tests/ui/excessive_precision.rs15
-rw-r--r--tests/ui/excessive_precision.stderr30
-rw-r--r--tests/ui/from_over_into.fixed9
-rw-r--r--tests/ui/from_over_into.rs9
-rw-r--r--tests/ui/from_over_into.stderr18
-rw-r--r--tests/ui/from_over_into_unfixable.rs6
-rw-r--r--tests/ui/incorrect_clone_impl_on_copy_type.fixed97
-rw-r--r--tests/ui/incorrect_clone_impl_on_copy_type.rs107
-rw-r--r--tests/ui/incorrect_clone_impl_on_copy_type.stderr40
-rw-r--r--tests/ui/issue_4266.stderr8
-rw-r--r--tests/ui/iter_with_drain.fixed2
-rw-r--r--tests/ui/iter_with_drain.rs2
-rw-r--r--tests/ui/lossy_float_literal.fixed4
-rw-r--r--tests/ui/lossy_float_literal.rs4
-rw-r--r--tests/ui/lossy_float_literal.stderr22
-rw-r--r--tests/ui/map_unwrap_or.rs29
-rw-r--r--tests/ui/match_same_arms_non_exhaustive.rs58
-rw-r--r--tests/ui/match_same_arms_non_exhaustive.stderr29
-rw-r--r--tests/ui/missing_const_for_fn/cant_be_const.rs9
-rw-r--r--tests/ui/missing_panics_doc.rs78
-rw-r--r--tests/ui/missing_panics_doc.stderr110
-rw-r--r--tests/ui/needless_lifetimes.stderr184
-rw-r--r--tests/ui/no_effect_return.rs81
-rw-r--r--tests/ui/no_effect_return.stderr70
-rw-r--r--tests/ui/redundant_closure_call_fixable.fixed47
-rw-r--r--tests/ui/redundant_closure_call_fixable.rs47
-rw-r--r--tests/ui/redundant_closure_call_fixable.stderr62
-rw-r--r--tests/ui/single_call_fn.rs75
-rw-r--r--tests/ui/single_call_fn.stderr55
-rw-r--r--tests/ui/single_element_loop.fixed2
-rw-r--r--tests/ui/single_element_loop.rs2
-rw-r--r--tests/ui/single_element_loop.stderr14
-rw-r--r--tests/ui/single_match.fixed40
-rw-r--r--tests/ui/single_match.rs40
-rw-r--r--tests/ui/single_range_in_vec_init.rs58
-rw-r--r--tests/ui/single_range_in_vec_init.stderr145
-rw-r--r--tests/ui/to_string_in_format_args_incremental.fixed9
-rw-r--r--tests/ui/to_string_in_format_args_incremental.rs9
-rw-r--r--tests/ui/to_string_in_format_args_incremental.stderr10
-rw-r--r--tests/ui/undocumented_unsafe_blocks.rs22
-rw-r--r--tests/ui/undocumented_unsafe_blocks.stderr26
-rw-r--r--tests/ui/unnecessary_cast.fixed27
-rw-r--r--tests/ui/unnecessary_cast.rs27
-rw-r--r--tests/ui/unnecessary_cast.stderr76
-rw-r--r--tests/ui/unnecessary_fold.fixed24
-rw-r--r--tests/ui/unnecessary_fold.rs24
-rw-r--r--tests/ui/unnecessary_fold.stderr56
-rw-r--r--tests/ui/unnecessary_struct_initialization.fixed2
-rw-r--r--tests/ui/unnecessary_struct_initialization.rs2
-rw-r--r--tests/ui/while_let_on_iterator.fixed1
-rw-r--r--tests/ui/while_let_on_iterator.rs1
-rw-r--r--tests/ui/while_let_on_iterator.stderr52
-rw-r--r--tests/workspace.rs40
-rw-r--r--tests/workspace_test/Cargo.toml2
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml10
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml9
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs2
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs1
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs5
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs1
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs13
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs1
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs1
-rw-r--r--tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs2
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml10
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml9
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs7
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs1
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs3
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs1
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs3
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs1
-rw-r--r--tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs9
-rw-r--r--util/gh-pages/versions.html9
-rwxr-xr-xutil/versions.py25
138 files changed, 4542 insertions, 590 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35b1075ff01..3b58e25c611 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4737,6 +4737,7 @@ Released 2018-09-13
 [`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use
 [`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg
 [`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens
+[`drain_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#drain_collect
 [`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds
 [`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy
 [`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop
@@ -4833,6 +4834,7 @@ Released 2018-09-13
 [`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
 [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
 [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor
+[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type
 [`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice
 [`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
 [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
@@ -5156,6 +5158,7 @@ Released 2018-09-13
 [`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee
 [`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening
 [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
+[`single_call_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn
 [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str
 [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names
 [`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
@@ -5164,6 +5167,7 @@ Released 2018-09-13
 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop
 [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
+[`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_range_in_vec_init
 [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
 [`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
 [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
@@ -5380,4 +5384,6 @@ Released 2018-09-13
 [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception
 [`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
 [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
+[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement
+[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes
 <!-- end autogenerated links to configuration documentation -->
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index 085dff8e63b..6c52563b8ed 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -94,6 +94,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat
 * [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
 * [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
 * [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
+* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn)
 
 
 ## `msrv`
@@ -209,7 +210,7 @@ default configuration of Clippy. By default, any configuration will replace the
 
 Default list:
 
-**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec<String>`)
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec<String>`)
 
 ---
 **Affected lints:**
@@ -695,3 +696,23 @@ Minimum chars an ident can have, anything below or equal to this will be linted.
 * [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
 
 
+## `accept-comment-above-statement`
+Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
+
+**Default Value:** `false` (`bool`)
+
+---
+**Affected lints:**
+* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
+
+
+## `accept-comment-above-attributes`
+Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
+
+**Default Value:** `false` (`bool`)
+
+---
+**Affected lints:**
+* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
+
+
diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs
index 25623144181..ee559d45dd1 100644
--- a/clippy_dev/src/fmt.rs
+++ b/clippy_dev/src/fmt.rs
@@ -35,6 +35,7 @@ struct FmtContext {
 }
 
 // the "main" function of cargo dev fmt
+#[allow(clippy::missing_panics_doc)]
 pub fn run(check: bool, verbose: bool) {
     fn try_run(context: &FmtContext) -> Result<bool, CliError> {
         let mut success = true;
diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs
index 56a269288c0..8aaa029f776 100644
--- a/clippy_dev/src/lib.rs
+++ b/clippy_dev/src/lib.rs
@@ -29,6 +29,10 @@ static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
 static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
 
 /// Returns the path to the `cargo-clippy` binary
+///
+/// # Panics
+///
+/// Panics if the path of current executable could not be retrieved.
 #[must_use]
 pub fn cargo_clippy_path() -> PathBuf {
     let mut path = std::env::current_exe().expect("failed to get current executable name");
@@ -61,6 +65,8 @@ pub fn clippy_project_root() -> PathBuf {
     panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
 }
 
+/// # Panics
+/// Panics if given command result was failed.
 pub fn exit_if_err(status: io::Result<ExitStatus>) {
     match status.expect("failed to run command").code() {
         Some(0) => {},
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index f970a32726b..f0ccdb0fe10 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -36,6 +36,7 @@ impl<T> Context for io::Result<T> {
 /// # Errors
 ///
 /// This function errors out if the files couldn't be created or written to.
+#[allow(clippy::missing_panics_doc)]
 pub fn create(
     pass: &String,
     lint_name: Option<&String>,
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 41055c168fc..71cf2aea0f8 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,15 +1,17 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::numeric_literal::NumericLiteral;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
+use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
 use if_chain::if_chain;
 use rustc_ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::def::Res;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, InferTy, Ty};
+use std::ops::ControlFlow;
 
 use super::UNNECESSARY_CAST;
 
@@ -59,7 +61,7 @@ pub(super) fn check<'tcx>(
         }
     }
 
-    // skip cast of local to type alias
+    // skip cast of local that is a type alias
     if let ExprKind::Cast(inner, ..) = expr.kind
         && let ExprKind::Path(qpath) = inner.kind
         && let QPath::Resolved(None, Path { res, .. }) = qpath
@@ -83,6 +85,11 @@ pub(super) fn check<'tcx>(
         }
     }
 
+    // skip cast of fn call that returns type alias
+    if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) {
+        return false;
+    }
+
     // skip cast to non-primitive type
     if_chain! {
         if let ExprKind::Cast(_, cast_to) = expr.kind;
@@ -223,3 +230,61 @@ fn fp_ty_mantissa_nbits(typ: Ty<'_>) -> u32 {
         _ => 0,
     }
 }
+
+/// Finds whether an `Expr` returns a type alias.
+///
+/// TODO: Maybe we should move this to `clippy_utils` so others won't need to go down this dark,
+/// dark path reimplementing this (or something similar).
+fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx>, cast_from: Ty<'tcx>) -> bool {
+    for_each_expr(expr, |expr| {
+        // Calls are a `Path`, and usage of locals are a `Path`. So, this checks
+        // - call() as i32
+        // - local as i32
+        if let ExprKind::Path(qpath) = expr.kind {
+            let res = cx.qpath_res(&qpath, expr.hir_id);
+            // Function call
+            if let Res::Def(DefKind::Fn, def_id) = res {
+                let Some(snippet) = snippet_opt(cx, cx.tcx.def_span(def_id)) else {
+                    return ControlFlow::Continue(());
+                };
+                // This is the worst part of this entire function. This is the only way I know of to
+                // check whether a function returns a type alias. Sure, you can get the return type
+                // from a function in the current crate as an hir ty, but how do you get it for
+                // external functions?? Simple: It's impossible. So, we check whether a part of the
+                // function's declaration snippet is exactly equal to the `Ty`. That way, we can
+                // see whether it's a type alias.
+                //
+                // Will this work for more complex types? Probably not!
+                if !snippet
+                    .split("->")
+                    .skip(0)
+                    .map(|s| {
+                        s.trim() == cast_from.to_string()
+                            || s.split("where").any(|ty| ty.trim() == cast_from.to_string())
+                    })
+                    .any(|a| a)
+                {
+                    return ControlFlow::Break(());
+                }
+            // Local usage
+            } else if let Res::Local(hir_id) = res
+                && let Some(parent) = get_parent_node(cx.tcx, hir_id)
+                && let Node::Local(l) = parent
+            {
+                if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) {
+                    return ControlFlow::Break::<()>(());
+                }
+
+                if let Some(ty) = l.ty
+                    && let TyKind::Path(qpath) = ty.kind
+                    && is_ty_alias(&qpath)
+                {
+                    return ControlFlow::Break::<()>(());
+                }
+            }
+        }
+
+        ControlFlow::Continue(())
+    })
+    .is_some()
+}
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 62317dc60eb..9c1e1f6702d 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -206,6 +206,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
     crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
     crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
+    crate::incorrect_impls::INCORRECT_CLONE_IMPL_ON_COPY_TYPE_INFO,
     crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO,
     crate::indexing_slicing::INDEXING_SLICING_INFO,
     crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO,
@@ -324,6 +325,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::DRAIN_COLLECT_INFO,
     crate::methods::ERR_EXPECT_INFO,
     crate::methods::EXPECT_FUN_CALL_INFO,
     crate::methods::EXPECT_USED_INFO,
@@ -568,8 +570,10 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::shadow::SHADOW_SAME_INFO,
     crate::shadow::SHADOW_UNRELATED_INFO,
     crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO,
+    crate::single_call_fn::SINGLE_CALL_FN_INFO,
     crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
     crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
+    crate::single_range_in_vec_init::SINGLE_RANGE_IN_VEC_INIT_INFO,
     crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
     crate::size_of_ref::SIZE_OF_REF_INFO,
     crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs
index 8f68f90a2a1..ec0ca50cfec 100644
--- a/clippy_lints/src/derivable_impls.rs
+++ b/clippy_lints/src/derivable_impls.rs
@@ -4,11 +4,13 @@ use clippy_utils::source::indent_of;
 use clippy_utils::{is_default_equivalent, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{
+    self as hir,
     def::{CtorKind, CtorOf, DefKind, Res},
-    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
+    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Adt, AdtDef, SubstsRef};
+use rustc_middle::ty::adjustment::{Adjust, PointerCast};
+use rustc_middle::ty::{self, Adt, AdtDef, SubstsRef, Ty, TypeckResults};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::sym;
 
@@ -75,13 +77,23 @@ fn is_path_self(e: &Expr<'_>) -> bool {
     }
 }
 
+fn contains_trait_object(ty: Ty<'_>) -> bool {
+    match ty.kind() {
+        ty::Ref(_, ty, _) => contains_trait_object(*ty),
+        ty::Adt(def, substs) => def.is_box() && substs[0].as_type().map_or(false, contains_trait_object),
+        ty::Dynamic(..) => true,
+        _ => false,
+    }
+}
+
 fn check_struct<'tcx>(
     cx: &LateContext<'tcx>,
     item: &'tcx Item<'_>,
-    self_ty: &Ty<'_>,
+    self_ty: &hir::Ty<'_>,
     func_expr: &Expr<'_>,
     adt_def: AdtDef<'_>,
     substs: SubstsRef<'_>,
+    typeck_results: &'tcx TypeckResults<'tcx>,
 ) {
     if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
         if let Some(PathSegment { args, .. }) = p.segments.last() {
@@ -96,10 +108,23 @@ fn check_struct<'tcx>(
             }
         }
     }
+
+    // the default() call might unsize coerce to a trait object (e.g. Box<T> to Box<dyn Trait>),
+    // which would not be the same if derived (see #10158).
+    // this closure checks both if the expr is equivalent to a `default()` call and does not
+    // have such coercions.
+    let is_default_without_adjusts = |expr| {
+        is_default_equivalent(cx, expr)
+            && typeck_results.expr_adjustments(expr).iter().all(|adj| {
+                !matches!(adj.kind, Adjust::Pointer(PointerCast::Unsize)
+                    if contains_trait_object(adj.target))
+            })
+    };
+
     let should_emit = match peel_blocks(func_expr).kind {
-        ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
-        ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
-        ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
+        ExprKind::Tup(fields) => fields.iter().all(is_default_without_adjusts),
+        ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(is_default_without_adjusts),
+        ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_without_adjusts(ef.expr)),
         _ => false,
     };
 
@@ -197,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
 
             then {
                 if adt_def.is_struct() {
-                    check_struct(cx, item, self_ty, func_expr, adt_def, substs);
+                    check_struct(cx, item, self_ty, func_expr, adt_def, substs, cx.tcx.typeck_body(*b));
                 } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
                     check_enum(cx, item, func_expr, adt_def);
                 }
diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs
index 384aca7fead..87d88f70752 100644
--- a/clippy_lints/src/doc.rs
+++ b/clippy_lints/src/doc.rs
@@ -571,6 +571,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut in_link = None;
     let mut in_heading = false;
     let mut is_rust = false;
+    let mut no_test = false;
     let mut edition = None;
     let mut ticks_unbalanced = false;
     let mut text_to_check: Vec<(CowStr<'_>, Span)> = Vec::new();
@@ -584,6 +585,8 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                         if item == "ignore" {
                             is_rust = false;
                             break;
+                        } else if item == "no_test" {
+                            no_test = true;
                         }
                         if let Some(stripped) = item.strip_prefix("edition") {
                             is_rust = true;
@@ -648,7 +651,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                 headers.errors |= in_heading && trimmed_text == "Errors";
                 headers.panics |= in_heading && trimmed_text == "Panics";
                 if in_code {
-                    if is_rust {
+                    if is_rust && !no_test {
                         let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
                         check_code(cx, &text, edition, span);
                     }
@@ -906,15 +909,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
             if is_panic(self.cx, macro_call.def_id)
                 || matches!(
                     self.cx.tcx.item_name(macro_call.def_id).as_str(),
-                    "assert" | "assert_eq" | "assert_ne" | "todo"
+                    "assert" | "assert_eq" | "assert_ne"
                 )
             {
                 self.panic_span = Some(macro_call.span);
             }
         }
 
-        // check for `unwrap`
-        if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
+        // check for `unwrap` and `expect` for both `Option` and `Result`
+        if let Some(arglists) = method_chain_args(expr, &["unwrap"]).or(method_chain_args(expr, &["expect"])) {
             let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
             if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
                 || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs
index e275efaba25..d85650712db 100644
--- a/clippy_lints/src/enum_clike.rs
+++ b/clippy_lints/src/enum_clike.rs
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
                         .const_eval_poly(def_id.to_def_id())
                         .ok()
                         .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty));
-                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
+                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
                         if let ty::Adt(adt, _) = ty.kind() {
                             if adt.is_enum() {
                                 ty = adt.repr().discr_type().to_ty(cx.tcx);
diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs
index 93bf50fd5e7..d182bb62195 100644
--- a/clippy_lints/src/float_literal.rs
+++ b/clippy_lints/src/float_literal.rs
@@ -82,19 +82,24 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
                     LitFloatType::Suffixed(ast::FloatTy::F64) => Some("f64"),
                     LitFloatType::Unsuffixed => None
                 };
-                let (is_whole, mut float_str) = match fty {
+                let (is_whole, is_inf, mut float_str) = match fty {
                     FloatTy::F32 => {
                         let value = sym_str.parse::<f32>().unwrap();
 
-                        (value.fract() == 0.0, formatter.format(value))
+                        (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
                     },
                     FloatTy::F64 => {
                         let value = sym_str.parse::<f64>().unwrap();
 
-                        (value.fract() == 0.0, formatter.format(value))
+
+                        (value.fract() == 0.0, value.is_infinite(), formatter.format(value))
                     },
                 };
 
+                if is_inf {
+                    return;
+                }
+
                 if is_whole && !sym_str.contains(|c| c == 'e' || c == 'E') {
                     // Normalize the literal by stripping the fractional portion
                     if sym_str.split('.').next().unwrap() != float_str {
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index 3c55a563af4..5e0fcd74339 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -215,7 +215,7 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
 // ranges [-16777215, 16777216) for type f32 as whole number floats outside
 // this range are lossy and ambiguous.
 #[expect(clippy::cast_possible_truncation)]
-fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
+fn get_integer_from_float_constant(value: &Constant<'_>) -> Option<i32> {
     match value {
         F32(num) if num.fract() == 0.0 => {
             if (-16_777_215.0..16_777_216.0).contains(num) {
diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs
index e25b45eaa2e..92d67ef359d 100644
--- a/clippy_lints/src/from_over_into.rs
+++ b/clippy_lints/src/from_over_into.rs
@@ -134,9 +134,10 @@ impl<'a, 'tcx> Visitor<'tcx> for SelfFinder<'a, 'tcx> {
                 kw::SelfUpper => self.upper.push(segment.ident.span),
                 _ => continue,
             }
+
+            self.invalid |= segment.ident.span.from_expansion();
         }
 
-        self.invalid |= path.span.from_expansion();
         if !self.invalid {
             walk_path(self, path);
         }
diff --git a/clippy_lints/src/incorrect_impls.rs b/clippy_lints/src/incorrect_impls.rs
new file mode 100644
index 00000000000..13cc0b23ba3
--- /dev/null
+++ b/clippy_lints/src/incorrect_impls.rs
@@ -0,0 +1,124 @@
+use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_node, last_path_segment, ty::implements_trait};
+use rustc_errors::Applicability;
+use rustc_hir::{ExprKind, ImplItem, ImplItemKind, ItemKind, Node, UnOp};
+use rustc_hir_analysis::hir_ty_to_ty;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::EarlyBinder;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{sym, symbol};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for manual implementations of `Clone` when `Copy` is already implemented.
+    ///
+    /// ### Why is this bad?
+    /// If both `Clone` and `Copy` are implemented, they must agree. This is done by dereferencing
+    /// `self` in `Clone`'s implementation. Anything else is incorrect.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// #[derive(Eq, PartialEq)]
+    /// struct A(u32);
+    ///
+    /// impl Clone for A {
+    ///     fn clone(&self) -> Self {
+    ///         Self(self.0)
+    ///     }
+    /// }
+    ///
+    /// impl Copy for A {}
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// #[derive(Eq, PartialEq)]
+    /// struct A(u32);
+    ///
+    /// impl Clone for A {
+    ///     fn clone(&self) -> Self {
+    ///         *self
+    ///     }
+    /// }
+    ///
+    /// impl Copy for A {}
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+    correctness,
+    "manual implementation of `Clone` on a `Copy` type"
+}
+declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE]);
+
+impl LateLintPass<'_> for IncorrectImpls {
+    #[expect(clippy::needless_return)]
+    fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
+        let node = get_parent_node(cx.tcx, impl_item.hir_id());
+        let Some(Node::Item(item)) = node else {
+            return;
+        };
+        let ItemKind::Impl(imp) = item.kind else {
+            return;
+        };
+        let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else {
+            return;
+        };
+        let trait_impl_def_id = trait_impl.def_id;
+        if cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) {
+            return;
+        }
+        let ImplItemKind::Fn(_, impl_item_id) = cx.tcx.hir().impl_item(impl_item.impl_item_id()).kind else {
+            return;
+        };
+        let body = cx.tcx.hir().body(impl_item_id);
+        let ExprKind::Block(block, ..) = body.value.kind else {
+            return;
+        };
+        // Above is duplicated from the `duplicate_manual_partial_ord_impl` branch.
+        // Remove it while solving conflicts once that PR is merged.
+
+        // Actual implementation; remove this comment once aforementioned PR is merged
+        if cx.tcx.is_diagnostic_item(sym::Clone, trait_impl_def_id)
+            && let Some(copy_def_id) = cx.tcx.get_diagnostic_item(sym::Copy)
+            && implements_trait(
+                    cx,
+                    hir_ty_to_ty(cx.tcx, imp.self_ty),
+                    copy_def_id,
+                    trait_impl.substs,
+                )
+        {
+            if impl_item.ident.name == sym::clone {
+                if block.stmts.is_empty()
+                    && let Some(expr) = block.expr
+                    && let ExprKind::Unary(UnOp::Deref, inner) = expr.kind
+                    && let ExprKind::Path(qpath) = inner.kind
+                    && last_path_segment(&qpath).ident.name == symbol::kw::SelfLower
+                {} else {
+                    span_lint_and_sugg(
+                        cx,
+                        INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+                        block.span,
+                        "incorrect implementation of `clone` on a `Copy` type",
+                        "change this to",
+                        "{ *self }".to_owned(),
+                        Applicability::MaybeIncorrect,
+                    );
+
+                    return;
+                }
+            }
+
+            if impl_item.ident.name == sym::clone_from {
+                span_lint_and_sugg(
+                    cx,
+                    INCORRECT_CLONE_IMPL_ON_COPY_TYPE,
+                    impl_item.span,
+                    "incorrect implementation of `clone_from` on a `Copy` type",
+                    "remove this",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+
+                return;
+            }
+        }
+    }
+}
diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs
index b992d689aa9..40378ee8205 100644
--- a/clippy_lints/src/items_after_test_module.rs
+++ b/clippy_lints/src/items_after_test_module.rs
@@ -1,4 +1,4 @@
-use clippy_utils::{diagnostics::span_lint_and_help, is_in_cfg_test};
+use clippy_utils::{diagnostics::span_lint_and_help, is_from_proc_macro, is_in_cfg_test};
 use rustc_hir::{HirId, ItemId, ItemKind, Mod};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -59,6 +59,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
             if !matches!(item.kind, ItemKind::Mod(_));
             if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself
             if !in_external_macro(cx.sess(), item.span);
+            if !is_from_proc_macro(cx, item);
 
             then {
                 span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined");
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 243d1fd8606..3fb4e6c8fa5 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -150,6 +150,7 @@ mod implicit_return;
 mod implicit_saturating_add;
 mod implicit_saturating_sub;
 mod inconsistent_struct_constructor;
+mod incorrect_impls;
 mod index_refutable_slice;
 mod indexing_slicing;
 mod infinite_iter;
@@ -286,8 +287,10 @@ mod semicolon_if_nothing_returned;
 mod serde_api;
 mod shadow;
 mod significant_drop_tightening;
+mod single_call_fn;
 mod single_char_lifetime_names;
 mod single_component_path_imports;
+mod single_range_in_vec_init;
 mod size_of_in_element_count;
 mod size_of_ref;
 mod slow_vector_initialization;
@@ -493,26 +496,27 @@ pub(crate) struct LintInfo {
     explanation: &'static str,
 }
 
-pub fn explain(name: &str) {
+pub fn explain(name: &str) -> i32 {
     let target = format!("clippy::{}", name.to_ascii_uppercase());
-    match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
-        Some(info) => {
-            println!("{}", info.explanation);
-            // Check if the lint has configuration
-            let mdconf = get_configuration_metadata();
-            if let Some(config_vec_positions) = mdconf
-                .iter()
-                .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
-            {
-                // If it has, print it
-                println!("### Configuration for {}:\n", info.lint.name_lower());
-                for position in config_vec_positions {
-                    let conf = &mdconf[position];
-                    println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
-                }
+    if let Some(info) = declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
+        println!("{}", info.explanation);
+        // Check if the lint has configuration
+        let mdconf = get_configuration_metadata();
+        if let Some(config_vec_positions) = mdconf
+            .iter()
+            .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
+        {
+            // If it has, print it
+            println!("### Configuration for {}:\n", info.lint.name_lower());
+            for position in config_vec_positions {
+                let conf = &mdconf[position];
+                println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
             }
-        },
-        None => println!("unknown lint: {name}"),
+        }
+        0
+    } else {
+        println!("unknown lint: {name}");
+        1
     }
 }
 
@@ -800,7 +804,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
     store.register_early_pass(|| Box::new(formatting::Formatting));
     store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints));
-    store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
     store.register_late_pass(|_| Box::new(returns::Return));
@@ -926,7 +929,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             enable_raw_pointer_heuristic_for_send,
         ))
     });
-    store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
+    let accept_comment_above_statement = conf.accept_comment_above_statement;
+    let accept_comment_above_attributes = conf.accept_comment_above_attributes;
+    store.register_late_pass(move |_| {
+        Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(
+            accept_comment_above_statement,
+            accept_comment_above_attributes,
+        ))
+    });
     let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args;
     store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined)));
     store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
@@ -1045,6 +1055,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
     let stack_size_threshold = conf.stack_size_threshold;
     store.register_late_pass(move |_| Box::new(large_stack_frames::LargeStackFrames::new(stack_size_threshold)));
+    store.register_late_pass(|_| Box::new(single_range_in_vec_init::SingleRangeInVecInit));
+    store.register_late_pass(|_| Box::new(incorrect_impls::IncorrectImpls));
+    store.register_late_pass(move |_| {
+        Box::new(single_call_fn::SingleCallFn {
+            avoid_breaking_exported_api,
+            def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(),
+        })
+    });
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index 7bc901e4e7f..852f6736585 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
+use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
@@ -201,7 +202,19 @@ fn check_fn_inner<'tcx>(
         span_lint_and_then(
             cx,
             NEEDLESS_LIFETIMES,
-            span.with_hi(sig.decl.output.span().hi()),
+            elidable_lts
+                .iter()
+                .map(|&lt| cx.tcx.def_span(lt))
+                .chain(usages.iter().filter_map(|usage| {
+                    if let LifetimeName::Param(def_id) = usage.res
+                        && elidable_lts.contains(&def_id)
+                    {
+                        return Some(usage.ident.span);
+                    }
+
+                    None
+                }))
+                .collect_vec(),
             &format!("the following explicit lifetimes could be elided: {lts}"),
             |diag| {
                 if sig.header.is_async() {
diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs
index ae8262ace96..3d2fbea63f5 100644
--- a/clippy_lints/src/matches/match_same_arms.rs
+++ b/clippy_lints/src/matches/match_same_arms.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{path_to_local, search_same, SpanlessEq, SpanlessHash};
+use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash};
 use core::cmp::Ordering;
 use core::iter;
 use core::slice;
@@ -9,6 +9,7 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
+use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Symbol;
@@ -103,17 +104,21 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
     let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
     for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) {
         if matches!(arm2.pat.kind, PatKind::Wild) {
-            span_lint_and_then(
-                cx,
-                MATCH_SAME_ARMS,
-                arm1.span,
-                "this match arm has an identical body to the `_` wildcard arm",
-                |diag| {
-                    diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect)
-                        .help("or try changing either arm body")
-                        .span_note(arm2.span, "`_` wildcard arm here");
-                },
-            );
+            if !cx.tcx.features().non_exhaustive_omitted_patterns_lint
+                || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id)
+            {
+                span_lint_and_then(
+                    cx,
+                    MATCH_SAME_ARMS,
+                    arm1.span,
+                    "this match arm has an identical body to the `_` wildcard arm",
+                    |diag| {
+                        diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect)
+                            .help("or try changing either arm body")
+                            .span_note(arm2.span, "`_` wildcard arm here");
+                    },
+                );
+            }
         } else {
             let back_block = backwards_blocking_idxs[j];
             let (keep_arm, move_arm) = if back_block < i || (back_block == 0 && forwards_blocking_idxs[i] <= j) {
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index 2d27be499f9..00fa3eb9bfe 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -38,6 +38,11 @@ declare_clippy_lint! {
     /// Checks for matches with a single arm where an `if let`
     /// will usually suffice.
     ///
+    /// This intentionally does not lint if there are comments
+    /// inside of the other arm, so as to allow the user to document
+    /// why having another explicit pattern with an empty body is necessary,
+    /// or because the comments need to be preserved for other reasons.
+    ///
     /// ### Why is this bad?
     /// Just readability – `if let` nests less than a `match`.
     ///
@@ -559,6 +564,9 @@ declare_clippy_lint! {
     /// ### What it does
     /// Checks for `match` with identical arm bodies.
     ///
+    /// Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is
+    /// enabled and disallowed.
+    ///
     /// ### Why is this bad?
     /// This is probably a copy & paste error. If arm bodies
     /// are the same on purpose, you can factor them
diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs
index abf2525a61c..8be3c178a29 100644
--- a/clippy_lints/src/matches/overlapping_arms.rs
+++ b/clippy_lints/src/matches/overlapping_arms.rs
@@ -41,7 +41,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                                 cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
                                 ty,
                             );
-                            miri_to_const(cx.tcx, min_constant)?
+                            miri_to_const(cx, min_constant)?
                         },
                     };
                     let rhs_const = match rhs {
@@ -52,7 +52,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                                 cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
                                 ty,
                             );
-                            miri_to_const(cx.tcx, max_constant)?
+                            miri_to_const(cx, max_constant)?
                         },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs
index ad47c13896c..35627d6c649 100644
--- a/clippy_lints/src/matches/single_match.rs
+++ b/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{expr_block, snippet};
+use clippy_utils::source::{expr_block, get_source_text, snippet};
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
 use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs};
 use core::cmp::max;
@@ -7,10 +7,26 @@ use rustc_errors::Applicability;
 use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::sym;
+use rustc_span::{sym, Span};
 
 use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
 
+/// Checks if there are comments contained within a span.
+/// This is a very "naive" check, as it just looks for the literal characters // and /* in the
+/// source text. This won't be accurate if there are potentially expressions contained within the
+/// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty
+/// match arms.
+fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
+    if let Some(ff) = get_source_text(cx, span)
+        && let Some(text) = ff.as_str()
+    {
+        text.as_bytes().windows(2)
+            .any(|w| w == b"//" || w == b"/*")
+    } else {
+        false
+    }
+}
+
 #[rustfmt::skip]
 pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
     if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
@@ -25,7 +41,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
             return;
         }
         let els = arms[1].body;
-        let els = if is_unit_expr(peel_blocks(els)) {
+        let els = if is_unit_expr(peel_blocks(els)) && !empty_arm_has_comment(cx, els.span) {
             None
         } else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind {
             if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() {
@@ -35,7 +51,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
             // block with 2+ statements or 1 expr and 1+ statement
             Some(els)
         } else {
-            // not a block, don't lint
+            // not a block or an emtpy block w/ comments, don't lint
             return;
         };
 
diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs
new file mode 100644
index 00000000000..d0c79dc11b0
--- /dev/null
+++ b/clippy_lints/src/methods/drain_collect.rs
@@ -0,0 +1,85 @@
+use crate::methods::DRAIN_COLLECT;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_range_full;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_lang_item;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_hir::ExprKind;
+use rustc_hir::LangItem;
+use rustc_hir::Path;
+use rustc_hir::QPath;
+use rustc_lint::LateContext;
+use rustc_middle::query::Key;
+use rustc_middle::ty;
+use rustc_middle::ty::Ty;
+use rustc_span::sym;
+use rustc_span::Symbol;
+
+/// Checks if both types match the given diagnostic item, e.g.:
+///
+/// `vec![1,2].drain(..).collect::<Vec<_>>()`
+///  ^^^^^^^^^                     ^^^^^^   true
+/// `vec![1,2].drain(..).collect::<HashSet<_>>()`
+///  ^^^^^^^^^                     ^^^^^^^^^^  false
+fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool {
+    if let Some(expr_adt_did) = expr.ty_adt_id()
+        && let Some(recv_adt_did) = recv.ty_adt_id()
+    {
+        cx.tcx.is_diagnostic_item(sym, expr_adt_did) && cx.tcx.is_diagnostic_item(sym, recv_adt_did)
+    } else {
+        false
+    }
+}
+
+/// Checks `std::{vec::Vec, collections::VecDeque}`.
+fn check_vec(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool {
+    (types_match_diagnostic_item(cx, expr, recv, sym::Vec)
+        || types_match_diagnostic_item(cx, expr, recv, sym::VecDeque))
+        && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path)))
+}
+
+/// Checks `std::string::String`
+fn check_string(cx: &LateContext<'_>, args: &[Expr<'_>], expr: Ty<'_>, recv: Ty<'_>, recv_path: &Path<'_>) -> bool {
+    is_type_lang_item(cx, expr, LangItem::String)
+        && is_type_lang_item(cx, recv, LangItem::String)
+        && matches!(args, [arg] if is_range_full(cx, arg, Some(recv_path)))
+}
+
+/// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`.
+fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option<&'static str> {
+    types_match_diagnostic_item(cx, expr, recv, sym::HashSet)
+        .then_some("HashSet")
+        .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::HashMap).then_some("HashMap"))
+        .or_else(|| types_match_diagnostic_item(cx, expr, recv, sym::BinaryHeap).then_some("BinaryHeap"))
+}
+
+pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, recv: &Expr<'_>) {
+    let expr_ty = cx.typeck_results().expr_ty(expr);
+    let recv_ty = cx.typeck_results().expr_ty(recv);
+    let recv_ty_no_refs = recv_ty.peel_refs();
+
+    if let ExprKind::Path(QPath::Resolved(_, recv_path)) = recv.kind
+        && let Some(typename) = check_vec(cx, args, expr_ty, recv_ty_no_refs, recv_path)
+            .then_some("Vec")
+            .or_else(|| check_string(cx, args, expr_ty, recv_ty_no_refs, recv_path).then_some("String"))
+            .or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs))
+    {
+        let recv = snippet(cx, recv.span, "<expr>");
+        let sugg = if let ty::Ref(..) = recv_ty.kind() {
+            format!("std::mem::take({recv})")
+        } else {
+            format!("std::mem::take(&mut {recv})")
+        };
+
+        span_lint_and_sugg(
+            cx,
+            DRAIN_COLLECT,
+            expr.span,
+            &format!("you seem to be trying to move all elements into a new `{typename}`"),
+            "consider using `mem::take`",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 183bd582a48..99c984ba65a 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -14,6 +14,7 @@ mod clone_on_copy;
 mod clone_on_ref_ptr;
 mod cloned_instead_of_copied;
 mod collapsible_str_replace;
+mod drain_collect;
 mod err_expect;
 mod expect_fun_call;
 mod expect_used;
@@ -3247,6 +3248,42 @@ declare_clippy_lint! {
     "manual reverse iteration of `DoubleEndedIterator`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`.
+    ///
+    /// > "Collection" in this context refers to any type with a `drain` method:
+    /// > `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String`
+    ///
+    /// ### Why is this bad?
+    /// Using `mem::take` is faster as it avoids the allocation.
+    /// When using `mem::take`, the old collection is replaced with an empty one and ownership of
+    /// the old collection is returned.
+    ///
+    /// ### Known issues
+    /// `mem::take(&mut vec)` is almost equivalent to `vec.drain(..).collect()`, except that
+    /// it also moves the **capacity**. The user might have explicitly written it this way
+    /// to keep the capacity on the original `Vec`.
+    ///
+    /// ### Example
+    /// ```rust
+    /// fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
+    ///     v.drain(..).collect()
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// use std::mem;
+    /// fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
+    ///     mem::take(v)
+    /// }
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub DRAIN_COLLECT,
+    perf,
+    "calling `.drain(..).collect()` to move all elements into a new collection"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3377,6 +3414,7 @@ impl_lint_pass!(Methods => [
     CLEAR_WITH_DRAIN,
     MANUAL_NEXT_BACK,
     UNNECESSARY_LITERAL_UNWRAP,
+    DRAIN_COLLECT
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3606,6 +3644,9 @@ impl Methods {
                                 manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
                             }
                         },
+                        Some(("drain", recv, args, ..)) => {
+                            drain_collect::check(cx, args, expr, recv);
+                        }
                         _ => {},
                     }
                 },
diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs
index 4c6328481e4..e931c6277f4 100644
--- a/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -4,12 +4,17 @@ use clippy_utils::ty::is_copy;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
+use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::ExprKind;
+use rustc_hir::Node;
+use rustc_hir::PatKind;
+use rustc_hir::QPath;
 use rustc_hir::{self, HirId, Path};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_span::source_map::Span;
-use rustc_span::{sym, Symbol};
+use rustc_span::sym;
 
 use super::MAP_UNWRAP_OR;
 
@@ -26,8 +31,22 @@ pub(super) fn check<'tcx>(
     // lint if the caller of `map()` is an `Option`
     if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) {
         if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) {
-            // Do not lint if the `map` argument uses identifiers in the `map`
-            // argument that are also used in the `unwrap_or` argument
+            // Replacing `.map(<f>).unwrap_or(<a>)` with `.map_or(<a>, <f>)` can sometimes lead to
+            // borrowck errors, see #10579 for one such instance.
+            // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint:
+            // ```
+            // let x = vec![1, 2];
+            // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x);
+            // ```
+            // This compiles, but changing it to `map_or` will produce a compile error:
+            // ```
+            // let x = vec![1, 2];
+            // x.get(0..1).map_or(x, |s| s.to_vec())
+            //                    ^ moving `x` here
+            // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure)
+            // ```
+            // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!)
+            // before the call to `unwrap_or`.
 
             let mut unwrap_visitor = UnwrapVisitor {
                 cx,
@@ -35,14 +54,18 @@ pub(super) fn check<'tcx>(
             };
             unwrap_visitor.visit_expr(unwrap_arg);
 
-            let mut map_expr_visitor = MapExprVisitor {
+            let mut reference_visitor = ReferenceVisitor {
                 cx,
                 identifiers: unwrap_visitor.identifiers,
-                found_identifier: false,
+                found_reference: false,
+                unwrap_or_span: unwrap_arg.span,
             };
-            map_expr_visitor.visit_expr(map_arg);
 
-            if map_expr_visitor.found_identifier {
+            let map = cx.tcx.hir();
+            let body = map.body(map.body_owned_by(map.enclosing_body_owner(expr.hir_id)));
+            reference_visitor.visit_body(body);
+
+            if reference_visitor.found_reference {
                 return;
             }
         }
@@ -91,14 +114,19 @@ pub(super) fn check<'tcx>(
 
 struct UnwrapVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    identifiers: FxHashSet<Symbol>,
+    identifiers: FxHashSet<HirId>,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::All;
 
-    fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
-        self.identifiers.insert(ident(path));
+    fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) {
+        if let Res::Local(local_id) = path.res
+            && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id)
+            && let PatKind::Binding(_, local_id, ..) = pat.kind
+        {
+            self.identifiers.insert(local_id);
+        }
         walk_path(self, path);
     }
 
@@ -107,32 +135,35 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
     }
 }
 
-struct MapExprVisitor<'a, 'tcx> {
+struct ReferenceVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
-    identifiers: FxHashSet<Symbol>,
-    found_identifier: bool,
+    identifiers: FxHashSet<HirId>,
+    found_reference: bool,
+    unwrap_or_span: Span,
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for MapExprVisitor<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> {
     type NestedFilter = nested_filter::All;
-
-    fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
-        if self.identifiers.contains(&ident(path)) {
-            self.found_identifier = true;
-            return;
+    fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) {
+        // If we haven't found a reference yet, check if this references
+        // one of the locals that was moved in the `unwrap_or` argument.
+        // We are only interested in exprs that appear before the `unwrap_or` call.
+        if !self.found_reference {
+            if expr.span < self.unwrap_or_span
+                && let ExprKind::Path(ref path) = expr.kind
+                && let QPath::Resolved(_, path) = path
+                && let Res::Local(local_id) = path.res
+                && let Some(Node::Pat(pat)) = self.cx.tcx.hir().find(local_id)
+                && let PatKind::Binding(_, local_id, ..) = pat.kind
+                && self.identifiers.contains(&local_id)
+            {
+                self.found_reference = true;
+            }
+            rustc_hir::intravisit::walk_expr(self, expr);
         }
-        walk_path(self, path);
     }
 
     fn nested_visit_map(&mut self) -> Self::Map {
         self.cx.tcx.hir()
     }
 }
-
-fn ident(path: &Path<'_>) -> Symbol {
-    path.segments
-        .last()
-        .expect("segments should be composed of at least 1 element")
-        .ident
-        .name
-}
diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs
index 5a3d12fd790..8ec15a1c1b7 100644
--- a/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/clippy_lints/src/methods/unnecessary_fold.rs
@@ -7,71 +7,120 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::PatKind;
 use rustc_lint::LateContext;
+use rustc_middle::ty;
 use rustc_span::{source_map::Span, sym};
 
 use super::UNNECESSARY_FOLD;
 
-pub(super) fn check(
+/// Do we need to suggest turbofish when suggesting a replacement method?
+/// Changing `fold` to `sum` needs it sometimes when the return type can't be
+/// inferred. This checks for some common cases where it can be safely omitted
+fn needs_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+    let parent = cx.tcx.hir().get_parent(expr.hir_id);
+
+    // some common cases where turbofish isn't needed:
+    // - assigned to a local variable with a type annotation
+    if let hir::Node::Local(local) = parent
+        && local.ty.is_some()
+    {
+        return false;
+    }
+
+    // - part of a function call argument, can be inferred from the function signature (provided that
+    //   the parameter is not a generic type parameter)
+    if let hir::Node::Expr(parent_expr) = parent
+        && let hir::ExprKind::Call(recv, args) = parent_expr.kind
+        && let hir::ExprKind::Path(ref qpath) = recv.kind
+        && let Some(fn_def_id) = cx.qpath_res(qpath, recv.hir_id).opt_def_id()
+        && let fn_sig = cx.tcx.fn_sig(fn_def_id).skip_binder().skip_binder()
+        && let Some(arg_pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
+        && let Some(ty) = fn_sig.inputs().get(arg_pos)
+        && !matches!(ty.kind(), ty::Param(_))
+    {
+        return false;
+    }
+
+    // if it's neither of those, stay on the safe side and suggest turbofish,
+    // even if it could work!
+    true
+}
+
+#[derive(Copy, Clone)]
+struct Replacement {
+    method_name: &'static str,
+    has_args: bool,
+    has_generic_return: bool,
+}
+
+fn check_fold_with_op(
     cx: &LateContext<'_>,
     expr: &hir::Expr<'_>,
-    init: &hir::Expr<'_>,
     acc: &hir::Expr<'_>,
     fold_span: Span,
+    op: hir::BinOpKind,
+    replacement: Replacement,
 ) {
-    fn check_fold_with_op(
-        cx: &LateContext<'_>,
-        expr: &hir::Expr<'_>,
-        acc: &hir::Expr<'_>,
-        fold_span: Span,
-        op: hir::BinOpKind,
-        replacement_method_name: &str,
-        replacement_has_args: bool,
-    ) {
-        if_chain! {
-            // Extract the body of the closure passed to fold
-            if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind;
-            let closure_body = cx.tcx.hir().body(body);
-            let closure_expr = peel_blocks(closure_body.value);
-
-            // Check if the closure body is of the form `acc <op> some_expr(x)`
-            if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind;
-            if bin_op.node == op;
-
-            // Extract the names of the two arguments to the closure
-            if let [param_a, param_b] = closure_body.params;
-            if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind;
-            if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind;
-
-            if path_to_local_id(left_expr, first_arg_id);
-            if replacement_has_args || path_to_local_id(right_expr, second_arg_id);
-
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let sugg = if replacement_has_args {
-                    format!(
-                        "{replacement_method_name}(|{second_arg_ident}| {r})",
-                        r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
-                    )
-                } else {
-                    format!(
-                        "{replacement_method_name}()",
-                    )
-                };
-
-                span_lint_and_sugg(
-                    cx,
-                    UNNECESSARY_FOLD,
-                    fold_span.with_hi(expr.span.hi()),
-                    // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
-                    "this `.fold` can be written more succinctly using another method",
-                    "try",
-                    sugg,
-                    applicability,
-                );
-            }
+    if_chain! {
+        // Extract the body of the closure passed to fold
+        if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind;
+        let closure_body = cx.tcx.hir().body(body);
+        let closure_expr = peel_blocks(closure_body.value);
+
+        // Check if the closure body is of the form `acc <op> some_expr(x)`
+        if let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind;
+        if bin_op.node == op;
+
+        // Extract the names of the two arguments to the closure
+        if let [param_a, param_b] = closure_body.params;
+        if let PatKind::Binding(_, first_arg_id, ..) = strip_pat_refs(param_a.pat).kind;
+        if let PatKind::Binding(_, second_arg_id, second_arg_ident, _) = strip_pat_refs(param_b.pat).kind;
+
+        if path_to_local_id(left_expr, first_arg_id);
+        if replacement.has_args || path_to_local_id(right_expr, second_arg_id);
+
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+
+            let turbofish = if replacement.has_generic_return {
+                format!("::<{}>", cx.typeck_results().expr_ty_adjusted(right_expr).peel_refs())
+            } else {
+                String::new()
+            };
+
+            let sugg = if replacement.has_args {
+                format!(
+                    "{method}{turbofish}(|{second_arg_ident}| {r})",
+                    method = replacement.method_name,
+                    r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
+                )
+            } else {
+                format!(
+                    "{method}{turbofish}()",
+                    method = replacement.method_name,
+                )
+            };
+
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_FOLD,
+                fold_span.with_hi(expr.span.hi()),
+                // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f)
+                "this `.fold` can be written more succinctly using another method",
+                "try",
+                sugg,
+                applicability,
+            );
         }
     }
+}
 
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    init: &hir::Expr<'_>,
+    acc: &hir::Expr<'_>,
+    fold_span: Span,
+) {
     // Check that this is a call to Iterator::fold rather than just some function called fold
     if !is_trait_method(cx, expr, sym::Iterator) {
         return;
@@ -80,11 +129,59 @@ pub(super) fn check(
     // Check if the first argument to .fold is a suitable literal
     if let hir::ExprKind::Lit(lit) = init.kind {
         match lit.node {
-            ast::LitKind::Bool(false) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, "any", true),
-            ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true),
-            ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false),
+            ast::LitKind::Bool(false) => {
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Or,
+                    Replacement {
+                        has_args: true,
+                        has_generic_return: false,
+                        method_name: "any",
+                    },
+                );
+            },
+            ast::LitKind::Bool(true) => {
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::And,
+                    Replacement {
+                        has_args: true,
+                        has_generic_return: false,
+                        method_name: "all",
+                    },
+                );
+            },
+            ast::LitKind::Int(0, _) => check_fold_with_op(
+                cx,
+                expr,
+                acc,
+                fold_span,
+                hir::BinOpKind::Add,
+                Replacement {
+                    has_args: false,
+                    has_generic_return: needs_turbofish(cx, expr),
+                    method_name: "sum",
+                },
+            ),
             ast::LitKind::Int(1, _) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false);
+                check_fold_with_op(
+                    cx,
+                    expr,
+                    acc,
+                    fold_span,
+                    hir::BinOpKind::Mul,
+                    Replacement {
+                        has_args: false,
+                        has_generic_return: needs_turbofish(cx, expr),
+                        method_name: "product",
+                    },
+                );
             },
             _ => (),
         }
diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs
index 4f967755bfa..e0904f17b8d 100644
--- a/clippy_lints/src/minmax.rs
+++ b/clippy_lints/src/minmax.rs
@@ -66,7 +66,7 @@ enum MinMax {
     Max,
 }
 
-fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
+fn min_max<'a, 'tcx>(cx: &LateContext<'tcx>, expr: &'a Expr<'a>) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> {
     match expr.kind {
         ExprKind::Call(path, args) => {
             if let ExprKind::Path(ref qpath) = path.kind {
@@ -99,12 +99,12 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
     }
 }
 
-fn fetch_const<'a>(
-    cx: &LateContext<'_>,
+fn fetch_const<'a, 'tcx>(
+    cx: &LateContext<'tcx>,
     receiver: Option<&'a Expr<'a>>,
     args: &'a [Expr<'a>],
     m: MinMax,
-) -> Option<(MinMax, Constant, &'a Expr<'a>)> {
+) -> Option<(MinMax, Constant<'tcx>, &'a Expr<'a>)> {
     let mut args = receiver.into_iter().chain(args);
     let first_arg = args.next()?;
     let second_arg = args.next()?;
diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs
index 349fcd2274d..439cae812b7 100644
--- a/clippy_lints/src/module_style.rs
+++ b/clippy_lints/src/module_style.rs
@@ -2,6 +2,7 @@ use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::{FileName, SourceFile, Span, SyntaxContext};
 use std::ffi::OsStr;
 use std::path::{Component, Path};
@@ -90,7 +91,14 @@ impl EarlyLintPass for ModStyle {
         // `{ foo => path/to/foo.rs, .. }
         let mut file_map = FxHashMap::default();
         for file in files.iter() {
-            if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() {
+            if let FileName::Real(name) = &file.name
+                && let Some(lp) = name.local_path()
+                && file.cnum == LOCAL_CRATE
+            {
+                // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887)
+                // Only check files in the current crate.
+                // Fix false positive that crate dependency in workspace sub directory
+                // is checked unintentionally.
                 let path = if lp.is_relative() {
                     lp
                 } else if let Ok(relative) = lp.strip_prefix(trim_to_src) {
diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs
index e3712190e67..a4c7da7e48d 100644
--- a/clippy_lints/src/no_effect.rs
+++ b/clippy_lints/src/no_effect.rs
@@ -1,11 +1,16 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
-use clippy_utils::is_lint_allowed;
 use clippy_utils::peel_blocks;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::has_drop;
+use clippy_utils::{get_parent_node, is_lint_allowed};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, PatKind, Stmt, StmtKind, UnsafeSource};
+use rustc_hir::{
+    is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, FnRetTy, ItemKind, Node, PatKind, Stmt, StmtKind,
+    UnsafeSource,
+};
+use rustc_hir_analysis::hir_ty_to_ty;
+use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -86,7 +91,43 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
 fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
     if let StmtKind::Semi(expr) = stmt.kind {
         if has_no_effect(cx, expr) {
-            span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect");
+            span_lint_hir_and_then(
+                cx,
+                NO_EFFECT,
+                expr.hir_id,
+                stmt.span,
+                "statement with no effect",
+                |diag| {
+                    for parent in cx.tcx.hir().parent_iter(stmt.hir_id) {
+                        if let Node::Item(item) = parent.1
+                            && let ItemKind::Fn(sig, ..) = item.kind
+                            && let FnRetTy::Return(ret_ty) = sig.decl.output
+                            && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id)
+                            && let [.., final_stmt] = block.stmts
+                            && final_stmt.hir_id == stmt.hir_id
+                        {
+                            let expr_ty = cx.typeck_results().expr_ty(expr);
+                            let mut ret_ty = hir_ty_to_ty(cx.tcx, ret_ty);
+
+                            // Remove `impl Future<Output = T>` to get `T`
+                            if cx.tcx.ty_is_opaque_future(ret_ty) &&
+                                let Some(true_ret_ty) = cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
+                            {
+                                ret_ty = true_ret_ty;
+                            }
+
+                            if ret_ty == expr_ty {
+                                diag.span_suggestion(
+                                    stmt.span.shrink_to_lo(),
+                                    "did you mean to return it?",
+                                    "return ",
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                        }
+                    }
+                },
+            );
             return true;
         }
     } else if let StmtKind::Local(local) = stmt.kind {
diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs
index 15dff126be7..f3e0c58a787 100644
--- a/clippy_lints/src/operators/float_cmp.rs
+++ b/clippy_lints/src/operators/float_cmp.rs
@@ -85,7 +85,7 @@ fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static
     }
 }
 
-fn is_allowed(val: &Constant) -> bool {
+fn is_allowed(val: &Constant<'_>) -> bool {
     match val {
         &Constant::F32(f) => f == 0.0 || f.is_infinite(),
         &Constant::F64(f) => f == 0.0 || f.is_infinite(),
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index dd7ded491e7..d2018aba9e3 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -296,8 +296,8 @@ fn check_possible_range_contains(
     }
 }
 
-struct RangeBounds<'a> {
-    val: Constant,
+struct RangeBounds<'a, 'tcx> {
+    val: Constant<'tcx>,
     expr: &'a Expr<'a>,
     id: HirId,
     name_span: Span,
@@ -309,7 +309,7 @@ struct RangeBounds<'a> {
 // Takes a binary expression such as x <= 2 as input
 // Breaks apart into various pieces, such as the value of the number,
 // hir id of the variable, and direction/inclusiveness of the operator
-fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<RangeBounds<'a>> {
+fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> Option<RangeBounds<'a, 'tcx>> {
     if let ExprKind::Binary(ref op, l, r) = ex.kind {
         let (inclusive, ordering) = match op.node {
             BinOpKind::Gt => (false, Ordering::Greater),
diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs
index 685d738cbb7..e36adef555e 100644
--- a/clippy_lints/src/redundant_clone.rs
+++ b/clippy_lints/src/redundant_clone.rs
@@ -320,8 +320,6 @@ fn base_local_and_movability<'tcx>(
     mir: &mir::Body<'tcx>,
     place: mir::Place<'tcx>,
 ) -> (mir::Local, CannotMoveOut) {
-    use rustc_middle::mir::PlaceRef;
-
     // Dereference. You cannot move things out from a borrowed value.
     let mut deref = false;
     // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
@@ -330,17 +328,14 @@ fn base_local_and_movability<'tcx>(
     // underlying type implements Copy
     let mut slice = false;
 
-    let PlaceRef { local, mut projection } = place.as_ref();
-    while let [base @ .., elem] = projection {
-        projection = base;
+    for (base, elem) in place.as_ref().iter_projections() {
+        let base_ty = base.ty(&mir.local_decls, cx.tcx).ty;
         deref |= matches!(elem, mir::ProjectionElem::Deref);
-        field |= matches!(elem, mir::ProjectionElem::Field(..))
-            && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
-        slice |= matches!(elem, mir::ProjectionElem::Index(..))
-            && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
+        field |= matches!(elem, mir::ProjectionElem::Field(..)) && has_drop(cx, base_ty);
+        slice |= matches!(elem, mir::ProjectionElem::Index(..)) && !is_copy(cx, base_ty);
     }
 
-    (local, deref || field || slice)
+    (place.local, deref || field || slice)
 }
 
 #[derive(Default)]
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs
index 2a42e73488f..b6ce4ebc28f 100644
--- a/clippy_lints/src/redundant_closure_call.rs
+++ b/clippy_lints/src/redundant_closure_call.rs
@@ -1,14 +1,14 @@
+use crate::rustc_lint::LintContext;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::get_parent_expr;
 use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
-use rustc_ast::ast;
-use rustc_ast::visit as ast_visit;
-use rustc_ast::visit::Visitor as AstVisitor;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor as HirVisitor;
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_hir::intravisit::Visitor;
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -51,59 +51,136 @@ impl ReturnVisitor {
     }
 }
 
-impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
-    fn visit_expr(&mut self, ex: &'ast ast::Expr) {
-        if let ast::ExprKind::Ret(_) | ast::ExprKind::Try(_) = ex.kind {
+impl<'tcx> Visitor<'tcx> for ReturnVisitor {
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
+        if let hir::ExprKind::Ret(_) | hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) = ex.kind {
             self.found_return = true;
+        } else {
+            hir_visit::walk_expr(self, ex);
         }
+    }
+}
 
-        ast_visit::walk_expr(self, ex);
+/// Checks if the body is owned by an async closure
+fn is_async_closure(body: &hir::Body<'_>) -> bool {
+    if let hir::ExprKind::Closure(closure) = body.value.kind
+        && let [resume_ty] = closure.fn_decl.inputs
+        && let hir::TyKind::Path(hir::QPath::LangItem(hir::LangItem::ResumeTy, ..)) = resume_ty.kind
+    {
+        true
+    } else {
+        false
     }
 }
 
-impl EarlyLintPass for RedundantClosureCall {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+/// Tries to find the innermost closure:
+/// ```rust,ignore
+/// (|| || || || 42)()()()()
+///  ^^^^^^^^^^^^^^          given this nested closure expression
+///           ^^^^^          we want to return this closure
+/// ```
+/// It also has a parameter for how many steps to go in at most, so as to
+/// not take more closures than there are calls.
+fn find_innermost_closure<'tcx>(
+    cx: &LateContext<'tcx>,
+    mut expr: &'tcx hir::Expr<'tcx>,
+    mut steps: usize,
+) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> {
+    let mut data = None;
+
+    while let hir::ExprKind::Closure(closure) = expr.kind
+        && let body = cx.tcx.hir().body(closure.body)
+        && {
+            let mut visitor = ReturnVisitor::new();
+            visitor.visit_expr(body.value);
+            !visitor.found_return
+        }
+        && steps > 0
+    {
+        expr = body.value;
+        data = Some((body.value, closure.fn_decl, if is_async_closure(body) {
+            hir::IsAsync::Async
+        } else {
+            hir::IsAsync::NotAsync
+        }));
+        steps -= 1;
+    }
+
+    data
+}
+
+/// "Walks up" the chain of calls to find the outermost call expression, and returns the depth:
+/// ```rust,ignore
+/// (|| || || 3)()()()
+///             ^^      this is the call expression we were given
+///                 ^^  this is what we want to return (and the depth is 3)
+/// ```
+fn get_parent_call_exprs<'tcx>(
+    cx: &LateContext<'tcx>,
+    mut expr: &'tcx hir::Expr<'tcx>,
+) -> (&'tcx hir::Expr<'tcx>, usize) {
+    let mut depth = 1;
+    while let Some(parent) = get_parent_expr(cx, expr)
+        && let hir::ExprKind::Call(recv, _) = parent.kind
+        && expr.span == recv.span
+    {
+        expr = parent;
+        depth += 1;
+    }
+    (expr, depth)
+}
+
+impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         if in_external_macro(cx.sess(), expr.span) {
             return;
         }
-        if_chain! {
-            if let ast::ExprKind::Call(ref paren, _) = expr.kind;
-            if let ast::ExprKind::Paren(ref closure) = paren.kind;
-            if let ast::ExprKind::Closure(box ast::Closure { ref asyncness, ref fn_decl, ref body, .. }) = closure.kind;
-            then {
-                let mut visitor = ReturnVisitor::new();
-                visitor.visit_expr(body);
-                if !visitor.found_return {
-                    span_lint_and_then(
-                        cx,
-                        REDUNDANT_CLOSURE_CALL,
-                        expr.span,
-                        "try not to call a closure in the expression where it is declared",
-                        |diag| {
-                            if fn_decl.inputs.is_empty() {
-                                let mut app = Applicability::MachineApplicable;
-                                let mut hint = Sugg::ast(cx, body, "..", closure.span.ctxt(), &mut app);
-
-                                if asyncness.is_async() {
-                                    // `async x` is a syntax error, so it becomes `async { x }`
-                                    if !matches!(body.kind, ast::ExprKind::Block(_, _)) {
-                                        hint = hint.blockify();
-                                    }
-
-                                    hint = hint.asyncify();
-                                }
-
-                                diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app);
+
+        if let hir::ExprKind::Call(recv, _) = expr.kind
+            // don't lint if the receiver is a call, too. 
+            // we do this in order to prevent linting multiple times; consider:
+            // `(|| || 1)()()`
+            //           ^^  we only want to lint for this call (but we walk up the calls to consider both calls).
+            // without this check, we'd end up linting twice.
+            && !matches!(recv.kind, hir::ExprKind::Call(..))
+            && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr)
+            && let Some((body, fn_decl, generator_kind)) = find_innermost_closure(cx, recv, call_depth)
+        {
+            span_lint_and_then(
+                cx,
+                REDUNDANT_CLOSURE_CALL,
+                full_expr.span,
+                "try not to call a closure in the expression where it is declared",
+                |diag| {
+                    if fn_decl.inputs.is_empty() {
+                        let mut applicability = Applicability::MachineApplicable;
+                        let mut hint = Sugg::hir_with_context(cx, body, full_expr.span.ctxt(), "..", &mut applicability);
+
+                        if generator_kind.is_async()
+                            && let hir::ExprKind::Closure(closure) = body.kind
+                        {
+                            let async_closure_body = cx.tcx.hir().body(closure.body);
+
+                            // `async x` is a syntax error, so it becomes `async { x }`
+                            if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) {
+                                hint = hint.blockify();
                             }
-                        },
-                    );
+
+                            hint = hint.asyncify();
+                        }
+
+                        diag.span_suggestion(
+                            full_expr.span,
+                            "try doing something like",
+                            hint.maybe_par(),
+                            applicability
+                        );
+                    }
                 }
-            }
+            );
         }
     }
-}
 
-impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
         fn count_closure_usage<'tcx>(
             cx: &LateContext<'tcx>,
diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs
new file mode 100644
index 00000000000..42753d2e951
--- /dev/null
+++ b/clippy_lints/src/single_call_fn.rs
@@ -0,0 +1,133 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{is_from_proc_macro, is_in_test_function};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for functions that are only used once. Does not lint tests.
+    ///
+    /// ### Why is this bad?
+    /// It's usually not, splitting a function into multiple parts often improves readability and in
+    /// the case of generics, can prevent the compiler from duplicating the function dozens of
+    /// time; instead, only duplicating a thunk. But this can prevent segmentation across a
+    /// codebase, where many small functions are used only once.
+    ///
+    /// Note: If this lint is used, prepare to allow this a lot.
+    ///
+    /// ### Example
+    /// ```rust
+    /// pub fn a<T>(t: &T)
+    /// where
+    ///     T: AsRef<str>,
+    /// {
+    ///     a_inner(t.as_ref())
+    /// }
+    ///
+    /// fn a_inner(t: &str) {
+    ///     /* snip */
+    /// }
+    ///
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// pub fn a<T>(t: &T)
+    /// where
+    ///     T: AsRef<str>,
+    /// {
+    ///     let t = t.as_ref();
+    ///     /* snip */
+    /// }
+    ///
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub SINGLE_CALL_FN,
+    restriction,
+    "checks for functions that are only used once"
+}
+impl_lint_pass!(SingleCallFn => [SINGLE_CALL_FN]);
+
+#[derive(Clone)]
+pub struct SingleCallFn {
+    pub avoid_breaking_exported_api: bool,
+    pub def_id_to_usage: FxHashMap<LocalDefId, (Span, Vec<Span>)>,
+}
+
+impl<'tcx> LateLintPass<'tcx> for SingleCallFn {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        kind: FnKind<'tcx>,
+        _: &'tcx FnDecl<'_>,
+        body: &'tcx Body<'_>,
+        span: Span,
+        def_id: LocalDefId,
+    ) {
+        if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id)
+            || in_external_macro(cx.sess(), span)
+            || is_from_proc_macro(cx, &(&kind, body, cx.tcx.local_def_id_to_hir_id(def_id), span))
+            || is_in_test_function(cx.tcx, body.value.hir_id)
+        {
+            return;
+        }
+
+        self.def_id_to_usage.insert(def_id, (span, vec![]));
+    }
+
+    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
+        let mut v = FnUsageVisitor {
+            cx,
+            def_id_to_usage: &mut self.def_id_to_usage,
+        };
+        cx.tcx.hir().visit_all_item_likes_in_crate(&mut v);
+
+        for usage in self.def_id_to_usage.values() {
+            let single_call_fn_span = usage.0;
+            if let [caller_span] = *usage.1 {
+                span_lint_and_help(
+                    cx,
+                    SINGLE_CALL_FN,
+                    single_call_fn_span,
+                    "this function is only used once",
+                    Some(caller_span),
+                    "used here",
+                );
+            }
+        }
+    }
+}
+
+struct FnUsageVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    def_id_to_usage: &'a mut FxHashMap<LocalDefId, (Span, Vec<Span>)>,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for FnUsageVisitor<'a, 'tcx> {
+    type NestedFilter = OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        let Self { cx, .. } = *self;
+
+        if let ExprKind::Path(qpath) = expr.kind
+            && let res = cx.qpath_res(&qpath, expr.hir_id)
+            && let Some(call_def_id) = res.opt_def_id()
+            && let Some(def_id) = call_def_id.as_local()
+            && let Some(usage) = self.def_id_to_usage.get_mut(&def_id)
+        {
+            usage.1.push(expr.span);
+        }
+
+        walk_expr(self, expr);
+    }
+}
diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs
new file mode 100644
index 00000000000..dfe8be7a6a6
--- /dev/null
+++ b/clippy_lints/src/single_range_in_vec_init.rs
@@ -0,0 +1,147 @@
+use clippy_utils::{
+    diagnostics::span_lint_and_then, get_trait_def_id, higher::VecArgs, macros::root_macro_call_first_node,
+    source::snippet_opt, ty::implements_trait,
+};
+use rustc_ast::{LitIntType, LitKind, UintTy};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, LangItem, QPath};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use std::fmt::{self, Display, Formatter};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `Vec` or array initializations that contain only one range.
+    ///
+    /// ### Why is this bad?
+    /// This is almost always incorrect, as it will result in a `Vec` that has only one element.
+    /// Almost always, the programmer intended for it to include all elements in the range or for
+    /// the end of the range to be the length instead.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let x = [0..200];
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// // If it was intended to include every element in the range...
+    /// let x = (0..200).collect::<Vec<i32>>();
+    /// // ...Or if 200 was meant to be the len
+    /// let x = [0; 200];
+    /// ```
+    #[clippy::version = "1.72.0"]
+    pub SINGLE_RANGE_IN_VEC_INIT,
+    suspicious,
+    "checks for initialization of `Vec` or arrays which consist of a single range"
+}
+declare_lint_pass!(SingleRangeInVecInit => [SINGLE_RANGE_IN_VEC_INIT]);
+
+enum SuggestedType {
+    Vec,
+    Array,
+}
+
+impl SuggestedType {
+    fn starts_with(&self) -> &'static str {
+        if matches!(self, SuggestedType::Vec) {
+            "vec!"
+        } else {
+            "["
+        }
+    }
+
+    fn ends_with(&self) -> &'static str {
+        if matches!(self, SuggestedType::Vec) { "" } else { "]" }
+    }
+}
+
+impl Display for SuggestedType {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        if matches!(&self, SuggestedType::Vec) {
+            write!(f, "a `Vec`")
+        } else {
+            write!(f, "an array")
+        }
+    }
+}
+
+impl LateLintPass<'_> for SingleRangeInVecInit {
+    fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        // inner_expr: `vec![0..200]` or `[0..200]`
+        //                   ^^^^^^       ^^^^^^^
+        // span: `vec![0..200]` or `[0..200]`
+        //        ^^^^^^^^^^^^      ^^^^^^^^
+        // suggested_type: What to print, "an array" or "a `Vec`"
+        let (inner_expr, span, suggested_type) = if let ExprKind::Array([inner_expr]) = expr.kind
+            && !expr.span.from_expansion()
+        {
+            (inner_expr, expr.span, SuggestedType::Array)
+        } else if let Some(macro_call) = root_macro_call_first_node(cx, expr)
+            && let Some(VecArgs::Vec([expr])) = VecArgs::hir(cx, expr)
+        {
+            (expr, macro_call.span, SuggestedType::Vec)
+        } else {
+            return;
+        };
+
+        let ExprKind::Struct(QPath::LangItem(lang_item, ..), [start, end], None) = inner_expr.kind else {
+            return;
+        };
+
+        if matches!(lang_item, LangItem::Range)
+            && let ty = cx.typeck_results().expr_ty(start.expr)
+            && let Some(snippet) = snippet_opt(cx, span)
+            // `is_from_proc_macro` will skip any `vec![]`. Let's not!
+            && snippet.starts_with(suggested_type.starts_with())
+            && snippet.ends_with(suggested_type.ends_with())
+            && let Some(start_snippet) = snippet_opt(cx, start.span)
+            && let Some(end_snippet) = snippet_opt(cx, end.span)
+        {
+            let should_emit_every_value = if let Some(step_def_id) = get_trait_def_id(cx, &["core", "iter", "Step"])
+                && implements_trait(cx, ty, step_def_id, &[])
+            {
+                true
+            } else {
+                false
+            };
+            let should_emit_of_len = if let Some(copy_def_id) = cx.tcx.lang_items().copy_trait()
+                && implements_trait(cx, ty, copy_def_id, &[])
+                && let ExprKind::Lit(lit_kind) = end.expr.kind
+                && let LitKind::Int(.., suffix_type) = lit_kind.node
+                && let LitIntType::Unsigned(UintTy::Usize) | LitIntType::Unsuffixed = suffix_type
+            {
+                true
+            } else {
+                false
+            };
+
+            if should_emit_every_value || should_emit_of_len {
+                span_lint_and_then(
+                    cx,
+                    SINGLE_RANGE_IN_VEC_INIT,
+                    span,
+                    &format!("{suggested_type} of `Range` that is only one element"),
+                    |diag| {
+                        if should_emit_every_value {
+                            diag.span_suggestion(
+                                span,
+                                "if you wanted a `Vec` that contains the entire range, try",
+                                format!("({start_snippet}..{end_snippet}).collect::<std::vec::Vec<{ty}>>()"),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+
+                        if should_emit_of_len {
+                            diag.span_suggestion(
+                                inner_expr.span,
+                                format!("if you wanted {suggested_type} of len {end_snippet}, try"),
+                                format!("{start_snippet}; {end_snippet}"),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    },
+                );
+            }
+        }
+    }
+}
diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs
index 2920684ade3..a9deee96784 100644
--- a/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{BytePos, Pos, Span, SyntaxContext};
 
 declare_clippy_lint! {
@@ -92,7 +92,22 @@ declare_clippy_lint! {
     "annotating safe code with a safety comment"
 }
 
-declare_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]);
+#[derive(Copy, Clone)]
+pub struct UndocumentedUnsafeBlocks {
+    accept_comment_above_statement: bool,
+    accept_comment_above_attributes: bool,
+}
+
+impl UndocumentedUnsafeBlocks {
+    pub fn new(accept_comment_above_statement: bool, accept_comment_above_attributes: bool) -> Self {
+        Self {
+            accept_comment_above_statement,
+            accept_comment_above_attributes,
+        }
+    }
+}
+
+impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]);
 
 impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
@@ -101,7 +116,12 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
             && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id)
             && !is_unsafe_from_proc_macro(cx, block.span)
             && !block_has_safety_comment(cx, block.span)
-            && !block_parents_have_safety_comment(cx, block.hir_id)
+            && !block_parents_have_safety_comment(
+                self.accept_comment_above_statement,
+                self.accept_comment_above_attributes,
+                cx,
+                block.hir_id,
+            )
         {
             let source_map = cx.tcx.sess.source_map();
             let span = if source_map.is_multiline(block.span) {
@@ -313,29 +333,95 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
 
 // Checks if any parent {expression, statement, block, local, const, static}
 // has a safety comment
-fn block_parents_have_safety_comment(cx: &LateContext<'_>, id: hir::HirId) -> bool {
+fn block_parents_have_safety_comment(
+    accept_comment_above_statement: bool,
+    accept_comment_above_attributes: bool,
+    cx: &LateContext<'_>,
+    id: hir::HirId,
+) -> bool {
     if let Some(node) = get_parent_node(cx.tcx, id) {
         return match node {
-            Node::Expr(expr) => !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span),
+            Node::Expr(expr) => {
+                if let Some(
+                    Node::Local(hir::Local { span, .. })
+                    | Node::Item(hir::Item {
+                        kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                        span,
+                        ..
+                    }),
+                ) = get_parent_node(cx.tcx, expr.hir_id)
+                {
+                    let hir_id = match get_parent_node(cx.tcx, expr.hir_id) {
+                        Some(Node::Local(hir::Local { hir_id, .. })) => *hir_id,
+                        Some(Node::Item(hir::Item { owner_id, .. })) => {
+                            cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id)
+                        },
+                        _ => unreachable!(),
+                    };
+
+                    // if unsafe block is part of a let/const/static statement,
+                    // and accept_comment_above_statement is set to true
+                    // we accept the safety comment in the line the precedes this statement.
+                    accept_comment_above_statement
+                        && span_with_attrs_in_body_has_safety_comment(
+                            cx,
+                            *span,
+                            hir_id,
+                            accept_comment_above_attributes,
+                        )
+                } else {
+                    !is_branchy(expr)
+                        && span_with_attrs_in_body_has_safety_comment(
+                            cx,
+                            expr.span,
+                            expr.hir_id,
+                            accept_comment_above_attributes,
+                        )
+                }
+            },
             Node::Stmt(hir::Stmt {
                 kind:
-                    hir::StmtKind::Local(hir::Local { span, .. })
-                    | hir::StmtKind::Expr(hir::Expr { span, .. })
-                    | hir::StmtKind::Semi(hir::Expr { span, .. }),
+                    hir::StmtKind::Local(hir::Local { span, hir_id, .. })
+                    | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. })
+                    | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }),
                 ..
             })
-            | Node::Local(hir::Local { span, .. })
-            | Node::Item(hir::Item {
+            | Node::Local(hir::Local { span, hir_id, .. }) => {
+                span_with_attrs_in_body_has_safety_comment(cx, *span, *hir_id, accept_comment_above_attributes)
+            },
+            Node::Item(hir::Item {
                 kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
                 span,
+                owner_id,
                 ..
-            }) => span_in_body_has_safety_comment(cx, *span),
+            }) => span_with_attrs_in_body_has_safety_comment(
+                cx,
+                *span,
+                cx.tcx.hir().local_def_id_to_hir_id(owner_id.def_id),
+                accept_comment_above_attributes,
+            ),
             _ => false,
         };
     }
     false
 }
 
+/// Extends `span` to also include its attributes, then checks if that span has a safety comment.
+fn span_with_attrs_in_body_has_safety_comment(
+    cx: &LateContext<'_>,
+    span: Span,
+    hir_id: HirId,
+    accept_comment_above_attributes: bool,
+) -> bool {
+    let span = if accept_comment_above_attributes {
+        include_attrs_in_span(cx, hir_id, span)
+    } else {
+        span
+    };
+
+    span_in_body_has_safety_comment(cx, span)
+}
+
 /// Checks if an expression is "branchy", e.g. loop, match/if/etc.
 fn is_branchy(expr: &hir::Expr<'_>) -> bool {
     matches!(
@@ -360,6 +446,15 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
     ) || span_in_body_has_safety_comment(cx, span)
 }
 
+fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
+    span.to(cx
+        .tcx
+        .hir()
+        .attrs(hir_id)
+        .iter()
+        .fold(span, |acc, attr| acc.to(attr.span)))
+}
+
 enum HasSafetyComment {
     Yes(BytePos),
     No,
@@ -546,7 +641,14 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
     for (_, node) in map.parent_iter(body.hir_id) {
         match node {
             Node::Expr(e) => span = e.span,
-            Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::Local(_) => (),
+            Node::Block(_)
+            | Node::Arm(_)
+            | Node::Stmt(_)
+            | Node::Local(_)
+            | Node::Item(hir::Item {
+                kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
+                ..
+            }) => (),
             _ => break,
         }
     }
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index f6c7c1fa065..f5d6cecc59c 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -21,6 +21,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
     "GitHub", "GitLab",
     "IPv4", "IPv6",
     "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript",
+    "WebAssembly",
     "NaN", "NaNs",
     "OAuth", "GraphQL",
     "OCaml",
@@ -289,7 +290,7 @@ define_Conf! {
     /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
     /// ```
     (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
-    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS.
+    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN.
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
@@ -538,6 +539,14 @@ define_Conf! {
     ///
     /// Minimum chars an ident can have, anything below or equal to this will be linted.
     (min_ident_chars_threshold: u64 = 1),
+    /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
+    ///
+    /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
+    (accept_comment_above_statement: bool = false),
+        /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
+    ///
+    /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
+    (accept_comment_above_attributes: bool = false),
 }
 
 /// Search for the configuration file.
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index cc3183759ae..72582ba7e78 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
 use rustc_middle::ty::{List, SubstsRef};
 use rustc_middle::{bug, span_bug};
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::SyntaxContext;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
@@ -22,7 +22,8 @@ use std::iter;
 
 /// A `LitKind`-like enum to fold constant `Expr`s into.
 #[derive(Debug, Clone)]
-pub enum Constant {
+pub enum Constant<'tcx> {
+    Adt(rustc_middle::mir::ConstantKind<'tcx>),
     /// A `String` (e.g., "abc").
     Str(String),
     /// A binary string (e.g., `b"abc"`).
@@ -38,20 +39,20 @@ pub enum Constant {
     /// `true` or `false`.
     Bool(bool),
     /// An array of constants.
-    Vec(Vec<Constant>),
+    Vec(Vec<Constant<'tcx>>),
     /// Also an array, but with only one constant, repeated N times.
-    Repeat(Box<Constant>, u64),
+    Repeat(Box<Constant<'tcx>>, u64),
     /// A tuple of constants.
-    Tuple(Vec<Constant>),
+    Tuple(Vec<Constant<'tcx>>),
     /// A raw pointer.
     RawPtr(u128),
     /// A reference
-    Ref(Box<Constant>),
+    Ref(Box<Constant<'tcx>>),
     /// A literal with syntax error.
     Err,
 }
 
-impl PartialEq for Constant {
+impl<'tcx> PartialEq for Constant<'tcx> {
     fn eq(&self, other: &Self) -> bool {
         match (self, other) {
             (Self::Str(ls), Self::Str(rs)) => ls == rs,
@@ -80,13 +81,16 @@ impl PartialEq for Constant {
     }
 }
 
-impl Hash for Constant {
+impl<'tcx> Hash for Constant<'tcx> {
     fn hash<H>(&self, state: &mut H)
     where
         H: Hasher,
     {
         std::mem::discriminant(self).hash(state);
         match *self {
+            Self::Adt(ref elem) => {
+                elem.hash(state);
+            },
             Self::Str(ref s) => {
                 s.hash(state);
             },
@@ -126,7 +130,7 @@ impl Hash for Constant {
     }
 }
 
-impl Constant {
+impl<'tcx> Constant<'tcx> {
     pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option<Ordering> {
         match (left, right) {
             (Self::Str(ls), Self::Str(rs)) => Some(ls.cmp(rs)),
@@ -209,7 +213,7 @@ impl Constant {
 }
 
 /// Parses a `LitKind` to a `Constant`.
-pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
+pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constant<'tcx> {
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
@@ -248,7 +252,7 @@ pub fn constant<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<Constant> {
+) -> Option<Constant<'tcx>> {
     ConstEvalLateContext::new(lcx, typeck_results).expr(e)
 }
 
@@ -257,7 +261,7 @@ pub fn constant_with_source<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<(Constant, ConstantSource)> {
+) -> Option<(Constant<'tcx>, ConstantSource)> {
     let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
     let res = ctxt.expr(e);
     res.map(|x| (x, ctxt.source))
@@ -268,7 +272,7 @@ pub fn constant_simple<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<Constant> {
+) -> Option<Constant<'tcx>> {
     constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
 }
 
@@ -338,7 +342,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 
     /// Simple constant folding: Insert an expression, get a constant or none.
-    pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
+    pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
         match e.kind {
             ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
             ExprKind::Block(block, _) => self.block(block),
@@ -392,13 +396,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
             },
             ExprKind::Index(arr, index) => self.index(arr, index),
             ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))),
-            // TODO: add other expressions.
+            ExprKind::Field(local_expr, ref field) => {
+                let result = self.expr(local_expr);
+                if let Some(Constant::Adt(constant)) = &self.expr(local_expr)
+                    && let ty::Adt(adt_def, _) = constant.ty().kind()
+                    && adt_def.is_struct()
+                    && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field)
+                {
+                    miri_to_const(self.lcx, desired_field)
+                }
+                else {
+                    result
+                }
+            },
             _ => None,
         }
     }
 
     #[expect(clippy::cast_possible_wrap)]
-    fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
+    fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
         use self::Constant::{Bool, Int};
         match *o {
             Bool(b) => Some(Bool(!b)),
@@ -414,7 +430,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
-    fn constant_negate(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> {
+    fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
         use self::Constant::{Int, F32, F64};
         match *o {
             Int(value) => {
@@ -433,28 +449,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
 
     /// Create `Some(Vec![..])` of all constants, unless there is any
     /// non-constant part.
-    fn multi(&mut self, vec: &[Expr<'_>]) -> Option<Vec<Constant>> {
+    fn multi(&mut self, vec: &[Expr<'_>]) -> Option<Vec<Constant<'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> {
+    fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<Constant<'tcx>> {
         let res = self.typeck_results.qpath_res(qpath, id);
         match res {
             Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => {
                 // Check if this constant is based on `cfg!(..)`,
                 // which is NOT constant for our purposes.
-                if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) &&
-                let Node::Item(&Item {
-                    kind: ItemKind::Const(_, body_id),
-                    ..
-                }) = node &&
-                let Node::Expr(&Expr {
-                    kind: ExprKind::Lit(_),
-                    span,
-                    ..
-                }) = self.lcx.tcx.hir().get(body_id.hir_id) &&
-                is_direct_expn_of(span, "cfg").is_some() {
+                if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id)
+                    && let Node::Item(Item { kind: ItemKind::Const(_, body_id), .. }) = node
+                    && let Node::Expr(Expr { kind: ExprKind::Lit(_), span, .. }) = self.lcx
+                        .tcx
+                        .hir()
+                        .get(body_id.hir_id)
+                    && is_direct_expn_of(*span, "cfg").is_some()
+                {
                     return None;
                 }
 
@@ -464,23 +477,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                 } else {
                     EarlyBinder::bind(substs).subst(self.lcx.tcx, self.substs)
                 };
-
                 let result = self
                     .lcx
                     .tcx
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
                     .ok()
                     .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx.tcx, result)?;
+                let result = miri_to_const(self.lcx, result)?;
                 self.source = ConstantSource::Constant;
                 Some(result)
             },
-            // FIXME: cover all usable cases.
             _ => None,
         }
     }
 
-    fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant> {
+    fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant<'tcx>> {
         let lhs = self.expr(lhs);
         let index = self.expr(index);
 
@@ -506,7 +517,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 
     /// A block can only yield a constant if it only has one constant expression.
-    fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
+    fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
         if block.stmts.is_empty()
             && let Some(expr) = block.expr
         {
@@ -539,7 +550,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
-    fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant> {
+    fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant<'tcx>> {
         if let Some(Constant::Bool(b)) = self.expr(cond) {
             if b {
                 self.expr(then)
@@ -551,7 +562,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         }
     }
 
-    fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant> {
+    fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> {
         let l = self.expr(left)?;
         let r = self.expr(right);
         match (l, r) {
@@ -644,23 +655,21 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 }
 
-pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant> {
+pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant<'tcx>> {
     use rustc_middle::mir::interpret::ConstValue;
     match result {
-        mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => {
-            match result.ty().kind() {
-                ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
-                ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
-                ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
-                    int.try_into().expect("invalid f32 bit representation"),
-                ))),
-                ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
-                    int.try_into().expect("invalid f64 bit representation"),
-                ))),
-                ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
-                // FIXME: implement other conversions.
-                _ => None,
-            }
+        mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
+            ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
+            ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
+            ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
+                int.try_into().expect("invalid f32 bit representation"),
+            ))),
+            ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
+                int.try_into().expect("invalid f64 bit representation"),
+            ))),
+            ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
+            _ => None,
         },
         mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
             ty::Ref(_, tam, _) => match tam.kind() {
@@ -676,35 +685,53 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
             _ => None,
         },
         mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
             ty::Array(sub_type, len) => match sub_type.kind() {
-                ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) {
+                ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(lcx.tcx) {
                     Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
                         .to_owned()
                         .array_chunks::<4>()
                         .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
-                        .collect::<Option<Vec<Constant>>>()
+                        .collect::<Option<Vec<Constant<'tcx>>>>()
                         .map(Constant::Vec),
                     _ => None,
                 },
-                ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(tcx) {
+                ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(lcx.tcx) {
                     Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
                         .to_owned()
                         .array_chunks::<8>()
                         .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
-                        .collect::<Option<Vec<Constant>>>()
+                        .collect::<Option<Vec<Constant<'tcx>>>>()
                         .map(Constant::Vec),
                     _ => None,
                 },
-                // FIXME: implement other array type conversions.
                 _ => None,
             },
             _ => None,
         },
-        // FIXME: implement other conversions.
         _ => None,
     }
 }
+
+fn field_of_struct<'tcx>(
+    adt_def: ty::AdtDef<'tcx>,
+    lcx: &LateContext<'tcx>,
+    result: mir::ConstantKind<'tcx>,
+    field: &Ident,
+) -> Option<mir::ConstantKind<'tcx>> {
+    let dc = lcx.tcx.destructure_mir_constant(lcx.param_env, result);
+    if let Some(dc_variant) = dc.variant
+        && let Some(variant) = adt_def.variants().get(dc_variant)
+        && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
+        && let Some(dc_field) = dc.fields.get(field_idx)
+    {
+        Some(*dc_field)
+    }
+    else {
+        None
+    }
+}
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 311f6dbc696..5b5e9fba6af 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1499,7 +1499,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                 && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
                 && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
                 && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
-                && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind)
+                && let Some(min_const) = miri_to_const(cx, min_const_kind)
                 && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
@@ -1515,7 +1515,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                         && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
                         && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
                         && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
-                        && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind)
+                        && let Some(max_const) = miri_to_const(cx, max_const_kind)
                         && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index e4a4936ff42..00f3abaec8a 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -9,7 +9,7 @@ use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::LateContext;
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
-use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, Symbol};
+use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol};
 use std::cell::RefCell;
 use std::ops::ControlFlow;
 use std::sync::atomic::{AtomicBool, Ordering};
@@ -415,8 +415,18 @@ pub fn find_format_arg_expr<'hir, 'ast>(
     start: &'hir Expr<'hir>,
     target: &'ast FormatArgument,
 ) -> Result<&'hir rustc_hir::Expr<'hir>, &'ast rustc_ast::Expr> {
+    let SpanData {
+        lo,
+        hi,
+        ctxt,
+        parent: _,
+    } = target.expr.span.data();
+
     for_each_expr(start, |expr| {
-        if expr.span == target.expr.span {
+        // When incremental compilation is enabled spans gain a parent during AST to HIR lowering,
+        // since we're comparing an AST span to a HIR one we need to ignore the parent field
+        let data = expr.span.data();
+        if data.lo == lo && data.hi == hi && data.ctxt == ctxt {
             ControlFlow::Break(expr)
         } else {
             ControlFlow::Continue(())
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index dcd372f689d..3e261b20465 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -284,13 +284,10 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
 }
 
 fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
-    let mut cursor = place.projection.as_ref();
-
-    while let [ref proj_base @ .., elem] = *cursor {
-        cursor = proj_base;
+    for (base, elem) in place.as_ref().iter_projections() {
         match elem {
             ProjectionElem::Field(..) => {
-                let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty;
+                let base_ty = base.ty(body, tcx).ty;
                 if let Some(def) = base_ty.ty_adt_def() {
                     // No union field accesses in `const fn`
                     if def.is_union() {
diff --git a/src/main.rs b/src/main.rs
index 188ff87abfc..300c84a1442 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -57,7 +57,9 @@ pub fn main() {
     if let Some(pos) = env::args().position(|a| a == "--explain") {
         if let Some(mut lint) = env::args().nth(pos + 1) {
             lint.make_ascii_lowercase();
-            clippy_lints::explain(&lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"));
+            process::exit(clippy_lints::explain(
+                &lint.strip_prefix("clippy::").unwrap_or(&lint).replace('-', "_"),
+            ));
         } else {
             show_help();
         }
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index d8ce0e2f55d..475b15a2414 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -1,4 +1,6 @@
 error: error reading Clippy's configuration file: unknown field `foobar`, expected one of
+           accept-comment-above-attributes
+           accept-comment-above-statement
            allow-dbg-in-tests
            allow-expect-in-tests
            allow-mixed-uninlined-format-args
@@ -65,6 +67,8 @@ LL | foobar = 42
    | ^^^^^^
 
 error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of
+           accept-comment-above-attributes
+           accept-comment-above-statement
            allow-dbg-in-tests
            allow-expect-in-tests
            allow-mixed-uninlined-format-args
diff --git a/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
new file mode 100644
index 00000000000..c2326678d0d
--- /dev/null
+++ b/tests/ui-toml/undocumented_unsafe_blocks/auxiliary/proc_macro_unsafe.rs
@@ -0,0 +1,18 @@
+//@compile-flags: --emit=link
+//@no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree};
+
+#[proc_macro]
+pub fn unsafe_block(input: TokenStream) -> TokenStream {
+    let span = input.into_iter().next().unwrap().span();
+    TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), {
+        let mut group = Group::new(Delimiter::Brace, TokenStream::new());
+        group.set_span(span);
+        TokenTree::Group(group)
+    }])
+}
diff --git a/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml
new file mode 100644
index 00000000000..e6dbb3d3784
--- /dev/null
+++ b/tests/ui-toml/undocumented_unsafe_blocks/clippy.toml
@@ -0,0 +1,2 @@
+accept-comment-above-statement = true
+accept-comment-above-attributes = true
diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
new file mode 100644
index 00000000000..c0976f0d600
--- /dev/null
+++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
@@ -0,0 +1,567 @@
+//@aux-build:proc_macro_unsafe.rs
+
+#![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
+#![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)]
+#![feature(lint_reasons)]
+
+extern crate proc_macro_unsafe;
+
+// Valid comments
+
+fn nested_local() {
+    let _ = {
+        let _ = {
+            // SAFETY:
+            let _ = unsafe {};
+        };
+    };
+}
+
+fn deep_nest() {
+    let _ = {
+        let _ = {
+            // SAFETY:
+            let _ = unsafe {};
+
+            // Safety:
+            unsafe {};
+
+            let _ = {
+                let _ = {
+                    let _ = {
+                        let _ = {
+                            let _ = {
+                                // Safety:
+                                let _ = unsafe {};
+
+                                // SAFETY:
+                                unsafe {};
+                            };
+                        };
+                    };
+
+                    // Safety:
+                    unsafe {};
+                };
+            };
+        };
+
+        // Safety:
+        unsafe {};
+    };
+
+    // SAFETY:
+    unsafe {};
+}
+
+fn local_tuple_expression() {
+    // Safety:
+    let _ = (42, unsafe {});
+}
+
+fn line_comment() {
+    // Safety:
+    unsafe {}
+}
+
+fn line_comment_newlines() {
+    // SAFETY:
+
+    unsafe {}
+}
+
+fn line_comment_empty() {
+    // Safety:
+    //
+    //
+    //
+    unsafe {}
+}
+
+fn line_comment_with_extras() {
+    // This is a description
+    // Safety:
+    unsafe {}
+}
+
+fn block_comment() {
+    /* Safety: */
+    unsafe {}
+}
+
+fn block_comment_newlines() {
+    /* SAFETY: */
+
+    unsafe {}
+}
+
+fn block_comment_with_extras() {
+    /* This is a description
+     * SAFETY:
+     */
+    unsafe {}
+}
+
+fn block_comment_terminator_same_line() {
+    /* This is a description
+     * Safety: */
+    unsafe {}
+}
+
+fn buried_safety() {
+    // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+    // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
+    // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
+    // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
+    // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
+    // laborum. Safety:
+    // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi
+    // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio
+    // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl
+    // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus.
+    unsafe {}
+}
+
+fn safety_with_prepended_text() {
+    // This is a test. safety:
+    unsafe {}
+}
+
+fn local_line_comment() {
+    // Safety:
+    let _ = unsafe {};
+}
+
+fn local_block_comment() {
+    /* SAFETY: */
+    let _ = unsafe {};
+}
+
+fn comment_array() {
+    // Safety:
+    let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+}
+
+fn comment_tuple() {
+    // sAFETY:
+    let _ = (42, unsafe {}, "test", unsafe {});
+}
+
+fn comment_unary() {
+    // SAFETY:
+    let _ = *unsafe { &42 };
+}
+
+#[allow(clippy::match_single_binding)]
+fn comment_match() {
+    // SAFETY:
+    let _ = match unsafe {} {
+        _ => {},
+    };
+}
+
+fn comment_addr_of() {
+    // Safety:
+    let _ = &unsafe {};
+}
+
+fn comment_repeat() {
+    // Safety:
+    let _ = [unsafe {}; 5];
+}
+
+fn comment_macro_call() {
+    macro_rules! t {
+        ($b:expr) => {
+            $b
+        };
+    }
+
+    t!(
+        // SAFETY:
+        unsafe {}
+    );
+}
+
+fn comment_macro_def() {
+    macro_rules! t {
+        () => {
+            // Safety:
+            unsafe {}
+        };
+    }
+
+    t!();
+}
+
+fn non_ascii_comment() {
+    // ॐ᧻໒ SaFeTy: ௵∰
+    unsafe {};
+}
+
+fn local_commented_block() {
+    let _ =
+        // safety:
+        unsafe {};
+}
+
+fn local_nest() {
+    // safety:
+    let _ = [(42, unsafe {}, unsafe {}), (52, unsafe {}, unsafe {})];
+}
+
+fn in_fn_call(x: *const u32) {
+    fn f(x: u32) {}
+
+    // Safety: reason
+    f(unsafe { *x });
+}
+
+fn multi_in_fn_call(x: *const u32) {
+    fn f(x: u32, y: u32) {}
+
+    // Safety: reason
+    f(unsafe { *x }, unsafe { *x });
+}
+
+fn in_multiline_fn_call(x: *const u32) {
+    fn f(x: u32, y: u32) {}
+
+    f(
+        // Safety: reason
+        unsafe { *x },
+        0,
+    );
+}
+
+fn in_macro_call(x: *const u32) {
+    // Safety: reason
+    println!("{}", unsafe { *x });
+}
+
+fn in_multiline_macro_call(x: *const u32) {
+    println!(
+        "{}",
+        // Safety: reason
+        unsafe { *x },
+    );
+}
+
+fn from_proc_macro() {
+    proc_macro_unsafe::unsafe_block!(token);
+}
+
+fn in_closure(x: *const u32) {
+    // Safety: reason
+    let _ = || unsafe { *x };
+}
+
+// Invalid comments
+
+#[rustfmt::skip]
+fn inline_block_comment() {
+    /* Safety: */ unsafe {}
+}
+
+fn no_comment() {
+    unsafe {}
+}
+
+fn no_comment_array() {
+    let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+}
+
+fn no_comment_tuple() {
+    let _ = (42, unsafe {}, "test", unsafe {});
+}
+
+fn no_comment_unary() {
+    let _ = *unsafe { &42 };
+}
+
+#[allow(clippy::match_single_binding)]
+fn no_comment_match() {
+    let _ = match unsafe {} {
+        _ => {},
+    };
+}
+
+fn no_comment_addr_of() {
+    let _ = &unsafe {};
+}
+
+fn no_comment_repeat() {
+    let _ = [unsafe {}; 5];
+}
+
+fn local_no_comment() {
+    let _ = unsafe {};
+}
+
+fn no_comment_macro_call() {
+    macro_rules! t {
+        ($b:expr) => {
+            $b
+        };
+    }
+
+    t!(unsafe {});
+}
+
+fn no_comment_macro_def() {
+    macro_rules! t {
+        () => {
+            unsafe {}
+        };
+    }
+
+    t!();
+}
+
+fn trailing_comment() {
+    unsafe {} // SAFETY:
+}
+
+fn internal_comment() {
+    unsafe {
+        // SAFETY:
+    }
+}
+
+fn interference() {
+    // SAFETY
+
+    let _ = 42;
+
+    unsafe {};
+}
+
+pub fn print_binary_tree() {
+    println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
+}
+
+mod unsafe_impl_smoke_test {
+    unsafe trait A {}
+
+    // error: no safety comment
+    unsafe impl A for () {}
+
+    // Safety: ok
+    unsafe impl A for (i32) {}
+
+    mod sub_mod {
+        // error:
+        unsafe impl B for (u32) {}
+        unsafe trait B {}
+    }
+
+    #[rustfmt::skip]
+    mod sub_mod2 {
+        //
+        // SAFETY: ok
+        //
+
+        unsafe impl B for (u32) {}
+        unsafe trait B {}
+    }
+}
+
+mod unsafe_impl_from_macro {
+    unsafe trait T {}
+
+    // error
+    macro_rules! no_safety_comment {
+        ($t:ty) => {
+            unsafe impl T for $t {}
+        };
+    }
+
+    // ok
+    no_safety_comment!(());
+
+    // ok
+    macro_rules! with_safety_comment {
+        ($t:ty) => {
+            // SAFETY:
+            unsafe impl T for $t {}
+        };
+    }
+
+    // ok
+    with_safety_comment!((i32));
+}
+
+mod unsafe_impl_macro_and_not_macro {
+    unsafe trait T {}
+
+    // error
+    macro_rules! no_safety_comment {
+        ($t:ty) => {
+            unsafe impl T for $t {}
+        };
+    }
+
+    // ok
+    no_safety_comment!(());
+
+    // error
+    unsafe impl T for (i32) {}
+
+    // ok
+    no_safety_comment!(u32);
+
+    // error
+    unsafe impl T for (bool) {}
+}
+
+#[rustfmt::skip]
+mod unsafe_impl_valid_comment {
+    unsafe trait SaFety {}
+    // SaFety:
+    unsafe impl SaFety for () {}
+
+    unsafe trait MultiLineComment {}
+    // The following impl is safe
+    // ...
+    // Safety: reason
+    unsafe impl MultiLineComment for () {}
+
+    unsafe trait NoAscii {}
+    // 安全 SAFETY: 以下のコードは安全です
+    unsafe impl NoAscii for () {}
+
+    unsafe trait InlineAndPrecedingComment {}
+    // SAFETY:
+    /* comment */ unsafe impl InlineAndPrecedingComment for () {}
+
+    unsafe trait BuriedSafety {}
+    // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+    // incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
+    // ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
+    // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
+    // occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
+    // laborum. Safety:
+    // Tellus elementum sagittis vitae et leo duis ut diam quam. Sit amet nulla facilisi
+    // morbi tempus iaculis urna. Amet luctus venenatis lectus magna. At quis risus sed vulputate odio
+    // ut. Luctus venenatis lectus magna fringilla urna. Tortor id aliquet lectus proin nibh nisl
+    // condimentum id venenatis. Vulputate dignissim suspendisse in est ante in nibh mauris cursus.
+    unsafe impl BuriedSafety for () {}
+
+    unsafe trait MultiLineBlockComment {}
+    /* This is a description
+     * Safety: */
+    unsafe impl MultiLineBlockComment for () {}
+}
+
+#[rustfmt::skip]
+mod unsafe_impl_invalid_comment {
+    unsafe trait NoComment {}
+
+    unsafe impl NoComment for () {}
+
+    unsafe trait InlineComment {}
+
+    /* SAFETY: */ unsafe impl InlineComment for () {}
+
+    unsafe trait TrailingComment {}
+
+    unsafe impl TrailingComment for () {} // SAFETY:
+
+    unsafe trait Interference {}
+    // SAFETY:
+    const BIG_NUMBER: i32 = 1000000;
+    unsafe impl Interference for () {}
+}
+
+unsafe trait ImplInFn {}
+
+fn impl_in_fn() {
+    // error
+    unsafe impl ImplInFn for () {}
+
+    // SAFETY: ok
+    unsafe impl ImplInFn for (i32) {}
+}
+
+unsafe trait CrateRoot {}
+
+// error
+unsafe impl CrateRoot for () {}
+
+// SAFETY: ok
+unsafe impl CrateRoot for (i32) {}
+
+fn issue_9142() {
+    // SAFETY: ok
+    let _ =
+        // we need this comment to avoid rustfmt putting
+        // it all on one line
+        unsafe {};
+
+    // SAFETY: this is more than one level away, so it should warn
+    let _ = {
+        if unsafe { true } {
+            todo!();
+        } else {
+            let bar = unsafe {};
+            todo!();
+            bar
+        }
+    };
+}
+
+pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    1
+}
+
+pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    2
+}
+
+fn issue_10832() {
+    // Safety: A safety comment
+    let _some_variable_with_a_very_long_name_to_break_the_line =
+        unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Another safety comment
+    const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Yet another safety comment
+    static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+}
+
+fn issue_8679<T: Copy>() {
+    // SAFETY:
+    #[allow(unsafe_code)]
+    unsafe {}
+
+    // SAFETY:
+    #[expect(unsafe_code, reason = "totally safe")]
+    unsafe {
+        *std::ptr::null::<T>()
+    };
+
+    // Safety: A safety comment
+    #[allow(unsafe_code)]
+    let _some_variable_with_a_very_long_name_to_break_the_line =
+        unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Another safety comment
+    #[allow(unsafe_code)]
+    const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Yet another safety comment
+    #[allow(unsafe_code)]
+    static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // SAFETY:
+    #[allow(unsafe_code)]
+    // This also works I guess
+    unsafe {}
+}
+
+fn main() {}
diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr
new file mode 100644
index 00000000000..9a0fd059389
--- /dev/null
+++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.stderr
@@ -0,0 +1,314 @@
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:263:19
+   |
+LL |     /* Safety: */ unsafe {}
+   |                   ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:267:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:271:14
+   |
+LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+   |              ^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:271:29
+   |
+LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+   |                             ^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:271:48
+   |
+LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
+   |                                                ^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:275:18
+   |
+LL |     let _ = (42, unsafe {}, "test", unsafe {});
+   |                  ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:275:37
+   |
+LL |     let _ = (42, unsafe {}, "test", unsafe {});
+   |                                     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:279:14
+   |
+LL |     let _ = *unsafe { &42 };
+   |              ^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:284:19
+   |
+LL |     let _ = match unsafe {} {
+   |                   ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:290:14
+   |
+LL |     let _ = &unsafe {};
+   |              ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:294:14
+   |
+LL |     let _ = [unsafe {}; 5];
+   |              ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:298:13
+   |
+LL |     let _ = unsafe {};
+   |             ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:308:8
+   |
+LL |     t!(unsafe {});
+   |        ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:314:13
+   |
+LL |             unsafe {}
+   |             ^^^^^^^^^
+...
+LL |     t!();
+   |     ---- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:322:5
+   |
+LL |     unsafe {} // SAFETY:
+   |     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:326:5
+   |
+LL |     unsafe {
+   |     ^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:336:5
+   |
+LL |     unsafe {};
+   |     ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:340:20
+   |
+LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:347:5
+   |
+LL |     unsafe impl A for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:354:9
+   |
+LL |         unsafe impl B for (u32) {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:375:13
+   |
+LL |             unsafe impl T for $t {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     no_safety_comment!(());
+   |     ---------------------- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:400:13
+   |
+LL |             unsafe impl T for $t {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     no_safety_comment!(());
+   |     ---------------------- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:408:5
+   |
+LL |     unsafe impl T for (i32) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:400:13
+   |
+LL |             unsafe impl T for $t {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     no_safety_comment!(u32);
+   |     ----------------------- in this macro invocation
+   |
+   = help: consider adding a safety comment on the preceding line
+   = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:414:5
+   |
+LL |     unsafe impl T for (bool) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:460:5
+   |
+LL |     unsafe impl NoComment for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:464:19
+   |
+LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:468:5
+   |
+LL |     unsafe impl TrailingComment for () {} // SAFETY:
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: constant item has unnecessary safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:472:5
+   |
+LL |     const BIG_NUMBER: i32 = 1000000;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider removing the safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:471:5
+   |
+LL |     // SAFETY:
+   |     ^^^^^^^^^^
+   = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings`
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:473:5
+   |
+LL |     unsafe impl Interference for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:480:5
+   |
+LL |     unsafe impl ImplInFn for () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe impl missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:489:1
+   |
+LL | unsafe impl CrateRoot for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: statement has unnecessary safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:502:5
+   |
+LL | /     let _ = {
+LL | |         if unsafe { true } {
+LL | |             todo!();
+LL | |         } else {
+...  |
+LL | |         }
+LL | |     };
+   | |______^
+   |
+help: consider removing the safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:501:5
+   |
+LL |     // SAFETY: this is more than one level away, so it should warn
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:503:12
+   |
+LL |         if unsafe { true } {
+   |            ^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:506:23
+   |
+LL |             let bar = unsafe {};
+   |                       ^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: aborting due to 35 previous errors
+
diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs
index f95af1017bc..7dd14e3824d 100644
--- a/tests/ui/arithmetic_side_effects.rs
+++ b/tests/ui/arithmetic_side_effects.rs
@@ -466,4 +466,19 @@ pub fn issue_10767() {
     &3.5_f32 + &1.3_f32;
 }
 
+pub fn issue_10792() {
+    struct One {
+        a: u32,
+    }
+    struct Two {
+        b: u32,
+        c: u64,
+    }
+    const ONE: One = One { a: 1 };
+    const TWO: Two = Two { b: 2, c: 3 };
+    let _ = 10 / ONE.a;
+    let _ = 10 / TWO.b;
+    let _ = 10 / TWO.c;
+}
+
 fn main() {}
diff --git a/tests/ui/auxiliary/extern_fake_libc.rs b/tests/ui/auxiliary/extern_fake_libc.rs
new file mode 100644
index 00000000000..eb5a5d2b836
--- /dev/null
+++ b/tests/ui/auxiliary/extern_fake_libc.rs
@@ -0,0 +1,10 @@
+#![allow(nonstandard_style)]
+#![allow(clippy::missing_safety_doc, unused)]
+
+type pid_t = i32;
+pub unsafe fn getpid() -> pid_t {
+    pid_t::from(0)
+}
+pub fn getpid_SAFE_TRUTH() -> pid_t {
+    unsafe { getpid() }
+}
diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs
index d9a1e76c077..6b164967a28 100644
--- a/tests/ui/auxiliary/macro_rules.rs
+++ b/tests/ui/auxiliary/macro_rules.rs
@@ -43,3 +43,10 @@ macro_rules! issue_10421 {
         b = a;
     };
 }
+
+#[macro_export]
+macro_rules! macro_with_panic {
+    () => {
+        panic!()
+    };
+}
diff --git a/tests/ui/clone_on_copy_impl.rs b/tests/ui/clone_on_copy_impl.rs
index 8f9f2a0db8c..b7c186bef77 100644
--- a/tests/ui/clone_on_copy_impl.rs
+++ b/tests/ui/clone_on_copy_impl.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::incorrect_clone_impl_on_copy_type)]
+
 use std::fmt;
 use std::marker::PhantomData;
 
diff --git a/tests/ui/crashes/ice-2774.stderr b/tests/ui/crashes/ice-2774.stderr
index c5ea0b16d1b..a166ccb3ee8 100644
--- a/tests/ui/crashes/ice-2774.stderr
+++ b/tests/ui/crashes/ice-2774.stderr
@@ -1,8 +1,8 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/ice-2774.rs:15:1
+  --> $DIR/ice-2774.rs:15:28
    |
 LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^                  ^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 help: elide the lifetimes
diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
index 0b0e0ad2684..37484f5ebd7 100644
--- a/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
@@ -1,8 +1,8 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes_impl_trait.rs:15:5
+  --> $DIR/needless_lifetimes_impl_trait.rs:15:12
    |
 LL |     fn baz<'a>(&'a self) -> impl Foo + 'a {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^   ^^                     ^^
    |
 note: the lint level is defined here
   --> $DIR/needless_lifetimes_impl_trait.rs:1:9
diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed
index aa0efb85c29..a10f3d01070 100644
--- a/tests/ui/derivable_impls.fixed
+++ b/tests/ui/derivable_impls.fixed
@@ -268,4 +268,25 @@ impl Default for OtherGenericType {
     }
 }
 
+mod issue10158 {
+    pub trait T {}
+
+    #[derive(Default)]
+    pub struct S {}
+    impl T for S {}
+
+    pub struct Outer {
+        pub inner: Box<dyn T>,
+    }
+
+    impl Default for Outer {
+        fn default() -> Self {
+            Outer {
+                // Box::<S>::default() adjusts to Box<dyn T>
+                inner: Box::<S>::default(),
+            }
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs
index 8dc999ad586..18cef1c5be8 100644
--- a/tests/ui/derivable_impls.rs
+++ b/tests/ui/derivable_impls.rs
@@ -304,4 +304,25 @@ impl Default for OtherGenericType {
     }
 }
 
+mod issue10158 {
+    pub trait T {}
+
+    #[derive(Default)]
+    pub struct S {}
+    impl T for S {}
+
+    pub struct Outer {
+        pub inner: Box<dyn T>,
+    }
+
+    impl Default for Outer {
+        fn default() -> Self {
+            Outer {
+                // Box::<S>::default() adjusts to Box<dyn T>
+                inner: Box::<S>::default(),
+            }
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs
index 843e1df8bc6..44e18bff83f 100644
--- a/tests/ui/derive.rs
+++ b/tests/ui/derive.rs
@@ -1,4 +1,4 @@
-#![allow(dead_code)]
+#![allow(clippy::incorrect_clone_impl_on_copy_type, dead_code)]
 #![warn(clippy::expl_impl_clone_on_copy)]
 
 #[derive(Copy)]
diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed
index d3aa2816cb6..14444df4c10 100644
--- a/tests/ui/doc/doc-fixable.fixed
+++ b/tests/ui/doc/doc-fixable.fixed
@@ -60,6 +60,7 @@ fn test_units() {
 /// GitHub GitLab
 /// IPv4 IPv6
 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// WebAssembly
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs
index d1e7d8017d7..542d33b13a4 100644
--- a/tests/ui/doc/doc-fixable.rs
+++ b/tests/ui/doc/doc-fixable.rs
@@ -60,6 +60,7 @@ fn test_units() {
 /// GitHub GitLab
 /// IPv4 IPv6
 /// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// WebAssembly
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr
index 6c67c903c75..94ef43afc08 100644
--- a/tests/ui/doc/doc-fixable.stderr
+++ b/tests/ui/doc/doc-fixable.stderr
@@ -132,7 +132,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:74:5
+  --> $DIR/doc-fixable.rs:75:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -143,7 +143,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:91:5
+  --> $DIR/doc-fixable.rs:92:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:99:8
+  --> $DIR/doc-fixable.rs:100:8
    |
 LL | /// ## CamelCaseThing
    |        ^^^^^^^^^^^^^^
@@ -165,7 +165,7 @@ LL | /// ## `CamelCaseThing`
    |        ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:102:7
+  --> $DIR/doc-fixable.rs:103:7
    |
 LL | /// # CamelCaseThing
    |       ^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL | /// # `CamelCaseThing`
    |       ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:104:22
+  --> $DIR/doc-fixable.rs:105:22
    |
 LL | /// Not a title #897 CamelCaseThing
    |                      ^^^^^^^^^^^^^^
@@ -187,7 +187,7 @@ LL | /// Not a title #897 `CamelCaseThing`
    |                      ~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:105:5
+  --> $DIR/doc-fixable.rs:106:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -198,7 +198,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:112:5
+  --> $DIR/doc-fixable.rs:113:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:125:5
+  --> $DIR/doc-fixable.rs:126:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +220,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:136:43
+  --> $DIR/doc-fixable.rs:137:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -231,7 +231,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
    |                                           ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:141:5
+  --> $DIR/doc-fixable.rs:142:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -242,7 +242,7 @@ LL | And `BarQuz` too.
    |     ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:142:1
+  --> $DIR/doc-fixable.rs:143:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -253,7 +253,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:147:43
+  --> $DIR/doc-fixable.rs:148:43
    |
 LL | /** E.g., serialization of an empty list: FooBar
    |                                           ^^^^^^
@@ -264,7 +264,7 @@ LL | /** E.g., serialization of an empty list: `FooBar`
    |                                           ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:152:5
+  --> $DIR/doc-fixable.rs:153:5
    |
 LL | And BarQuz too.
    |     ^^^^^^
@@ -275,7 +275,7 @@ LL | And `BarQuz` too.
    |     ~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:153:1
+  --> $DIR/doc-fixable.rs:154:1
    |
 LL | be_sure_we_got_to_the_end_of_it
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -286,7 +286,7 @@ LL | `be_sure_we_got_to_the_end_of_it`
    |
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:164:5
+  --> $DIR/doc-fixable.rs:165:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -297,7 +297,7 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:183:22
+  --> $DIR/doc-fixable.rs:184:22
    |
 LL | /// An iterator over mycrate::Collection's values.
    |                      ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs
new file mode 100644
index 00000000000..f1a2c0575ee
--- /dev/null
+++ b/tests/ui/doc/needless_doctest_main.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::needless_doctest_main)]
+//! issue 10491:
+//! ```rust,no_test
+//! use std::collections::HashMap;
+//!
+//! fn main() {
+//!     let mut m = HashMap::new();
+//!     m.insert(1u32, 2u32);
+//! }
+//! ```
+
+/// some description here
+/// ```rust,no_test
+/// fn main() {
+///     foo()
+/// }
+/// ```
+fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/drain_collect.fixed b/tests/ui/drain_collect.fixed
new file mode 100644
index 00000000000..11001bd319f
--- /dev/null
+++ b/tests/ui/drain_collect.fixed
@@ -0,0 +1,77 @@
+//@run-rustfix
+
+#![deny(clippy::drain_collect)]
+#![allow(dead_code)]
+
+use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
+
+fn binaryheap(b: &mut BinaryHeap<i32>) -> BinaryHeap<i32> {
+    std::mem::take(b)
+}
+
+fn binaryheap_dont_lint(b: &mut BinaryHeap<i32>) -> HashSet<i32> {
+    b.drain().collect()
+}
+
+fn hashmap(b: &mut HashMap<i32, i32>) -> HashMap<i32, i32> {
+    std::mem::take(b)
+}
+
+fn hashmap_dont_lint(b: &mut HashMap<i32, i32>) -> Vec<(i32, i32)> {
+    b.drain().collect()
+}
+
+fn hashset(b: &mut HashSet<i32>) -> HashSet<i32> {
+    std::mem::take(b)
+}
+
+fn hashset_dont_lint(b: &mut HashSet<i32>) -> Vec<i32> {
+    b.drain().collect()
+}
+
+fn vecdeque(b: &mut VecDeque<i32>) -> VecDeque<i32> {
+    std::mem::take(b)
+}
+
+fn vecdeque_dont_lint(b: &mut VecDeque<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn vec(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec2(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec3(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec4(b: &mut Vec<i32>) -> Vec<i32> {
+    std::mem::take(b)
+}
+
+fn vec_no_reborrow() -> Vec<i32> {
+    let mut b = vec![1, 2, 3];
+    std::mem::take(&mut b)
+}
+
+fn vec_dont_lint(b: &mut Vec<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn string(b: &mut String) -> String {
+    std::mem::take(b)
+}
+
+fn string_dont_lint(b: &mut String) -> HashSet<char> {
+    b.drain(..).collect()
+}
+
+fn not_whole_length(v: &mut Vec<i32>) -> Vec<i32> {
+    v.drain(1..).collect()
+}
+
+fn main() {}
diff --git a/tests/ui/drain_collect.rs b/tests/ui/drain_collect.rs
new file mode 100644
index 00000000000..373a3ca3506
--- /dev/null
+++ b/tests/ui/drain_collect.rs
@@ -0,0 +1,77 @@
+//@run-rustfix
+
+#![deny(clippy::drain_collect)]
+#![allow(dead_code)]
+
+use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
+
+fn binaryheap(b: &mut BinaryHeap<i32>) -> BinaryHeap<i32> {
+    b.drain().collect()
+}
+
+fn binaryheap_dont_lint(b: &mut BinaryHeap<i32>) -> HashSet<i32> {
+    b.drain().collect()
+}
+
+fn hashmap(b: &mut HashMap<i32, i32>) -> HashMap<i32, i32> {
+    b.drain().collect()
+}
+
+fn hashmap_dont_lint(b: &mut HashMap<i32, i32>) -> Vec<(i32, i32)> {
+    b.drain().collect()
+}
+
+fn hashset(b: &mut HashSet<i32>) -> HashSet<i32> {
+    b.drain().collect()
+}
+
+fn hashset_dont_lint(b: &mut HashSet<i32>) -> Vec<i32> {
+    b.drain().collect()
+}
+
+fn vecdeque(b: &mut VecDeque<i32>) -> VecDeque<i32> {
+    b.drain(..).collect()
+}
+
+fn vecdeque_dont_lint(b: &mut VecDeque<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn vec(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(..).collect()
+}
+
+fn vec2(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(0..).collect()
+}
+
+fn vec3(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(..b.len()).collect()
+}
+
+fn vec4(b: &mut Vec<i32>) -> Vec<i32> {
+    b.drain(0..b.len()).collect()
+}
+
+fn vec_no_reborrow() -> Vec<i32> {
+    let mut b = vec![1, 2, 3];
+    b.drain(..).collect()
+}
+
+fn vec_dont_lint(b: &mut Vec<i32>) -> HashSet<i32> {
+    b.drain(..).collect()
+}
+
+fn string(b: &mut String) -> String {
+    b.drain(..).collect()
+}
+
+fn string_dont_lint(b: &mut String) -> HashSet<char> {
+    b.drain(..).collect()
+}
+
+fn not_whole_length(v: &mut Vec<i32>) -> Vec<i32> {
+    v.drain(1..).collect()
+}
+
+fn main() {}
diff --git a/tests/ui/drain_collect.stderr b/tests/ui/drain_collect.stderr
new file mode 100644
index 00000000000..0792f0254cb
--- /dev/null
+++ b/tests/ui/drain_collect.stderr
@@ -0,0 +1,68 @@
+error: you seem to be trying to move all elements into a new `BinaryHeap`
+  --> $DIR/drain_collect.rs:9:5
+   |
+LL |     b.drain().collect()
+   |     ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+   |
+note: the lint level is defined here
+  --> $DIR/drain_collect.rs:3:9
+   |
+LL | #![deny(clippy::drain_collect)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: you seem to be trying to move all elements into a new `HashMap`
+  --> $DIR/drain_collect.rs:17:5
+   |
+LL |     b.drain().collect()
+   |     ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `HashSet`
+  --> $DIR/drain_collect.rs:25:5
+   |
+LL |     b.drain().collect()
+   |     ^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:33:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:41:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:45:5
+   |
+LL |     b.drain(0..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:49:5
+   |
+LL |     b.drain(..b.len()).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:53:5
+   |
+LL |     b.drain(0..b.len()).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: you seem to be trying to move all elements into a new `Vec`
+  --> $DIR/drain_collect.rs:58:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(&mut b)`
+
+error: you seem to be trying to move all elements into a new `String`
+  --> $DIR/drain_collect.rs:66:5
+   |
+LL |     b.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `std::mem::take(b)`
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed
index 1bcaa33a049..7bb4da453c1 100644
--- a/tests/ui/excessive_precision.fixed
+++ b/tests/ui/excessive_precision.fixed
@@ -1,6 +1,12 @@
 //@run-rustfix
 #![warn(clippy::excessive_precision)]
-#![allow(dead_code, unused_variables, clippy::print_literal, clippy::useless_vec)]
+#![allow(
+    dead_code,
+    overflowing_literals,
+    unused_variables,
+    clippy::print_literal,
+    clippy::useless_vec
+)]
 
 fn main() {
     // Consts
@@ -66,4 +72,11 @@ fn main() {
 
     // issue #7745
     let _ = 0_f64;
+
+    // issue #9910
+    const INF1: f32 = 1.0e+33f32;
+    const INF2: f64 = 1.0e+3300f64;
+    const NEG_INF1: f32 = -1.0e+33f32;
+    const NEG_INF2: f64 = -1.0e+3300f64;
+    const NEG_INF3: f32 = -3.40282357e+38_f32;
 }
diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs
index cee937e07e1..e8d6ab6870a 100644
--- a/tests/ui/excessive_precision.rs
+++ b/tests/ui/excessive_precision.rs
@@ -1,6 +1,12 @@
 //@run-rustfix
 #![warn(clippy::excessive_precision)]
-#![allow(dead_code, unused_variables, clippy::print_literal, clippy::useless_vec)]
+#![allow(
+    dead_code,
+    overflowing_literals,
+    unused_variables,
+    clippy::print_literal,
+    clippy::useless_vec
+)]
 
 fn main() {
     // Consts
@@ -66,4 +72,11 @@ fn main() {
 
     // issue #7745
     let _ = 1.000_000_000_000_001e-324_f64;
+
+    // issue #9910
+    const INF1: f32 = 1.0e+33f32;
+    const INF2: f64 = 1.0e+3300f64;
+    const NEG_INF1: f32 = -1.0e+33f32;
+    const NEG_INF2: f64 = -1.0e+3300f64;
+    const NEG_INF3: f32 = -3.40282357e+38_f32;
 }
diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr
index 42d9d4de193..348ad183d7d 100644
--- a/tests/ui/excessive_precision.stderr
+++ b/tests/ui/excessive_precision.stderr
@@ -1,5 +1,5 @@
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:15:26
+  --> $DIR/excessive_precision.rs:21:26
    |
 LL |     const BAD32_1: f32 = 0.123_456_789_f32;
    |                          ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32`
@@ -7,85 +7,85 @@ LL |     const BAD32_1: f32 = 0.123_456_789_f32;
    = note: `-D clippy::excessive-precision` implied by `-D warnings`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:16:26
+  --> $DIR/excessive_precision.rs:22:26
    |
 LL |     const BAD32_2: f32 = 0.123_456_789;
    |                          ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:17:26
+  --> $DIR/excessive_precision.rs:23:26
    |
 LL |     const BAD32_3: f32 = 0.100_000_000_000_1;
    |                          ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:18:29
+  --> $DIR/excessive_precision.rs:24:29
    |
 LL |     const BAD32_EDGE: f32 = 1.000_000_9;
    |                             ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:22:26
+  --> $DIR/excessive_precision.rs:28:26
    |
 LL |     const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:25:22
+  --> $DIR/excessive_precision.rs:31:22
    |
 LL |     println!("{:?}", 8.888_888_888_888_888_888_888);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:36:22
+  --> $DIR/excessive_precision.rs:42:22
    |
 LL |     let bad32: f32 = 1.123_456_789;
    |                      ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:37:26
+  --> $DIR/excessive_precision.rs:43:26
    |
 LL |     let bad32_suf: f32 = 1.123_456_789_f32;
    |                          ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:38:21
+  --> $DIR/excessive_precision.rs:44:21
    |
 LL |     let bad32_inf = 1.123_456_789_f32;
    |                     ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:48:36
+  --> $DIR/excessive_precision.rs:54:36
    |
 LL |     let bad_vec32: Vec<f32> = vec![0.123_456_789];
    |                                    ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:49:36
+  --> $DIR/excessive_precision.rs:55:36
    |
 LL |     let bad_vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:53:24
+  --> $DIR/excessive_precision.rs:59:24
    |
 LL |     let bad_e32: f32 = 1.123_456_788_888e-10;
    |                        ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:56:27
+  --> $DIR/excessive_precision.rs:62:27
    |
 LL |     let bad_bige32: f32 = 1.123_456_788_888E-10;
    |                           ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:65:13
+  --> $DIR/excessive_precision.rs:71:13
    |
 LL |     let _ = 2.225_073_858_507_201_1e-308_f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64`
 
 error: float has excessive precision
-  --> $DIR/excessive_precision.rs:68:13
+  --> $DIR/excessive_precision.rs:74:13
    |
 LL |     let _ = 1.000_000_000_000_001e-324_f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64`
diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed
index d18f9387565..00895e594f6 100644
--- a/tests/ui/from_over_into.fixed
+++ b/tests/ui/from_over_into.fixed
@@ -60,6 +60,15 @@ impl From<String> for A {
     }
 }
 
+struct PathInExpansion;
+
+impl From<PathInExpansion> for String {
+    fn from(val: PathInExpansion) -> Self {
+        // non self/Self paths in expansions are fine
+        panic!()
+    }
+}
+
 #[clippy::msrv = "1.40"]
 fn msrv_1_40() {
     struct FromOverInto<T>(Vec<T>);
diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs
index de8ff0b06bd..7f8c76693fd 100644
--- a/tests/ui/from_over_into.rs
+++ b/tests/ui/from_over_into.rs
@@ -60,6 +60,15 @@ impl From<String> for A {
     }
 }
 
+struct PathInExpansion;
+
+impl Into<String> for PathInExpansion {
+    fn into(self) -> String {
+        // non self/Self paths in expansions are fine
+        panic!()
+    }
+}
+
 #[clippy::msrv = "1.40"]
 fn msrv_1_40() {
     struct FromOverInto<T>(Vec<T>);
diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr
index 6039f86fe67..498b00de5ad 100644
--- a/tests/ui/from_over_into.stderr
+++ b/tests/ui/from_over_into.stderr
@@ -59,7 +59,21 @@ LL ~         val.0
    |
 
 error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
-  --> $DIR/from_over_into.rs:78:5
+  --> $DIR/from_over_into.rs:65:1
+   |
+LL | impl Into<String> for PathInExpansion {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+           https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+help: replace the `Into` implementation with `From<PathInExpansion>`
+   |
+LL ~ impl From<PathInExpansion> for String {
+LL ~     fn from(val: PathInExpansion) -> Self {
+   |
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into.rs:87:5
    |
 LL |     impl<T> Into<FromOverInto<T>> for Vec<T> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,5 +85,5 @@ LL ~         fn from(val: Vec<T>) -> Self {
 LL ~             FromOverInto(val)
    |
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/from_over_into_unfixable.rs b/tests/ui/from_over_into_unfixable.rs
index 92d3504bc23..c769e38eb33 100644
--- a/tests/ui/from_over_into_unfixable.rs
+++ b/tests/ui/from_over_into_unfixable.rs
@@ -3,14 +3,14 @@
 struct InMacro(String);
 
 macro_rules! in_macro {
-    ($e:ident) => {
-        $e
+    () => {
+        Self::new()
     };
 }
 
 impl Into<InMacro> for String {
     fn into(self) -> InMacro {
-        InMacro(in_macro!(self))
+        InMacro(in_macro!())
     }
 }
 
diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.fixed b/tests/ui/incorrect_clone_impl_on_copy_type.fixed
new file mode 100644
index 00000000000..ac482dcda1e
--- /dev/null
+++ b/tests/ui/incorrect_clone_impl_on_copy_type.fixed
@@ -0,0 +1,97 @@
+//@run-rustfix
+#![allow(clippy::clone_on_copy, unused)]
+#![no_main]
+
+// lint
+
+struct A(u32);
+
+impl Clone for A {
+    fn clone(&self) -> Self { *self }
+
+    
+}
+
+impl Copy for A {}
+
+// do not lint
+
+struct B(u32);
+
+impl Clone for B {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl Copy for B {}
+
+// do not lint derived (clone's implementation is `*self` here anyway)
+
+#[derive(Clone, Copy)]
+struct C(u32);
+
+// do not lint derived (fr this time)
+
+struct D(u32);
+
+#[automatically_derived]
+impl Clone for D {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for D {}
+
+// do not lint if clone is not manually implemented
+
+struct E(u32);
+
+#[automatically_derived]
+impl Clone for E {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for E {}
+
+// lint since clone is not derived
+
+#[derive(Copy)]
+struct F(u32);
+
+impl Clone for F {
+    fn clone(&self) -> Self { *self }
+
+    
+}
+
+// do not lint since copy has more restrictive bounds
+
+#[derive(Eq, PartialEq)]
+struct Uwu<A: Copy>(A);
+
+impl<A: Copy> Clone for Uwu<A> {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}
diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.rs b/tests/ui/incorrect_clone_impl_on_copy_type.rs
new file mode 100644
index 00000000000..00775874ff5
--- /dev/null
+++ b/tests/ui/incorrect_clone_impl_on_copy_type.rs
@@ -0,0 +1,107 @@
+//@run-rustfix
+#![allow(clippy::clone_on_copy, unused)]
+#![no_main]
+
+// lint
+
+struct A(u32);
+
+impl Clone for A {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for A {}
+
+// do not lint
+
+struct B(u32);
+
+impl Clone for B {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl Copy for B {}
+
+// do not lint derived (clone's implementation is `*self` here anyway)
+
+#[derive(Clone, Copy)]
+struct C(u32);
+
+// do not lint derived (fr this time)
+
+struct D(u32);
+
+#[automatically_derived]
+impl Clone for D {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for D {}
+
+// do not lint if clone is not manually implemented
+
+struct E(u32);
+
+#[automatically_derived]
+impl Clone for E {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl Copy for E {}
+
+// lint since clone is not derived
+
+#[derive(Copy)]
+struct F(u32);
+
+impl Clone for F {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+// do not lint since copy has more restrictive bounds
+
+#[derive(Eq, PartialEq)]
+struct Uwu<A: Copy>(A);
+
+impl<A: Copy> Clone for Uwu<A> {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        source.clone();
+        *self = source.clone();
+    }
+}
+
+impl<A: std::fmt::Debug + Copy + Clone> Copy for Uwu<A> {}
diff --git a/tests/ui/incorrect_clone_impl_on_copy_type.stderr b/tests/ui/incorrect_clone_impl_on_copy_type.stderr
new file mode 100644
index 00000000000..0021841aa86
--- /dev/null
+++ b/tests/ui/incorrect_clone_impl_on_copy_type.stderr
@@ -0,0 +1,40 @@
+error: incorrect implementation of `clone` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:10:29
+   |
+LL |       fn clone(&self) -> Self {
+   |  _____________________________^
+LL | |         Self(self.0)
+LL | |     }
+   | |_____^ help: change this to: `{ *self }`
+   |
+   = note: `#[deny(clippy::incorrect_clone_impl_on_copy_type)]` on by default
+
+error: incorrect implementation of `clone_from` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:14:5
+   |
+LL | /     fn clone_from(&mut self, source: &Self) {
+LL | |         source.clone();
+LL | |         *self = source.clone();
+LL | |     }
+   | |_____^ help: remove this
+
+error: incorrect implementation of `clone` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:81:29
+   |
+LL |       fn clone(&self) -> Self {
+   |  _____________________________^
+LL | |         Self(self.0)
+LL | |     }
+   | |_____^ help: change this to: `{ *self }`
+
+error: incorrect implementation of `clone_from` on a `Copy` type
+  --> $DIR/incorrect_clone_impl_on_copy_type.rs:85:5
+   |
+LL | /     fn clone_from(&mut self, source: &Self) {
+LL | |         source.clone();
+LL | |         *self = source.clone();
+LL | |     }
+   | |_____^ help: remove this
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr
index fd553aa4538..5b60646ef21 100644
--- a/tests/ui/issue_4266.stderr
+++ b/tests/ui/issue_4266.stderr
@@ -1,16 +1,16 @@
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/issue_4266.rs:4:1
+  --> $DIR/issue_4266.rs:4:16
    |
 LL | async fn sink1<'a>(_: &'a str) {} // lint
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^      ^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/issue_4266.rs:8:1
+  --> $DIR/issue_4266.rs:8:21
    |
 LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^      ^^
 
 error: methods called `new` usually take no `self`
   --> $DIR/issue_4266.rs:28:22
diff --git a/tests/ui/iter_with_drain.fixed b/tests/ui/iter_with_drain.fixed
index 24a95c4d0fe..7a8c6770101 100644
--- a/tests/ui/iter_with_drain.fixed
+++ b/tests/ui/iter_with_drain.fixed
@@ -2,7 +2,7 @@
 // will emits unused mut warnings after fixing
 #![allow(unused_mut)]
 // will emits needless collect warnings after fixing
-#![allow(clippy::needless_collect)]
+#![allow(clippy::needless_collect, clippy::drain_collect)]
 #![warn(clippy::iter_with_drain)]
 use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
 
diff --git a/tests/ui/iter_with_drain.rs b/tests/ui/iter_with_drain.rs
index a118c981ee3..cf3a935c349 100644
--- a/tests/ui/iter_with_drain.rs
+++ b/tests/ui/iter_with_drain.rs
@@ -2,7 +2,7 @@
 // will emits unused mut warnings after fixing
 #![allow(unused_mut)]
 // will emits needless collect warnings after fixing
-#![allow(clippy::needless_collect)]
+#![allow(clippy::needless_collect, clippy::drain_collect)]
 #![warn(clippy::iter_with_drain)]
 use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
 
diff --git a/tests/ui/lossy_float_literal.fixed b/tests/ui/lossy_float_literal.fixed
index a2088575610..e19f4980cd7 100644
--- a/tests/ui/lossy_float_literal.fixed
+++ b/tests/ui/lossy_float_literal.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::lossy_float_literal)]
+#![allow(overflowing_literals, unused)]
 
 fn main() {
     // Lossy whole-number float literals
@@ -32,4 +33,7 @@ fn main() {
     let _: f64 = 1e99;
     let _: f64 = 1E99;
     let _: f32 = 0.1;
+
+    const INF1: f32 = 1000000000000000000000000000000000f32;
+    const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32;
 }
diff --git a/tests/ui/lossy_float_literal.rs b/tests/ui/lossy_float_literal.rs
index 1a75f214c85..a2a1cfb317e 100644
--- a/tests/ui/lossy_float_literal.rs
+++ b/tests/ui/lossy_float_literal.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::lossy_float_literal)]
+#![allow(overflowing_literals, unused)]
 
 fn main() {
     // Lossy whole-number float literals
@@ -32,4 +33,7 @@ fn main() {
     let _: f64 = 1e99;
     let _: f64 = 1E99;
     let _: f32 = 0.1;
+
+    const INF1: f32 = 1000000000000000000000000000000000f32;
+    const NEG_INF1: f32 = -340282357000000000000000000000000000001_f32;
 }
diff --git a/tests/ui/lossy_float_literal.stderr b/tests/ui/lossy_float_literal.stderr
index d2193c0c819..2d72b16430c 100644
--- a/tests/ui/lossy_float_literal.stderr
+++ b/tests/ui/lossy_float_literal.stderr
@@ -1,5 +1,5 @@
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:6:18
+  --> $DIR/lossy_float_literal.rs:7:18
    |
 LL |     let _: f32 = 16_777_217.0;
    |                  ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0`
@@ -7,61 +7,61 @@ LL |     let _: f32 = 16_777_217.0;
    = note: `-D clippy::lossy-float-literal` implied by `-D warnings`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:7:18
+  --> $DIR/lossy_float_literal.rs:8:18
    |
 LL |     let _: f32 = 16_777_219.0;
    |                  ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:8:18
+  --> $DIR/lossy_float_literal.rs:9:18
    |
 LL |     let _: f32 = 16_777_219.;
    |                  ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:9:18
+  --> $DIR/lossy_float_literal.rs:10:18
    |
 LL |     let _: f32 = 16_777_219.000;
    |                  ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:10:13
+  --> $DIR/lossy_float_literal.rs:11:13
    |
 LL |     let _ = 16_777_219f32;
    |             ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:11:19
+  --> $DIR/lossy_float_literal.rs:12:19
    |
 LL |     let _: f32 = -16_777_219.0;
    |                   ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:12:18
+  --> $DIR/lossy_float_literal.rs:13:18
    |
 LL |     let _: f64 = 9_007_199_254_740_993.0;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:13:18
+  --> $DIR/lossy_float_literal.rs:14:18
    |
 LL |     let _: f64 = 9_007_199_254_740_993.;
    |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:14:18
+  --> $DIR/lossy_float_literal.rs:15:18
    |
 LL |     let _: f64 = 9_007_199_254_740_993.00;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:15:13
+  --> $DIR/lossy_float_literal.rs:16:13
    |
 LL |     let _ = 9_007_199_254_740_993f64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64`
 
 error: literal cannot be represented as the underlying type without loss of precision
-  --> $DIR/lossy_float_literal.rs:16:19
+  --> $DIR/lossy_float_literal.rs:17:19
    |
 LL |     let _: f64 = -9_007_199_254_740_993.0;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs
index cb25d8567aa..0cd49dd7760 100644
--- a/tests/ui/map_unwrap_or.rs
+++ b/tests/ui/map_unwrap_or.rs
@@ -94,3 +94,32 @@ fn msrv_1_41() {
 
     let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0);
 }
+
+mod issue_10579 {
+    // Different variations of the same issue.
+    fn v1() {
+        let x = vec![1, 2, 3, 0];
+        let y = x.strip_suffix(&[0]).map(|s| s.to_vec()).unwrap_or(x);
+        println!("{y:?}");
+    }
+    fn v2() {
+        let x = vec![1, 2, 3, 0];
+        let y = Some(()).map(|_| x.to_vec()).unwrap_or(x);
+        println!("{y:?}");
+    }
+    fn v3() {
+        let x = vec![1, 2, 3, 0];
+        let xref = &x;
+        let y = Some(()).map(|_| xref.to_vec()).unwrap_or(x);
+        println!("{y:?}");
+    }
+    fn v4() {
+        struct VecInStruct {
+            v: Vec<u8>,
+        }
+        let s = VecInStruct { v: vec![1, 2, 3, 0] };
+
+        let y = Some(()).map(|_| s.v.clone()).unwrap_or(s.v);
+        println!("{y:?}");
+    }
+}
diff --git a/tests/ui/match_same_arms_non_exhaustive.rs b/tests/ui/match_same_arms_non_exhaustive.rs
new file mode 100644
index 00000000000..07421173a33
--- /dev/null
+++ b/tests/ui/match_same_arms_non_exhaustive.rs
@@ -0,0 +1,58 @@
+#![feature(non_exhaustive_omitted_patterns_lint)]
+#![warn(clippy::match_same_arms)]
+#![no_main]
+
+use std::sync::atomic::Ordering; // #[non_exhaustive] enum
+
+pub fn f(x: Ordering) {
+    match x {
+        Ordering::Relaxed => println!("relaxed"),
+        Ordering::Release => println!("release"),
+        Ordering::Acquire => println!("acquire"),
+        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => panic!(),
+    }
+}
+
+mod f {
+    #![deny(non_exhaustive_omitted_patterns)]
+
+    use super::*;
+
+    pub fn f(x: Ordering) {
+        match x {
+            Ordering::Relaxed => println!("relaxed"),
+            Ordering::Release => println!("release"),
+            Ordering::Acquire => println!("acquire"),
+            Ordering::AcqRel | Ordering::SeqCst => panic!(),
+            _ => panic!(),
+        }
+    }
+}
+
+// Below should still lint
+
+pub fn g(x: Ordering) {
+    match x {
+        Ordering::Relaxed => println!("relaxed"),
+        Ordering::Release => println!("release"),
+        Ordering::Acquire => println!("acquire"),
+        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        _ => panic!(),
+    }
+}
+
+mod g {
+    use super::*;
+
+    pub fn g(x: Ordering) {
+        match x {
+            Ordering::Relaxed => println!("relaxed"),
+            Ordering::Release => println!("release"),
+            Ordering::Acquire => println!("acquire"),
+            Ordering::AcqRel | Ordering::SeqCst => panic!(),
+            _ => panic!(),
+        }
+    }
+}
diff --git a/tests/ui/match_same_arms_non_exhaustive.stderr b/tests/ui/match_same_arms_non_exhaustive.stderr
new file mode 100644
index 00000000000..088f7d5c062
--- /dev/null
+++ b/tests/ui/match_same_arms_non_exhaustive.stderr
@@ -0,0 +1,29 @@
+error: this match arm has an identical body to the `_` wildcard arm
+  --> $DIR/match_same_arms_non_exhaustive.rs:41:9
+   |
+LL |         Ordering::AcqRel | Ordering::SeqCst => panic!(),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
+   |
+   = help: or try changing either arm body
+note: `_` wildcard arm here
+  --> $DIR/match_same_arms_non_exhaustive.rs:42:9
+   |
+LL |         _ => panic!(),
+   |         ^^^^^^^^^^^^^
+   = note: `-D clippy::match-same-arms` implied by `-D warnings`
+
+error: this match arm has an identical body to the `_` wildcard arm
+  --> $DIR/match_same_arms_non_exhaustive.rs:54:13
+   |
+LL |             Ordering::AcqRel | Ordering::SeqCst => panic!(),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
+   |
+   = help: or try changing either arm body
+note: `_` wildcard arm here
+  --> $DIR/match_same_arms_non_exhaustive.rs:55:13
+   |
+LL |             _ => panic!(),
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs
index 286d208b25b..abadf82fe4b 100644
--- a/tests/ui/missing_const_for_fn/cant_be_const.rs
+++ b/tests/ui/missing_const_for_fn/cant_be_const.rs
@@ -157,3 +157,12 @@ impl Issue10617 {
         self.0
     }
 }
+
+union U {
+    f: u32,
+}
+
+// Do not lint because accessing union fields from const functions is unstable
+fn h(u: U) -> u32 {
+    unsafe { u.f }
+}
diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs
index 10aa436d6cd..0e1533fc1ab 100644
--- a/tests/ui/missing_panics_doc.rs
+++ b/tests/ui/missing_panics_doc.rs
@@ -1,5 +1,12 @@
+//@aux-build:macro_rules.rs
 #![warn(clippy::missing_panics_doc)]
 #![allow(clippy::option_map_unit_fn, clippy::unnecessary_literal_unwrap)]
+
+#[macro_use]
+extern crate macro_rules;
+
+use macro_rules::macro_with_panic;
+
 fn main() {}
 
 /// This needs to be documented
@@ -14,11 +21,6 @@ pub fn panic() {
 }
 
 /// This needs to be documented
-pub fn todo() {
-    todo!()
-}
-
-/// This needs to be documented
 pub fn inner_body(opt: Option<u32>) {
     opt.map(|x| {
         if x == 10 {
@@ -81,15 +83,6 @@ pub fn inner_body_documented(opt: Option<u32>) {
 /// # Panics
 ///
 /// We still need to do this part
-pub fn todo_documented() {
-    todo!()
-}
-
-/// This is documented
-///
-/// # Panics
-///
-/// We still need to do this part
 pub fn unreachable_amd_panic_documented() {
     if true { unreachable!() } else { panic!() }
 }
@@ -114,6 +107,11 @@ pub fn assert_ne_documented() {
     assert_ne!(x, 0);
 }
 
+/// `todo!()` is fine
+pub fn todo() {
+    todo!()
+}
+
 /// This is okay because it is private
 fn unwrap_private() {
     let result = Err("Hi");
@@ -126,11 +124,6 @@ fn panic_private() {
 }
 
 /// This is okay because it is private
-fn todo_private() {
-    todo!()
-}
-
-/// This is okay because it is private
 fn inner_body_private(opt: Option<u32>) {
     opt.map(|x| {
         if x == 10 {
@@ -151,3 +144,50 @@ pub fn debug_assertions() {
     debug_assert_eq!(1, 2);
     debug_assert_ne!(1, 2);
 }
+
+// all function must be triggered the lint.
+// `pub` is required, because the lint does not consider unreachable items
+pub mod issue10240 {
+    pub fn option_unwrap<T>(v: &[T]) -> &T {
+        let o: Option<&T> = v.last();
+        o.unwrap()
+    }
+
+    pub fn option_expect<T>(v: &[T]) -> &T {
+        let o: Option<&T> = v.last();
+        o.expect("passed an empty thing")
+    }
+
+    pub fn result_unwrap<T>(v: &[T]) -> &T {
+        let res: Result<&T, &str> = v.last().ok_or("oh noes");
+        res.unwrap()
+    }
+
+    pub fn result_expect<T>(v: &[T]) -> &T {
+        let res: Result<&T, &str> = v.last().ok_or("oh noes");
+        res.expect("passed an empty thing")
+    }
+
+    pub fn last_unwrap(v: &[u32]) -> u32 {
+        *v.last().unwrap()
+    }
+
+    pub fn last_expect(v: &[u32]) -> u32 {
+        *v.last().expect("passed an empty thing")
+    }
+}
+
+fn from_external_macro_should_not_lint() {
+    macro_with_panic!()
+}
+
+macro_rules! some_macro_that_panics {
+    () => {
+        panic!()
+    };
+}
+
+fn from_declared_macro_should_lint_at_macrosite() {
+    // Not here.
+    some_macro_that_panics!()
+}
diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr
index 183c262ce0b..3dbe2dfbd88 100644
--- a/tests/ui/missing_panics_doc.stderr
+++ b/tests/ui/missing_panics_doc.stderr
@@ -1,87 +1,147 @@
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:6:1
+  --> $DIR/missing_panics_doc.rs:13:1
    |
 LL | pub fn unwrap() {
    | ^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:8:5
+  --> $DIR/missing_panics_doc.rs:15:5
    |
 LL |     result.unwrap()
    |     ^^^^^^^^^^^^^^^
    = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:12:1
+  --> $DIR/missing_panics_doc.rs:19:1
    |
 LL | pub fn panic() {
    | ^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:13:5
+  --> $DIR/missing_panics_doc.rs:20:5
    |
 LL |     panic!("This function panics")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:17:1
-   |
-LL | pub fn todo() {
-   | ^^^^^^^^^^^^^
-   |
-note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:18:5
-   |
-LL |     todo!()
-   |     ^^^^^^^
-
-error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:22:1
+  --> $DIR/missing_panics_doc.rs:24:1
    |
 LL | pub fn inner_body(opt: Option<u32>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:25:13
+  --> $DIR/missing_panics_doc.rs:27:13
    |
 LL |             panic!()
    |             ^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:31:1
+  --> $DIR/missing_panics_doc.rs:33:1
    |
 LL | pub fn unreachable_and_panic() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:32:39
+  --> $DIR/missing_panics_doc.rs:34:39
    |
 LL |     if true { unreachable!() } else { panic!() }
    |                                       ^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:36:1
+  --> $DIR/missing_panics_doc.rs:38:1
    |
 LL | pub fn assert_eq() {
    | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:38:5
+  --> $DIR/missing_panics_doc.rs:40:5
    |
 LL |     assert_eq!(x, 0);
    |     ^^^^^^^^^^^^^^^^
 
 error: docs for function which may panic missing `# Panics` section
-  --> $DIR/missing_panics_doc.rs:42:1
+  --> $DIR/missing_panics_doc.rs:44:1
    |
 LL | pub fn assert_ne() {
    | ^^^^^^^^^^^^^^^^^^
    |
 note: first possible panic found here
-  --> $DIR/missing_panics_doc.rs:44:5
+  --> $DIR/missing_panics_doc.rs:46:5
    |
 LL |     assert_ne!(x, 0);
    |     ^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:151:5
+   |
+LL |     pub fn option_unwrap<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:153:9
+   |
+LL |         o.unwrap()
+   |         ^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:156:5
+   |
+LL |     pub fn option_expect<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:158:9
+   |
+LL |         o.expect("passed an empty thing")
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:161:5
+   |
+LL |     pub fn result_unwrap<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:163:9
+   |
+LL |         res.unwrap()
+   |         ^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:166:5
+   |
+LL |     pub fn result_expect<T>(v: &[T]) -> &T {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:168:9
+   |
+LL |         res.expect("passed an empty thing")
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:171:5
+   |
+LL |     pub fn last_unwrap(v: &[u32]) -> u32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:172:10
+   |
+LL |         *v.last().unwrap()
+   |          ^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> $DIR/missing_panics_doc.rs:175:5
+   |
+LL |     pub fn last_expect(v: &[u32]) -> u32 {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> $DIR/missing_panics_doc.rs:176:10
+   |
+LL |         *v.last().expect("passed an empty thing")
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr
index 86acc4e0046..0da67b600a3 100644
--- a/tests/ui/needless_lifetimes.stderr
+++ b/tests/ui/needless_lifetimes.stderr
@@ -1,8 +1,8 @@
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:18:1
+  --> $DIR/needless_lifetimes.rs:18:23
    |
 LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^  ^^       ^^          ^^
    |
    = note: `-D clippy::needless-lifetimes` implied by `-D warnings`
 help: elide the lifetimes
@@ -12,10 +12,10 @@ LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:20:1
+  --> $DIR/needless_lifetimes.rs:20:24
    |
 LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^  ^^       ^^          ^^
    |
 help: elide the lifetimes
    |
@@ -24,10 +24,10 @@ LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:30:1
+  --> $DIR/needless_lifetimes.rs:30:15
    |
 LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               ^^      ^^                 ^^
    |
 help: elide the lifetimes
    |
@@ -36,10 +36,10 @@ LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:42:1
+  --> $DIR/needless_lifetimes.rs:42:31
    |
 LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^                  ^^
    |
 help: elide the lifetimes
    |
@@ -48,10 +48,10 @@ LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:49:1
+  --> $DIR/needless_lifetimes.rs:49:27
    |
 LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -60,10 +60,10 @@ LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:66:1
+  --> $DIR/needless_lifetimes.rs:66:26
    |
 LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^                  ^^
    |
 help: elide the lifetimes
    |
@@ -72,10 +72,10 @@ LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:73:1
+  --> $DIR/needless_lifetimes.rs:73:22
    |
 LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -84,10 +84,10 @@ LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:82:1
+  --> $DIR/needless_lifetimes.rs:82:21
    |
 LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^      ^^                        ^^
    |
 help: elide the lifetimes
    |
@@ -96,10 +96,10 @@ LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:87:1
+  --> $DIR/needless_lifetimes.rs:87:28
    |
 LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^         ^^                        ^^
    |
 help: elide the lifetimes
    |
@@ -108,10 +108,10 @@ LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
    |
 
 error: the following explicit lifetimes could be elided: 'a, 'b
-  --> $DIR/needless_lifetimes.rs:99:1
+  --> $DIR/needless_lifetimes.rs:99:21
    |
 LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^  ^^          ^^        ^^
    |
 help: elide the lifetimes
    |
@@ -120,10 +120,10 @@ LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:123:1
+  --> $DIR/needless_lifetimes.rs:123:15
    |
 LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |               ^^               ^^                   ^^
    |
 help: elide the lifetimes
    |
@@ -132,10 +132,10 @@ LL + fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> $DIR/needless_lifetimes.rs:153:5
+  --> $DIR/needless_lifetimes.rs:153:21
    |
 LL |     fn self_and_out<'s>(&'s self) -> &'s u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -144,10 +144,10 @@ LL +     fn self_and_out(&self) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 't
-  --> $DIR/needless_lifetimes.rs:160:5
+  --> $DIR/needless_lifetimes.rs:160:30
    |
 LL |     fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^                 ^^
    |
 help: elide the lifetimes
    |
@@ -156,10 +156,10 @@ LL +     fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's
-  --> $DIR/needless_lifetimes.rs:167:5
+  --> $DIR/needless_lifetimes.rs:167:26
    |
 LL |     fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -168,10 +168,10 @@ LL +     fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
    |
 
 error: the following explicit lifetimes could be elided: 's, 't
-  --> $DIR/needless_lifetimes.rs:171:5
+  --> $DIR/needless_lifetimes.rs:171:29
    |
 LL |     fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^  ^^   ^^            ^^
    |
 help: elide the lifetimes
    |
@@ -180,10 +180,10 @@ LL +     fn distinct_self_and_in(&self, _x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:190:1
+  --> $DIR/needless_lifetimes.rs:190:19
    |
 LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^            ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -192,10 +192,10 @@ LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:208:1
+  --> $DIR/needless_lifetimes.rs:208:25
    |
 LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^                ^^
    |
 help: elide the lifetimes
    |
@@ -204,10 +204,10 @@ LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:216:1
+  --> $DIR/needless_lifetimes.rs:216:21
    |
 LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^             ^^
    |
 help: elide the lifetimes
    |
@@ -216,10 +216,10 @@ LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:231:1
+  --> $DIR/needless_lifetimes.rs:231:22
    |
 LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^         ^^               ^^
    |
 help: elide the lifetimes
    |
@@ -228,10 +228,10 @@ LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:237:1
+  --> $DIR/needless_lifetimes.rs:237:18
    |
 LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^                 ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -240,10 +240,10 @@ LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'b
-  --> $DIR/needless_lifetimes.rs:255:1
+  --> $DIR/needless_lifetimes.rs:255:24
    |
 LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^                     ^^
    |
 help: elide the lifetimes
    |
@@ -252,10 +252,10 @@ LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:263:1
+  --> $DIR/needless_lifetimes.rs:263:20
    |
 LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^             ^^
    |
 help: elide the lifetimes
    |
@@ -264,10 +264,10 @@ LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:267:1
+  --> $DIR/needless_lifetimes.rs:267:30
    |
 LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^         ^^          ^
    |
 help: elide the lifetimes
    |
@@ -276,10 +276,10 @@ LL + fn named_input_elided_output(_arg: &str) -> &str {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:275:1
+  --> $DIR/needless_lifetimes.rs:275:19
    |
 LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^                                ^^
    |
 help: elide the lifetimes
    |
@@ -288,10 +288,10 @@ LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:311:1
+  --> $DIR/needless_lifetimes.rs:311:24
    |
 LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^      ^^             ^^
    |
 help: elide the lifetimes
    |
@@ -300,10 +300,10 @@ LL + fn out_return_type_lts(e: &str) -> Cow<'_> {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:318:9
+  --> $DIR/needless_lifetimes.rs:318:24
    |
 LL |         fn needless_lt<'a>(x: &'a u8) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -312,10 +312,10 @@ LL +         fn needless_lt(x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:322:9
+  --> $DIR/needless_lifetimes.rs:322:24
    |
 LL |         fn needless_lt<'a>(_x: &'a u8) {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                        ^^       ^^
    |
 help: elide the lifetimes
    |
@@ -324,10 +324,10 @@ LL +         fn needless_lt(_x: &u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:335:9
+  --> $DIR/needless_lifetimes.rs:335:16
    |
 LL |         fn baz<'a>(&'a self) -> impl Foo + 'a {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^^   ^^                     ^^
    |
 help: elide the lifetimes
    |
@@ -336,10 +336,10 @@ LL +         fn baz(&self) -> impl Foo + '_ {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:367:5
+  --> $DIR/needless_lifetimes.rs:367:55
    |
 LL |     fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                       ^^      ^^                                    ^^
    |
 help: elide the lifetimes
    |
@@ -348,10 +348,10 @@ LL +     fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:376:5
+  --> $DIR/needless_lifetimes.rs:376:26
    |
 LL |     fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                          ^^                           ^^                ^^
    |
 help: elide the lifetimes
    |
@@ -360,10 +360,10 @@ LL +     fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:388:5
+  --> $DIR/needless_lifetimes.rs:388:32
    |
 LL |     fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                ^^         ^^                ^^
    |
 help: elide the lifetimes
    |
@@ -372,10 +372,10 @@ LL +     fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:403:5
+  --> $DIR/needless_lifetimes.rs:403:28
    |
 LL |     fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^      ^^                               ^^
    |
 help: elide the lifetimes
    |
@@ -384,10 +384,10 @@ LL +     fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:416:5
+  --> $DIR/needless_lifetimes.rs:416:28
    |
 LL |     fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -396,10 +396,10 @@ LL +     fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:419:5
+  --> $DIR/needless_lifetimes.rs:419:28
    |
 LL |     fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -408,10 +408,10 @@ LL +     fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:441:9
+  --> $DIR/needless_lifetimes.rs:441:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -420,10 +420,10 @@ LL +         fn implicit(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:444:9
+  --> $DIR/needless_lifetimes.rs:444:25
    |
 LL |         fn implicit_mut<'a>(&'a mut self) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^   ^^               ^^
    |
 help: elide the lifetimes
    |
@@ -432,10 +432,10 @@ LL +         fn implicit_mut(&mut self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:455:9
+  --> $DIR/needless_lifetimes.rs:455:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^                          ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -444,10 +444,10 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:461:9
+  --> $DIR/needless_lifetimes.rs:461:21
    |
 LL |         fn implicit<'a>(&'a self) -> &'a ();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                     ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -456,10 +456,10 @@ LL +         fn implicit(&self) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:462:9
+  --> $DIR/needless_lifetimes.rs:462:30
    |
 LL |         fn implicit_provided<'a>(&'a self) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                              ^^   ^^           ^^
    |
 help: elide the lifetimes
    |
@@ -468,10 +468,10 @@ LL +         fn implicit_provided(&self) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:471:9
+  --> $DIR/needless_lifetimes.rs:471:31
    |
 LL |         fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^                          ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -480,10 +480,10 @@ LL +         fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:472:9
+  --> $DIR/needless_lifetimes.rs:472:40
    |
 LL |         fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        ^^                          ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -492,10 +492,10 @@ LL +         fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:481:5
+  --> $DIR/needless_lifetimes.rs:481:12
    |
 LL |     fn foo<'a>(x: &'a u8, y: &'_ u8) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -504,10 +504,10 @@ LL +     fn foo(x: &u8, y: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:483:5
+  --> $DIR/needless_lifetimes.rs:483:12
    |
 LL |     fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^      ^^
    |
 help: elide the lifetimes
    |
@@ -516,10 +516,10 @@ LL +     fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:490:5
+  --> $DIR/needless_lifetimes.rs:490:18
    |
 LL |     fn one_input<'a>(x: &'a u8) -> &'a u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^      ^^         ^^
    |
 help: elide the lifetimes
    |
@@ -528,10 +528,10 @@ LL +     fn one_input(x: &u8) -> &u8 {
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:495:5
+  --> $DIR/needless_lifetimes.rs:495:42
    |
 LL |     fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                          ^^          ^^
    |
 help: elide the lifetimes
    |
@@ -540,10 +540,10 @@ LL +     fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8)
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:511:9
+  --> $DIR/needless_lifetimes.rs:511:22
    |
 LL |         fn one_input<'a>(x: &'a u8) -> &'a u8 {
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^      ^^         ^^
    |
    = note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: elide the lifetimes
diff --git a/tests/ui/no_effect_return.rs b/tests/ui/no_effect_return.rs
new file mode 100644
index 00000000000..231dd063ad8
--- /dev/null
+++ b/tests/ui/no_effect_return.rs
@@ -0,0 +1,81 @@
+#![allow(clippy::unused_unit, dead_code, unused)]
+#![no_main]
+
+use std::ops::ControlFlow;
+
+fn a() -> u32 {
+    {
+        0u32;
+    }
+    0
+}
+
+async fn b() -> u32 {
+    {
+        0u32;
+    }
+    0
+}
+
+type C = i32;
+async fn c() -> C {
+    {
+        0i32 as C;
+    }
+    0
+}
+
+fn d() -> u128 {
+    {
+        // not last stmt
+        0u128;
+        println!("lol");
+    }
+    0
+}
+
+fn e() -> u32 {
+    {
+        // mismatched types
+        0u16;
+    }
+    0
+}
+
+fn f() -> [u16; 1] {
+    {
+        [1u16];
+    }
+    [1]
+}
+
+fn g() -> ControlFlow<()> {
+    {
+        ControlFlow::Break::<()>(());
+    }
+    ControlFlow::Continue(())
+}
+
+fn h() -> Vec<u16> {
+    {
+        // function call, so this won't trigger `no_effect`. not an issue with this change, but the
+        // lint itself (but also not really.)
+        vec![0u16];
+    }
+    vec![]
+}
+
+fn i() -> () {
+    {
+        ();
+    }
+    ()
+}
+
+fn j() {
+    {
+        // does not suggest on function without explicit return type
+        ();
+    }
+    ()
+}
diff --git a/tests/ui/no_effect_return.stderr b/tests/ui/no_effect_return.stderr
new file mode 100644
index 00000000000..779900e1859
--- /dev/null
+++ b/tests/ui/no_effect_return.stderr
@@ -0,0 +1,70 @@
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:8:9
+   |
+LL |         0u32;
+   |         -^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+   |
+   = note: `-D clippy::no-effect` implied by `-D warnings`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:15:9
+   |
+LL |         0u32;
+   |         -^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:23:9
+   |
+LL |         0i32 as C;
+   |         -^^^^^^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:31:9
+   |
+LL |         0u128;
+   |         ^^^^^^
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:40:9
+   |
+LL |         0u16;
+   |         ^^^^^
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:47:9
+   |
+LL |         [1u16];
+   |         -^^^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:54:9
+   |
+LL |         ControlFlow::Break::<()>(());
+   |         -^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:70:9
+   |
+LL |         ();
+   |         -^^
+   |         |
+   |         help: did you mean to return it?: `return`
+
+error: statement with no effect
+  --> $DIR/no_effect_return.rs:78:9
+   |
+LL |         ();
+   |         ^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed
index 61aed2733fe..f3669a669ea 100644
--- a/tests/ui/redundant_closure_call_fixable.fixed
+++ b/tests/ui/redundant_closure_call_fixable.fixed
@@ -3,6 +3,7 @@
 #![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(clippy::redundant_async_block)]
+#![allow(clippy::type_complexity)]
 #![allow(unused)]
 
 async fn something() -> u32 {
@@ -38,4 +39,50 @@ fn main() {
         };
     }
     m2!();
+    issue9956();
+}
+
+fn issue9956() {
+    assert_eq!(43, 42);
+
+    // ... and some more interesting cases I've found while implementing the fix
+
+    // not actually immediately calling the closure:
+    let a = (|| 42);
+    dbg!(a());
+
+    // immediately calling it inside of a macro
+    dbg!(42);
+
+    // immediately calling only one closure, so we can't remove the other ones
+    let a = (|| || 123);
+    dbg!(a()());
+
+    // nested async closures
+    let a = async { 1 };
+    let h = async { a.await };
+
+    // macro expansion tests
+    macro_rules! echo {
+        ($e:expr) => {
+            $e
+        };
+    }
+    let a = 1;
+    assert_eq!(a, 1);
+    let a = 123;
+    assert_eq!(a, 123);
+
+    // chaining calls, but not closures
+    fn x() -> fn() -> fn() -> fn() -> i32 {
+        || || || 42
+    }
+    let _ = x()()()();
+
+    fn bar() -> fn(i32, i32) {
+        foo
+    }
+    fn foo(_: i32, _: i32) {}
+    bar()(42, 5);
+    foo(42, 5);
 }
diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs
index 56b28663539..db8c7f80df4 100644
--- a/tests/ui/redundant_closure_call_fixable.rs
+++ b/tests/ui/redundant_closure_call_fixable.rs
@@ -3,6 +3,7 @@
 #![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(clippy::redundant_async_block)]
+#![allow(clippy::type_complexity)]
 #![allow(unused)]
 
 async fn something() -> u32 {
@@ -38,4 +39,50 @@ fn main() {
         };
     }
     m2!();
+    issue9956();
+}
+
+fn issue9956() {
+    assert_eq!((|| || 43)()(), 42);
+
+    // ... and some more interesting cases I've found while implementing the fix
+
+    // not actually immediately calling the closure:
+    let a = (|| 42);
+    dbg!(a());
+
+    // immediately calling it inside of a macro
+    dbg!((|| 42)());
+
+    // immediately calling only one closure, so we can't remove the other ones
+    let a = (|| || || 123)();
+    dbg!(a()());
+
+    // nested async closures
+    let a = (|| || || || async || 1)()()()()();
+    let h = async { a.await };
+
+    // macro expansion tests
+    macro_rules! echo {
+        ($e:expr) => {
+            $e
+        };
+    }
+    let a = (|| echo!(|| echo!(|| 1)))()()();
+    assert_eq!(a, 1);
+    let a = (|| echo!((|| 123)))()();
+    assert_eq!(a, 123);
+
+    // chaining calls, but not closures
+    fn x() -> fn() -> fn() -> fn() -> i32 {
+        || || || 42
+    }
+    let _ = x()()()();
+
+    fn bar() -> fn(i32, i32) {
+        foo
+    }
+    fn foo(_: i32, _: i32) {}
+    bar()((|| || 42)()(), 5);
+    foo((|| || 42)()(), 5);
 }
diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr
index 8a1f0771659..618f5e071d6 100644
--- a/tests/ui/redundant_closure_call_fixable.stderr
+++ b/tests/ui/redundant_closure_call_fixable.stderr
@@ -1,5 +1,5 @@
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:17:13
+  --> $DIR/redundant_closure_call_fixable.rs:18:13
    |
 LL |     let a = (|| 42)();
    |             ^^^^^^^^^ help: try doing something like: `42`
@@ -7,7 +7,7 @@ LL |     let a = (|| 42)();
    = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:18:13
+  --> $DIR/redundant_closure_call_fixable.rs:19:13
    |
 LL |       let b = (async || {
    |  _____________^
@@ -27,7 +27,7 @@ LL ~     };
    |
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:23:13
+  --> $DIR/redundant_closure_call_fixable.rs:24:13
    |
 LL |       let c = (|| {
    |  _____________^
@@ -47,13 +47,13 @@ LL ~     };
    |
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:28:13
+  --> $DIR/redundant_closure_call_fixable.rs:29:13
    |
 LL |     let d = (async || something().await)();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:37:13
+  --> $DIR/redundant_closure_call_fixable.rs:38:13
    |
 LL |             (|| m!())()
    |             ^^^^^^^^^^^ help: try doing something like: `m!()`
@@ -64,7 +64,7 @@ LL |     m2!();
    = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:32:13
+  --> $DIR/redundant_closure_call_fixable.rs:33:13
    |
 LL |             (|| 0)()
    |             ^^^^^^^^ help: try doing something like: `0`
@@ -74,5 +74,53 @@ LL |     m2!();
    |
    = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 6 previous errors
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:46:16
+   |
+LL |     assert_eq!((|| || 43)()(), 42);
+   |                ^^^^^^^^^^^^^^ help: try doing something like: `43`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:55:10
+   |
+LL |     dbg!((|| 42)());
+   |          ^^^^^^^^^ help: try doing something like: `42`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:58:13
+   |
+LL |     let a = (|| || || 123)();
+   |             ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:62:13
+   |
+LL |     let a = (|| || || || async || 1)()()()()();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { 1 }`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:71:13
+   |
+LL |     let a = (|| echo!(|| echo!(|| 1)))()()();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `1`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:73:13
+   |
+LL |     let a = (|| echo!((|| 123)))()();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `123`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:86:11
+   |
+LL |     bar()((|| || 42)()(), 5);
+   |           ^^^^^^^^^^^^^^ help: try doing something like: `42`
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:87:9
+   |
+LL |     foo((|| || 42)()(), 5);
+   |         ^^^^^^^^^^^^^^ help: try doing something like: `42`
+
+error: aborting due to 14 previous errors
 
diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs
new file mode 100644
index 00000000000..bfb773187fb
--- /dev/null
+++ b/tests/ui/single_call_fn.rs
@@ -0,0 +1,75 @@
+//@aux-build:proc_macros.rs
+//@compile-flags: --test
+#![allow(clippy::redundant_closure_call, unused)]
+#![warn(clippy::single_call_fn)]
+#![no_main]
+
+#[macro_use]
+extern crate proc_macros;
+
+// Do not lint since it's public
+pub fn f() {}
+
+fn i() {}
+fn j() {}
+
+fn h() {
+    // Linted
+    let a = i;
+    // Do not lint closures
+    let a = (|| {
+        // Not linted
+        a();
+        // Imo, it's reasonable to lint this as the function is still only being used once. Just in
+        // a closure.
+        j();
+    });
+    a();
+}
+
+fn g() {
+    f();
+}
+
+fn c() {
+    println!("really");
+    println!("long");
+    println!("function...");
+}
+
+fn d() {
+    c();
+}
+
+fn a() {}
+
+fn b() {
+    a();
+
+    external! {
+        fn lol() {
+            lol_inner();
+        }
+        fn lol_inner() {}
+    }
+    with_span! {
+        span
+        fn lol2() {
+            lol2_inner();
+        }
+        fn lol2_inner() {}
+    }
+}
+
+fn e() {
+    b();
+    b();
+}
+
+#[test]
+fn k() {}
+
+#[test]
+fn l() {
+    k();
+}
diff --git a/tests/ui/single_call_fn.stderr b/tests/ui/single_call_fn.stderr
new file mode 100644
index 00000000000..bb92e3cf71a
--- /dev/null
+++ b/tests/ui/single_call_fn.stderr
@@ -0,0 +1,55 @@
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:34:1
+   |
+LL | / fn c() {
+LL | |     println!("really");
+LL | |     println!("long");
+LL | |     println!("function...");
+LL | | }
+   | |_^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:41:5
+   |
+LL |     c();
+   |     ^
+   = note: `-D clippy::single-call-fn` implied by `-D warnings`
+
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:13:1
+   |
+LL | fn i() {}
+   | ^^^^^^^^^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:18:13
+   |
+LL |     let a = i;
+   |             ^
+
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:44:1
+   |
+LL | fn a() {}
+   | ^^^^^^^^^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:47:5
+   |
+LL |     a();
+   |     ^
+
+error: this function is only used once
+  --> $DIR/single_call_fn.rs:14:1
+   |
+LL | fn j() {}
+   | ^^^^^^^^^
+   |
+help: used here
+  --> $DIR/single_call_fn.rs:25:9
+   |
+LL |         j();
+   |         ^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed
index 1697a0cf29b..598f259415d 100644
--- a/tests/ui/single_element_loop.fixed
+++ b/tests/ui/single_element_loop.fixed
@@ -1,6 +1,8 @@
 //@run-rustfix
 // Tests from for_loop.rs that don't have suggestions
 
+#![allow(clippy::single_range_in_vec_init)]
+
 #[warn(clippy::single_element_loop)]
 fn main() {
     let item1 = 2;
diff --git a/tests/ui/single_element_loop.rs b/tests/ui/single_element_loop.rs
index 860424f42dd..3fc461735a4 100644
--- a/tests/ui/single_element_loop.rs
+++ b/tests/ui/single_element_loop.rs
@@ -1,6 +1,8 @@
 //@run-rustfix
 // Tests from for_loop.rs that don't have suggestions
 
+#![allow(clippy::single_range_in_vec_init)]
+
 #[warn(clippy::single_element_loop)]
 fn main() {
     let item1 = 2;
diff --git a/tests/ui/single_element_loop.stderr b/tests/ui/single_element_loop.stderr
index 14437a59745..c40c6198945 100644
--- a/tests/ui/single_element_loop.stderr
+++ b/tests/ui/single_element_loop.stderr
@@ -1,5 +1,5 @@
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:7:5
+  --> $DIR/single_element_loop.rs:9:5
    |
 LL | /     for item in &[item1] {
 LL | |         dbg!(item);
@@ -16,7 +16,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:11:5
+  --> $DIR/single_element_loop.rs:13:5
    |
 LL | /     for item in [item1].iter() {
 LL | |         dbg!(item);
@@ -32,7 +32,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:15:5
+  --> $DIR/single_element_loop.rs:17:5
    |
 LL | /     for item in &[0..5] {
 LL | |         dbg!(item);
@@ -48,7 +48,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:19:5
+  --> $DIR/single_element_loop.rs:21:5
    |
 LL | /     for item in [0..5].iter_mut() {
 LL | |         dbg!(item);
@@ -64,7 +64,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:23:5
+  --> $DIR/single_element_loop.rs:25:5
    |
 LL | /     for item in [0..5] {
 LL | |         dbg!(item);
@@ -80,7 +80,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:27:5
+  --> $DIR/single_element_loop.rs:29:5
    |
 LL | /     for item in [0..5].into_iter() {
 LL | |         dbg!(item);
@@ -96,7 +96,7 @@ LL +     }
    |
 
 error: for loop over a single element
-  --> $DIR/single_element_loop.rs:46:5
+  --> $DIR/single_element_loop.rs:48:5
    |
 LL | /     for _ in [42] {
 LL | |         let _f = |n: u32| {
diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed
index a54e658bf23..e7b1fd6a85f 100644
--- a/tests/ui/single_match.fixed
+++ b/tests/ui/single_match.fixed
@@ -212,3 +212,43 @@ fn issue_10808(bar: Option<i32>) {
         }
     }
 }
+
+mod issue8634 {
+    struct SomeError(i32, i32);
+
+    fn foo(x: Result<i32, ()>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(()) => {
+                // Ignore this error because blah blah blah.
+            },
+        }
+    }
+
+    fn bar(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                // TODO: Process the error properly.
+            },
+        }
+    }
+
+    fn block_comment(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                /*
+                let's make sure that this also
+                does not lint block comments.
+                */
+            },
+        }
+    }
+}
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index f296c6c4d1c..1515a7053e5 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -270,3 +270,43 @@ fn issue_10808(bar: Option<i32>) {
         _ => {},
     }
 }
+
+mod issue8634 {
+    struct SomeError(i32, i32);
+
+    fn foo(x: Result<i32, ()>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(()) => {
+                // Ignore this error because blah blah blah.
+            },
+        }
+    }
+
+    fn bar(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                // TODO: Process the error properly.
+            },
+        }
+    }
+
+    fn block_comment(x: Result<i32, SomeError>) {
+        match x {
+            Ok(y) => {
+                println!("Yay! {y}");
+            },
+            Err(_) => {
+                /*
+                let's make sure that this also
+                does not lint block comments.
+                */
+            },
+        }
+    }
+}
diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs
new file mode 100644
index 00000000000..abf784e0f0e
--- /dev/null
+++ b/tests/ui/single_range_in_vec_init.rs
@@ -0,0 +1,58 @@
+//@aux-build:proc_macros.rs
+#![allow(clippy::no_effect, clippy::useless_vec, unused)]
+#![warn(clippy::single_range_in_vec_init)]
+#![feature(generic_arg_infer)]
+
+#[macro_use]
+extern crate proc_macros;
+
+macro_rules! a {
+    () => {
+        vec![0..200];
+    };
+}
+
+fn awa<T: PartialOrd>(start: T, end: T) {
+    [start..end];
+}
+
+fn awa_vec<T: PartialOrd>(start: T, end: T) {
+    vec![start..end];
+}
+
+fn main() {
+    // Lint
+    [0..200];
+    vec![0..200];
+    [0u8..200];
+    [0usize..200];
+    [0..200usize];
+    vec![0u8..200];
+    vec![0usize..200];
+    vec![0..200usize];
+    // Only suggest collect
+    [0..200isize];
+    vec![0..200isize];
+    // Do not lint
+    [0..200, 0..100];
+    vec![0..200, 0..100];
+    [0.0..200.0];
+    vec![0.0..200.0];
+    // `Copy` is not implemented for `Range`, so this doesn't matter
+    // [0..200; 2];
+    // [vec!0..200; 2];
+
+    // Unfortunately skips any macros
+    a!();
+
+    // Skip external macros and procedural macros
+    external! {
+        [0..200];
+        vec![0..200];
+    }
+    with_span! {
+        span
+        [0..200];
+        vec![0..200];
+    }
+}
diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr
new file mode 100644
index 00000000000..3e3d521f4a5
--- /dev/null
+++ b/tests/ui/single_range_in_vec_init.stderr
@@ -0,0 +1,145 @@
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:25:5
+   |
+LL |     [0..200];
+   |     ^^^^^^^^
+   |
+   = note: `-D clippy::single-range-in-vec-init` implied by `-D warnings`
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200).collect::<std::vec::Vec<i32>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200, try
+   |
+LL |     [0; 200];
+   |      ~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:26:5
+   |
+LL |     vec![0..200];
+   |     ^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200).collect::<std::vec::Vec<i32>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200, try
+   |
+LL |     vec![0; 200];
+   |          ~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:27:5
+   |
+LL |     [0u8..200];
+   |     ^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0u8..200).collect::<std::vec::Vec<u8>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200, try
+   |
+LL |     [0u8; 200];
+   |      ~~~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:28:5
+   |
+LL |     [0usize..200];
+   |     ^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0usize..200).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200, try
+   |
+LL |     [0usize; 200];
+   |      ~~~~~~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:29:5
+   |
+LL |     [0..200usize];
+   |     ^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200usize).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted an array of len 200usize, try
+   |
+LL |     [0; 200usize];
+   |      ~~~~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:30:5
+   |
+LL |     vec![0u8..200];
+   |     ^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0u8..200).collect::<std::vec::Vec<u8>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200, try
+   |
+LL |     vec![0u8; 200];
+   |          ~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:31:5
+   |
+LL |     vec![0usize..200];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0usize..200).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200, try
+   |
+LL |     vec![0usize; 200];
+   |          ~~~~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:32:5
+   |
+LL |     vec![0..200usize];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200usize).collect::<std::vec::Vec<usize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+help: if you wanted a `Vec` of len 200usize, try
+   |
+LL |     vec![0; 200usize];
+   |          ~~~~~~~~~~~
+
+error: an array of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:34:5
+   |
+LL |     [0..200isize];
+   |     ^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200isize).collect::<std::vec::Vec<isize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: a `Vec` of `Range` that is only one element
+  --> $DIR/single_range_in_vec_init.rs:35:5
+   |
+LL |     vec![0..200isize];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if you wanted a `Vec` that contains the entire range, try
+   |
+LL |     (0..200isize).collect::<std::vec::Vec<isize>>();
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/to_string_in_format_args_incremental.fixed b/tests/ui/to_string_in_format_args_incremental.fixed
new file mode 100644
index 00000000000..9f75ad895cd
--- /dev/null
+++ b/tests/ui/to_string_in_format_args_incremental.fixed
@@ -0,0 +1,9 @@
+//@run-rustfix
+//@compile-flags: -C incremental=target/debug/test/incr
+
+// see https://github.com/rust-lang/rust-clippy/issues/10969
+
+fn main() {
+    let s = "Hello, world!";
+    println!("{}", s);
+}
diff --git a/tests/ui/to_string_in_format_args_incremental.rs b/tests/ui/to_string_in_format_args_incremental.rs
new file mode 100644
index 00000000000..67115f7c5a7
--- /dev/null
+++ b/tests/ui/to_string_in_format_args_incremental.rs
@@ -0,0 +1,9 @@
+//@run-rustfix
+//@compile-flags: -C incremental=target/debug/test/incr
+
+// see https://github.com/rust-lang/rust-clippy/issues/10969
+
+fn main() {
+    let s = "Hello, world!";
+    println!("{}", s.to_string());
+}
diff --git a/tests/ui/to_string_in_format_args_incremental.stderr b/tests/ui/to_string_in_format_args_incremental.stderr
new file mode 100644
index 00000000000..a992c542914
--- /dev/null
+++ b/tests/ui/to_string_in_format_args_incremental.stderr
@@ -0,0 +1,10 @@
+error: `to_string` applied to a type that implements `Display` in `println!` args
+  --> $DIR/to_string_in_format_args_incremental.rs:8:21
+   |
+LL |     println!("{}", s.to_string());
+   |                     ^^^^^^^^^^^^ help: remove this
+   |
+   = note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs
index 229d150851a..f4e7f1943ae 100644
--- a/tests/ui/undocumented_unsafe_blocks.rs
+++ b/tests/ui/undocumented_unsafe_blocks.rs
@@ -509,4 +509,26 @@ fn issue_9142() {
     };
 }
 
+pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    1
+}
+
+pub const unsafe fn a_const_function_with_a_very_long_name_to_break_the_line() -> u32 {
+    2
+}
+
+fn issue_10832() {
+    // Safety: A safety comment. But it will warn anyways
+    let _some_variable_with_a_very_long_name_to_break_the_line =
+        unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Another safety comment. But it will warn anyways
+    const _SOME_CONST_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+
+    // Safety: Yet another safety comment. But it will warn anyways
+    static _SOME_STATIC_WITH_A_VERY_LONG_NAME_TO_BREAK_THE_LINE: u32 =
+        unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+}
+
 fn main() {}
diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr
index d1c1bb5ffea..ee1d3aa285a 100644
--- a/tests/ui/undocumented_unsafe_blocks.stderr
+++ b/tests/ui/undocumented_unsafe_blocks.stderr
@@ -318,5 +318,29 @@ LL |             let bar = unsafe {};
    |
    = help: consider adding a safety comment on the preceding line
 
-error: aborting due to 36 previous errors
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:523:9
+   |
+LL |         unsafe { a_function_with_a_very_long_name_to_break_the_line() };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:527:9
+   |
+LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: unsafe block missing a safety comment
+  --> $DIR/undocumented_unsafe_blocks.rs:531:9
+   |
+LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a safety comment on the preceding line
+
+error: aborting due to 39 previous errors
 
diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed
index f56cee3a364..8efd44baf59 100644
--- a/tests/ui/unnecessary_cast.fixed
+++ b/tests/ui/unnecessary_cast.fixed
@@ -1,13 +1,17 @@
 //@run-rustfix
+//@aux-build:extern_fake_libc.rs
 #![warn(clippy::unnecessary_cast)]
 #![allow(
-    unused,
     clippy::borrow_as_ptr,
     clippy::no_effect,
     clippy::nonstandard_macro_braces,
-    clippy::unnecessary_operation
+    clippy::unnecessary_operation,
+    nonstandard_style,
+    unused
 )]
 
+extern crate extern_fake_libc;
+
 type PtrConstU8 = *const u8;
 type PtrMutU8 = *mut u8;
 
@@ -19,6 +23,21 @@ fn uwu<T, U>(ptr: *const T) -> *const U {
     ptr as *const U
 }
 
+mod fake_libc {
+    type pid_t = i32;
+    pub unsafe fn getpid() -> pid_t {
+        pid_t::from(0)
+    }
+    // Make sure a where clause does not break it
+    pub fn getpid_SAFE_TRUTH<T: Clone>(t: &T) -> pid_t
+    where
+        T: Clone,
+    {
+        t;
+        unsafe { getpid() }
+    }
+}
+
 #[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
@@ -82,6 +101,10 @@ fn main() {
     // or from
     let x: I32Alias = 1;
     let y = x as u64;
+    fake_libc::getpid_SAFE_TRUTH(&0u32) as i32;
+    extern_fake_libc::getpid_SAFE_TRUTH() as i32;
+    let pid = unsafe { fake_libc::getpid() };
+    pid as i32;
 
     let i8_ptr: *const i8 = &1;
     let u8_ptr: *const u8 = &1;
diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs
index b4623df6909..c7723ef51f9 100644
--- a/tests/ui/unnecessary_cast.rs
+++ b/tests/ui/unnecessary_cast.rs
@@ -1,13 +1,17 @@
 //@run-rustfix
+//@aux-build:extern_fake_libc.rs
 #![warn(clippy::unnecessary_cast)]
 #![allow(
-    unused,
     clippy::borrow_as_ptr,
     clippy::no_effect,
     clippy::nonstandard_macro_braces,
-    clippy::unnecessary_operation
+    clippy::unnecessary_operation,
+    nonstandard_style,
+    unused
 )]
 
+extern crate extern_fake_libc;
+
 type PtrConstU8 = *const u8;
 type PtrMutU8 = *mut u8;
 
@@ -19,6 +23,21 @@ fn uwu<T, U>(ptr: *const T) -> *const U {
     ptr as *const U
 }
 
+mod fake_libc {
+    type pid_t = i32;
+    pub unsafe fn getpid() -> pid_t {
+        pid_t::from(0)
+    }
+    // Make sure a where clause does not break it
+    pub fn getpid_SAFE_TRUTH<T: Clone>(t: &T) -> pid_t
+    where
+        T: Clone,
+    {
+        t;
+        unsafe { getpid() }
+    }
+}
+
 #[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
@@ -82,6 +101,10 @@ fn main() {
     // or from
     let x: I32Alias = 1;
     let y = x as u64;
+    fake_libc::getpid_SAFE_TRUTH(&0u32) as i32;
+    extern_fake_libc::getpid_SAFE_TRUTH() as i32;
+    let pid = unsafe { fake_libc::getpid() };
+    pid as i32;
 
     let i8_ptr: *const i8 = &1;
     let u8_ptr: *const u8 = &1;
diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr
index 618fbd4faaf..f0443556fb4 100644
--- a/tests/ui/unnecessary_cast.stderr
+++ b/tests/ui/unnecessary_cast.stderr
@@ -1,5 +1,5 @@
 error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`)
-  --> $DIR/unnecessary_cast.rs:15:5
+  --> $DIR/unnecessary_cast.rs:19:5
    |
 LL |     ptr as *const T
    |     ^^^^^^^^^^^^^^^ help: try: `ptr`
@@ -7,223 +7,223 @@ LL |     ptr as *const T
    = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:25:5
+  --> $DIR/unnecessary_cast.rs:44:5
    |
 LL |     1i32 as i32;
    |     ^^^^^^^^^^^ help: try: `1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:26:5
+  --> $DIR/unnecessary_cast.rs:45:5
    |
 LL |     1f32 as f32;
    |     ^^^^^^^^^^^ help: try: `1_f32`
 
 error: casting to the same type is unnecessary (`bool` -> `bool`)
-  --> $DIR/unnecessary_cast.rs:27:5
+  --> $DIR/unnecessary_cast.rs:46:5
    |
 LL |     false as bool;
    |     ^^^^^^^^^^^^^ help: try: `false`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:30:5
+  --> $DIR/unnecessary_cast.rs:49:5
    |
 LL |     -1_i32 as i32;
    |     ^^^^^^^^^^^^^ help: try: `-1_i32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:31:5
+  --> $DIR/unnecessary_cast.rs:50:5
    |
 LL |     - 1_i32 as i32;
    |     ^^^^^^^^^^^^^^ help: try: `- 1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:32:5
+  --> $DIR/unnecessary_cast.rs:51:5
    |
 LL |     -1f32 as f32;
    |     ^^^^^^^^^^^^ help: try: `-1_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:33:5
+  --> $DIR/unnecessary_cast.rs:52:5
    |
 LL |     1_i32 as i32;
    |     ^^^^^^^^^^^^ help: try: `1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:34:5
+  --> $DIR/unnecessary_cast.rs:53:5
    |
 LL |     1_f32 as f32;
    |     ^^^^^^^^^^^^ help: try: `1_f32`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
-  --> $DIR/unnecessary_cast.rs:36:22
+  --> $DIR/unnecessary_cast.rs:55:22
    |
 LL |     let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
-  --> $DIR/unnecessary_cast.rs:38:5
+  --> $DIR/unnecessary_cast.rs:57:5
    |
 LL |     [1u8, 2].as_ptr() as *const u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`)
-  --> $DIR/unnecessary_cast.rs:40:5
+  --> $DIR/unnecessary_cast.rs:59:5
    |
 LL |     [1u8, 2].as_mut_ptr() as *mut u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
-  --> $DIR/unnecessary_cast.rs:51:5
+  --> $DIR/unnecessary_cast.rs:70:5
    |
 LL |     owo::<u32>([1u32].as_ptr()) as *const u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::<u32>([1u32].as_ptr())`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
-  --> $DIR/unnecessary_cast.rs:52:5
+  --> $DIR/unnecessary_cast.rs:71:5
    |
 LL |     uwu::<u32, u8>([1u32].as_ptr()) as *const u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u8>([1u32].as_ptr())`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
-  --> $DIR/unnecessary_cast.rs:54:5
+  --> $DIR/unnecessary_cast.rs:73:5
    |
 LL |     uwu::<u32, u32>([1u32].as_ptr()) as *const u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u32>([1u32].as_ptr())`
 
 error: casting integer literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:116:9
+  --> $DIR/unnecessary_cast.rs:139:9
    |
 LL |         100 as f32;
    |         ^^^^^^^^^^ help: try: `100_f32`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:117:9
+  --> $DIR/unnecessary_cast.rs:140:9
    |
 LL |         100 as f64;
    |         ^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:118:9
+  --> $DIR/unnecessary_cast.rs:141:9
    |
 LL |         100_i32 as f64;
    |         ^^^^^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:119:17
+  --> $DIR/unnecessary_cast.rs:142:17
    |
 LL |         let _ = -100 as f32;
    |                 ^^^^^^^^^^^ help: try: `-100_f32`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:120:17
+  --> $DIR/unnecessary_cast.rs:143:17
    |
 LL |         let _ = -100 as f64;
    |                 ^^^^^^^^^^^ help: try: `-100_f64`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:121:17
+  --> $DIR/unnecessary_cast.rs:144:17
    |
 LL |         let _ = -100_i32 as f64;
    |                 ^^^^^^^^^^^^^^^ help: try: `-100_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:122:9
+  --> $DIR/unnecessary_cast.rs:145:9
    |
 LL |         100. as f32;
    |         ^^^^^^^^^^^ help: try: `100_f32`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:123:9
+  --> $DIR/unnecessary_cast.rs:146:9
    |
 LL |         100. as f64;
    |         ^^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:135:9
+  --> $DIR/unnecessary_cast.rs:158:9
    |
 LL |         1 as u32;
    |         ^^^^^^^^ help: try: `1_u32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:136:9
+  --> $DIR/unnecessary_cast.rs:159:9
    |
 LL |         0x10 as i32;
    |         ^^^^^^^^^^^ help: try: `0x10_i32`
 
 error: casting integer literal to `usize` is unnecessary
-  --> $DIR/unnecessary_cast.rs:137:9
+  --> $DIR/unnecessary_cast.rs:160:9
    |
 LL |         0b10 as usize;
    |         ^^^^^^^^^^^^^ help: try: `0b10_usize`
 
 error: casting integer literal to `u16` is unnecessary
-  --> $DIR/unnecessary_cast.rs:138:9
+  --> $DIR/unnecessary_cast.rs:161:9
    |
 LL |         0o73 as u16;
    |         ^^^^^^^^^^^ help: try: `0o73_u16`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:139:9
+  --> $DIR/unnecessary_cast.rs:162:9
    |
 LL |         1_000_000_000 as u32;
    |         ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:141:9
+  --> $DIR/unnecessary_cast.rs:164:9
    |
 LL |         1.0 as f64;
    |         ^^^^^^^^^^ help: try: `1.0_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:142:9
+  --> $DIR/unnecessary_cast.rs:165:9
    |
 LL |         0.5 as f32;
    |         ^^^^^^^^^^ help: try: `0.5_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:146:17
+  --> $DIR/unnecessary_cast.rs:169:17
    |
 LL |         let _ = -1 as i32;
    |                 ^^^^^^^^^ help: try: `-1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:147:17
+  --> $DIR/unnecessary_cast.rs:170:17
    |
 LL |         let _ = -1.0 as f32;
    |                 ^^^^^^^^^^^ help: try: `-1.0_f32`
 
 error: casting to the same type is unnecessary (`i32` -> `i32`)
-  --> $DIR/unnecessary_cast.rs:153:18
+  --> $DIR/unnecessary_cast.rs:176:18
    |
 LL |         let _ = &(x as i32);
    |                  ^^^^^^^^^^ help: try: `{ x }`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:159:22
+  --> $DIR/unnecessary_cast.rs:182:22
    |
 LL |         let _: i32 = -(1) as i32;
    |                      ^^^^^^^^^^^ help: try: `-1_i32`
 
 error: casting integer literal to `i64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:161:22
+  --> $DIR/unnecessary_cast.rs:184:22
    |
 LL |         let _: i64 = -(1) as i64;
    |                      ^^^^^^^^^^^ help: try: `-1_i64`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:168:22
+  --> $DIR/unnecessary_cast.rs:191:22
    |
 LL |         let _: f64 = (-8.0 as f64).exp();
    |                      ^^^^^^^^^^^^^ help: try: `(-8.0_f64)`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:170:23
+  --> $DIR/unnecessary_cast.rs:193:23
    |
 LL |         let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
    |                       ^^^^^^^^^^^^ help: try: `8.0_f64`
 
 error: casting to the same type is unnecessary (`f32` -> `f32`)
-  --> $DIR/unnecessary_cast.rs:178:20
+  --> $DIR/unnecessary_cast.rs:201:20
    |
 LL |         let _num = foo() as f32;
    |                    ^^^^^^^^^^^^ help: try: `foo()`
diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed
index 2bed14973ca..bd1d4a152ae 100644
--- a/tests/ui/unnecessary_fold.fixed
+++ b/tests/ui/unnecessary_fold.fixed
@@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() {
         .any(|x| x > 2);
 }
 
+fn issue10000() {
+    use std::collections::HashMap;
+    use std::hash::BuildHasher;
+
+    fn anything<T>(_: T) {}
+    fn num(_: i32) {}
+    fn smoketest_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
+        map.insert(0, 0);
+        assert_eq!(map.values().sum::<i32>(), 0);
+
+        // more cases:
+        let _ = map.values().sum::<i32>();
+        let _ = map.values().product::<i32>();
+        let _: i32 = map.values().sum();
+        let _: i32 = map.values().product();
+        anything(map.values().sum::<i32>());
+        anything(map.values().product::<i32>());
+        num(map.values().sum());
+        num(map.values().product());
+    }
+
+    smoketest_map(HashMap::new());
+}
+
 fn main() {}
diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs
index a3cec8ea3d5..d27cc460c44 100644
--- a/tests/ui/unnecessary_fold.rs
+++ b/tests/ui/unnecessary_fold.rs
@@ -49,4 +49,28 @@ fn unnecessary_fold_over_multiple_lines() {
         .fold(false, |acc, x| acc || x > 2);
 }
 
+fn issue10000() {
+    use std::collections::HashMap;
+    use std::hash::BuildHasher;
+
+    fn anything<T>(_: T) {}
+    fn num(_: i32) {}
+    fn smoketest_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
+        map.insert(0, 0);
+        assert_eq!(map.values().fold(0, |x, y| x + y), 0);
+
+        // more cases:
+        let _ = map.values().fold(0, |x, y| x + y);
+        let _ = map.values().fold(1, |x, y| x * y);
+        let _: i32 = map.values().fold(0, |x, y| x + y);
+        let _: i32 = map.values().fold(1, |x, y| x * y);
+        anything(map.values().fold(0, |x, y| x + y));
+        anything(map.values().fold(1, |x, y| x * y));
+        num(map.values().fold(0, |x, y| x + y));
+        num(map.values().fold(1, |x, y| x * y));
+    }
+
+    smoketest_map(HashMap::new());
+}
+
 fn main() {}
diff --git a/tests/ui/unnecessary_fold.stderr b/tests/ui/unnecessary_fold.stderr
index 22c44588ab7..98979f7477f 100644
--- a/tests/ui/unnecessary_fold.stderr
+++ b/tests/ui/unnecessary_fold.stderr
@@ -36,5 +36,59 @@ error: this `.fold` can be written more succinctly using another method
 LL |         .fold(false, |acc, x| acc || x > 2);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)`
 
-error: aborting due to 6 previous errors
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:60:33
+   |
+LL |         assert_eq!(map.values().fold(0, |x, y| x + y), 0);
+   |                                 ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:63:30
+   |
+LL |         let _ = map.values().fold(0, |x, y| x + y);
+   |                              ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:64:30
+   |
+LL |         let _ = map.values().fold(1, |x, y| x * y);
+   |                              ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:65:35
+   |
+LL |         let _: i32 = map.values().fold(0, |x, y| x + y);
+   |                                   ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:66:35
+   |
+LL |         let _: i32 = map.values().fold(1, |x, y| x * y);
+   |                                   ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:67:31
+   |
+LL |         anything(map.values().fold(0, |x, y| x + y));
+   |                               ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:68:31
+   |
+LL |         anything(map.values().fold(1, |x, y| x * y));
+   |                               ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::<i32>()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:69:26
+   |
+LL |         num(map.values().fold(0, |x, y| x + y));
+   |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()`
+
+error: this `.fold` can be written more succinctly using another method
+  --> $DIR/unnecessary_fold.rs:70:26
+   |
+LL |         num(map.values().fold(1, |x, y| x * y));
+   |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()`
+
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed
index bdf746cf2c4..eae1271d1aa 100644
--- a/tests/ui/unnecessary_struct_initialization.fixed
+++ b/tests/ui/unnecessary_struct_initialization.fixed
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused)]
+#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)]
 #![warn(clippy::unnecessary_struct_initialization)]
 
 struct S {
diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs
index 7271e2f957a..4abd560f84b 100644
--- a/tests/ui/unnecessary_struct_initialization.rs
+++ b/tests/ui/unnecessary_struct_initialization.rs
@@ -1,6 +1,6 @@
 //@run-rustfix
 
-#![allow(unused)]
+#![allow(clippy::incorrect_clone_impl_on_copy_type, unused)]
 #![warn(clippy::unnecessary_struct_initialization)]
 
 struct S {
diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed
index 11f0de07c62..41a380ab8f6 100644
--- a/tests/ui/while_let_on_iterator.fixed
+++ b/tests/ui/while_let_on_iterator.fixed
@@ -6,6 +6,7 @@
     clippy::manual_find,
     clippy::never_loop,
     clippy::redundant_closure_call,
+    clippy::single_range_in_vec_init,
     clippy::uninlined_format_args,
     clippy::useless_vec
 )]
diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs
index e54575dd3b4..4c6433880b6 100644
--- a/tests/ui/while_let_on_iterator.rs
+++ b/tests/ui/while_let_on_iterator.rs
@@ -6,6 +6,7 @@
     clippy::manual_find,
     clippy::never_loop,
     clippy::redundant_closure_call,
+    clippy::single_range_in_vec_init,
     clippy::uninlined_format_args,
     clippy::useless_vec
 )]
diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr
index f8a66f2ad3e..3236765e1db 100644
--- a/tests/ui/while_let_on_iterator.stderr
+++ b/tests/ui/while_let_on_iterator.stderr
@@ -1,5 +1,5 @@
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:15:5
+  --> $DIR/while_let_on_iterator.rs:16:5
    |
 LL |     while let Option::Some(x) = iter.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
@@ -7,151 +7,151 @@ LL |     while let Option::Some(x) = iter.next() {
    = note: `-D clippy::while-let-on-iterator` implied by `-D warnings`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:20:5
+  --> $DIR/while_let_on_iterator.rs:21:5
    |
 LL |     while let Some(x) = iter.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:25:5
+  --> $DIR/while_let_on_iterator.rs:26:5
    |
 LL |     while let Some(_) = iter.next() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:101:9
+  --> $DIR/while_let_on_iterator.rs:102:9
    |
 LL |         while let Some([..]) = it.next() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:108:9
+  --> $DIR/while_let_on_iterator.rs:109:9
    |
 LL |         while let Some([_x]) = it.next() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:121:9
+  --> $DIR/while_let_on_iterator.rs:122:9
    |
 LL |         while let Some(x @ [_]) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:141:9
+  --> $DIR/while_let_on_iterator.rs:142:9
    |
 LL |         while let Some(_) = y.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:198:9
+  --> $DIR/while_let_on_iterator.rs:199:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:209:5
+  --> $DIR/while_let_on_iterator.rs:210:5
    |
 LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:211:9
+  --> $DIR/while_let_on_iterator.rs:212:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:220:9
+  --> $DIR/while_let_on_iterator.rs:221:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:229:9
+  --> $DIR/while_let_on_iterator.rs:230:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:246:9
+  --> $DIR/while_let_on_iterator.rs:247:9
    |
 LL |         while let Some(m) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:261:13
+  --> $DIR/while_let_on_iterator.rs:262:13
    |
 LL |             while let Some(i) = self.0.next() {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:293:13
+  --> $DIR/while_let_on_iterator.rs:294:13
    |
 LL |             while let Some(i) = self.0.0.0.next() {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:322:5
+  --> $DIR/while_let_on_iterator.rs:323:5
    |
 LL |     while let Some(n) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:334:9
+  --> $DIR/while_let_on_iterator.rs:335:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:348:5
+  --> $DIR/while_let_on_iterator.rs:349:5
    |
 LL |     while let Some(x) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:359:5
+  --> $DIR/while_let_on_iterator.rs:360:5
    |
 LL |     while let Some(x) = it.0.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:394:5
+  --> $DIR/while_let_on_iterator.rs:395:5
    |
 LL |     while let Some(x) = s.x.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:401:5
+  --> $DIR/while_let_on_iterator.rs:402:5
    |
 LL |     while let Some(x) = x[0].next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:409:9
+  --> $DIR/while_let_on_iterator.rs:410:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:419:9
+  --> $DIR/while_let_on_iterator.rs:420:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:429:9
+  --> $DIR/while_let_on_iterator.rs:430:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:439:9
+  --> $DIR/while_let_on_iterator.rs:440:9
    |
 LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:449:5
+  --> $DIR/while_let_on_iterator.rs:450:5
    |
 LL |     while let Some(..) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
diff --git a/tests/workspace.rs b/tests/workspace.rs
index c9cbc50546c..699ab2be199 100644
--- a/tests/workspace.rs
+++ b/tests/workspace.rs
@@ -7,6 +7,46 @@ use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE};
 mod test_utils;
 
 #[test]
+fn test_module_style_with_dep_in_subdir() {
+    if IS_RUSTC_TEST_SUITE {
+        return;
+    }
+    let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    let target_dir = root.join("target").join("workspace_test");
+    let cwd = root.join("tests/workspace_test");
+
+    // Make sure we start with a clean state
+    Command::new("cargo")
+        .current_dir(&cwd)
+        .env("CARGO_TARGET_DIR", &target_dir)
+        .arg("clean")
+        .args(["-p", "pass-no-mod-with-dep-in-subdir"])
+        .args(["-p", "pass-mod-with-dep-in-subdir"])
+        .output()
+        .unwrap();
+
+    // [#8887](https://github.com/rust-lang/rust-clippy/issues/8887)
+    // `mod.rs` checks should not be applied to crate dependencies
+    // located in the subdirectory of workspace
+    let output = Command::new(&*CARGO_CLIPPY_PATH)
+        .current_dir(&cwd)
+        .env("CARGO_INCREMENTAL", "0")
+        .env("CARGO_TARGET_DIR", &target_dir)
+        .arg("clippy")
+        .args(["-p", "pass-no-mod-with-dep-in-subdir"])
+        .args(["-p", "pass-mod-with-dep-in-subdir"])
+        .arg("--")
+        .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
+        .output()
+        .unwrap();
+
+    println!("status: {}", output.status);
+    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
+    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
+    assert!(output.status.success());
+}
+
+#[test]
 fn test_no_deps_ignores_path_deps_in_workspaces() {
     if IS_RUSTC_TEST_SUITE {
         return;
diff --git a/tests/workspace_test/Cargo.toml b/tests/workspace_test/Cargo.toml
index bf5b4ca5288..d24b278ccc2 100644
--- a/tests/workspace_test/Cargo.toml
+++ b/tests/workspace_test/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
 edition = "2018"
 
 [workspace]
-members = ["subcrate"]
+members = ["subcrate", "module_style/pass_no_mod_with_dep_in_subdir", "module_style/pass_mod_with_dep_in_subdir"]
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml
new file mode 100644
index 00000000000..15dcde4e30a
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "pass-mod-with-dep-in-subdir"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+dep-no-mod = { path = "dep_no_mod"}
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml
new file mode 100644
index 00000000000..55569bc25ed
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "dep-no-mod"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs
new file mode 100644
index 00000000000..7b0966a4586
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo.rs
@@ -0,0 +1,2 @@
+pub mod hello;
+pub struct Thing;
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs
new file mode 100644
index 00000000000..99940dce528
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/foo/hello.rs
@@ -0,0 +1 @@
+pub struct Hello;
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs
new file mode 100644
index 00000000000..c62f9acbf2c
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/dep_no_mod/src/lib.rs
@@ -0,0 +1,5 @@
+pub mod foo;
+
+pub fn foo() {
+    let _ = foo::Thing;
+}
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/bad/mod.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs
new file mode 100644
index 00000000000..5cb4795e945
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/main.rs
@@ -0,0 +1,13 @@
+#![deny(clippy::self_named_module_files)]
+
+mod bad;
+mod more;
+extern crate dep_no_mod;
+
+fn main() {
+    let _ = bad::Thing;
+    let _ = more::foo::Foo;
+    let _ = more::inner::Inner;
+    let _ = dep_no_mod::foo::Thing;
+    let _ = dep_no_mod::foo::hello::Hello;
+}
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs
new file mode 100644
index 00000000000..4a835673a59
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/foo.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs
new file mode 100644
index 00000000000..aa84f78cc2c
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/inner/mod.rs
@@ -0,0 +1 @@
+pub struct Inner;
diff --git a/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs
new file mode 100644
index 00000000000..d79569f78ff
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_mod_with_dep_in_subdir/src/more/mod.rs
@@ -0,0 +1,2 @@
+pub mod foo;
+pub mod inner;
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml
new file mode 100644
index 00000000000..060cb18dc9f
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "pass-no-mod-with-dep-in-subdir"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+dep-with-mod = { path = "dep_with_mod"}
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml
new file mode 100644
index 00000000000..b25725cd561
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "dep-with-mod"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs
new file mode 100644
index 00000000000..4647424f2c2
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/lib.rs
@@ -0,0 +1,7 @@
+pub mod with_mod;
+
+pub fn foo() {
+    let _ = with_mod::Thing;
+    let _ = with_mod::inner::stuff::Inner;
+    let _ = with_mod::inner::stuff::most::Snarks;
+}
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs
new file mode 100644
index 00000000000..91cd540a28f
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner.rs
@@ -0,0 +1 @@
+pub mod stuff;
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs
new file mode 100644
index 00000000000..7713fa9d35c
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff.rs
@@ -0,0 +1,3 @@
+pub mod most;
+
+pub struct Inner;
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs
new file mode 100644
index 00000000000..5a5eaf9670f
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/inner/stuff/most.rs
@@ -0,0 +1 @@
+pub struct Snarks;
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs
new file mode 100644
index 00000000000..a12734db7cb
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/dep_with_mod/src/with_mod/mod.rs
@@ -0,0 +1,3 @@
+pub mod inner;
+
+pub struct Thing;
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/good.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs
new file mode 100644
index 00000000000..42eb99cd7a3
--- /dev/null
+++ b/tests/workspace_test/module_style/pass_no_mod_with_dep_in_subdir/src/main.rs
@@ -0,0 +1,9 @@
+#![deny(clippy::mod_module_files)]
+
+mod good;
+pub use dep_with_mod::with_mod::Thing;
+
+fn main() {
+    let _ = good::Thing;
+    let _ = dep_with_mod::with_mod::Thing;
+}
diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html
index 6e810a349bf..31ce8819329 100644
--- a/util/gh-pages/versions.html
+++ b/util/gh-pages/versions.html
@@ -36,7 +36,7 @@
                 <ul class="list-group">
                     <a class="list-group-item" ng-repeat="version in data | orderBy:versionOrder:true"
                        href="./{{version}}/index.html">
-                        {{normalizeVersionDisplay(version)}}
+                        {{version}}
                     </a>
                 </ul>
             </article>
@@ -54,18 +54,15 @@
         .controller('docVersions', function ($scope, $http) {
             $scope.loading = true;
 
-            $scope.normalizeVersionDisplay = function(v) {
-                return v.replace(/^v/, '');
-            };
-
             $scope.normalizeVersion = function(v) {
-                return v.replace(/^v/, '').replace(/^rust-/, '');
+                return v.replace(/^rust-/, '');
             };
 
             $scope.versionOrder = function(v) {
                 if (v === 'master') { return Infinity; }
                 if (v === 'stable') { return Number.MAX_VALUE; }
                 if (v === 'beta') { return Number.MAX_VALUE - 1; }
+                if (v === 'pre-1.29.0') { return Number.MIN_VALUE; }
 
                 return $scope.normalizeVersion(v)
                     .split('.')
diff --git a/util/versions.py b/util/versions.py
index 0cfa007d1b2..c041fc606a8 100755
--- a/util/versions.py
+++ b/util/versions.py
@@ -1,24 +1,27 @@
 #!/usr/bin/env python
 
 import json
+import logging as log
 import os
 import sys
-import logging as log
-log.basicConfig(level=log.INFO, format='%(levelname)s: %(message)s')
+
+log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
 
 
 def key(v):
-    if v == 'master':
-        return float('inf')
-    if v == 'stable':
+    if v == "master":
+        return float("inf")
+    if v == "stable":
         return sys.maxsize
-    if v == 'beta':
+    if v == "beta":
         return sys.maxsize - 1
+    if v == "pre-1.29.0":
+        return -1
 
-    v = v.replace('v', '').replace('rust-', '')
+    v = v.replace("rust-", "")
 
     s = 0
-    for i, val in enumerate(v.split('.')[::-1]):
+    for i, val in enumerate(v.split(".")[::-1]):
         s += int(val) * 100**i
 
     return s
@@ -31,7 +34,11 @@ def main():
 
     outdir = sys.argv[1]
     versions = [
-        dir for dir in os.listdir(outdir) if not dir.startswith(".") and os.path.isdir(os.path.join(outdir, dir))
+        dir
+        for dir in os.listdir(outdir)
+        if not dir.startswith(".")
+        and not dir.startswith("v")
+        and os.path.isdir(os.path.join(outdir, dir))
     ]
     versions.sort(key=key)