about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2022-07-28 18:47:48 +0200
committerPhilipp Krones <hello@philkrones.com>2022-07-28 18:55:32 +0200
commit0905ec465dc10ca5314df843ff65168cc4d3870a (patch)
treeb974b2b80f1332ec1fb4982f1403ed5bf372bcb4
parentc31637e08229aec48f2f24713be593010e39c6f4 (diff)
parent70bca2988b30e4c9b694562dd035912c81916820 (diff)
downloadrust-0905ec465dc10ca5314df843ff65168cc4d3870a.tar.gz
rust-0905ec465dc10ca5314df843ff65168cc4d3870a.zip
Merge remote-tracking branch 'upstream/master' into rustup
-rw-r--r--CHANGELOG.md3
-rw-r--r--Cargo.toml2
-rw-r--r--book/src/continuous_integration/github_actions.md6
-rw-r--r--book/src/development/adding_lints.md45
-rw-r--r--book/src/development/infrastructure/book.md2
-rw-r--r--clippy_dev/src/fmt.rs8
-rw-r--r--clippy_dev/src/lib.rs1
-rw-r--r--clippy_dev/src/main.rs11
-rw-r--r--clippy_dev/src/new_lint.rs321
-rw-r--r--clippy_dev/src/update_lints.rs10
-rw-r--r--clippy_lints/Cargo.toml2
-rw-r--r--clippy_lints/src/as_conversions.rs2
-rw-r--r--clippy_lints/src/assertions_on_result_states.rs98
-rw-r--r--clippy_lints/src/cargo/mod.rs10
-rw-r--r--clippy_lints/src/case_sensitive_file_extension_comparisons.rs5
-rw-r--r--clippy_lints/src/dereference.rs3
-rw-r--r--clippy_lints/src/format.rs19
-rw-r--r--clippy_lints/src/format_impl.rs2
-rw-r--r--clippy_lints/src/lib.register_all.rs2
-rw-r--r--clippy_lints/src/lib.register_lints.rs3
-rw-r--r--clippy_lints/src/lib.register_nursery.rs2
-rw-r--r--clippy_lints/src/lib.register_pedantic.rs2
-rw-r--r--clippy_lints/src/lib.register_restriction.rs1
-rw-r--r--clippy_lints/src/lib.register_style.rs2
-rw-r--r--clippy_lints/src/lib.rs9
-rw-r--r--clippy_lints/src/lifetimes.rs2
-rw-r--r--clippy_lints/src/loops/while_let_loop.rs2
-rw-r--r--clippy_lints/src/macro_use.rs3
-rw-r--r--clippy_lints/src/matches/mod.rs30
-rw-r--r--clippy_lints/src/methods/inefficient_to_string.rs2
-rw-r--r--clippy_lints/src/methods/mod.rs34
-rw-r--r--clippy_lints/src/methods/obfuscated_if_else.rs42
-rw-r--r--clippy_lints/src/mismatching_type_param_order.rs24
-rw-r--r--clippy_lints/src/missing_doc.rs21
-rw-r--r--clippy_lints/src/mutable_debug_assertion.rs4
-rw-r--r--clippy_lints/src/non_copy_const.rs18
-rw-r--r--clippy_lints/src/operators/arithmetic.rs119
-rw-r--r--clippy_lints/src/operators/assign_op_pattern.rs80
-rw-r--r--clippy_lints/src/operators/mod.rs47
-rw-r--r--clippy_lints/src/question_mark.rs4
-rw-r--r--clippy_lints/src/ranges.rs2
-rw-r--r--clippy_lints/src/same_name_method.rs10
-rw-r--r--clippy_lints/src/std_instead_of_core.rs96
-rw-r--r--clippy_lints/src/strings.rs4
-rw-r--r--clippy_lints/src/unused_self.rs17
-rw-r--r--clippy_lints/src/utils/conf.rs6
-rw-r--r--clippy_utils/src/consts.rs20
-rw-r--r--clippy_utils/src/diagnostics.rs8
-rw-r--r--clippy_utils/src/hir_utils.rs33
-rw-r--r--clippy_utils/src/lib.rs4
-rw-r--r--tests/compile-test.rs41
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml2
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr12
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.toml2
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr12
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.toml2
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr12
-rw-r--r--tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml2
-rw-r--r--tests/ui-cargo/cargo_common_metadata/pass_publish_empty/Cargo.toml2
-rw-r--r--tests/ui-cargo/cargo_common_metadata/pass_publish_false/Cargo.toml2
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml1
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml1
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml1
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml1
-rw-r--r--tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml1
-rw-r--r--tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml3
-rw-r--r--tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml3
-rw-r--r--tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml3
-rw-r--r--tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml3
-rw-r--r--tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml1
-rw-r--r--tests/ui-cargo/module_style/fail_mod/Cargo.toml3
-rw-r--r--tests/ui-cargo/module_style/fail_no_mod/Cargo.toml3
-rw-r--r--tests/ui-cargo/module_style/pass_mod/Cargo.toml3
-rw-r--r--tests/ui-cargo/module_style/pass_no_mod/Cargo.toml3
-rw-r--r--tests/ui-cargo/multiple_config_files/no_warn/Cargo.toml1
-rw-r--r--tests/ui-cargo/multiple_config_files/warn/Cargo.toml1
-rw-r--r--tests/ui-cargo/multiple_config_files/warn/src/main.rs2
-rw-r--r--tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml2
-rw-r--r--tests/ui-internal/check_clippy_version_attribute.stderr8
-rw-r--r--tests/ui-internal/default_lint.stderr2
-rw-r--r--tests/ui-internal/if_chain_style.stderr2
-rw-r--r--tests/ui-toml/arithmetic_allowed/arithmetic_allowed.rs24
-rw-r--r--tests/ui-toml/arithmetic_allowed/clippy.toml1
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr1
-rw-r--r--tests/ui/arithmetic.fixed27
-rw-r--r--tests/ui/arithmetic.rs27
-rw-r--r--tests/ui/assertions_on_result_states.fixed69
-rw-r--r--tests/ui/assertions_on_result_states.rs69
-rw-r--r--tests/ui/assertions_on_result_states.stderr40
-rw-r--r--tests/ui/assign_ops.fixed11
-rw-r--r--tests/ui/assign_ops.rs11
-rw-r--r--tests/ui/assign_ops.stderr32
-rw-r--r--tests/ui/crashes/ice-9238.rs12
-rw-r--r--tests/ui/crashes/ice-9242.rs8
-rw-r--r--tests/ui/crate_level_checks/entrypoint_recursion.rs1
-rw-r--r--tests/ui/crate_level_checks/entrypoint_recursion.stderr2
-rw-r--r--tests/ui/declare_interior_mutable_const/others.rs22
-rw-r--r--tests/ui/declare_interior_mutable_const/others.stderr13
-rw-r--r--tests/ui/derive.rs1
-rw-r--r--tests/ui/derive.stderr20
-rw-r--r--tests/ui/expect_tool_lint_rfc_2383.rs12
-rw-r--r--tests/ui/format.fixed6
-rw-r--r--tests/ui/format.rs6
-rw-r--r--tests/ui/format.stderr14
-rw-r--r--tests/ui/match_same_arms2.rs10
-rw-r--r--tests/ui/mismatching_type_param_order.rs4
-rw-r--r--tests/ui/needless_borrow.fixed25
-rw-r--r--tests/ui/needless_borrow.rs25
-rw-r--r--tests/ui/needless_borrow.stderr14
-rw-r--r--tests/ui/obfuscated_if_else.fixed7
-rw-r--r--tests/ui/obfuscated_if_else.rs7
-rw-r--r--tests/ui/obfuscated_if_else.stderr10
-rw-r--r--tests/ui/std_instead_of_core.rs6
-rw-r--r--tests/ui/std_instead_of_core.stderr28
-rw-r--r--tests/ui/temporary_assignment.rs1
-rw-r--r--tests/ui/temporary_assignment.stderr8
-rw-r--r--tests/ui/unused_self.rs9
117 files changed, 1578 insertions, 345 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 920d397add7..2278a8dc16b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3437,9 +3437,11 @@ Released 2018-09-13
 [`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
 [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
 [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
+[`arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic
 [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
 [`as_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore
 [`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants
+[`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_result_states
 [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern
 [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops
 [`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async
@@ -3793,6 +3795,7 @@ Released 2018-09-13
 [`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
 [`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
 [`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref
+[`obfuscated_if_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#obfuscated_if_else
 [`octal_escapes`]: https://rust-lang.github.io/rust-clippy/master/index.html#octal_escapes
 [`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect
 [`only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#only_used_in_recursion
diff --git a/Cargo.toml b/Cargo.toml
index 644ca6318f6..69deaca0b4b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,6 +32,7 @@ compiletest_rs = { version = "0.8", features = ["tmp"] }
 tester = "0.9"
 regex = "1.5"
 toml = "0.5"
+walkdir = "2.3"
 # This is used by the `collect-metadata` alias.
 filetime = "0.2"
 
@@ -41,6 +42,7 @@ filetime = "0.2"
 rustc-workspace-hack = "1.0"
 
 # UI test dependencies
+clap = { version = "3.1", features = ["derive"] }
 clippy_utils = { path = "clippy_utils" }
 derive-new = "0.5"
 if_chain = "1.0"
diff --git a/book/src/continuous_integration/github_actions.md b/book/src/continuous_integration/github_actions.md
index 42a43ef1380..339287a7dd9 100644
--- a/book/src/continuous_integration/github_actions.md
+++ b/book/src/continuous_integration/github_actions.md
@@ -1,7 +1,7 @@
 # GitHub Actions
 
-On the GitHub hosted runners, Clippy from the latest stable Rust version comes
-pre-installed. So all you have to do is to run `cargo clippy`.
+GitHub hosted runners using the latest stable version of Rust have Clippy pre-installed.
+It is as simple as running `cargo clippy` to run lints against the codebase.
 
 ```yml
 on: push
@@ -15,7 +15,7 @@ jobs:
   clippy_check:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v1
+      - uses: actions/checkout@v3
       - name: Run Clippy
         run: cargo clippy --all-targets --all-features
 ```
diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md
index d06297f2e07..da781eb970d 100644
--- a/book/src/development/adding_lints.md
+++ b/book/src/development/adding_lints.md
@@ -10,6 +10,10 @@ because that's clearly a non-descriptive name.
 - [Adding a new lint](#adding-a-new-lint)
   - [Setup](#setup)
   - [Getting Started](#getting-started)
+    - [Defining Our Lint](#defining-our-lint)
+      - [Standalone](#standalone)
+      - [Specific Type](#specific-type)
+      - [Tests Location](#tests-location)
   - [Testing](#testing)
     - [Cargo lints](#cargo-lints)
   - [Rustfix tests](#rustfix-tests)
@@ -36,17 +40,38 @@ See the [Basics](basics.md#get-the-code) documentation.
 ## Getting Started
 
 There is a bit of boilerplate code that needs to be set up when creating a new
-lint. Fortunately, you can use the clippy dev tools to handle this for you. We
+lint. Fortunately, you can use the Clippy dev tools to handle this for you. We
 are naming our new lint `foo_functions` (lints are generally written in snake
-case), and we don't need type information so it will have an early pass type
-(more on this later on). If you're not sure if the name you chose fits the lint,
-take a look at our [lint naming guidelines][lint_naming]. To get started on this
-lint you can run `cargo dev new_lint --name=foo_functions --pass=early
---category=pedantic` (category will default to nursery if not provided). This
-command will create two files: `tests/ui/foo_functions.rs` and
-`clippy_lints/src/foo_functions.rs`, as well as [registering the
-lint](#lint-registration). For cargo lints, two project hierarchies (fail/pass)
-will be created by default under `tests/ui-cargo`.
+case), and we don't need type information, so it will have an early pass type
+(more on this later). If you're unsure if the name you chose fits the lint,
+take a look at our [lint naming guidelines][lint_naming].
+
+## Defining Our Lint
+To get started, there are two ways to define our lint.
+
+### Standalone
+Command: `cargo dev new_lint --name=foo_functions --pass=early --category=pedantic`
+(category will default to nursery if not provided)
+
+This command will create a new file: `clippy_lints/src/foo_functions.rs`, as well
+as [register the lint](#lint-registration).
+
+### Specific Type
+Command: `cargo dev new_lint --name=foo_functions --type=functions --category=pedantic`
+
+This command will create a new file: `clippy_lints/src/{type}/foo_functions.rs`.
+
+Notice how this command has a `--type` flag instead of `--pass`. Unlike a standalone
+definition, this lint won't be registered in the traditional sense. Instead, you will
+call your lint from within the type's lint pass, found in `clippy_lints/src/{type}/mod.rs`.
+
+A "type" is just the name of a directory in `clippy_lints/src`, like `functions` in
+the example command. These are groupings of lints with common behaviors, so if your
+lint falls into one, it would be best to add it to that type.
+
+### Tests Location
+Both commands will create a file: `tests/ui/foo_functions.rs`. For cargo lints,
+two project hierarchies (fail/pass) will be created by default under `tests/ui-cargo`.
 
 Next, we'll open up these files and add our lint!
 
diff --git a/book/src/development/infrastructure/book.md b/book/src/development/infrastructure/book.md
index b62314c6735..a4874219185 100644
--- a/book/src/development/infrastructure/book.md
+++ b/book/src/development/infrastructure/book.md
@@ -25,7 +25,7 @@ instructions for other options.
 ## Make changes
 
 The book's
-[src](https://github.com/joshrotenberg/rust-clippy/tree/clippy_guide/book/src)
+[src](https://github.com/rust-lang/rust-clippy/tree/master/book/src)
 directory contains all of the markdown files used to generate the book. If you
 want to see your changes in real time, you can use the mdbook `serve` command to
 run a web server locally that will automatically update changes as they are
diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs
index d513a229b7e..3b27f061eb0 100644
--- a/clippy_dev/src/fmt.rs
+++ b/clippy_dev/src/fmt.rs
@@ -13,7 +13,7 @@ pub enum CliError {
     IoError(io::Error),
     RustfmtNotInstalled,
     WalkDirError(walkdir::Error),
-    RaSetupActive,
+    IntellijSetupActive,
 }
 
 impl From<io::Error> for CliError {
@@ -48,7 +48,7 @@ pub fn run(check: bool, verbose: bool) {
             .expect("Failed to read clippy Cargo.toml")
             .contains(&"[target.'cfg(NOT_A_PLATFORM)'.dependencies]")
         {
-            return Err(CliError::RaSetupActive);
+            return Err(CliError::IntellijSetupActive);
         }
 
         rustfmt_test(context)?;
@@ -93,11 +93,11 @@ pub fn run(check: bool, verbose: bool) {
             CliError::WalkDirError(err) => {
                 eprintln!("error: {}", err);
             },
-            CliError::RaSetupActive => {
+            CliError::IntellijSetupActive => {
                 eprintln!(
                     "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.
 Not formatting because that would format the local repo as well!
-Please revert the changes to Cargo.tomls first."
+Please revert the changes to Cargo.tomls with `cargo dev remove intellij`."
                 );
             },
         }
diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs
index 8536e242992..8a6bd1cbdf5 100644
--- a/clippy_dev/src/lib.rs
+++ b/clippy_dev/src/lib.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(let_else)]
 #![feature(once_cell)]
 #![feature(rustc_private)]
diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs
index a29ba2d0c85..a417d3dd8a4 100644
--- a/clippy_dev/src/main.rs
+++ b/clippy_dev/src/main.rs
@@ -36,7 +36,8 @@ fn main() {
             match new_lint::create(
                 matches.get_one::<String>("pass"),
                 matches.get_one::<String>("name"),
-                matches.get_one::<String>("category"),
+                matches.get_one::<String>("category").map(String::as_str),
+                matches.get_one::<String>("type").map(String::as_str),
                 matches.contains_id("msrv"),
             ) {
                 Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
@@ -157,7 +158,8 @@ fn get_clap_config() -> ArgMatches {
                         .help("Specify whether the lint runs during the early or late pass")
                         .takes_value(true)
                         .value_parser([PossibleValue::new("early"), PossibleValue::new("late")])
-                        .required(true),
+                        .conflicts_with("type")
+                        .required_unless_present("type"),
                     Arg::new("name")
                         .short('n')
                         .long("name")
@@ -183,6 +185,11 @@ fn get_clap_config() -> ArgMatches {
                             PossibleValue::new("internal_warn"),
                         ])
                         .takes_value(true),
+                    Arg::new("type")
+                        .long("type")
+                        .help("What directory the lint belongs in")
+                        .takes_value(true)
+                        .required(false),
                     Arg::new("msrv").long("msrv").help("Add MSRV config code to the lint"),
                 ]),
             Command::new("setup")
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index 7d7e760ef44..03d2ef3d19e 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -1,5 +1,5 @@
 use crate::clippy_project_root;
-use indoc::indoc;
+use indoc::{indoc, writedoc};
 use std::fmt::Write as _;
 use std::fs::{self, OpenOptions};
 use std::io::prelude::*;
@@ -10,6 +10,7 @@ struct LintData<'a> {
     pass: &'a str,
     name: &'a str,
     category: &'a str,
+    ty: Option<&'a str>,
     project_root: PathBuf,
 }
 
@@ -37,26 +38,44 @@ impl<T> Context for io::Result<T> {
 pub fn create(
     pass: Option<&String>,
     lint_name: Option<&String>,
-    category: Option<&String>,
+    category: Option<&str>,
+    mut ty: Option<&str>,
     msrv: bool,
 ) -> io::Result<()> {
+    if category == Some("cargo") && ty.is_none() {
+        // `cargo` is a special category, these lints should always be in `clippy_lints/src/cargo`
+        ty = Some("cargo");
+    }
+
     let lint = LintData {
-        pass: pass.expect("`pass` argument is validated by clap"),
+        pass: pass.map_or("", String::as_str),
         name: lint_name.expect("`name` argument is validated by clap"),
         category: category.expect("`category` argument is validated by clap"),
+        ty,
         project_root: clippy_project_root(),
     };
 
     create_lint(&lint, msrv).context("Unable to create lint implementation")?;
     create_test(&lint).context("Unable to create a test for the new lint")?;
-    add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")
+
+    if lint.ty.is_none() {
+        add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?;
+    }
+
+    Ok(())
 }
 
 fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
-    let lint_contents = get_lint_file_contents(lint, enable_msrv);
+    if let Some(ty) = lint.ty {
+        create_lint_for_ty(lint, enable_msrv, ty)
+    } else {
+        let lint_contents = get_lint_file_contents(lint, enable_msrv);
+        let lint_path = format!("clippy_lints/src/{}.rs", lint.name);
+        write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes())?;
+        println!("Generated lint file: `{}`", lint_path);
 
-    let lint_path = format!("clippy_lints/src/{}.rs", lint.name);
-    write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes())
+        Ok(())
+    }
 }
 
 fn create_test(lint: &LintData<'_>) -> io::Result<()> {
@@ -75,16 +94,22 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
 
     if lint.category == "cargo" {
         let relative_test_dir = format!("tests/ui-cargo/{}", lint.name);
-        let test_dir = lint.project_root.join(relative_test_dir);
+        let test_dir = lint.project_root.join(&relative_test_dir);
         fs::create_dir(&test_dir)?;
 
         create_project_layout(lint.name, &test_dir, "fail", "Content that triggers the lint goes here")?;
-        create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint")
+        create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint")?;
+
+        println!("Generated test directories: `{relative_test_dir}/pass`, `{relative_test_dir}/fail`");
     } else {
         let test_path = format!("tests/ui/{}.rs", lint.name);
         let test_contents = get_test_file_contents(lint.name, None);
-        write_file(lint.project_root.join(test_path), test_contents)
+        write_file(lint.project_root.join(&test_path), test_contents)?;
+
+        println!("Generated test file: `{}`", test_path);
     }
+
+    Ok(())
 }
 
 fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
@@ -204,7 +229,6 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
         },
     };
 
-    let version = get_stabilization_version();
     let lint_name = lint.name;
     let category = lint.category;
     let name_camel = to_camel_case(lint.name);
@@ -238,32 +262,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
         )
     });
 
-    let _ = write!(
-        result,
-        indoc! {r#"
-            declare_clippy_lint! {{
-                /// ### What it does
-                ///
-                /// ### Why is this bad?
-                ///
-                /// ### Example
-                /// ```rust
-                /// // example code where clippy issues a warning
-                /// ```
-                /// Use instead:
-                /// ```rust
-                /// // example code which does not raise clippy warning
-                /// ```
-                #[clippy::version = "{version}"]
-                pub {name_upper},
-                {category},
-                "default lint description"
-            }}
-        "#},
-        version = version,
-        name_upper = name_upper,
-        category = category,
-    );
+    let _ = write!(result, "{}", get_lint_declaration(&name_upper, category));
 
     result.push_str(&if enable_msrv {
         format!(
@@ -312,6 +311,254 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
     result
 }
 
+fn get_lint_declaration(name_upper: &str, category: &str) -> String {
+    format!(
+        indoc! {r#"
+            declare_clippy_lint! {{
+                /// ### What it does
+                ///
+                /// ### Why is this bad?
+                ///
+                /// ### Example
+                /// ```rust
+                /// // example code where clippy issues a warning
+                /// ```
+                /// Use instead:
+                /// ```rust
+                /// // example code which does not raise clippy warning
+                /// ```
+                #[clippy::version = "{version}"]
+                pub {name_upper},
+                {category},
+                "default lint description"
+            }}
+        "#},
+        version = get_stabilization_version(),
+        name_upper = name_upper,
+        category = category,
+    )
+}
+
+fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::Result<()> {
+    match ty {
+        "cargo" => assert_eq!(
+            lint.category, "cargo",
+            "Lints of type `cargo` must have the `cargo` category"
+        ),
+        _ if lint.category == "cargo" => panic!("Lints of category `cargo` must have the `cargo` type"),
+        _ => {},
+    }
+
+    let ty_dir = lint.project_root.join(format!("clippy_lints/src/{}", ty));
+    assert!(
+        ty_dir.exists() && ty_dir.is_dir(),
+        "Directory `{}` does not exist!",
+        ty_dir.display()
+    );
+
+    let lint_file_path = ty_dir.join(format!("{}.rs", lint.name));
+    assert!(
+        !lint_file_path.exists(),
+        "File `{}` already exists",
+        lint_file_path.display()
+    );
+
+    let mod_file_path = ty_dir.join("mod.rs");
+    let context_import = setup_mod_file(&mod_file_path, lint)?;
+
+    let name_upper = lint.name.to_uppercase();
+    let mut lint_file_contents = String::new();
+
+    if enable_msrv {
+        let _ = writedoc!(
+            lint_file_contents,
+            r#"
+                use clippy_utils::{{meets_msrv, msrvs}};
+                use rustc_lint::{{{context_import}, LintContext}};
+                use rustc_semver::RustcVersion;
+
+                use super::{name_upper};
+
+                // TODO: Adjust the parameters as necessary
+                pub(super) fn check(cx: &{context_import}, msrv: Option<RustcVersion>) {{
+                    if !meets_msrv(msrv, todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{
+                        return;
+                    }}
+                    todo!();
+                }}
+           "#,
+            context_import = context_import,
+            name_upper = name_upper,
+        );
+    } else {
+        let _ = writedoc!(
+            lint_file_contents,
+            r#"
+                use rustc_lint::{{{context_import}, LintContext}};
+
+                use super::{name_upper};
+
+                // TODO: Adjust the parameters as necessary
+                pub(super) fn check(cx: &{context_import}) {{
+                    todo!();
+                }}
+           "#,
+            context_import = context_import,
+            name_upper = name_upper,
+        );
+    }
+
+    write_file(lint_file_path.as_path(), lint_file_contents)?;
+    println!("Generated lint file: `clippy_lints/src/{}/{}.rs`", ty, lint.name);
+    println!(
+        "Be sure to add a call to `{}::check` in `clippy_lints/src/{}/mod.rs`!",
+        lint.name, ty
+    );
+
+    Ok(())
+}
+
+#[allow(clippy::too_many_lines)]
+fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> {
+    use super::update_lints::{match_tokens, LintDeclSearchResult};
+    use rustc_lexer::TokenKind;
+
+    let lint_name_upper = lint.name.to_uppercase();
+
+    let mut file_contents = fs::read_to_string(path)?;
+    assert!(
+        !file_contents.contains(&lint_name_upper),
+        "Lint `{}` already defined in `{}`",
+        lint.name,
+        path.display()
+    );
+
+    let mut offset = 0usize;
+    let mut last_decl_curly_offset = None;
+    let mut lint_context = None;
+
+    let mut iter = rustc_lexer::tokenize(&file_contents).map(|t| {
+        let range = offset..offset + t.len;
+        offset = range.end;
+
+        LintDeclSearchResult {
+            token_kind: t.kind,
+            content: &file_contents[range.clone()],
+            range,
+        }
+    });
+
+    // Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
+    while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token_kind == TokenKind::Ident) {
+        let mut iter = iter
+            .by_ref()
+            .filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
+
+        match content {
+            "declare_clippy_lint" => {
+                // matches `!{`
+                match_tokens!(iter, Bang OpenBrace);
+                if let Some(LintDeclSearchResult { range, .. }) =
+                    iter.find(|result| result.token_kind == TokenKind::CloseBrace)
+                {
+                    last_decl_curly_offset = Some(range.end);
+                }
+            },
+            "impl" => {
+                let mut token = iter.next();
+                match token {
+                    // matches <'foo>
+                    Some(LintDeclSearchResult {
+                        token_kind: TokenKind::Lt,
+                        ..
+                    }) => {
+                        match_tokens!(iter, Lifetime { .. } Gt);
+                        token = iter.next();
+                    },
+                    None => break,
+                    _ => {},
+                }
+
+                if let Some(LintDeclSearchResult {
+                    token_kind: TokenKind::Ident,
+                    content,
+                    ..
+                }) = token
+                {
+                    // Get the appropriate lint context struct
+                    lint_context = match content {
+                        "LateLintPass" => Some("LateContext"),
+                        "EarlyLintPass" => Some("EarlyContext"),
+                        _ => continue,
+                    };
+                }
+            },
+            _ => {},
+        }
+    }
+
+    drop(iter);
+
+    let last_decl_curly_offset =
+        last_decl_curly_offset.unwrap_or_else(|| panic!("No lint declarations found in `{}`", path.display()));
+    let lint_context =
+        lint_context.unwrap_or_else(|| panic!("No lint pass implementation found in `{}`", path.display()));
+
+    // Add the lint declaration to `mod.rs`
+    file_contents.replace_range(
+        // Remove the trailing newline, which should always be present
+        last_decl_curly_offset..=last_decl_curly_offset,
+        &format!("\n\n{}", get_lint_declaration(&lint_name_upper, lint.category)),
+    );
+
+    // Add the lint to `impl_lint_pass`/`declare_lint_pass`
+    let impl_lint_pass_start = file_contents.find("impl_lint_pass!").unwrap_or_else(|| {
+        file_contents
+            .find("declare_lint_pass!")
+            .unwrap_or_else(|| panic!("failed to find `impl_lint_pass`/`declare_lint_pass`"))
+    });
+
+    let mut arr_start = file_contents[impl_lint_pass_start..].find('[').unwrap_or_else(|| {
+        panic!("malformed `impl_lint_pass`/`declare_lint_pass`");
+    });
+
+    arr_start += impl_lint_pass_start;
+
+    let mut arr_end = file_contents[arr_start..]
+        .find(']')
+        .expect("failed to find `impl_lint_pass` terminator");
+
+    arr_end += arr_start;
+
+    let mut arr_content = file_contents[arr_start + 1..arr_end].to_string();
+    arr_content.retain(|c| !c.is_whitespace());
+
+    let mut new_arr_content = String::new();
+    for ident in arr_content
+        .split(',')
+        .chain(std::iter::once(&*lint_name_upper))
+        .filter(|s| !s.is_empty())
+    {
+        let _ = write!(new_arr_content, "\n    {},", ident);
+    }
+    new_arr_content.push('\n');
+
+    file_contents.replace_range(arr_start + 1..arr_end, &new_arr_content);
+
+    // Just add the mod declaration at the top, it'll be fixed by rustfmt
+    file_contents.insert_str(0, &format!("mod {};\n", &lint.name));
+
+    let mut file = OpenOptions::new()
+        .write(true)
+        .truncate(true)
+        .open(path)
+        .context(format!("trying to open: `{}`", path.display()))?;
+    file.write_all(file_contents.as_bytes())
+        .context(format!("writing to file: `{}`", path.display()))?;
+
+    Ok(lint_context)
+}
+
 #[test]
 fn test_camel_case() {
     let s = "a_lint";
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index c089f4d8ce4..aed38bc2817 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -824,10 +824,12 @@ macro_rules! match_tokens {
     }
 }
 
-struct LintDeclSearchResult<'a> {
-    token_kind: TokenKind,
-    content: &'a str,
-    range: Range<usize>,
+pub(crate) use match_tokens;
+
+pub(crate) struct LintDeclSearchResult<'a> {
+    pub token_kind: TokenKind,
+    pub content: &'a str,
+    pub range: Range<usize>,
 }
 
 /// Parse a source file looking for `declare_clippy_lint` macro invocations.
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index 79a56dc405d..9a3f042ffc0 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -18,7 +18,7 @@ quine-mc_cluskey = "0.2"
 regex-syntax = "0.6"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
-tempfile = { version = "3.2", optional = true }
+tempfile = { version = "3.3.0", optional = true }
 toml = "0.5"
 unicode-normalization = "0.1"
 unicode-script = { version = "0.5", default-features = false }
diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs
index 6e5c8f44581..c7a76e5f907 100644
--- a/clippy_lints/src/as_conversions.rs
+++ b/clippy_lints/src/as_conversions.rs
@@ -11,7 +11,7 @@ declare_clippy_lint! {
     /// Note that this lint is specialized in linting *every single* use of `as`
     /// regardless of whether good alternatives exist or not.
     /// If you want more precise lints for `as`, please consider using these separate lints:
-    /// `unnecessary_cast`, `cast_lossless/possible_truncation/possible_wrap/precision_loss/sign_loss`,
+    /// `unnecessary_cast`, `cast_lossless/cast_possible_truncation/cast_possible_wrap/cast_precision_loss/cast_sign_loss`,
     /// `fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`.
     /// There is a good explanation the reason why this lint should work in this way and how it is useful
     /// [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122).
diff --git a/clippy_lints/src/assertions_on_result_states.rs b/clippy_lints/src/assertions_on_result_states.rs
new file mode 100644
index 00000000000..b6affdee523
--- /dev/null
+++ b/clippy_lints/src/assertions_on_result_states.rs
@@ -0,0 +1,98 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::path_res;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
+use clippy_utils::usage::local_used_after_expr;
+use rustc_errors::Applicability;
+use rustc_hir::def::Res;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `assert!(r.is_ok())` or `assert!(r.is_err())` calls.
+    ///
+    /// ### Why is this bad?
+    /// An assertion failure cannot output an useful message of the error.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// # let r = Ok::<_, ()>(());
+    /// assert!(r.is_ok());
+    /// # let r = Err::<_, ()>(());
+    /// assert!(r.is_err());
+    /// ```
+    #[clippy::version = "1.64.0"]
+    pub ASSERTIONS_ON_RESULT_STATES,
+    style,
+    "`assert!(r.is_ok())`/`assert!(r.is_err())` gives worse error message than directly calling `r.unwrap()`/`r.unwrap_err()`"
+}
+
+declare_lint_pass!(AssertionsOnResultStates => [ASSERTIONS_ON_RESULT_STATES]);
+
+impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
+        if let Some(macro_call) = root_macro_call_first_node(cx, e)
+            && matches!(cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::assert_macro))
+            && let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn)
+            && matches!(panic_expn, PanicExpn::Empty)
+            && let ExprKind::MethodCall(method_segment, [recv], _) = condition.kind
+            && let result_type_with_refs = cx.typeck_results().expr_ty(recv)
+            && let result_type = result_type_with_refs.peel_refs()
+            && is_type_diagnostic_item(cx, result_type, sym::Result)
+            && let ty::Adt(_, substs) = result_type.kind()
+        {
+            if !is_copy(cx, result_type) {
+                if result_type_with_refs != result_type {
+                    return;
+                } else if let Res::Local(binding_id) = path_res(cx, recv)
+                    && local_used_after_expr(cx, binding_id, recv) {
+                    return;
+                }
+            }
+            let mut app = Applicability::MachineApplicable;
+            match method_segment.ident.as_str() {
+                "is_ok" if has_debug_impl(cx, substs.type_at(1)) => {
+                    span_lint_and_sugg(
+                        cx,
+                        ASSERTIONS_ON_RESULT_STATES,
+                        macro_call.span,
+                        "called `assert!` with `Result::is_ok`",
+                        "replace with",
+                        format!(
+                            "{}.unwrap()",
+                            snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
+                        ),
+                        app,
+                    );
+                }
+                "is_err" if has_debug_impl(cx, substs.type_at(0)) => {
+                    span_lint_and_sugg(
+                        cx,
+                        ASSERTIONS_ON_RESULT_STATES,
+                        macro_call.span,
+                        "called `assert!` with `Result::is_err`",
+                        "replace with",
+                        format!(
+                            "{}.unwrap_err()",
+                            snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
+                        ),
+                        app,
+                    );
+                }
+                _ => (),
+            };
+        }
+    }
+}
+
+/// This checks whether a given type is known to implement Debug.
+fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    cx.tcx
+        .get_diagnostic_item(sym::Debug)
+        .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
+}
diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs
index abe95c6663f..9f45db86a09 100644
--- a/clippy_lints/src/cargo/mod.rs
+++ b/clippy_lints/src/cargo/mod.rs
@@ -1,3 +1,8 @@
+mod common_metadata;
+mod feature_name;
+mod multiple_crate_versions;
+mod wildcard_dependencies;
+
 use cargo_metadata::MetadataCommand;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_lint_allowed;
@@ -6,11 +11,6 @@ use rustc_lint::{LateContext, LateLintPass, Lint};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::DUMMY_SP;
 
-mod common_metadata;
-mod feature_name;
-mod multiple_crate_versions;
-mod wildcard_dependencies;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks to see if all common metadata is defined in
diff --git a/clippy_lints/src/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
index 7af200708ff..7eff71d5007 100644
--- a/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
+++ b/clippy_lints/src/case_sensitive_file_extension_comparisons.rs
@@ -24,7 +24,10 @@ declare_clippy_lint! {
     /// Use instead:
     /// ```rust
     /// fn is_rust_file(filename: &str) -> bool {
-    ///     filename.rsplit('.').next().map(|ext| ext.eq_ignore_ascii_case("rs")) == Some(true)
+    ///     let filename = std::path::Path::new(filename);
+    ///     filename.extension()
+    ///         .map(|ext| ext.eq_ignore_ascii_case("rs"))
+    ///         .unwrap_or(false)
     /// }
     /// ```
     #[clippy::version = "1.51.0"]
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index 8c7cf7748be..a90f894a7b1 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -1028,9 +1028,10 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
             let mut app = Applicability::MachineApplicable;
             let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
             span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| {
+                let calls_field = matches!(expr.kind, ExprKind::Field(..)) && matches!(data.position, Position::Callee);
                 let sugg = if !snip_is_macro
-                    && expr.precedence().order() < data.position.precedence()
                     && !has_enclosing_paren(&snip)
+                    && (expr.precedence().order() < data.position.precedence() || calls_field)
                 {
                     format!("({})", snip)
                 } else {
diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index 0aa085fc71b..925a8cb8dee 100644
--- a/clippy_lints/src/format.rs
+++ b/clippy_lints/src/format.rs
@@ -9,7 +9,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::kw;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -85,22 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
                         ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
                         _ => false,
                     };
-                    let sugg = if format_args.format_string_span.contains(value.span) {
-                        // Implicit argument. e.g. `format!("{x}")` span points to `{x}`
-                        let spdata = value.span.data();
-                        let span = Span::new(
-                            spdata.lo + BytePos(1),
-                            spdata.hi - BytePos(1),
-                            spdata.ctxt,
-                            spdata.parent
-                        );
-                        let snip = snippet_with_applicability(cx, span, "..", &mut applicability);
-                        if is_new_string {
-                            snip.into()
-                        } else {
-                            format!("{snip}.to_string()")
-                        }
-                    } else if is_new_string {
+                    let sugg = if is_new_string {
                         snippet_with_applicability(cx, value.span, "..", &mut applicability).into_owned()
                     } else {
                         let sugg = Sugg::hir_with_applicability(cx, value, "<arg>", &mut applicability);
diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index ef8be9e878f..04b5be6c80e 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/clippy_lints/src/format_impl.rs
@@ -141,7 +141,7 @@ fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) {
         // Get the hir_id of the object we are calling the method on
         if let ExprKind::MethodCall(path, [ref self_arg, ..], _) = expr.kind;
         // Is the method to_string() ?
-        if path.ident.name == sym!(to_string);
+        if path.ident.name == sym::to_string;
         // Is the method a part of the ToString trait? (i.e. not to_string() implemented
         // separately)
         if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs
index 9afc714b11c..5be1c417bf8 100644
--- a/clippy_lints/src/lib.register_all.rs
+++ b/clippy_lints/src/lib.register_all.rs
@@ -6,6 +6,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE),
     LintId::of(approx_const::APPROX_CONSTANT),
     LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
+    LintId::of(assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES),
     LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC),
     LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS),
     LintId::of(attrs::DEPRECATED_CFG_ATTR),
@@ -187,6 +188,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
     LintId::of(methods::NEEDLESS_SPLITN),
     LintId::of(methods::NEW_RET_NO_SELF),
     LintId::of(methods::NO_EFFECT_REPLACE),
+    LintId::of(methods::OBFUSCATED_IF_ELSE),
     LintId::of(methods::OK_EXPECT),
     LintId::of(methods::OPTION_AS_REF_DEREF),
     LintId::of(methods::OPTION_FILTER_MAP),
diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs
index 91d27bf526d..99bde35cf15 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -42,6 +42,7 @@ store.register_lints(&[
     asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
     asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
     assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
+    assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES,
     async_yields_async::ASYNC_YIELDS_ASYNC,
     attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON,
     attrs::BLANKET_CLIPPY_RESTRICTION_LINTS,
@@ -330,6 +331,7 @@ store.register_lints(&[
     methods::NEEDLESS_SPLITN,
     methods::NEW_RET_NO_SELF,
     methods::NO_EFFECT_REPLACE,
+    methods::OBFUSCATED_IF_ELSE,
     methods::OK_EXPECT,
     methods::OPTION_AS_REF_DEREF,
     methods::OPTION_FILTER_MAP,
@@ -417,6 +419,7 @@ store.register_lints(&[
     only_used_in_recursion::ONLY_USED_IN_RECURSION,
     open_options::NONSENSICAL_OPEN_OPTIONS,
     operators::ABSURD_EXTREME_COMPARISONS,
+    operators::ARITHMETIC,
     operators::ASSIGN_OP_PATTERN,
     operators::BAD_BIT_MASK,
     operators::CMP_NAN,
diff --git a/clippy_lints/src/lib.register_nursery.rs b/clippy_lints/src/lib.register_nursery.rs
index 642d629971d..f961952991f 100644
--- a/clippy_lints/src/lib.register_nursery.rs
+++ b/clippy_lints/src/lib.register_nursery.rs
@@ -28,6 +28,8 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
     LintId::of(strings::STRING_LIT_AS_BYTES),
     LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
     LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
+    LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
+    LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
     LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
     LintId::of(unused_rounding::UNUSED_ROUNDING),
     LintId::of(use_self::USE_SELF),
diff --git a/clippy_lints/src/lib.register_pedantic.rs b/clippy_lints/src/lib.register_pedantic.rs
index a1b54665814..4d4b89687d0 100644
--- a/clippy_lints/src/lib.register_pedantic.rs
+++ b/clippy_lints/src/lib.register_pedantic.rs
@@ -86,8 +86,6 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
     LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
     LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
     LintId::of(strings::STRING_ADD_ASSIGN),
-    LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
-    LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
     LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
     LintId::of(types::LINKEDLIST),
     LintId::of(types::OPTION_OPTION),
diff --git a/clippy_lints/src/lib.register_restriction.rs b/clippy_lints/src/lib.register_restriction.rs
index 43f1c892eb9..495abd8387e 100644
--- a/clippy_lints/src/lib.register_restriction.rs
+++ b/clippy_lints/src/lib.register_restriction.rs
@@ -48,6 +48,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
     LintId::of(mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION),
     LintId::of(module_style::MOD_MODULE_FILES),
     LintId::of(module_style::SELF_NAMED_MODULE_FILES),
+    LintId::of(operators::ARITHMETIC),
     LintId::of(operators::FLOAT_ARITHMETIC),
     LintId::of(operators::FLOAT_CMP_CONST),
     LintId::of(operators::INTEGER_ARITHMETIC),
diff --git a/clippy_lints/src/lib.register_style.rs b/clippy_lints/src/lib.register_style.rs
index 15a1bc569af..e029a5235e7 100644
--- a/clippy_lints/src/lib.register_style.rs
+++ b/clippy_lints/src/lib.register_style.rs
@@ -4,6 +4,7 @@
 
 store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
+    LintId::of(assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES),
     LintId::of(blacklisted_name::BLACKLISTED_NAME),
     LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
     LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON),
@@ -70,6 +71,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
     LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
     LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
     LintId::of(methods::NEW_RET_NO_SELF),
+    LintId::of(methods::OBFUSCATED_IF_ELSE),
     LintId::of(methods::OK_EXPECT),
     LintId::of(methods::OPTION_MAP_OR_NONE),
     LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 1988c24578e..197c415f2a9 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -4,7 +4,6 @@
 #![feature(control_flow_enum)]
 #![feature(drain_filter)]
 #![feature(iter_intersperse)]
-#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(let_else)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
@@ -174,6 +173,7 @@ mod as_conversions;
 mod as_underscore;
 mod asm_syntax;
 mod assertions_on_constants;
+mod assertions_on_result_states;
 mod async_yields_async;
 mod attrs;
 mod await_holding_invalid;
@@ -548,6 +548,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         store.register_late_pass(|| Box::new(utils::internal_lints::MsrvAttrImpl));
     }
 
+    let arithmetic_allowed = conf.arithmetic_allowed.clone();
+    store.register_late_pass(move || Box::new(operators::arithmetic::Arithmetic::new(arithmetic_allowed.clone())));
     store.register_late_pass(|| Box::new(utils::dump_hir::DumpHir));
     store.register_late_pass(|| Box::new(utils::author::Author));
     let await_holding_invalid_types = conf.await_holding_invalid_types.clone();
@@ -727,6 +729,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(unnecessary_sort_by::UnnecessarySortBy));
     store.register_late_pass(move || Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api)));
     store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants));
+    store.register_late_pass(|| Box::new(assertions_on_result_states::AssertionsOnResultStates));
     store.register_late_pass(|| Box::new(transmuting_null::TransmutingNull));
     store.register_late_pass(|| Box::new(path_buf_push_overwrite::PathBufPushOverwrite));
     store.register_late_pass(|| Box::new(inherent_to_string::InherentToString));
@@ -782,7 +785,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     store.register_late_pass(|| Box::new(default::Default::default()));
-    store.register_late_pass(|| Box::new(unused_self::UnusedSelf));
+    store.register_late_pass(move || Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api)));
     store.register_late_pass(|| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
     store.register_late_pass(|| Box::new(exit::Exit));
     store.register_late_pass(|| Box::new(to_digit_is_some::ToDigitIsSome));
@@ -916,7 +919,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
     store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
     store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
-    store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports));
+    store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports::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 3f69cc20388..573a7c016b8 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -460,7 +460,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
                 let mut sub_visitor = RefVisitor::new(self.cx);
                 sub_visitor.visit_fn_decl(decl);
                 self.nested_elision_site_lts.append(&mut sub_visitor.all_lts());
-                return;
             },
             TyKind::TraitObject(bounds, ref lt, _) => {
                 if !lt.is_elided() {
@@ -469,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
                 for bound in bounds {
                     self.visit_poly_trait_ref(bound, TraitBoundModifier::None);
                 }
-                return;
             },
             _ => walk_ty(self, ty),
         }
diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs
index ca617859db4..45af6be2653 100644
--- a/clippy_lints/src/loops/while_let_loop.rs
+++ b/clippy_lints/src/loops/while_let_loop.rs
@@ -11,7 +11,7 @@ use rustc_lint::LateContext;
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) {
     let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) {
         ([stmt, stmts @ ..], expr) => {
-            if let StmtKind::Local(&Local { init: Some(e), els: None, .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
+            if let StmtKind::Local(&Local { init: Some(e), .. }) | StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind {
                 (e, !stmts.is_empty() || expr.is_some())
             } else {
                 return;
diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs
index d573a1b4fbb..6b78c162065 100644
--- a/clippy_lints/src/macro_use.rs
+++ b/clippy_lints/src/macro_use.rs
@@ -35,7 +35,8 @@ struct PathAndSpan {
     span: Span,
 }
 
-/// `MacroRefData` includes the name of the macro.
+/// `MacroRefData` includes the name of the macro
+/// and the path from `SourceMap::span_to_filename`.
 #[derive(Debug, Clone)]
 pub struct MacroRefData {
     name: String,
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index d55082c66dc..b638f271602 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -1,13 +1,3 @@
-use clippy_utils::source::{snippet_opt, span_starts_with, walk_span_to_context};
-use clippy_utils::{higher, in_constant, meets_msrv, msrvs};
-use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
-use rustc_lexer::{tokenize, TokenKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
-use rustc_semver::RustcVersion;
-use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{Span, SpanData, SyntaxContext};
-
 mod collapsible_match;
 mod infallible_destructuring_match;
 mod manual_map;
@@ -31,6 +21,16 @@ mod single_match;
 mod try_err;
 mod wild_in_or_pats;
 
+use clippy_utils::source::{snippet_opt, span_starts_with, walk_span_to_context};
+use clippy_utils::{higher, in_constant, meets_msrv, msrvs};
+use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
+use rustc_lexer::{tokenize, TokenKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{Span, SpanData, SyntaxContext};
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for matches with a single arm where an `if let`
@@ -793,18 +793,13 @@ declare_clippy_lint! {
     /// ### Example
     /// ```rust,ignore
     /// # use std::sync::Mutex;
-    ///
     /// # struct State {}
-    ///
     /// # impl State {
     /// #     fn foo(&self) -> bool {
     /// #         true
     /// #     }
-    ///
     /// #     fn bar(&self) {}
     /// # }
-    ///
-    ///
     /// let mutex = Mutex::new(State {});
     ///
     /// match mutex.lock().unwrap().foo() {
@@ -815,22 +810,17 @@ declare_clippy_lint! {
     /// };
     ///
     /// println!("All done!");
-    ///
     /// ```
     /// Use instead:
     /// ```rust
     /// # use std::sync::Mutex;
-    ///
     /// # struct State {}
-    ///
     /// # impl State {
     /// #     fn foo(&self) -> bool {
     /// #         true
     /// #     }
-    ///
     /// #     fn bar(&self) {}
     /// # }
-    ///
     /// let mutex = Mutex::new(State {});
     ///
     /// let is_foo = mutex.lock().unwrap().foo();
diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs
index 06ead144afa..f52170df662 100644
--- a/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/clippy_lints/src/methods/inefficient_to_string.rs
@@ -14,7 +14,7 @@ use super::INEFFICIENT_TO_STRING;
 /// Checks for the `INEFFICIENT_TO_STRING` lint
 pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
     if_chain! {
-        if args.len() == 1 && method_name == sym!(to_string);
+        if args.len() == 1 && method_name == sym::to_string;
         if let Some(to_string_meth_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
         if match_def_path(cx, to_string_meth_did, &paths::TO_STRING_METHOD);
         if let Some(substs) = cx.typeck_results().node_substs_opt(expr.hir_id);
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 6981b4a6631..202fbc1f7f6 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -46,6 +46,7 @@ mod map_unwrap_or;
 mod needless_option_as_deref;
 mod needless_option_take;
 mod no_effect_replace;
+mod obfuscated_if_else;
 mod ok_expect;
 mod option_as_ref_deref;
 mod option_map_or_none;
@@ -2263,6 +2264,35 @@ declare_clippy_lint! {
     "replace with no effect"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usages of `.then_some(..).unwrap_or(..)`
+    ///
+    /// ### Why is this bad?
+    /// This can be written more clearly with `if .. else ..`
+    ///
+    /// ### Limitations
+    /// This lint currently only looks for usages of
+    /// `.then_some(..).unwrap_or(..)`, but will be expanded
+    /// to account for similar patterns.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let x = true;
+    /// x.then_some("a").unwrap_or("b");
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let x = true;
+    /// if x { "a" } else { "b" };
+    /// ```
+    #[clippy::version = "1.64.0"]
+    pub OBFUSCATED_IF_ELSE,
+    style,
+    "use of `.then_some(..).unwrap_or(..)` can be written \
+    more clearly with `if .. else ..`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Option<RustcVersion>,
@@ -2364,6 +2394,7 @@ impl_lint_pass!(Methods => [
     IS_DIGIT_ASCII_RADIX,
     NEEDLESS_OPTION_TAKE,
     NO_EFFECT_REPLACE,
+    OBFUSCATED_IF_ELSE,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -2772,6 +2803,9 @@ impl Methods {
                     Some(("map", [m_recv, m_arg], span)) => {
                         option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
                     },
+                    Some(("then_some", [t_recv, t_arg], _)) => {
+                        obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg);
+                    },
                     _ => {},
                 },
                 ("unwrap_or_else", [u_arg]) => match method_call(recv) {
diff --git a/clippy_lints/src/methods/obfuscated_if_else.rs b/clippy_lints/src/methods/obfuscated_if_else.rs
new file mode 100644
index 00000000000..4d7427b2662
--- /dev/null
+++ b/clippy_lints/src/methods/obfuscated_if_else.rs
@@ -0,0 +1,42 @@
+// run-rustfix
+
+use super::OBFUSCATED_IF_ELSE;
+use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_with_applicability};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'_>,
+    then_recv: &'tcx hir::Expr<'_>,
+    then_arg: &'tcx hir::Expr<'_>,
+    unwrap_arg: &'tcx hir::Expr<'_>,
+) {
+    // something.then_some(blah).unwrap_or(blah)
+    // ^^^^^^^^^-then_recv ^^^^-then_arg   ^^^^- unwrap_arg
+    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- expr
+
+    let recv_ty = cx.typeck_results().expr_ty(then_recv);
+
+    if recv_ty.is_bool() {
+        let mut applicability = Applicability::MachineApplicable;
+        let sugg = format!(
+            "if {} {{ {} }} else {{ {} }}",
+            snippet_with_applicability(cx, then_recv.span, "..", &mut applicability),
+            snippet_with_applicability(cx, then_arg.span, "..", &mut applicability),
+            snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability)
+        );
+
+        span_lint_and_sugg(
+            cx,
+            OBFUSCATED_IF_ELSE,
+            expr.span,
+            "use of `.then_some(..).unwrap_or(..)` can be written \
+            more clearly with `if .. else ..`",
+            "try",
+            sugg,
+            applicability,
+        );
+    }
+}
diff --git a/clippy_lints/src/mismatching_type_param_order.rs b/clippy_lints/src/mismatching_type_param_order.rs
index 254d9a70010..f763e0d24c9 100644
--- a/clippy_lints/src/mismatching_type_param_order.rs
+++ b/clippy_lints/src/mismatching_type_param_order.rs
@@ -18,6 +18,11 @@ declare_clippy_lint! {
     /// Naming type parameters inconsistently may cause you to refer to the
     /// wrong type parameter.
     ///
+    /// ### Limitations
+    /// This lint only applies to impl blocks with simple generic params, e.g.
+    /// `A`. If there is anything more complicated, such as a tuple, it will be
+    /// ignored.
+    ///
     /// ### Example
     /// ```rust
     /// struct Foo<A, B> {
@@ -53,14 +58,15 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
             if !generic_args.args.is_empty();
             then {
                 // get the name and span of the generic parameters in the Impl
-                let impl_params = generic_args.args.iter()
-                .filter_map(|p|
+                let mut impl_params = Vec::new();
+                for p in generic_args.args.iter() {
                     match p {
                         GenericArg::Type(Ty {kind: TyKind::Path(QPath::Resolved(_, path)), ..}) =>
-                            Some((path.segments[0].ident.to_string(), path.span)),
-                        _ => None,
-                    }
-                );
+                            impl_params.push((path.segments[0].ident.to_string(), path.span)),
+                        GenericArg::Type(_) => return,
+                        _ => (),
+                    };
+                }
 
                 // find the type that the Impl is for
                 // only lint on struct/enum/union for now
@@ -83,8 +89,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
                     type_param_names.iter().enumerate().map(|(i, param)| (param, i)).collect();
 
                 let type_name = segment.ident;
-                for (i, (impl_param_name, impl_param_span)) in impl_params.enumerate() {
-                    if mismatch_param_name(i, &impl_param_name, &type_param_names_hashmap) {
+                for (i, (impl_param_name, impl_param_span)) in impl_params.iter().enumerate() {
+                    if mismatch_param_name(i, impl_param_name, &type_param_names_hashmap) {
                         let msg = format!("`{}` has a similarly named generic type parameter `{}` in its declaration, but in a different order",
                                           type_name, impl_param_name);
                         let help = format!("try `{}`, or a name that does not conflict with `{}`'s generic params",
@@ -92,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
                         span_lint_and_help(
                             cx,
                             MISMATCHING_TYPE_PARAM_ORDER,
-                            impl_param_span,
+                            *impl_param_span,
                             &msg,
                             None,
                             &help
diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs
index a20377f320b..b99052e66ba 100644
--- a/clippy_lints/src/missing_doc.rs
+++ b/clippy_lints/src/missing_doc.rs
@@ -7,7 +7,8 @@
 
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
-use rustc_ast::ast;
+use if_chain::if_chain;
+use rustc_ast::ast::{self, MetaItem, MetaItemKind};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::{self, DefIdTree};
@@ -57,6 +58,20 @@ impl MissingDoc {
         *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
     }
 
+    fn has_include(meta: Option<MetaItem>) -> bool {
+        if_chain! {
+            if let Some(meta) = meta;
+            if let MetaItemKind::List(list) = meta.kind;
+            if let Some(meta) = list.get(0);
+            if let Some(name) = meta.ident();
+            then {
+                name.name == sym::include
+            } else {
+                false
+            }
+        }
+    }
+
     fn check_missing_docs_attrs(
         &self,
         cx: &LateContext<'_>,
@@ -80,7 +95,9 @@ impl MissingDoc {
             return;
         }
 
-        let has_doc = attrs.iter().any(|a| a.doc_str().is_some());
+        let has_doc = attrs
+            .iter()
+            .any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
         if !has_doc {
             span_lint(
                 cx,
diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs
index 44fdf84c6df..321db08dfe8 100644
--- a/clippy_lints/src/mutable_debug_assertion.rs
+++ b/clippy_lints/src/mutable_debug_assertion.rs
@@ -95,10 +95,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
                 self.found = true;
                 return;
             },
-            ExprKind::If(..) => {
-                self.found = true;
-                return;
-            },
             ExprKind::Path(_) => {
                 if let Some(adj) = self.cx.typeck_results().adjustments().get(expr.hir_id) {
                     if adj
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index 6bce5fbd4c1..72c86f28bbc 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -251,14 +251,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'_>) {
         if let ItemKind::Const(hir_ty, body_id) = it.kind {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            if !macro_backtrace(it.span).last().map_or(false, |macro_call| {
-                matches!(
-                    cx.tcx.get_diagnostic_name(macro_call.def_id),
-                    Some(sym::thread_local_macro)
-                )
-            }) && is_unfrozen(cx, ty)
-                && is_value_unfrozen_poly(cx, body_id, ty)
-            {
+            if !ignored_macro(cx, it) && is_unfrozen(cx, ty) && is_value_unfrozen_poly(cx, body_id, ty) {
                 lint(cx, Source::Item { item: it.span });
             }
         }
@@ -445,3 +438,12 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
         }
     }
 }
+
+fn ignored_macro(cx: &LateContext<'_>, it: &rustc_hir::Item<'_>) -> bool {
+    macro_backtrace(it.span).any(|macro_call| {
+        matches!(
+            cx.tcx.get_diagnostic_name(macro_call.def_id),
+            Some(sym::thread_local_macro)
+        )
+    })
+}
diff --git a/clippy_lints/src/operators/arithmetic.rs b/clippy_lints/src/operators/arithmetic.rs
new file mode 100644
index 00000000000..800cf249f5c
--- /dev/null
+++ b/clippy_lints/src/operators/arithmetic.rs
@@ -0,0 +1,119 @@
+#![allow(
+    // False positive
+    clippy::match_same_arms
+)]
+
+use super::ARITHMETIC;
+use clippy_utils::{consts::constant_simple, diagnostics::span_lint};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::impl_lint_pass;
+use rustc_span::source_map::Span;
+
+const HARD_CODED_ALLOWED: &[&str] = &["std::num::Saturating", "std::string::String", "std::num::Wrapping"];
+
+#[derive(Debug)]
+pub struct Arithmetic {
+    allowed: FxHashSet<String>,
+    // Used to check whether expressions are constants, such as in enum discriminants and consts
+    const_span: Option<Span>,
+    expr_span: Option<Span>,
+}
+
+impl_lint_pass!(Arithmetic => [ARITHMETIC]);
+
+impl Arithmetic {
+    #[must_use]
+    pub fn new(mut allowed: FxHashSet<String>) -> Self {
+        allowed.extend(HARD_CODED_ALLOWED.iter().copied().map(String::from));
+        Self {
+            allowed,
+            const_span: None,
+            expr_span: None,
+        }
+    }
+
+    /// Checks if the given `expr` has any of the inner `allowed` elements.
+    fn is_allowed_ty(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+        self.allowed.contains(
+            cx.typeck_results()
+                .expr_ty(expr)
+                .to_string()
+                .split('<')
+                .next()
+                .unwrap_or_default(),
+        )
+    }
+
+    fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
+        span_lint(cx, ARITHMETIC, expr.span, "arithmetic detected");
+        self.expr_span = Some(expr.span);
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for Arithmetic {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+        if self.expr_span.is_some() {
+            return;
+        }
+        if let Some(span) = self.const_span && span.contains(expr.span) {
+            return;
+        }
+        match &expr.kind {
+            hir::ExprKind::Binary(op, lhs, rhs) | hir::ExprKind::AssignOp(op, lhs, rhs) => {
+                let (
+                    hir::BinOpKind::Add
+                    | hir::BinOpKind::Sub
+                    | hir::BinOpKind::Mul
+                    | hir::BinOpKind::Div
+                    | hir::BinOpKind::Rem
+                    | hir::BinOpKind::Shl
+                    | hir::BinOpKind::Shr
+                ) = op.node else {
+                    return;
+                };
+                if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
+                    return;
+                }
+                self.issue_lint(cx, expr);
+            },
+            hir::ExprKind::Unary(hir::UnOp::Neg, _) => {
+                // CTFE already takes care of things like `-1` that do not overflow.
+                if constant_simple(cx, cx.typeck_results(), expr).is_none() {
+                    self.issue_lint(cx, expr);
+                }
+            },
+            _ => {},
+        }
+    }
+
+    fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
+        let body_owner = cx.tcx.hir().body_owner_def_id(body.id());
+        match cx.tcx.hir().body_owner_kind(body_owner) {
+            hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
+                let body_span = cx.tcx.def_span(body_owner);
+                if let Some(span) = self.const_span && span.contains(body_span) {
+                    return;
+                }
+                self.const_span = Some(body_span);
+            },
+            hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => {},
+        }
+    }
+
+    fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
+        let body_owner = cx.tcx.hir().body_owner(body.id());
+        let body_span = cx.tcx.hir().span(body_owner);
+        if let Some(span) = self.const_span && span.contains(body_span) {
+            return;
+        }
+        self.const_span = None;
+    }
+
+    fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+        if Some(expr.span) == self.expr_span {
+            self.expr_span = None;
+        }
+    }
+}
diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs
index 979e0a66707..945a09a647c 100644
--- a/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/clippy_lints/src/operators/assign_op_pattern.rs
@@ -8,6 +8,10 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_lint::LateContext;
+use rustc_middle::mir::FakeReadCause;
+use rustc_middle::ty::BorrowKind;
+use rustc_trait_selection::infer::TyCtxtInferExt;
+use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 use super::ASSIGN_OP_PATTERN;
 
@@ -29,6 +33,16 @@ pub(super) fn check<'tcx>(
                     .map_or(true, |t| t.path.res.def_id() != trait_id);
                 if implements_trait(cx, ty, trait_id, &[rty.into()]);
                 then {
+                    // Primitive types execute assign-ops right-to-left. Every other type is left-to-right.
+                    if !(ty.is_primitive() && rty.is_primitive()) {
+                        // TODO: This will have false negatives as it doesn't check if the borrows are
+                        // actually live at the end of their respective expressions.
+                        let mut_borrows = mut_borrows_in_expr(cx, assignee);
+                        let imm_borrows = imm_borrows_in_expr(cx, rhs);
+                        if mut_borrows.iter().any(|id| imm_borrows.contains(id)) {
+                            return;
+                        }
+                    }
                     span_lint_and_then(
                         cx,
                         ASSIGN_OP_PATTERN,
@@ -99,3 +113,69 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
         walk_expr(self, expr);
     }
 }
+
+fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
+    struct S(hir::HirIdSet);
+    impl Delegate<'_> for S {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+            if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) {
+                self.0.insert(match place.place.base {
+                    PlaceBase::Local(id) => id,
+                    PlaceBase::Upvar(id) => id.var_path.hir_id,
+                    _ => return,
+                });
+            }
+        }
+
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+    }
+
+    let mut s = S(hir::HirIdSet::default());
+    cx.tcx.infer_ctxt().enter(|infcx| {
+        let mut v = ExprUseVisitor::new(
+            &mut s,
+            &infcx,
+            cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
+            cx.param_env,
+            cx.typeck_results(),
+        );
+        v.consume_expr(e);
+    });
+    s.0
+}
+
+fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
+    struct S(hir::HirIdSet);
+    impl Delegate<'_> for S {
+        fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: hir::HirId, kind: BorrowKind) {
+            if matches!(kind, BorrowKind::MutBorrow) {
+                self.0.insert(match place.place.base {
+                    PlaceBase::Local(id) => id,
+                    PlaceBase::Upvar(id) => id.var_path.hir_id,
+                    _ => return,
+                });
+            }
+        }
+
+        fn consume(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+        fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: hir::HirId) {}
+        fn copy(&mut self, _: &PlaceWithHirId<'_>, _: hir::HirId) {}
+    }
+
+    let mut s = S(hir::HirIdSet::default());
+    cx.tcx.infer_ctxt().enter(|infcx| {
+        let mut v = ExprUseVisitor::new(
+            &mut s,
+            &infcx,
+            cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
+            cx.param_env,
+            cx.typeck_results(),
+        );
+        v.consume_expr(e);
+    });
+    s.0
+}
diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs
index 35fe405bcf1..bb6d99406b4 100644
--- a/clippy_lints/src/operators/mod.rs
+++ b/clippy_lints/src/operators/mod.rs
@@ -1,7 +1,3 @@
-use rustc_hir::{Body, Expr, ExprKind, UnOp};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_tool_lint, impl_lint_pass};
-
 mod absurd_extreme_comparisons;
 mod assign_op_pattern;
 mod bit_mask;
@@ -25,6 +21,12 @@ mod ptr_eq;
 mod self_assignment;
 mod verbose_bit_mask;
 
+pub(crate) mod arithmetic;
+
+use rustc_hir::{Body, Expr, ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for comparisons where one side of the relation is
@@ -59,6 +61,42 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for any kind of arithmetic operation of any type.
+    ///
+    /// Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing according to the [Rust
+    /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
+    /// or can panic (`/`, `%`). Known safe built-in types like `Wrapping` or `Saturing` are filtered
+    /// away.
+    ///
+    /// ### Why is this bad?
+    /// Integer overflow will trigger a panic in debug builds or will wrap in
+    /// release mode. Division by zero will cause a panic in either mode. In some applications one
+    /// wants explicitly checked, wrapping or saturating arithmetic.
+    ///
+    /// #### Example
+    /// ```rust
+    /// # let a = 0;
+    /// a + 1;
+    /// ```
+    ///
+    /// Third-party types also tend to overflow.
+    ///
+    /// #### Example
+    /// ```ignore,rust
+    /// use rust_decimal::Decimal;
+    /// let _n = Decimal::MAX + Decimal::MAX;
+    /// ```
+    ///
+    /// ### Allowed types
+    /// Custom allowed types can be specified through the "arithmetic-allowed" filter.
+    #[clippy::version = "1.64.0"]
+    pub ARITHMETIC,
+    restriction,
+    "any arithmetic expression that could overflow or panic"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for integer arithmetic operations which could overflow or panic.
     ///
     /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable
@@ -747,6 +785,7 @@ pub struct Operators {
 }
 impl_lint_pass!(Operators => [
     ABSURD_EXTREME_COMPARISONS,
+    ARITHMETIC,
     INTEGER_ARITHMETIC,
     FLOAT_ARITHMETIC,
     ASSIGN_OP_PATTERN,
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index f0155ed6051..fd0a53839e6 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -123,8 +123,8 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
     if_chain! {
         if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
         if !is_else_clause(cx.tcx, expr);
-        if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind;
-        if let PatKind::Binding(annot, bind_id, ident, _) = fields[0].kind;
+        if let PatKind::TupleStruct(ref path1, [field], None) = let_pat.kind;
+        if let PatKind::Binding(annot, bind_id, ident, _) = field.kind;
         let caller_ty = cx.typeck_results().expr_ty(let_expr);
         let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
         if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 547d4da8187..056637c2048 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -396,7 +396,7 @@ fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args:
         // `.iter()` and `.len()` called on same `Path`
         if let ExprKind::Path(QPath::Resolved(_, iter_path)) = iter_args[0].kind;
         if let ExprKind::Path(QPath::Resolved(_, len_path)) = len_args[0].kind;
-        if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);
+        if SpanlessEq::new(cx).eq_path_segments(iter_path.segments, len_path.segments);
         then {
             span_lint(cx,
                 RANGE_ZIP_WITH_LEN,
diff --git a/clippy_lints/src/same_name_method.rs b/clippy_lints/src/same_name_method.rs
index 20184d54b76..73f8e083b29 100644
--- a/clippy_lints/src/same_name_method.rs
+++ b/clippy_lints/src/same_name_method.rs
@@ -55,11 +55,11 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
             if matches!(cx.tcx.def_kind(id.def_id), DefKind::Impl)
                 && let item = cx.tcx.hir().item(id)
                 && let ItemKind::Impl(Impl {
-                  items,
-                  of_trait,
-                  self_ty,
-                  ..
-                                      }) = &item.kind
+                    items,
+                    of_trait,
+                    self_ty,
+                    ..
+                }) = &item.kind
                 && let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
             {
                 if !map.contains_key(res) {
diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs
index 56f2a7bae15..ffd63cc687a 100644
--- a/clippy_lints/src/std_instead_of_core.rs
+++ b/clippy_lints/src/std_instead_of_core.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::{def::Res, HirId, Path, PathSegment};
-use rustc_lint::{LateContext, LateLintPass, Lint};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{sym, symbol::kw, Symbol};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{sym, symbol::kw, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -63,7 +63,7 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     ///
     /// Crates which have `no_std` compatibility and may optionally require alloc may wish to ensure types are
-    /// imported from alloc to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
+    /// imported from core to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
     /// is also useful for crates migrating to become `no_std` compatible.
     ///
     /// ### Example
@@ -81,39 +81,55 @@ declare_clippy_lint! {
     "type is imported from alloc when available in core"
 }
 
-declare_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
+#[derive(Default)]
+pub struct StdReexports {
+    // Paths which can be either a module or a macro (e.g. `std::env`) will cause this check to happen
+    // twice. First for the mod, second for the macro. This is used to avoid the lint reporting for the macro
+    // when the path could be also be used to access the module.
+    prev_span: Span,
+}
+impl_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
 
 impl<'tcx> LateLintPass<'tcx> for StdReexports {
     fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
-        // std_instead_of_core
-        check_path(cx, path, sym::std, sym::core, STD_INSTEAD_OF_CORE);
-        // std_instead_of_alloc
-        check_path(cx, path, sym::std, sym::alloc, STD_INSTEAD_OF_ALLOC);
-        // alloc_instead_of_core
-        check_path(cx, path, sym::alloc, sym::core, ALLOC_INSTEAD_OF_CORE);
-    }
-}
-
-fn check_path(cx: &LateContext<'_>, path: &Path<'_>, krate: Symbol, suggested_crate: Symbol, lint: &'static Lint) {
-    if_chain! {
-        // check if path resolves to the suggested crate.
-        if let Res::Def(_, def_id) = path.res;
-        if suggested_crate == cx.tcx.crate_name(def_id.krate);
-
-        // check if the first segment of the path is the crate we want to identify
-        if let Some(path_root_segment) = get_first_segment(path);
-
-        // check if the path matches the crate we want to suggest the other path for.
-        if krate == path_root_segment.ident.name;
-        then {
-            span_lint_and_help(
-                cx,
-                lint,
-                path.span,
-                &format!("used import from `{}` instead of `{}`", krate, suggested_crate),
-                None,
-                &format!("consider importing the item from `{}`", suggested_crate),
-            );
+        if let Res::Def(_, def_id) = path.res
+            && let Some(first_segment) = get_first_segment(path)
+        {
+            let (lint, msg, help) = match first_segment.ident.name {
+                sym::std => match cx.tcx.crate_name(def_id.krate) {
+                    sym::core => (
+                        STD_INSTEAD_OF_CORE,
+                        "used import from `std` instead of `core`",
+                        "consider importing the item from `core`",
+                    ),
+                    sym::alloc => (
+                        STD_INSTEAD_OF_ALLOC,
+                        "used import from `std` instead of `alloc`",
+                        "consider importing the item from `alloc`",
+                    ),
+                    _ => {
+                        self.prev_span = path.span;
+                        return;
+                    },
+                },
+                sym::alloc => {
+                    if cx.tcx.crate_name(def_id.krate) == sym::core {
+                        (
+                            ALLOC_INSTEAD_OF_CORE,
+                            "used import from `alloc` instead of `core`",
+                            "consider importing the item from `core`",
+                        )
+                    } else {
+                        self.prev_span = path.span;
+                        return;
+                    }
+                },
+                _ => return,
+            };
+            if path.span != self.prev_span {
+                span_lint_and_help(cx, lint, path.span, msg, None, help);
+                self.prev_span = path.span;
+            }
         }
     }
 }
@@ -123,12 +139,10 @@ fn check_path(cx: &LateContext<'_>, path: &Path<'_>, krate: Symbol, suggested_cr
 /// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`]
 /// is returned.
 fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
-    let segment = path.segments.first()?;
-
-    // A global path will have PathRoot as the first segment. In this case, return the segment after.
-    if segment.ident.name == kw::PathRoot {
-        path.segments.get(1)
-    } else {
-        Some(segment)
+    match path.segments {
+        // A global path will have PathRoot as the first segment. In this case, return the segment after.
+        [x, y, ..] if x.ident.name == kw::PathRoot => Some(y),
+        [x, ..] => Some(x),
+        _ => None,
     }
 }
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index eb704a07451..22eb06b3646 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -394,7 +394,7 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
             if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
-            if path.ident.name == sym!(to_string);
+            if path.ident.name == sym::to_string;
             let ty = cx.typeck_results().expr_ty(self_arg);
             if let ty::Ref(_, ty, ..) = ty.kind();
             if *ty.kind() == ty::Str;
@@ -444,7 +444,7 @@ impl<'tcx> LateLintPass<'tcx> for StringToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
             if let ExprKind::MethodCall(path, [self_arg, ..], _) = &expr.kind;
-            if path.ident.name == sym!(to_string);
+            if path.ident.name == sym::to_string;
             let ty = cx.typeck_results().expr_ty(self_arg);
             if is_type_diagnostic_item(cx, ty, sym::String);
             then {
diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs
index fd9d5b52e50..51c65d898cf 100644
--- a/clippy_lints/src/unused_self.rs
+++ b/clippy_lints/src/unused_self.rs
@@ -3,7 +3,7 @@ use clippy_utils::visitors::is_local_used;
 use if_chain::if_chain;
 use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -35,7 +35,19 @@ declare_clippy_lint! {
     "methods that contain a `self` argument but don't use it"
 }
 
-declare_lint_pass!(UnusedSelf => [UNUSED_SELF]);
+pub struct UnusedSelf {
+    avoid_breaking_exported_api: bool,
+}
+
+impl_lint_pass!(UnusedSelf => [UNUSED_SELF]);
+
+impl UnusedSelf {
+    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+        Self {
+            avoid_breaking_exported_api,
+        }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>) {
@@ -49,6 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
             if assoc_item.fn_has_self_parameter;
             if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
+            if !cx.access_levels.is_exported(impl_item.def_id) || !self.avoid_breaking_exported_api;
             let body = cx.tcx.hir().body(*body_id);
             if let [self_param, ..] = body.params;
             if !is_local_used(cx, body, self_param.pat.hir_id);
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index 38e5c5e5b73..6e033b3be2d 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -191,7 +191,11 @@ macro_rules! define_Conf {
 }
 
 define_Conf! {
-    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
+    /// Lint: Arithmetic.
+    ///
+    /// Suppress checking of the passed type names.
+    (arithmetic_allowed: 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.
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 6d4a48b53de..351a3f4aec8 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -619,32 +619,24 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
         },
         mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
             ty::Array(sub_type, len) => match sub_type.kind() {
-                ty::Float(FloatTy::F32) => match len.to_valtree().try_to_machine_usize(tcx) {
+                ty::Float(FloatTy::F32) => match len.kind().try_to_machine_usize(tcx) {
                     Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
                         .to_owned()
-                        .chunks(4)
-                        .map(|chunk| {
-                            Some(Constant::F32(f32::from_le_bytes(
-                                chunk.try_into().expect("this shouldn't happen"),
-                            )))
-                        })
+                        .array_chunks::<4>()
+                        .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
                         .collect::<Option<Vec<Constant>>>()
                         .map(Constant::Vec),
                     _ => None,
                 },
-                ty::Float(FloatTy::F64) => match len.to_valtree().try_to_machine_usize(tcx) {
+                ty::Float(FloatTy::F64) => match len.kind().try_to_machine_usize(tcx) {
                     Some(len) => alloc
                         .inner()
                         .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
                         .to_owned()
-                        .chunks(8)
-                        .map(|chunk| {
-                            Some(Constant::F64(f64::from_le_bytes(
-                                chunk.try_into().expect("this shouldn't happen"),
-                            )))
-                        })
+                        .array_chunks::<8>()
+                        .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
                         .collect::<Option<Vec<Constant>>>()
                         .map(Constant::Vec),
                     _ => None,
diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs
index 7f55db3b31f..ad95369b9ef 100644
--- a/clippy_utils/src/diagnostics.rs
+++ b/clippy_utils/src/diagnostics.rs
@@ -155,13 +155,7 @@ where
     });
 }
 
-pub fn span_lint_hir(
-    cx: &LateContext<'_>,
-    lint: &'static Lint,
-    hir_id: HirId,
-    sp: Span,
-    msg: &str,
-) {
+pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
     cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| {
         let mut diag = diag.build(msg);
         docs_link(&mut diag, lint);
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 77c974582ec..eaf260ddfb8 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -127,9 +127,6 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     /// Checks whether two blocks are the same.
     fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
-        if self.cannot_be_compared_block(left) || self.cannot_be_compared_block(right) {
-            return false;
-        }
         match (left.stmts, left.expr, right.stmts, right.expr) {
             ([], None, [], None) => {
                 // For empty blocks, check to see if the tokens are equal. This will catch the case where a macro
@@ -180,36 +177,13 @@ impl HirEqInterExpr<'_, '_, '_> {
         }
     }
 
-    fn cannot_be_compared_block(&mut self, block: &Block<'_>) -> bool {
-        if block.stmts.last().map_or(false, |stmt| {
-            matches!(
-                stmt.kind,
-                StmtKind::Semi(semi_expr) if self.should_ignore(semi_expr)
-            )
-        }) {
-            return true;
-        }
-
-        if let Some(block_expr) = block.expr
-            && self.should_ignore(block_expr)
-        {
-            return true
-        }
-
-        false
-    }
-
     fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
-        if macro_backtrace(expr.span).last().map_or(false, |macro_call| {
+        macro_backtrace(expr.span).last().map_or(false, |macro_call| {
             matches!(
                 &self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
                 Some(sym::todo_macro | sym::unimplemented_macro)
             )
-        }) {
-            return true;
-        }
-
-        false
+        })
     }
 
     pub fn eq_array_length(&mut self, left: ArrayLen, right: ArrayLen) -> bool {
@@ -327,7 +301,8 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
             _ => false,
         };
-        is_eq || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right))
+        (is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
+            || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right))
     }
 
     fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool {
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 2fdda9fac16..9ffbc73dc62 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1,7 +1,7 @@
+#![feature(array_chunks)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(let_else)]
-#![cfg_attr(bootstrap, feature(let_chains))]
 #![feature(lint_reasons)]
 #![feature(once_cell)]
 #![feature(rustc_private)]
@@ -2141,7 +2141,7 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
 
 static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = OnceLock::new();
 
-fn with_test_item_names<'tcx>(tcx: TyCtxt<'tcx>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
+fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
     let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
     let mut map: MutexGuard<'_, FxHashMap<LocalDefId, Vec<Symbol>>> = cache.lock().unwrap();
     let value = map.entry(module);
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 3615d07154d..92ac1a2be56 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -433,7 +433,7 @@ fn rustfix_coverage_known_exceptions_accuracy() {
         let rs_path = Path::new("tests/ui").join(filename);
         assert!(
             rs_path.exists(),
-            "`{}` does not exists",
+            "`{}` does not exist",
             rs_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
         );
         let fixed_path = rs_path.with_extension("fixed");
@@ -445,6 +445,45 @@ fn rustfix_coverage_known_exceptions_accuracy() {
     }
 }
 
+#[test]
+fn ui_cargo_toml_metadata() {
+    let ui_cargo_path = Path::new("tests/ui-cargo");
+    let cargo_common_metadata_path = ui_cargo_path.join("cargo_common_metadata");
+    let publish_exceptions =
+        ["fail_publish", "fail_publish_true", "pass_publish_empty"].map(|path| cargo_common_metadata_path.join(path));
+
+    for entry in walkdir::WalkDir::new(ui_cargo_path) {
+        let entry = entry.unwrap();
+        let path = entry.path();
+        if path.file_name() != Some(OsStr::new("Cargo.toml")) {
+            continue;
+        }
+
+        let toml = fs::read_to_string(path).unwrap().parse::<toml::Value>().unwrap();
+
+        let package = toml.as_table().unwrap().get("package").unwrap().as_table().unwrap();
+
+        let name = package.get("name").unwrap().as_str().unwrap().replace('-', "_");
+        assert!(
+            path.parent()
+                .unwrap()
+                .components()
+                .map(|component| component.as_os_str().to_string_lossy().replace('-', "_"))
+                .any(|s| *s == name)
+                || path.starts_with(&cargo_common_metadata_path),
+            "{:?} has incorrect package name",
+            path
+        );
+
+        let publish = package.get("publish").and_then(toml::Value::as_bool).unwrap_or(true);
+        assert!(
+            !publish || publish_exceptions.contains(&path.parent().unwrap().to_path_buf()),
+            "{:?} lacks `publish = false`",
+            path
+        );
+    }
+}
+
 /// Restores an env var on drop
 #[must_use]
 struct VarGuard {
diff --git a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml
index ae0a6032996..bc8e428f859 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/fail/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "cargo_common_metadata_fail"
 version = "0.1.0"
 publish = false
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
index 5e9aa8dc36a..86953142bef 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.stderr
@@ -1,16 +1,16 @@
-error: package `cargo_common_metadata` is missing `package.description` metadata
+error: package `cargo_common_metadata_fail` is missing `package.description` metadata
    |
    = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
-error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata
+error: package `cargo_common_metadata_fail` is missing `either package.license or package.license_file` metadata
 
-error: package `cargo_common_metadata` is missing `package.repository` metadata
+error: package `cargo_common_metadata_fail` is missing `package.repository` metadata
 
-error: package `cargo_common_metadata` is missing `package.readme` metadata
+error: package `cargo_common_metadata_fail` is missing `package.readme` metadata
 
-error: package `cargo_common_metadata` is missing `package.keywords` metadata
+error: package `cargo_common_metadata_fail` is missing `package.keywords` metadata
 
-error: package `cargo_common_metadata` is missing `package.categories` metadata
+error: package `cargo_common_metadata_fail` is missing `package.categories` metadata
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.toml
index 7595696353c..5005b83f59d 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "cargo_common_metadata_fail_publish"
 version = "0.1.0"
 publish = ["some-registry-name"]
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
index 5e9aa8dc36a..ac1b5e8e903 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.stderr
@@ -1,16 +1,16 @@
-error: package `cargo_common_metadata` is missing `package.description` metadata
+error: package `cargo_common_metadata_fail_publish` is missing `package.description` metadata
    |
    = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
-error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata
+error: package `cargo_common_metadata_fail_publish` is missing `either package.license or package.license_file` metadata
 
-error: package `cargo_common_metadata` is missing `package.repository` metadata
+error: package `cargo_common_metadata_fail_publish` is missing `package.repository` metadata
 
-error: package `cargo_common_metadata` is missing `package.readme` metadata
+error: package `cargo_common_metadata_fail_publish` is missing `package.readme` metadata
 
-error: package `cargo_common_metadata` is missing `package.keywords` metadata
+error: package `cargo_common_metadata_fail_publish` is missing `package.keywords` metadata
 
-error: package `cargo_common_metadata` is missing `package.categories` metadata
+error: package `cargo_common_metadata_fail_publish` is missing `package.categories` metadata
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.toml
index 7e5b88383cc..51858eecd0a 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "cargo_common_metadata_fail_publish_true"
 version = "0.1.0"
 publish = true
 
diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
index 5e9aa8dc36a..be32c0dc418 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
+++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.stderr
@@ -1,16 +1,16 @@
-error: package `cargo_common_metadata` is missing `package.description` metadata
+error: package `cargo_common_metadata_fail_publish_true` is missing `package.description` metadata
    |
    = note: `-D clippy::cargo-common-metadata` implied by `-D warnings`
 
-error: package `cargo_common_metadata` is missing `either package.license or package.license_file` metadata
+error: package `cargo_common_metadata_fail_publish_true` is missing `either package.license or package.license_file` metadata
 
-error: package `cargo_common_metadata` is missing `package.repository` metadata
+error: package `cargo_common_metadata_fail_publish_true` is missing `package.repository` metadata
 
-error: package `cargo_common_metadata` is missing `package.readme` metadata
+error: package `cargo_common_metadata_fail_publish_true` is missing `package.readme` metadata
 
-error: package `cargo_common_metadata` is missing `package.keywords` metadata
+error: package `cargo_common_metadata_fail_publish_true` is missing `package.keywords` metadata
 
-error: package `cargo_common_metadata` is missing `package.categories` metadata
+error: package `cargo_common_metadata_fail_publish_true` is missing `package.categories` metadata
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml
index cb4774d43a2..9f6e51fb4d9 100644
--- a/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/pass/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "cargo_common_metadata_pass"
 version = "0.1.0"
 publish = false
 description = "A test package for the cargo_common_metadata lint"
diff --git a/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/Cargo.toml
index 0a879c99b5b..828efee3a8f 100644
--- a/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "cargo_common_metadata_pass_publish_empty"
 version = "0.1.0"
 publish = []
 
diff --git a/tests/ui-cargo/cargo_common_metadata/pass_publish_false/Cargo.toml b/tests/ui-cargo/cargo_common_metadata/pass_publish_false/Cargo.toml
index ae0a6032996..45a5bf7c574 100644
--- a/tests/ui-cargo/cargo_common_metadata/pass_publish_false/Cargo.toml
+++ b/tests/ui-cargo/cargo_common_metadata/pass_publish_false/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "cargo_common_metadata_pass_publish_false"
 version = "0.1.0"
 publish = false
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml b/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml
index 73ec29c5803..946d1b366f0 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/fail_both_diff/Cargo.toml
@@ -2,6 +2,7 @@
 name = "fail-both-diff"
 version = "0.1.0"
 rust-version = "1.56"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml b/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml
index 2d6d547e4fe..46b92a1050e 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/fail_both_same/Cargo.toml
@@ -2,6 +2,7 @@
 name = "fail-both-same"
 version = "0.1.0"
 rust-version = "1.57.0"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml b/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml
index 36a53bd829d..189cc9f68dc 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/fail_cargo/Cargo.toml
@@ -2,6 +2,7 @@
 name = "fail-cargo"
 version = "0.1.0"
 rust-version = "1.56.1"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml b/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml
index 9f644a1a39a..bdb7f261d9e 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/fail_clippy/Cargo.toml
@@ -1,6 +1,7 @@
 [package]
 name = "fail-clippy"
 version = "0.1.0"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml
index 5380e993b29..84448ea41f6 100644
--- a/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.toml
@@ -2,6 +2,7 @@
 name = "fail-file-attr"
 version = "0.1.0"
 rust-version = "1.13"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml b/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml
index 1f9bd8f9a84..809c0e74875 100644
--- a/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/pass_both_same/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "fail-both-same"
+name = "pass-both-same"
 version = "0.1.0"
 rust-version = "1.13.0"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml b/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml
index 77538027c0f..32d404f842c 100644
--- a/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/pass_cargo/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "fail-cargo"
+name = "pass-cargo"
 version = "0.1.0"
 rust-version = "1.13.0"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml b/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml
index 9f644a1a39a..cc937d6e625 100644
--- a/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/pass_clippy/Cargo.toml
@@ -1,6 +1,7 @@
 [package]
-name = "fail-clippy"
+name = "pass-clippy"
 version = "0.1.0"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml b/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml
index f0387cd90b8..8ef689880d4 100644
--- a/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/pass_file_attr/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "fail-file-attr"
+name = "pass-file-attr"
 version = "0.1.0"
 rust-version = "1.59"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml b/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml
index a19d5b33fe5..e9f94594f70 100644
--- a/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml
+++ b/tests/ui-cargo/cargo_rust_version/warn_both_diff/Cargo.toml
@@ -2,6 +2,7 @@
 name = "warn-both-diff"
 version = "0.1.0"
 rust-version = "1.56.0"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/module_style/fail_mod/Cargo.toml b/tests/ui-cargo/module_style/fail_mod/Cargo.toml
index 27b61c09fb4..b3d36a9fb64 100644
--- a/tests/ui-cargo/module_style/fail_mod/Cargo.toml
+++ b/tests/ui-cargo/module_style/fail_mod/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "fail"
+name = "fail-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
 
diff --git a/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml b/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml
index 27b61c09fb4..3610d13c1f3 100644
--- a/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml
+++ b/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "fail"
+name = "fail-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
 
diff --git a/tests/ui-cargo/module_style/pass_mod/Cargo.toml b/tests/ui-cargo/module_style/pass_mod/Cargo.toml
index 27b61c09fb4..1c2991695bc 100644
--- a/tests/ui-cargo/module_style/pass_mod/Cargo.toml
+++ b/tests/ui-cargo/module_style/pass_mod/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "fail"
+name = "pass-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
 
diff --git a/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml b/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml
index 3c0896dd2cd..4180aaf5185 100644
--- a/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml
+++ b/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml
@@ -1,7 +1,8 @@
 [package]
-name = "pass"
+name = "pass-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
 
diff --git a/tests/ui-cargo/multiple_config_files/no_warn/Cargo.toml b/tests/ui-cargo/multiple_config_files/no_warn/Cargo.toml
index 79c973cbfd2..7eb56cc4e9d 100644
--- a/tests/ui-cargo/multiple_config_files/no_warn/Cargo.toml
+++ b/tests/ui-cargo/multiple_config_files/no_warn/Cargo.toml
@@ -2,6 +2,7 @@
 name = "no_warn"
 version = "0.1.0"
 edition = "2021"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/multiple_config_files/warn/Cargo.toml b/tests/ui-cargo/multiple_config_files/warn/Cargo.toml
index 3d5c707579b..b4847d070aa 100644
--- a/tests/ui-cargo/multiple_config_files/warn/Cargo.toml
+++ b/tests/ui-cargo/multiple_config_files/warn/Cargo.toml
@@ -2,6 +2,7 @@
 name = "warn"
 version = "0.1.0"
 edition = "2021"
+publish = false
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/tests/ui-cargo/multiple_config_files/warn/src/main.rs b/tests/ui-cargo/multiple_config_files/warn/src/main.rs
index 2d0b4a7948c..e7a11a969c0 100644
--- a/tests/ui-cargo/multiple_config_files/warn/src/main.rs
+++ b/tests/ui-cargo/multiple_config_files/warn/src/main.rs
@@ -1,5 +1,3 @@
-// ignore-windows
-
 fn main() {
     println!("Hello, world!");
 }
diff --git a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml
index b4b49bb369a..6c46571c5bf 100644
--- a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml
+++ b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cargo_common_metadata"
+name = "multiple_crate_versions"
 version = "0.1.0"
 publish = false
 
diff --git a/tests/ui-internal/check_clippy_version_attribute.stderr b/tests/ui-internal/check_clippy_version_attribute.stderr
index 67e1a07b7f5..5331075885c 100644
--- a/tests/ui-internal/check_clippy_version_attribute.stderr
+++ b/tests/ui-internal/check_clippy_version_attribute.stderr
@@ -17,7 +17,7 @@ LL | #![deny(clippy::internal)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[deny(clippy::invalid_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
    = help: please use a valid sematic version, see `doc/adding_lints.md`
-   = note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this item has an invalid `clippy::version` attribute
   --> $DIR/check_clippy_version_attribute.rs:48:1
@@ -32,7 +32,7 @@ LL | | }
    | |_^
    |
    = help: please use a valid sematic version, see `doc/adding_lints.md`
-   = note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this lint is missing the `clippy::version` attribute or version value
   --> $DIR/check_clippy_version_attribute.rs:59:1
@@ -48,7 +48,7 @@ LL | | }
    |
    = note: `#[deny(clippy::missing_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
    = help: please use a `clippy::version` attribute, see `doc/adding_lints.md`
-   = note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this lint is missing the `clippy::version` attribute or version value
   --> $DIR/check_clippy_version_attribute.rs:67:1
@@ -62,7 +62,7 @@ LL | | }
    | |_^
    |
    = help: please use a `clippy::version` attribute, see `doc/adding_lints.md`
-   = note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui-internal/default_lint.stderr b/tests/ui-internal/default_lint.stderr
index af6735f4e4d..8961bd4624f 100644
--- a/tests/ui-internal/default_lint.stderr
+++ b/tests/ui-internal/default_lint.stderr
@@ -15,7 +15,7 @@ note: the lint level is defined here
 LL | #![deny(clippy::internal)]
    |         ^^^^^^^^^^^^^^^^
    = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]`
-   = note: this error originates in the macro `$crate::declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/tests/ui-internal/if_chain_style.stderr b/tests/ui-internal/if_chain_style.stderr
index d0f100f0069..24106510e73 100644
--- a/tests/ui-internal/if_chain_style.stderr
+++ b/tests/ui-internal/if_chain_style.stderr
@@ -56,7 +56,7 @@ LL | |         }
 LL | |     }
    | |_____^
    |
-   = note: this error originates in the macro `__if_chain` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__if_chain` which comes from the expansion of the macro `if_chain` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `let` expression should be above the `if_chain!`
   --> $DIR/if_chain_style.rs:40:9
diff --git a/tests/ui-toml/arithmetic_allowed/arithmetic_allowed.rs b/tests/ui-toml/arithmetic_allowed/arithmetic_allowed.rs
new file mode 100644
index 00000000000..195fabdbf71
--- /dev/null
+++ b/tests/ui-toml/arithmetic_allowed/arithmetic_allowed.rs
@@ -0,0 +1,24 @@
+#![warn(clippy::arithmetic)]
+
+use core::ops::Add;
+
+#[derive(Clone, Copy)]
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+impl Add for Point {
+    type Output = Self;
+
+    fn add(self, other: Self) -> Self {
+        todo!()
+    }
+}
+
+fn main() {
+    let _ = Point { x: 1, y: 0 } + Point { x: 2, y: 3 };
+
+    let point: Point = Point { x: 1, y: 0 };
+    let _ = point + point;
+}
diff --git a/tests/ui-toml/arithmetic_allowed/clippy.toml b/tests/ui-toml/arithmetic_allowed/clippy.toml
new file mode 100644
index 00000000000..cc40570b12a
--- /dev/null
+++ b/tests/ui-toml/arithmetic_allowed/clippy.toml
@@ -0,0 +1 @@
+arithmetic-allowed = ["Point"]
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 1d87fd91a25..fe5139c4768 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -3,6 +3,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            allow-expect-in-tests
            allow-unwrap-in-tests
            allowed-scripts
+           arithmetic-allowed
            array-size-threshold
            avoid-breaking-exported-api
            await-holding-invalid-types
diff --git a/tests/ui/arithmetic.fixed b/tests/ui/arithmetic.fixed
new file mode 100644
index 00000000000..a2a1c4394c2
--- /dev/null
+++ b/tests/ui/arithmetic.fixed
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![allow(clippy::unnecessary_owned_empty_strings)]
+#![feature(saturating_int_impl)]
+#![warn(clippy::arithmetic)]
+
+use core::num::{Saturating, Wrapping};
+
+pub fn hard_coded_allowed() {
+    let _ = Saturating(0u32) + Saturating(0u32);
+    let _ = String::new() + "";
+    let _ = Wrapping(0u32) + Wrapping(0u32);
+
+    let saturating: Saturating<u32> = Saturating(0u32);
+    let string: String = String::new();
+    let wrapping: Wrapping<u32> = Wrapping(0u32);
+
+    let inferred_saturating = saturating + saturating;
+    let inferred_string = string + "";
+    let inferred_wrapping = wrapping + wrapping;
+
+    let _ = inferred_saturating + inferred_saturating;
+    let _ = inferred_string + "";
+    let _ = inferred_wrapping + inferred_wrapping;
+}
+
+fn main() {}
diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs
new file mode 100644
index 00000000000..a2a1c4394c2
--- /dev/null
+++ b/tests/ui/arithmetic.rs
@@ -0,0 +1,27 @@
+// run-rustfix
+
+#![allow(clippy::unnecessary_owned_empty_strings)]
+#![feature(saturating_int_impl)]
+#![warn(clippy::arithmetic)]
+
+use core::num::{Saturating, Wrapping};
+
+pub fn hard_coded_allowed() {
+    let _ = Saturating(0u32) + Saturating(0u32);
+    let _ = String::new() + "";
+    let _ = Wrapping(0u32) + Wrapping(0u32);
+
+    let saturating: Saturating<u32> = Saturating(0u32);
+    let string: String = String::new();
+    let wrapping: Wrapping<u32> = Wrapping(0u32);
+
+    let inferred_saturating = saturating + saturating;
+    let inferred_string = string + "";
+    let inferred_wrapping = wrapping + wrapping;
+
+    let _ = inferred_saturating + inferred_saturating;
+    let _ = inferred_string + "";
+    let _ = inferred_wrapping + inferred_wrapping;
+}
+
+fn main() {}
diff --git a/tests/ui/assertions_on_result_states.fixed b/tests/ui/assertions_on_result_states.fixed
new file mode 100644
index 00000000000..7bde72e4b6b
--- /dev/null
+++ b/tests/ui/assertions_on_result_states.fixed
@@ -0,0 +1,69 @@
+// run-rustfix
+#![warn(clippy::assertions_on_result_states)]
+
+use std::result::Result;
+
+struct Foo;
+
+#[derive(Debug)]
+struct DebugFoo;
+
+#[derive(Copy, Clone, Debug)]
+struct CopyFoo;
+
+macro_rules! get_ok_macro {
+    () => {
+        Ok::<_, DebugFoo>(Foo)
+    };
+}
+
+fn main() {
+    // test ok
+    let r: Result<Foo, DebugFoo> = Ok(Foo);
+    debug_assert!(r.is_ok());
+    r.unwrap();
+
+    // test ok with non-debug error type
+    let r: Result<Foo, Foo> = Ok(Foo);
+    assert!(r.is_ok());
+
+    // test temporary ok
+    fn get_ok() -> Result<Foo, DebugFoo> {
+        Ok(Foo)
+    }
+    get_ok().unwrap();
+
+    // test macro ok
+    get_ok_macro!().unwrap();
+
+    // test ok that shouldn't be moved
+    let r: Result<CopyFoo, DebugFoo> = Ok(CopyFoo);
+    fn test_ref_unmoveable_ok(r: &Result<CopyFoo, DebugFoo>) {
+        assert!(r.is_ok());
+    }
+    test_ref_unmoveable_ok(&r);
+    assert!(r.is_ok());
+    r.unwrap();
+
+    // test ok that is copied
+    let r: Result<CopyFoo, CopyFoo> = Ok(CopyFoo);
+    r.unwrap();
+    r.unwrap();
+
+    // test reference to ok
+    let r: Result<CopyFoo, CopyFoo> = Ok(CopyFoo);
+    fn test_ref_copy_ok(r: &Result<CopyFoo, CopyFoo>) {
+        r.unwrap();
+    }
+    test_ref_copy_ok(&r);
+    r.unwrap();
+
+    // test err
+    let r: Result<DebugFoo, Foo> = Err(Foo);
+    debug_assert!(r.is_err());
+    r.unwrap_err();
+
+    // test err with non-debug value type
+    let r: Result<Foo, Foo> = Err(Foo);
+    assert!(r.is_err());
+}
diff --git a/tests/ui/assertions_on_result_states.rs b/tests/ui/assertions_on_result_states.rs
new file mode 100644
index 00000000000..4c5af81efc2
--- /dev/null
+++ b/tests/ui/assertions_on_result_states.rs
@@ -0,0 +1,69 @@
+// run-rustfix
+#![warn(clippy::assertions_on_result_states)]
+
+use std::result::Result;
+
+struct Foo;
+
+#[derive(Debug)]
+struct DebugFoo;
+
+#[derive(Copy, Clone, Debug)]
+struct CopyFoo;
+
+macro_rules! get_ok_macro {
+    () => {
+        Ok::<_, DebugFoo>(Foo)
+    };
+}
+
+fn main() {
+    // test ok
+    let r: Result<Foo, DebugFoo> = Ok(Foo);
+    debug_assert!(r.is_ok());
+    assert!(r.is_ok());
+
+    // test ok with non-debug error type
+    let r: Result<Foo, Foo> = Ok(Foo);
+    assert!(r.is_ok());
+
+    // test temporary ok
+    fn get_ok() -> Result<Foo, DebugFoo> {
+        Ok(Foo)
+    }
+    assert!(get_ok().is_ok());
+
+    // test macro ok
+    assert!(get_ok_macro!().is_ok());
+
+    // test ok that shouldn't be moved
+    let r: Result<CopyFoo, DebugFoo> = Ok(CopyFoo);
+    fn test_ref_unmoveable_ok(r: &Result<CopyFoo, DebugFoo>) {
+        assert!(r.is_ok());
+    }
+    test_ref_unmoveable_ok(&r);
+    assert!(r.is_ok());
+    r.unwrap();
+
+    // test ok that is copied
+    let r: Result<CopyFoo, CopyFoo> = Ok(CopyFoo);
+    assert!(r.is_ok());
+    r.unwrap();
+
+    // test reference to ok
+    let r: Result<CopyFoo, CopyFoo> = Ok(CopyFoo);
+    fn test_ref_copy_ok(r: &Result<CopyFoo, CopyFoo>) {
+        assert!(r.is_ok());
+    }
+    test_ref_copy_ok(&r);
+    r.unwrap();
+
+    // test err
+    let r: Result<DebugFoo, Foo> = Err(Foo);
+    debug_assert!(r.is_err());
+    assert!(r.is_err());
+
+    // test err with non-debug value type
+    let r: Result<Foo, Foo> = Err(Foo);
+    assert!(r.is_err());
+}
diff --git a/tests/ui/assertions_on_result_states.stderr b/tests/ui/assertions_on_result_states.stderr
new file mode 100644
index 00000000000..13c2dd877a9
--- /dev/null
+++ b/tests/ui/assertions_on_result_states.stderr
@@ -0,0 +1,40 @@
+error: called `assert!` with `Result::is_ok`
+  --> $DIR/assertions_on_result_states.rs:24:5
+   |
+LL |     assert!(r.is_ok());
+   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
+   |
+   = note: `-D clippy::assertions-on-result-states` implied by `-D warnings`
+
+error: called `assert!` with `Result::is_ok`
+  --> $DIR/assertions_on_result_states.rs:34:5
+   |
+LL |     assert!(get_ok().is_ok());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()`
+
+error: called `assert!` with `Result::is_ok`
+  --> $DIR/assertions_on_result_states.rs:37:5
+   |
+LL |     assert!(get_ok_macro!().is_ok());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()`
+
+error: called `assert!` with `Result::is_ok`
+  --> $DIR/assertions_on_result_states.rs:50:5
+   |
+LL |     assert!(r.is_ok());
+   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
+
+error: called `assert!` with `Result::is_ok`
+  --> $DIR/assertions_on_result_states.rs:56:9
+   |
+LL |         assert!(r.is_ok());
+   |         ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
+
+error: called `assert!` with `Result::is_err`
+  --> $DIR/assertions_on_result_states.rs:64:5
+   |
+LL |     assert!(r.is_err());
+   |     ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed
index 52b1b3afe16..da034b51cfd 100644
--- a/tests/ui/assign_ops.fixed
+++ b/tests/ui/assign_ops.fixed
@@ -1,5 +1,7 @@
 // run-rustfix
 
+use core::num::Wrapping;
+
 #[allow(dead_code, unused_assignments)]
 #[warn(clippy::assign_op_pattern)]
 fn main() {
@@ -18,4 +20,13 @@ fn main() {
     a = 6 << a;
     let mut s = String::new();
     s += "bla";
+
+    // Issue #9180
+    let mut a = Wrapping(0u32);
+    a += Wrapping(1u32);
+    let mut v = vec![0u32, 1u32];
+    v[0] += v[1];
+    let mut v = vec![Wrapping(0u32), Wrapping(1u32)];
+    v[0] = v[0] + v[1];
+    let _ = || v[0] = v[0] + v[1];
 }
diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs
index 527a46b2c2b..337bb02c8a6 100644
--- a/tests/ui/assign_ops.rs
+++ b/tests/ui/assign_ops.rs
@@ -1,5 +1,7 @@
 // run-rustfix
 
+use core::num::Wrapping;
+
 #[allow(dead_code, unused_assignments)]
 #[warn(clippy::assign_op_pattern)]
 fn main() {
@@ -18,4 +20,13 @@ fn main() {
     a = 6 << a;
     let mut s = String::new();
     s = s + "bla";
+
+    // Issue #9180
+    let mut a = Wrapping(0u32);
+    a = a + Wrapping(1u32);
+    let mut v = vec![0u32, 1u32];
+    v[0] = v[0] + v[1];
+    let mut v = vec![Wrapping(0u32), Wrapping(1u32)];
+    v[0] = v[0] + v[1];
+    let _ = || v[0] = v[0] + v[1];
 }
diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr
index 3486bd8da4d..63a938ab4b4 100644
--- a/tests/ui/assign_ops.stderr
+++ b/tests/ui/assign_ops.stderr
@@ -1,5 +1,5 @@
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:7:5
+  --> $DIR/assign_ops.rs:9:5
    |
 LL |     a = a + 1;
    |     ^^^^^^^^^ help: replace it with: `a += 1`
@@ -7,52 +7,64 @@ LL |     a = a + 1;
    = note: `-D clippy::assign-op-pattern` implied by `-D warnings`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:8:5
+  --> $DIR/assign_ops.rs:10:5
    |
 LL |     a = 1 + a;
    |     ^^^^^^^^^ help: replace it with: `a += 1`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:9:5
+  --> $DIR/assign_ops.rs:11:5
    |
 LL |     a = a - 1;
    |     ^^^^^^^^^ help: replace it with: `a -= 1`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:10:5
+  --> $DIR/assign_ops.rs:12:5
    |
 LL |     a = a * 99;
    |     ^^^^^^^^^^ help: replace it with: `a *= 99`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:11:5
+  --> $DIR/assign_ops.rs:13:5
    |
 LL |     a = 42 * a;
    |     ^^^^^^^^^^ help: replace it with: `a *= 42`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:12:5
+  --> $DIR/assign_ops.rs:14:5
    |
 LL |     a = a / 2;
    |     ^^^^^^^^^ help: replace it with: `a /= 2`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:13:5
+  --> $DIR/assign_ops.rs:15:5
    |
 LL |     a = a % 5;
    |     ^^^^^^^^^ help: replace it with: `a %= 5`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:14:5
+  --> $DIR/assign_ops.rs:16:5
    |
 LL |     a = a & 1;
    |     ^^^^^^^^^ help: replace it with: `a &= 1`
 
 error: manual implementation of an assign operation
-  --> $DIR/assign_ops.rs:20:5
+  --> $DIR/assign_ops.rs:22:5
    |
 LL |     s = s + "bla";
    |     ^^^^^^^^^^^^^ help: replace it with: `s += "bla"`
 
-error: aborting due to 9 previous errors
+error: manual implementation of an assign operation
+  --> $DIR/assign_ops.rs:26:5
+   |
+LL |     a = a + Wrapping(1u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a += Wrapping(1u32)`
+
+error: manual implementation of an assign operation
+  --> $DIR/assign_ops.rs:28:5
+   |
+LL |     v[0] = v[0] + v[1];
+   |     ^^^^^^^^^^^^^^^^^^ help: replace it with: `v[0] += v[1]`
+
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/crashes/ice-9238.rs b/tests/ui/crashes/ice-9238.rs
new file mode 100644
index 00000000000..ee6abd519f1
--- /dev/null
+++ b/tests/ui/crashes/ice-9238.rs
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+#![warn(clippy::branches_sharing_code)]
+
+const fn f() -> usize {
+    2
+}
+const C: [f64; f()] = [0f64; f()];
+
+fn main() {
+    let _ = if true { C[0] } else { C[1] };
+}
diff --git a/tests/ui/crashes/ice-9242.rs b/tests/ui/crashes/ice-9242.rs
new file mode 100644
index 00000000000..0099e6e2f34
--- /dev/null
+++ b/tests/ui/crashes/ice-9242.rs
@@ -0,0 +1,8 @@
+enum E {
+    X(),
+    Y,
+}
+
+fn main() {
+    let _ = if let E::X() = E::X() { 1 } else { 2 };
+}
diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs
index 7ff5a16ed86..1b3bcece6f1 100644
--- a/tests/ui/crate_level_checks/entrypoint_recursion.rs
+++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs
@@ -1,5 +1,4 @@
 // ignore-macos
-// ignore-windows
 
 #![feature(rustc_attrs)]
 
diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr
index f52fc949f6c..459cf12a1c2 100644
--- a/tests/ui/crate_level_checks/entrypoint_recursion.stderr
+++ b/tests/ui/crate_level_checks/entrypoint_recursion.stderr
@@ -1,5 +1,5 @@
 error: recursing into entrypoint `a`
-  --> $DIR/entrypoint_recursion.rs:11:5
+  --> $DIR/entrypoint_recursion.rs:10:5
    |
 LL |     a();
    |     ^
diff --git a/tests/ui/declare_interior_mutable_const/others.rs b/tests/ui/declare_interior_mutable_const/others.rs
index 62af545db50..896596b5679 100644
--- a/tests/ui/declare_interior_mutable_const/others.rs
+++ b/tests/ui/declare_interior_mutable_const/others.rs
@@ -31,9 +31,25 @@ const NO_ANN: &dyn Display = &70;
 static STATIC_TUPLE: (AtomicUsize, String) = (ATOMIC, STRING);
 //^ there should be no lints on this line
 
-// issue #8493
-thread_local! {
-    static THREAD_LOCAL: Cell<i32> = const { Cell::new(0) };
+mod issue_8493 {
+    use std::cell::Cell;
+
+    thread_local! {
+        static _BAR: Cell<i32> = const { Cell::new(0) };
+    }
+
+    macro_rules! issue_8493 {
+        () => {
+            const _BAZ: Cell<usize> = Cell::new(0); //~ ERROR interior mutable
+            static _FOOBAR: () = {
+                thread_local! {
+                    static _VAR: Cell<i32> = const { Cell::new(0) };
+                }
+            };
+        };
+    }
+
+    issue_8493!();
 }
 
 fn main() {}
diff --git a/tests/ui/declare_interior_mutable_const/others.stderr b/tests/ui/declare_interior_mutable_const/others.stderr
index fd0689dfc4c..1fd6d7322a7 100644
--- a/tests/ui/declare_interior_mutable_const/others.stderr
+++ b/tests/ui/declare_interior_mutable_const/others.stderr
@@ -35,5 +35,16 @@ LL | declare_const!(_ONCE: Once = Once::new()); //~ ERROR interior mutable
    |
    = note: this error originates in the macro `declare_const` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 4 previous errors
+error: a `const` item should never be interior mutable
+  --> $DIR/others.rs:43:13
+   |
+LL |             const _BAZ: Cell<usize> = Cell::new(0); //~ ERROR interior mutable
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     issue_8493!();
+   |     ------------- in this macro invocation
+   |
+   = note: this error originates in the macro `issue_8493` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
 
diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs
index b276c384c04..c629c0e5353 100644
--- a/tests/ui/derive.rs
+++ b/tests/ui/derive.rs
@@ -1,7 +1,6 @@
 #![allow(dead_code)]
 #![warn(clippy::expl_impl_clone_on_copy)]
 
-
 #[derive(Copy)]
 struct Qux;
 
diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr
index 82a70ceecc3..fabfd025392 100644
--- a/tests/ui/derive.stderr
+++ b/tests/ui/derive.stderr
@@ -1,5 +1,5 @@
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:8:1
+  --> $DIR/derive.rs:7:1
    |
 LL | / impl Clone for Qux {
 LL | |     fn clone(&self) -> Self {
@@ -10,7 +10,7 @@ LL | | }
    |
    = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings`
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:8:1
+  --> $DIR/derive.rs:7:1
    |
 LL | / impl Clone for Qux {
 LL | |     fn clone(&self) -> Self {
@@ -20,7 +20,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:32:1
+  --> $DIR/derive.rs:31:1
    |
 LL | / impl<'a> Clone for Lt<'a> {
 LL | |     fn clone(&self) -> Self {
@@ -30,7 +30,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:32:1
+  --> $DIR/derive.rs:31:1
    |
 LL | / impl<'a> Clone for Lt<'a> {
 LL | |     fn clone(&self) -> Self {
@@ -40,7 +40,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:43:1
+  --> $DIR/derive.rs:42:1
    |
 LL | / impl Clone for BigArray {
 LL | |     fn clone(&self) -> Self {
@@ -50,7 +50,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:43:1
+  --> $DIR/derive.rs:42:1
    |
 LL | / impl Clone for BigArray {
 LL | |     fn clone(&self) -> Self {
@@ -60,7 +60,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:54:1
+  --> $DIR/derive.rs:53:1
    |
 LL | / impl Clone for FnPtr {
 LL | |     fn clone(&self) -> Self {
@@ -70,7 +70,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:54:1
+  --> $DIR/derive.rs:53:1
    |
 LL | / impl Clone for FnPtr {
 LL | |     fn clone(&self) -> Self {
@@ -80,7 +80,7 @@ LL | | }
    | |_^
 
 error: you are implementing `Clone` explicitly on a `Copy` type
-  --> $DIR/derive.rs:74:1
+  --> $DIR/derive.rs:73:1
    |
 LL | / impl<T: Clone> Clone for Generic2<T> {
 LL | |     fn clone(&self) -> Self {
@@ -90,7 +90,7 @@ LL | | }
    | |_^
    |
 note: consider deriving `Clone` or removing `Copy`
-  --> $DIR/derive.rs:74:1
+  --> $DIR/derive.rs:73:1
    |
 LL | / impl<T: Clone> Clone for Generic2<T> {
 LL | |     fn clone(&self) -> Self {
diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs
index 28b37f96e91..985835ffa65 100644
--- a/tests/ui/expect_tool_lint_rfc_2383.rs
+++ b/tests/ui/expect_tool_lint_rfc_2383.rs
@@ -22,9 +22,9 @@ mod rustc_ok {
 
         #[expect(illegal_floating_point_literal_pattern)]
         match x {
-            5.0 => {}
-            6.0 => {}
-            _ => {}
+            5.0 => {},
+            6.0 => {},
+            _ => {},
         }
     }
 }
@@ -38,9 +38,9 @@ mod rustc_warn {
 
         #[expect(illegal_floating_point_literal_pattern)]
         match x {
-            5 => {}
-            6 => {}
-            _ => {}
+            5 => {},
+            6 => {},
+            _ => {},
         }
     }
 }
diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed
index d08f8f52495..f4db2d20c71 100644
--- a/tests/ui/format.fixed
+++ b/tests/ui/format.fixed
@@ -84,4 +84,10 @@ fn main() {
     let _ = x.to_string();
     let _ = format!("{x:?}"); // Don't lint on debug
     let _ = x.to_string();
+
+    // Issue #9234
+    let abc = "abc";
+    let _ = abc.to_string();
+    let xx = "xx";
+    let _ = xx.to_string();
 }
diff --git a/tests/ui/format.rs b/tests/ui/format.rs
index 4a10b580d26..bf687cb1e96 100644
--- a/tests/ui/format.rs
+++ b/tests/ui/format.rs
@@ -86,4 +86,10 @@ fn main() {
     let _ = format!("{x}");
     let _ = format!("{x:?}"); // Don't lint on debug
     let _ = format!("{y}", y = x);
+
+    // Issue #9234
+    let abc = "abc";
+    let _ = format!("{abc}");
+    let xx = "xx";
+    let _ = format!("{xx}");
 }
diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr
index f25c7fb1ff1..a0f8e7d1937 100644
--- a/tests/ui/format.stderr
+++ b/tests/ui/format.stderr
@@ -111,5 +111,17 @@ error: useless use of `format!`
 LL |     let _ = format!("{y}", y = x);
    |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
-error: aborting due to 17 previous errors
+error: useless use of `format!`
+  --> $DIR/format.rs:92:13
+   |
+LL |     let _ = format!("{abc}");
+   |             ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
+
+error: useless use of `format!`
+  --> $DIR/format.rs:94:13
+   |
+LL |     let _ = format!("{xx}");
+   |             ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs
index dbfeb4379d5..7aba5b447d5 100644
--- a/tests/ui/match_same_arms2.rs
+++ b/tests/ui/match_same_arms2.rs
@@ -1,5 +1,5 @@
 #![warn(clippy::match_same_arms)]
-#![allow(clippy::blacklisted_name)]
+#![allow(clippy::blacklisted_name, clippy::diverging_sub_expression)]
 
 fn bar<T>(_: T) {}
 fn foo() -> bool {
@@ -227,4 +227,12 @@ fn main() {
         Some(Bar { y: 0, x: 5, .. }) => 1,
         _ => 200,
     };
+
+    let _ = match 0 {
+        0 => todo!(),
+        1 => todo!(),
+        2 => core::convert::identity::<u32>(todo!()),
+        3 => core::convert::identity::<u32>(todo!()),
+        _ => 5,
+    };
 }
diff --git a/tests/ui/mismatching_type_param_order.rs b/tests/ui/mismatching_type_param_order.rs
index 8f286c9304c..8c0da84d8e9 100644
--- a/tests/ui/mismatching_type_param_order.rs
+++ b/tests/ui/mismatching_type_param_order.rs
@@ -57,4 +57,8 @@ fn main() {
         B: Copy,
     {
     }
+
+    // if the types are complicated, do not lint
+    impl<K, V, B> Foo<(K, V), B> {}
+    impl<K, V, A> Foo<(K, V), A> {}
 }
diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed
index 09afe2ddbbf..bfd2725ecaa 100644
--- a/tests/ui/needless_borrow.fixed
+++ b/tests/ui/needless_borrow.fixed
@@ -158,3 +158,28 @@ fn check_expect_suppression() {
     #[expect(clippy::needless_borrow)]
     let _ = x(&&a);
 }
+
+#[allow(dead_code)]
+mod issue9160 {
+    pub struct S<F> {
+        f: F,
+    }
+
+    impl<T, F> S<F>
+    where
+        F: Fn() -> T,
+    {
+        fn calls_field(&self) -> T {
+            (self.f)()
+        }
+    }
+
+    impl<T, F> S<F>
+    where
+        F: FnMut() -> T,
+    {
+        fn calls_mut_field(&mut self) -> T {
+            (self.f)()
+        }
+    }
+}
diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs
index 3ae4722a1f8..c457d8c5471 100644
--- a/tests/ui/needless_borrow.rs
+++ b/tests/ui/needless_borrow.rs
@@ -158,3 +158,28 @@ fn check_expect_suppression() {
     #[expect(clippy::needless_borrow)]
     let _ = x(&&a);
 }
+
+#[allow(dead_code)]
+mod issue9160 {
+    pub struct S<F> {
+        f: F,
+    }
+
+    impl<T, F> S<F>
+    where
+        F: Fn() -> T,
+    {
+        fn calls_field(&self) -> T {
+            (&self.f)()
+        }
+    }
+
+    impl<T, F> S<F>
+    where
+        F: FnMut() -> T,
+    {
+        fn calls_mut_field(&mut self) -> T {
+            (&mut self.f)()
+        }
+    }
+}
diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr
index 8a2e2b98959..66588689d81 100644
--- a/tests/ui/needless_borrow.stderr
+++ b/tests/ui/needless_borrow.stderr
@@ -120,5 +120,17 @@ error: this expression creates a reference which is immediately dereferenced by
 LL |     (&&5).foo();
    |     ^^^^^ help: change this to: `(&5)`
 
-error: aborting due to 20 previous errors
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:173:13
+   |
+LL |             (&self.f)()
+   |             ^^^^^^^^^ help: change this to: `(self.f)`
+
+error: this expression borrows a value the compiler would automatically borrow
+  --> $DIR/needless_borrow.rs:182:13
+   |
+LL |             (&mut self.f)()
+   |             ^^^^^^^^^^^^^ help: change this to: `(self.f)`
+
+error: aborting due to 22 previous errors
 
diff --git a/tests/ui/obfuscated_if_else.fixed b/tests/ui/obfuscated_if_else.fixed
new file mode 100644
index 00000000000..62d932c2c6b
--- /dev/null
+++ b/tests/ui/obfuscated_if_else.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+
+#![warn(clippy::obfuscated_if_else)]
+
+fn main() {
+    if true { "a" } else { "b" };
+}
diff --git a/tests/ui/obfuscated_if_else.rs b/tests/ui/obfuscated_if_else.rs
new file mode 100644
index 00000000000..273be9092a7
--- /dev/null
+++ b/tests/ui/obfuscated_if_else.rs
@@ -0,0 +1,7 @@
+// run-rustfix
+
+#![warn(clippy::obfuscated_if_else)]
+
+fn main() {
+    true.then_some("a").unwrap_or("b");
+}
diff --git a/tests/ui/obfuscated_if_else.stderr b/tests/ui/obfuscated_if_else.stderr
new file mode 100644
index 00000000000..e4180c28869
--- /dev/null
+++ b/tests/ui/obfuscated_if_else.stderr
@@ -0,0 +1,10 @@
+error: use of `.then_some(..).unwrap_or(..)` can be written more clearly with `if .. else ..`
+  --> $DIR/obfuscated_if_else.rs:6:5
+   |
+LL |     true.then_some("a").unwrap_or("b");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `if true { "a" } else { "b" }`
+   |
+   = note: `-D clippy::obfuscated-if-else` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/std_instead_of_core.rs b/tests/ui/std_instead_of_core.rs
index 74f05ec1f65..6b27475de4c 100644
--- a/tests/ui/std_instead_of_core.rs
+++ b/tests/ui/std_instead_of_core.rs
@@ -9,6 +9,8 @@ fn std_instead_of_core() {
     use std::hash::Hasher;
     // Absolute path
     use ::std::hash::Hash;
+    // Don't lint on `env` macro
+    use std::env;
 
     // Multiple imports
     use std::fmt::{Debug, Result};
@@ -20,10 +22,14 @@ fn std_instead_of_core() {
     // Types
     let cell = std::cell::Cell::new(8u32);
     let cell_absolute = ::std::cell::Cell::new(8u32);
+
+    let _ = std::env!("PATH");
 }
 
 #[warn(clippy::std_instead_of_alloc)]
 fn std_instead_of_alloc() {
+    // Only lint once.
+    use std::vec;
     use std::vec::Vec;
 }
 
diff --git a/tests/ui/std_instead_of_core.stderr b/tests/ui/std_instead_of_core.stderr
index 9f1644835c1..bc49dabf586 100644
--- a/tests/ui/std_instead_of_core.stderr
+++ b/tests/ui/std_instead_of_core.stderr
@@ -16,7 +16,7 @@ LL |     use ::std::hash::Hash;
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:14:20
+  --> $DIR/std_instead_of_core.rs:16:20
    |
 LL |     use std::fmt::{Debug, Result};
    |                    ^^^^^
@@ -24,7 +24,7 @@ LL |     use std::fmt::{Debug, Result};
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:14:27
+  --> $DIR/std_instead_of_core.rs:16:27
    |
 LL |     use std::fmt::{Debug, Result};
    |                           ^^^^^^
@@ -32,7 +32,7 @@ LL |     use std::fmt::{Debug, Result};
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:17:15
+  --> $DIR/std_instead_of_core.rs:19:15
    |
 LL |     let ptr = std::ptr::null::<u32>();
    |               ^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |     let ptr = std::ptr::null::<u32>();
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:18:19
+  --> $DIR/std_instead_of_core.rs:20:19
    |
 LL |     let ptr_mut = ::std::ptr::null_mut::<usize>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL |     let ptr_mut = ::std::ptr::null_mut::<usize>();
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:21:16
+  --> $DIR/std_instead_of_core.rs:23:16
    |
 LL |     let cell = std::cell::Cell::new(8u32);
    |                ^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL |     let cell = std::cell::Cell::new(8u32);
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `core`
-  --> $DIR/std_instead_of_core.rs:22:25
+  --> $DIR/std_instead_of_core.rs:24:25
    |
 LL |     let cell_absolute = ::std::cell::Cell::new(8u32);
    |                         ^^^^^^^^^^^^^^^^^
@@ -64,16 +64,24 @@ LL |     let cell_absolute = ::std::cell::Cell::new(8u32);
    = help: consider importing the item from `core`
 
 error: used import from `std` instead of `alloc`
-  --> $DIR/std_instead_of_core.rs:27:9
+  --> $DIR/std_instead_of_core.rs:32:9
+   |
+LL |     use std::vec;
+   |         ^^^^^^^^
+   |
+   = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
+   = help: consider importing the item from `alloc`
+
+error: used import from `std` instead of `alloc`
+  --> $DIR/std_instead_of_core.rs:33:9
    |
 LL |     use std::vec::Vec;
    |         ^^^^^^^^^^^^^
    |
-   = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
    = help: consider importing the item from `alloc`
 
 error: used import from `alloc` instead of `core`
-  --> $DIR/std_instead_of_core.rs:32:9
+  --> $DIR/std_instead_of_core.rs:38:9
    |
 LL |     use alloc::slice::from_ref;
    |         ^^^^^^^^^^^^^^^^^^^^^^
@@ -81,5 +89,5 @@ LL |     use alloc::slice::from_ref;
    = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
    = help: consider importing the item from `core`
 
-error: aborting due to 10 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs
index b4a931043b0..ac4c1bc6597 100644
--- a/tests/ui/temporary_assignment.rs
+++ b/tests/ui/temporary_assignment.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::temporary_assignment)]
-#![allow(const_item_mutation)]
 
 use std::ops::{Deref, DerefMut};
 
diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr
index 4cc32c79f05..7d79901a28d 100644
--- a/tests/ui/temporary_assignment.stderr
+++ b/tests/ui/temporary_assignment.stderr
@@ -1,5 +1,5 @@
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:48:5
+  --> $DIR/temporary_assignment.rs:47:5
    |
 LL |     Struct { field: 0 }.field = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     Struct { field: 0 }.field = 1;
    = note: `-D clippy::temporary-assignment` implied by `-D warnings`
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:49:5
+  --> $DIR/temporary_assignment.rs:48:5
    |
 LL | /     MultiStruct {
 LL | |         structure: Struct { field: 0 },
@@ -17,13 +17,13 @@ LL | |     .field = 1;
    | |______________^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:54:5
+  --> $DIR/temporary_assignment.rs:53:5
    |
 LL |     ArrayStruct { array: [0] }.array[0] = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:55:5
+  --> $DIR/temporary_assignment.rs:54:5
    |
 LL |     (0, 0).0 = 1;
    |     ^^^^^^^^^^^^
diff --git a/tests/ui/unused_self.rs b/tests/ui/unused_self.rs
index 08bf58fec7c..92e8e1dba69 100644
--- a/tests/ui/unused_self.rs
+++ b/tests/ui/unused_self.rs
@@ -53,8 +53,17 @@ mod unused_self_allow {
         // shouldn't trigger
         fn unused_self_move(self) {}
     }
+
+    pub struct D;
+
+    impl D {
+        // shouldn't trigger for public methods
+        pub fn unused_self_move(self) {}
+    }
 }
 
+pub use unused_self_allow::D;
+
 mod used_self {
     use std::pin::Pin;