Fix coerce_container_to_any false positive on autoderef (#15057)

Fixes the false positive reported in rust-lang/rust-clippy#15045. ~I
still need to work out how to fix the suggestion.~

changelog: none
diff --git a/.github/ISSUE_TEMPLATE/new_lint.yml b/.github/ISSUE_TEMPLATE/new_lint.yml
index b49493e..4647406 100644
--- a/.github/ISSUE_TEMPLATE/new_lint.yml
+++ b/.github/ISSUE_TEMPLATE/new_lint.yml
@@ -1,5 +1,7 @@
 name: New lint suggestion
-description: Suggest a new Clippy lint.
+description: |
+  Suggest a new Clippy lint (currently not accepting new lints)
+  Check out the Clippy book for more information about the feature freeze.
 labels: ["A-lint"]
 body:
   - type: markdown
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 9e49f60..83bfd8e 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -32,6 +32,10 @@
 
 Delete this line and everything above before opening your PR.
 
+Note that we are currently not taking in new PRs that add new lints. We are in a
+feature freeze. Check out the book for more information. If you open a
+feature-adding pull request, its review will be delayed.
+
 ---
 
 *Please write a short comment explaining your change (or "none" for internal only changes)*
diff --git a/.github/workflows/feature_freeze.yml b/.github/workflows/feature_freeze.yml
new file mode 100644
index 0000000..a5f8d4b
--- /dev/null
+++ b/.github/workflows/feature_freeze.yml
@@ -0,0 +1,25 @@
+name: Feature freeze check
+
+on:
+  pull_request:
+    paths:
+      - 'clippy_lints/src/declared_lints.rs'
+
+jobs:
+  auto-comment:
+    runs-on: ubuntu-latest
+
+    steps:
+    - name: Check PR Changes
+      id: pr-changes
+      run: echo "::set-output name=changes::${{ toJson(github.event.pull_request.changed_files) }}"
+
+    - name: Create Comment
+      if: steps.pr-changes.outputs.changes != '[]'
+      run: |
+        # Use GitHub API to create a comment on the PR
+        PR_NUMBER=${{ github.event.pull_request.number }}
+        COMMENT="**Seems that you are trying to add a new lint!**\nWe are currently in a [feature freeze](https://doc.rust-lang.org/nightly/clippy/development/feature_freeze.html), so we are delaying all lint-adding PRs to August 1st and focusing on bugfixes.\nThanks a lot for your contribution, and sorry for the inconvenience.\nWith ❤ from the Clippy team"
+        GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
+        COMMENT_URL="https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/comments"
+        curl -s -H "Authorization: token ${GITHUB_TOKEN}" -X POST $COMMENT_URL -d "{\"body\":\"$COMMENT\"}"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0cfe89a..a92fbdc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,94 @@
 
 ## Unreleased / Beta / In Rust Nightly
 
-[1e5237f4...master](https://github.com/rust-lang/rust-clippy/compare/1e5237f4...master)
+[03a5b6b9...master](https://github.com/rust-lang/rust-clippy/compare/03a5b6b9...master)
+
+## Rust 1.88
+
+Current stable, released 2025-06-26
+
+[View all 126 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2025-03-21T10%3A30%3A57Z..2025-05-01T08%3A03%3A26Z+base%3Amaster)
+
+### New Lints
+
+* Added [`swap_with_temporary`] to `complexity` [#14046](https://github.com/rust-lang/rust-clippy/pull/14046)
+* Added [`redundant_test_prefix`] to `restriction` [#13710](https://github.com/rust-lang/rust-clippy/pull/13710)
+* Added [`manual_dangling_ptr`] to `style` [#14107](https://github.com/rust-lang/rust-clippy/pull/14107)
+* Added [`char_indices_as_byte_indices`] to `correctness` [#13435](https://github.com/rust-lang/rust-clippy/pull/13435)
+* Added [`manual_abs_diff`] to `complexity` [#14482](https://github.com/rust-lang/rust-clippy/pull/14482)
+* Added [`ignore_without_reason`] to `pedantic` [#13931](https://github.com/rust-lang/rust-clippy/pull/13931)
+
+### Moves and Deprecations
+
+* Moved [`uninlined_format_args`] to `style` (from `pedantic`)
+  [#14160](https://github.com/rust-lang/rust-clippy/pull/14160)
+* [`match_on_vec_items`] deprecated in favor of [`indexing_slicing`]
+  [#14217](https://github.com/rust-lang/rust-clippy/pull/14217)
+* Removed superseded lints: `transmute_float_to_int`, `transmute_int_to_char`,
+  `transmute_int_to_float`, `transmute_num_to_bytes` (now in rustc)
+  [#14703](https://github.com/rust-lang/rust-clippy/pull/14703)
+
+### Enhancements
+
+* Configuration renamed from `lint-inconsistent-struct-field-initializers`
+  to `check-inconsistent-struct-field-initializers`
+  [#14280](https://github.com/rust-lang/rust-clippy/pull/14280)
+* Paths in `disallowed_*` configurations are now validated
+  [#14397](https://github.com/rust-lang/rust-clippy/pull/14397)
+* [`borrow_as_ptr`] now lints implicit casts as well
+  [#14408](https://github.com/rust-lang/rust-clippy/pull/14408)
+* [`iter_kv_map`] now recognizes references on maps
+  [#14596](https://github.com/rust-lang/rust-clippy/pull/14596)
+* [`empty_enum_variants_with_brackets`] no longer lints reachable enums or enums used 
+  as functions within same crate [#12971](https://github.com/rust-lang/rust-clippy/pull/12971)
+* [`needless_lifetimes`] now checks for lifetime uses in closures
+  [#14608](https://github.com/rust-lang/rust-clippy/pull/14608)
+* [`wildcard_imports`] now lints on `pub use` when `warn_on_all_wildcard_imports` is enabled
+  [#14182](https://github.com/rust-lang/rust-clippy/pull/14182)
+* [`collapsible_if`] now recognizes the `let_chains` feature
+  [#14481](https://github.com/rust-lang/rust-clippy/pull/14481)
+* [`match_single_binding`] now allows macros in scrutinee and patterns
+  [#14635](https://github.com/rust-lang/rust-clippy/pull/14635)
+* [`needless_borrow`] does not contradict the compiler's
+  `dangerous_implicit_autorefs` lint even though the references
+  are not mandatory
+  [#14810](https://github.com/rust-lang/rust-clippy/pull/14810)
+
+### False Positive Fixes
+
+* [`double_ended_iterator_last`] and [`needless_collect`] fixed FP when iter has side effects
+  [#14490](https://github.com/rust-lang/rust-clippy/pull/14490)
+* [`mut_from_ref`] fixed FP where lifetimes nested in types were not considered
+  [#14471](https://github.com/rust-lang/rust-clippy/pull/14471)
+* [`redundant_clone`] fixed FP in overlapping lifetime
+  [#14237](https://github.com/rust-lang/rust-clippy/pull/14237)
+* [`map_entry`] fixed FP where lint would trigger without insert calls present
+  [#14568](https://github.com/rust-lang/rust-clippy/pull/14568)
+* [`iter_cloned_collect`] fixed FP with custom `From`/`IntoIterator` impl
+  [#14473](https://github.com/rust-lang/rust-clippy/pull/14473)
+* [`shadow_unrelated`] fixed FP in destructuring assignments
+  [#14381](https://github.com/rust-lang/rust-clippy/pull/14381)
+* [`redundant_clone`] fixed FP on enum cast
+  [#14395](https://github.com/rust-lang/rust-clippy/pull/14395)
+* [`collapsible_if`] fixed FP on block stmt before expr
+  [#14730](https://github.com/rust-lang/rust-clippy/pull/14730)
+
+### ICE Fixes
+
+* [`missing_const_for_fn`] fix ICE with `-Z validate-mir` compilation option
+  [#14776](https://github.com/rust-lang/rust-clippy/pull/14776)
+
+### Documentation Improvements
+
+* [`missing_asserts_for_indexing`] improved documentation and examples
+  [#14108](https://github.com/rust-lang/rust-clippy/pull/14108)
+
+### Others
+
+* We're testing with edition 2024 now
+  [#14602](https://github.com/rust-lang/rust-clippy/pull/14602)
+* Don't warn about unloaded crates in `clippy.toml` disallowed paths
+  [#14733](https://github.com/rust-lang/rust-clippy/pull/14733)
 
 ## Rust 1.87
 
@@ -5729,6 +5816,7 @@
 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
 [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
+[`doc_broken_link`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_broken_link
 [`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks
 [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg
 [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation
@@ -5967,6 +6055,7 @@
 [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
 [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
 [`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite
+[`manual_is_multiple_of`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_multiple_of
 [`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two
 [`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and
 [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
diff --git a/Cargo.toml b/Cargo.toml
index 5584ded..8cbdcf4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.89"
+version = "0.1.90"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -24,6 +24,7 @@
 clippy_config = { path = "clippy_config" }
 clippy_lints = { path = "clippy_lints" }
 clippy_utils = { path = "clippy_utils" }
+declare_clippy_lint = { path = "declare_clippy_lint" }
 rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }
 clippy_lints_internal = { path = "clippy_lints_internal", optional = true }
 tempfile = { version = "3.20", optional = true }
@@ -58,6 +59,7 @@
 [features]
 integration = ["dep:tempfile"]
 internal = ["dep:clippy_lints_internal", "dep:tempfile"]
+jemalloc = []
 
 [package.metadata.rust-analyzer]
 # This package uses #[feature(rustc_private)]
diff --git a/book/src/README.md b/book/src/README.md
index 5d2c397..db73b49 100644
--- a/book/src/README.md
+++ b/book/src/README.md
@@ -1,5 +1,9 @@
 # Clippy
 
+[### IMPORTANT NOTE FOR CONTRIBUTORS ================](development/feature_freeze.md)
+
+----
+
 [![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](https://github.com/rust-lang/rust-clippy#license)
 
 A collection of lints to catch common mistakes and improve your
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 39fe735..b66c348 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -13,6 +13,7 @@
     - [GitLab CI](continuous_integration/gitlab.md)
     - [Travis CI](continuous_integration/travis.md)
 - [Development](development/README.md)
+    - [IMPORTANT: FEATURE FREEZE](development/feature_freeze.md)
     - [Basics](development/basics.md)
     - [Adding Lints](development/adding_lints.md)
     - [Defining Lints](development/defining_lints.md)
diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md
index 2b89e94..a42a298 100644
--- a/book/src/development/adding_lints.md
+++ b/book/src/development/adding_lints.md
@@ -1,5 +1,8 @@
 # Adding a new lint
 
+[### IMPORTANT NOTE FOR CONTRIBUTORS ================](feature_freeze.md)
+
+
 You are probably here because you want to add a new lint to Clippy. If this is
 the first time you're contributing to Clippy, this document guides you through
 creating an example lint from scratch.
diff --git a/book/src/development/feature_freeze.md b/book/src/development/feature_freeze.md
new file mode 100644
index 0000000..260cb13
--- /dev/null
+++ b/book/src/development/feature_freeze.md
@@ -0,0 +1,55 @@
+# IMPORTANT: FEATURE FREEZE
+
+This is a temporary notice.
+
+From the 26th of June until the 18th of September we will perform a feature freeze. Only bugfix PRs will be reviewed
+except already open ones. Every feature-adding PR opened in between those dates will be moved into a
+milestone to be reviewed separately at another time.
+
+We do this because of the long backlog of bugs that need to be addressed
+in order to continue being the state-of-the-art linter that Clippy has become known for being.
+
+## For contributors
+
+If you are a contributor or are planning to become one, **please do not open a lint-adding PR**, we have lots of open
+bugs of all levels of difficulty that you can address instead!
+
+We currently have about 800 lints, each one posing a maintainability challenge that needs to account to every possible
+use case of the whole ecosystem. Bugs are natural in every software, but the Clippy team considers that Clippy needs a
+refinement period.
+
+If you open a PR at this time, we will not review it but push it into a milestone until the refinement period ends,
+adding additional load into our reviewing schedules.
+
+## I want to help, what can I do
+
+Thanks a lot to everyone who wants to help Clippy become better software in this feature freeze period!
+If you'd like to help, making a bugfix, making sure that it works, and opening a PR is a great step!
+
+To find things to fix, go to the [tracking issue][tracking_issue], find an issue that you like, go there and claim that
+issue with `@rustbot claim`.
+
+As a general metric and always taking into account your skill and knowledge level, you can use this guide:
+
+- 🟥 [ICEs][search_ice], these are compiler errors that causes Clippy to panic and crash. Usually involves high-level
+debugging, sometimes interacting directly with the upstream compiler. Difficult to fix but a great challenge that
+improves a lot developer workflows!
+
+- 🟧 [Suggestion causes bug][sugg_causes_bug], Clippy suggested code that changed logic in some silent way.
+Unacceptable, as this may have disastrous consequences. Easier to fix than ICEs
+
+- 🟨 [Suggestion causes error][sugg_causes_error], Clippy suggested code snippet that caused a compiler error
+when applied. We need to make sure that Clippy doesn't suggest using a variable twice at the same time or similar
+easy-to-happen occurrences.
+
+- 🟩 [False positives][false_positive], a lint should not have fired, the easiest of them all, as this is "just"
+identifying the root of a false positive and making an exception for those cases.
+
+Note that false negatives do not have priority unless the case is very clear, as they are a feature-request in a
+trench coat.
+
+[search_ice]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc+state%3Aopen+label%3A%22I-ICE%22
+[sugg_causes_bug]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc%20state%3Aopen%20label%3AI-suggestion-causes-bug
+[sugg_causes_error]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc%20state%3Aopen%20label%3AI-suggestion-causes-error%20
+[false_positive]: https://github.com/rust-lang/rust-clippy/issues?q=sort%3Aupdated-desc%20state%3Aopen%20label%3AI-false-positive
+[tracking_issue]: https://github.com/rust-lang/rust-clippy/issues/15086
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index ab46aab..992ed2c 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -488,6 +488,13 @@
 ## `disallowed-macros`
 The list of disallowed macros, written as fully qualified paths.
 
+**Fields:**
+- `path` (required): the fully qualified path to the macro that should be disallowed
+- `reason` (optional): explanation why this macro is disallowed
+- `replacement` (optional): suggested alternative macro
+- `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry
+  if the path doesn't exist, instead of emitting an error
+
 **Default Value:** `[]`
 
 ---
@@ -498,6 +505,13 @@
 ## `disallowed-methods`
 The list of disallowed methods, written as fully qualified paths.
 
+**Fields:**
+- `path` (required): the fully qualified path to the method that should be disallowed
+- `reason` (optional): explanation why this method is disallowed
+- `replacement` (optional): suggested alternative method
+- `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry
+  if the path doesn't exist, instead of emitting an error
+
 **Default Value:** `[]`
 
 ---
@@ -520,6 +534,13 @@
 ## `disallowed-types`
 The list of disallowed types, written as fully qualified paths.
 
+**Fields:**
+- `path` (required): the fully qualified path to the type that should be disallowed
+- `reason` (optional): explanation why this type is disallowed
+- `replacement` (optional): suggested alternative type
+- `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry
+  if the path doesn't exist, instead of emitting an error
+
 **Default Value:** `[]`
 
 ---
@@ -871,6 +892,7 @@
 * [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
 * [`unused_trait_names`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names)
 * [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
+* [`zero_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr)
 
 
 ## `pass-by-value-size-limit`
diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml
index 0606245..858366c 100644
--- a/clippy_config/Cargo.toml
+++ b/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_config"
-version = "0.1.89"
+version = "0.1.90"
 edition = "2024"
 publish = false
 
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 064825e..555f54b 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -575,10 +575,24 @@
     #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)]
     cyclomatic_complexity_threshold: u64 = 25,
     /// The list of disallowed macros, written as fully qualified paths.
+    ///
+    /// **Fields:**
+    /// - `path` (required): the fully qualified path to the macro that should be disallowed
+    /// - `reason` (optional): explanation why this macro is disallowed
+    /// - `replacement` (optional): suggested alternative macro
+    /// - `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry
+    ///   if the path doesn't exist, instead of emitting an error
     #[disallowed_paths_allow_replacements = true]
     #[lints(disallowed_macros)]
     disallowed_macros: Vec<DisallowedPath> = Vec::new(),
     /// The list of disallowed methods, written as fully qualified paths.
+    ///
+    /// **Fields:**
+    /// - `path` (required): the fully qualified path to the method that should be disallowed
+    /// - `reason` (optional): explanation why this method is disallowed
+    /// - `replacement` (optional): suggested alternative method
+    /// - `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry
+    ///   if the path doesn't exist, instead of emitting an error
     #[disallowed_paths_allow_replacements = true]
     #[lints(disallowed_methods)]
     disallowed_methods: Vec<DisallowedPath> = Vec::new(),
@@ -588,6 +602,13 @@
     #[lints(disallowed_names)]
     disallowed_names: Vec<String> = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect(),
     /// The list of disallowed types, written as fully qualified paths.
+    ///
+    /// **Fields:**
+    /// - `path` (required): the fully qualified path to the type that should be disallowed
+    /// - `reason` (optional): explanation why this type is disallowed
+    /// - `replacement` (optional): suggested alternative type
+    /// - `allow-invalid` (optional, `false` by default): when set to `true`, it will ignore this entry
+    ///   if the path doesn't exist, instead of emitting an error
     #[disallowed_paths_allow_replacements = true]
     #[lints(disallowed_types)]
     disallowed_types: Vec<DisallowedPath> = Vec::new(),
@@ -773,6 +794,7 @@
         unnested_or_patterns,
         unused_trait_names,
         use_self,
+        zero_ptr,
     )]
     msrv: Msrv = Msrv::default(),
     /// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs
index e0e0367..0d66f16 100644
--- a/clippy_dev/src/lint.rs
+++ b/clippy_dev/src/lint.rs
@@ -13,7 +13,7 @@
 
     if is_file {
         exit_if_err(
-            Command::new(env::var("CARGO").unwrap_or("cargo".into()))
+            Command::new(env::var("CARGO").unwrap_or_else(|_| "cargo".into()))
                 .args(["run", "--bin", "clippy-driver", "--"])
                 .args(["-L", "./target/debug"])
                 .args(["-Z", "no-codegen"])
@@ -26,7 +26,7 @@
         );
     } else {
         exit_if_err(
-            Command::new(env::var("CARGO").unwrap_or("cargo".into()))
+            Command::new(env::var("CARGO").unwrap_or_else(|_| "cargo".into()))
                 .arg("build")
                 .status(),
         );
diff --git a/clippy_dev/src/release.rs b/clippy_dev/src/release.rs
index 62c1bee..15392dd 100644
--- a/clippy_dev/src/release.rs
+++ b/clippy_dev/src/release.rs
@@ -5,6 +5,7 @@
     "clippy_config/Cargo.toml",
     "clippy_lints/Cargo.toml",
     "clippy_utils/Cargo.toml",
+    "declare_clippy_lint/Cargo.toml",
     "Cargo.toml",
 ];
 
diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs
index a2d1236..498ffeb 100644
--- a/clippy_dev/src/serve.rs
+++ b/clippy_dev/src/serve.rs
@@ -28,7 +28,7 @@
         .map(mtime);
 
         if times.iter().any(|&time| index_time < time) {
-            Command::new(env::var("CARGO").unwrap_or("cargo".into()))
+            Command::new(env::var("CARGO").unwrap_or_else(|_| "cargo".into()))
                 .arg("collect-metadata")
                 .spawn()
                 .unwrap()
diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs
index 08592f2..5f6e874 100644
--- a/clippy_dev/src/update_lints.rs
+++ b/clippy_dev/src/update_lints.rs
@@ -4,8 +4,9 @@
 use itertools::Itertools;
 use std::collections::HashSet;
 use std::fmt::Write;
+use std::fs;
 use std::ops::Range;
-use std::path::{Path, PathBuf};
+use std::path::{self, Path, PathBuf};
 use walkdir::{DirEntry, WalkDir};
 
 const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev update_lints`.\n\
@@ -36,123 +37,164 @@
     deprecated: &[DeprecatedLint],
     renamed: &[RenamedLint],
 ) {
-    FileUpdater::default().update_files_checked(
+    let mut updater = FileUpdater::default();
+    updater.update_file_checked(
         "cargo dev update_lints",
         update_mode,
-        &mut [
-            (
-                "README.md",
-                &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
-                    write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
-                }),
-            ),
-            (
-                "book/src/README.md",
-                &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
-                    write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
-                }),
-            ),
-            (
-                "CHANGELOG.md",
-                &mut update_text_region_fn(
-                    "<!-- begin autogenerated links to lint list -->\n",
-                    "<!-- end autogenerated links to lint list -->",
-                    |dst| {
-                        for lint in lints
-                            .iter()
-                            .map(|l| &*l.name)
-                            .chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
-                            .chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
-                            .sorted()
-                        {
-                            writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
-                        }
-                    },
-                ),
-            ),
-            (
-                "clippy_lints/src/lib.rs",
-                &mut update_text_region_fn(
-                    "// begin lints modules, do not remove this comment, it's used in `update_lints`\n",
-                    "// end lints modules, do not remove this comment, it's used in `update_lints`",
-                    |dst| {
-                        for lint_mod in lints.iter().map(|l| &l.module).sorted().dedup() {
-                            writeln!(dst, "mod {lint_mod};").unwrap();
-                        }
-                    },
-                ),
-            ),
-            ("clippy_lints/src/declared_lints.rs", &mut |_, src, dst| {
-                dst.push_str(GENERATED_FILE_COMMENT);
-                dst.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
-                for (module_name, lint_name) in lints.iter().map(|l| (&l.module, l.name.to_uppercase())).sorted() {
-                    writeln!(dst, "    crate::{module_name}::{lint_name}_INFO,").unwrap();
+        "README.md",
+        &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
+            write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
+        }),
+    );
+    updater.update_file_checked(
+        "cargo dev update_lints",
+        update_mode,
+        "book/src/README.md",
+        &mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
+            write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
+        }),
+    );
+    updater.update_file_checked(
+        "cargo dev update_lints",
+        update_mode,
+        "CHANGELOG.md",
+        &mut update_text_region_fn(
+            "<!-- begin autogenerated links to lint list -->\n",
+            "<!-- end autogenerated links to lint list -->",
+            |dst| {
+                for lint in lints
+                    .iter()
+                    .map(|l| &*l.name)
+                    .chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
+                    .chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
+                    .sorted()
+                {
+                    writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
                 }
-                dst.push_str("];\n");
-                UpdateStatus::from_changed(src != dst)
-            }),
-            ("clippy_lints/src/deprecated_lints.rs", &mut |_, src, dst| {
-                let mut searcher = RustSearcher::new(src);
-                assert!(
-                    searcher.find_token(Token::Ident("declare_with_version"))
-                        && searcher.find_token(Token::Ident("declare_with_version")),
-                    "error reading deprecated lints"
-                );
-                dst.push_str(&src[..searcher.pos() as usize]);
-                dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n");
-                for lint in deprecated {
-                    write!(
-                        dst,
-                        "    #[clippy::version = \"{}\"]\n    (\"{}\", \"{}\"),\n",
-                        lint.version, lint.name, lint.reason,
-                    )
-                    .unwrap();
-                }
-                dst.push_str(
-                    "]}\n\n\
+            },
+        ),
+    );
+    updater.update_file_checked(
+        "cargo dev update_lints",
+        update_mode,
+        "clippy_lints/src/deprecated_lints.rs",
+        &mut |_, src, dst| {
+            let mut searcher = RustSearcher::new(src);
+            assert!(
+                searcher.find_token(Token::Ident("declare_with_version"))
+                    && searcher.find_token(Token::Ident("declare_with_version")),
+                "error reading deprecated lints"
+            );
+            dst.push_str(&src[..searcher.pos() as usize]);
+            dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n");
+            for lint in deprecated {
+                write!(
+                    dst,
+                    "    #[clippy::version = \"{}\"]\n    (\"{}\", \"{}\"),\n",
+                    lint.version, lint.name, lint.reason,
+                )
+                .unwrap();
+            }
+            dst.push_str(
+                "]}\n\n\
                     #[rustfmt::skip]\n\
                     declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\
                 ",
-                );
-                for lint in renamed {
-                    write!(
-                        dst,
-                        "    #[clippy::version = \"{}\"]\n    (\"{}\", \"{}\"),\n",
-                        lint.version, lint.old_name, lint.new_name,
-                    )
-                    .unwrap();
-                }
-                dst.push_str("]}\n");
-                UpdateStatus::from_changed(src != dst)
-            }),
-            ("tests/ui/deprecated.rs", &mut |_, src, dst| {
-                dst.push_str(GENERATED_FILE_COMMENT);
-                for lint in deprecated {
-                    writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
-                }
-                dst.push_str("\nfn main() {}\n");
-                UpdateStatus::from_changed(src != dst)
-            }),
-            ("tests/ui/rename.rs", &mut move |_, src, dst| {
-                let mut seen_lints = HashSet::new();
-                dst.push_str(GENERATED_FILE_COMMENT);
-                dst.push_str("#![allow(clippy::duplicated_attributes)]\n");
-                for lint in renamed {
-                    if seen_lints.insert(&lint.new_name) {
-                        writeln!(dst, "#![allow({})]", lint.new_name).unwrap();
-                    }
-                }
-                seen_lints.clear();
-                for lint in renamed {
-                    if seen_lints.insert(&lint.old_name) {
-                        writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
-                    }
-                }
-                dst.push_str("\nfn main() {}\n");
-                UpdateStatus::from_changed(src != dst)
-            }),
-        ],
+            );
+            for lint in renamed {
+                write!(
+                    dst,
+                    "    #[clippy::version = \"{}\"]\n    (\"{}\", \"{}\"),\n",
+                    lint.version, lint.old_name, lint.new_name,
+                )
+                .unwrap();
+            }
+            dst.push_str("]}\n");
+            UpdateStatus::from_changed(src != dst)
+        },
     );
+    updater.update_file_checked(
+        "cargo dev update_lints",
+        update_mode,
+        "tests/ui/deprecated.rs",
+        &mut |_, src, dst| {
+            dst.push_str(GENERATED_FILE_COMMENT);
+            for lint in deprecated {
+                writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
+            }
+            dst.push_str("\nfn main() {}\n");
+            UpdateStatus::from_changed(src != dst)
+        },
+    );
+    updater.update_file_checked(
+        "cargo dev update_lints",
+        update_mode,
+        "tests/ui/rename.rs",
+        &mut move |_, src, dst| {
+            let mut seen_lints = HashSet::new();
+            dst.push_str(GENERATED_FILE_COMMENT);
+            dst.push_str("#![allow(clippy::duplicated_attributes)]\n");
+            for lint in renamed {
+                if seen_lints.insert(&lint.new_name) {
+                    writeln!(dst, "#![allow({})]", lint.new_name).unwrap();
+                }
+            }
+            seen_lints.clear();
+            for lint in renamed {
+                if seen_lints.insert(&lint.old_name) {
+                    writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
+                }
+            }
+            dst.push_str("\nfn main() {}\n");
+            UpdateStatus::from_changed(src != dst)
+        },
+    );
+    for (crate_name, lints) in lints.iter().into_group_map_by(|&l| {
+        let Some(path::Component::Normal(name)) = l.path.components().next() else {
+            // All paths should start with `{crate_name}/src` when parsed from `find_lint_decls`
+            panic!("internal error: can't read crate name from path `{}`", l.path.display());
+        };
+        name
+    }) {
+        updater.update_file_checked(
+            "cargo dev update_lints",
+            update_mode,
+            Path::new(crate_name).join("src/lib.rs"),
+            &mut update_text_region_fn(
+                "// begin lints modules, do not remove this comment, it's used in `update_lints`\n",
+                "// end lints modules, do not remove this comment, it's used in `update_lints`",
+                |dst| {
+                    for lint_mod in lints
+                        .iter()
+                        .filter(|l| !l.module.is_empty())
+                        .map(|l| l.module.split_once("::").map_or(&*l.module, |x| x.0))
+                        .sorted()
+                        .dedup()
+                    {
+                        writeln!(dst, "mod {lint_mod};").unwrap();
+                    }
+                },
+            ),
+        );
+        updater.update_file_checked(
+            "cargo dev update_lints",
+            update_mode,
+            Path::new(crate_name).join("src/declared_lints.rs"),
+            &mut |_, src, dst| {
+                dst.push_str(GENERATED_FILE_COMMENT);
+                dst.push_str("pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[\n");
+                for (module_path, lint_name) in lints.iter().map(|l| (&l.module, l.name.to_uppercase())).sorted() {
+                    if module_path.is_empty() {
+                        writeln!(dst, "    crate::{lint_name}_INFO,").unwrap();
+                    } else {
+                        writeln!(dst, "    crate::{module_path}::{lint_name}_INFO,").unwrap();
+                    }
+                }
+                dst.push_str("];\n");
+                UpdateStatus::from_changed(src != dst)
+            },
+        );
+    }
 }
 
 fn round_to_fifty(count: usize) -> usize {
@@ -186,13 +228,25 @@
 pub fn find_lint_decls() -> Vec<Lint> {
     let mut lints = Vec::with_capacity(1000);
     let mut contents = String::new();
-    for (file, module) in read_src_with_module("clippy_lints/src".as_ref()) {
-        parse_clippy_lint_decls(
-            file.path(),
-            File::open_read_to_cleared_string(file.path(), &mut contents),
-            &module,
-            &mut lints,
-        );
+    for e in expect_action(fs::read_dir("."), ErrAction::Read, ".") {
+        let e = expect_action(e, ErrAction::Read, ".");
+        if !expect_action(e.file_type(), ErrAction::Read, ".").is_dir() {
+            continue;
+        }
+        let Ok(mut name) = e.file_name().into_string() else {
+            continue;
+        };
+        if name.starts_with("clippy_lints") && name != "clippy_lints_internal" {
+            name.push_str("/src");
+            for (file, module) in read_src_with_module(name.as_ref()) {
+                parse_clippy_lint_decls(
+                    file.path(),
+                    File::open_read_to_cleared_string(file.path(), &mut contents),
+                    &module,
+                    &mut lints,
+                );
+            }
+        }
     }
     lints.sort_by(|lhs, rhs| lhs.name.cmp(&rhs.name));
     lints
@@ -204,7 +258,7 @@
         let e = expect_action(e, ErrAction::Read, src_root);
         let path = e.path().as_os_str().as_encoded_bytes();
         if let Some(path) = path.strip_suffix(b".rs")
-            && let Some(path) = path.get("clippy_lints/src/".len()..)
+            && let Some(path) = path.get(src_root.as_os_str().len() + 1..)
         {
             if path == b"lib" {
                 Some((e, String::new()))
@@ -332,17 +386,13 @@
 
 /// Removes the line splices and surrounding quotes from a string literal
 fn parse_str_lit(s: &str) -> String {
-    let (s, mode) = if let Some(s) = s.strip_prefix("r") {
-        (s.trim_matches('#'), rustc_literal_escaper::Mode::RawStr)
-    } else {
-        (s, rustc_literal_escaper::Mode::Str)
-    };
+    let s = s.strip_prefix("r").unwrap_or(s).trim_matches('#');
     let s = s
         .strip_prefix('"')
         .and_then(|s| s.strip_suffix('"'))
         .unwrap_or_else(|| panic!("expected quoted string, found `{s}`"));
     let mut res = String::with_capacity(s.len());
-    rustc_literal_escaper::unescape_unicode(s, mode, &mut |_, ch| {
+    rustc_literal_escaper::unescape_str(s, &mut |_, ch| {
         if let Ok(ch) = ch {
             res.push(ch);
         }
diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs
index c4808b7..89962a1 100644
--- a/clippy_dev/src/utils.rs
+++ b/clippy_dev/src/utils.rs
@@ -383,21 +383,6 @@
         self.update_file_checked_inner(tool, mode, path.as_ref(), update);
     }
 
-    #[expect(clippy::type_complexity)]
-    pub fn update_files_checked(
-        &mut self,
-        tool: &str,
-        mode: UpdateMode,
-        files: &mut [(
-            impl AsRef<Path>,
-            &mut dyn FnMut(&Path, &str, &mut String) -> UpdateStatus,
-        )],
-    ) {
-        for (path, update) in files {
-            self.update_file_checked_inner(tool, mode, path.as_ref(), update);
-        }
-    }
-
     pub fn update_file(
         &mut self,
         path: impl AsRef<Path>,
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index 39e4e2e..c03cc99 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_lints"
-version = "0.1.89"
+version = "0.1.90"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -13,6 +13,7 @@
 cargo_metadata = "0.18"
 clippy_config = { path = "../clippy_config" }
 clippy_utils = { path = "../clippy_utils" }
+declare_clippy_lint = { path = "../declare_clippy_lint" }
 itertools = "0.12"
 quine-mc_cluskey = "0.2"
 regex-syntax = "0.8"
diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs
index cb63fad..b8f93ee 100644
--- a/clippy_lints/src/attrs/inline_always.rs
+++ b/clippy_lints/src/attrs/inline_always.rs
@@ -1,29 +1,22 @@
 use super::INLINE_ALWAYS;
-use super::utils::is_word;
 use clippy_utils::diagnostics::span_lint;
+use rustc_attr_data_structures::{AttributeKind, InlineAttr, find_attr};
 use rustc_hir::Attribute;
 use rustc_lint::LateContext;
+use rustc_span::Span;
 use rustc_span::symbol::Symbol;
-use rustc_span::{Span, sym};
 
 pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) {
     if span.from_expansion() {
         return;
     }
 
-    for attr in attrs {
-        if let Some(values) = attr.meta_item_list() {
-            if values.len() != 1 || !attr.has_name(sym::inline) {
-                continue;
-            }
-            if is_word(&values[0], sym::always) {
-                span_lint(
-                    cx,
-                    INLINE_ALWAYS,
-                    attr.span(),
-                    format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
-                );
-            }
-        }
+    if let Some(span) = find_attr!(attrs, AttributeKind::Inline(InlineAttr::Always, span) => *span) {
+        span_lint(
+            cx,
+            INLINE_ALWAYS,
+            span,
+            format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
+        );
     }
 }
diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs
index 9a12429..91c2dc7 100644
--- a/clippy_lints/src/attrs/mod.rs
+++ b/clippy_lints/src/attrs/mod.rs
@@ -207,7 +207,7 @@
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for usage of the `#[allow]` attribute and suggests replacing it with
-    /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
+    /// the `#[expect]` attribute (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html))
     ///
     /// This lint only warns outer attributes (`#[allow]`), as inner attributes
     /// (`#![allow]`) are usually used to enable or disable lints on a global scale.
diff --git a/clippy_lints/src/attrs/utils.rs b/clippy_lints/src/attrs/utils.rs
index a5ce213..7b66f91 100644
--- a/clippy_lints/src/attrs/utils.rs
+++ b/clippy_lints/src/attrs/utils.rs
@@ -46,11 +46,13 @@
 }
 
 fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, block: &Block<'_>) -> bool {
-    block.stmts.first().map_or(
-        block
-            .expr
-            .as_ref()
-            .is_some_and(|e| is_relevant_expr(cx, typeck_results, e)),
+    block.stmts.first().map_or_else(
+        || {
+            block
+                .expr
+                .as_ref()
+                .is_some_and(|e| is_relevant_expr(cx, typeck_results, e))
+        },
         |stmt| match &stmt.kind {
             StmtKind::Let(_) => true,
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs
index ae36bb7..8f95e44 100644
--- a/clippy_lints/src/bool_assert_comparison.rs
+++ b/clippy_lints/src/bool_assert_comparison.rs
@@ -56,7 +56,7 @@
         .and_then(|trait_id| {
             cx.tcx.associated_items(trait_id).find_by_ident_and_kind(
                 cx.tcx,
-                Ident::from_str("Output"),
+                Ident::with_dummy_span(sym::Output),
                 ty::AssocTag::Type,
                 trait_id,
             )
diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs
index 7cde007..70c9c45 100644
--- a/clippy_lints/src/borrow_deref_ref.rs
+++ b/clippy_lints/src/borrow_deref_ref.rs
@@ -2,9 +2,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed, is_mutable};
+use clippy_utils::{get_parent_expr, is_expr_temporary_value, is_from_proc_macro, is_lint_allowed, is_mutable};
 use rustc_errors::Applicability;
-use rustc_hir::{BorrowKind, ExprKind, UnOp};
+use rustc_hir::{BorrowKind, Expr, ExprKind, Node, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty;
@@ -48,7 +48,7 @@
 declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
 
 impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) {
         if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, addrof_target) = e.kind
             && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind
             && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..))
@@ -76,6 +76,9 @@
             && let e_ty = cx.typeck_results().expr_ty_adjusted(e)
             // check if the reference is coercing to a mutable reference
             && (!matches!(e_ty.kind(), ty::Ref(_, _, Mutability::Mut)) || is_mutable(cx, deref_target))
+            // If the new borrow might be itself borrowed mutably and the original reference is not a temporary
+            // value, do not propose to use it directly.
+            && (is_expr_temporary_value(cx, deref_target) || !potentially_bound_to_mutable_ref(cx, e))
             && let Some(deref_text) = deref_target.span.get_source_text(cx)
         {
             span_lint_and_then(
@@ -110,3 +113,9 @@
         }
     }
 }
+
+/// Checks if `expr` is used as part of a `let` statement containing a `ref mut` binding.
+fn potentially_bound_to_mutable_ref<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
+    matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::LetStmt(let_stmt)
+             if let_stmt.pat.contains_explicit_ref_binding() == Some(Mutability::Mut))
+}
diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs
index a2ecb5f..2eebe84 100644
--- a/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -3,7 +3,7 @@
 use clippy_utils::source::snippet;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
-use clippy_utils::{expr_or_init, sym};
+use clippy_utils::{expr_or_init, is_in_const_context, sym};
 use rustc_abi::IntegerType;
 use rustc_errors::{Applicability, Diag};
 use rustc_hir::def::{DefKind, Res};
@@ -168,7 +168,9 @@
 
     span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, msg, |diag| {
         diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
-        if !cast_from.is_floating_point() {
+        // TODO: Remove the condition for const contexts when `try_from` and other commonly used methods
+        // become const fn.
+        if !is_in_const_context(cx) && !cast_from.is_floating_point() {
             offer_suggestion(cx, expr, cast_expr, cast_to_span, diag);
         }
     });
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs
index 9a1ad8a..a70bd88 100644
--- a/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/clippy_lints/src/casts/cast_sign_loss.rs
@@ -168,7 +168,7 @@
 
     // Rust's integer pow() functions take an unsigned exponent.
     let exponent_val = get_const_unsigned_int_eval(cx, exponent, None);
-    let exponent_is_even = exponent_val.map(|val| val % 2 == 0);
+    let exponent_is_even = exponent_val.map(|val| val.is_multiple_of(2));
 
     match (base_sign, exponent_is_even) {
         // Non-negative bases always return non-negative results, ignoring overflow.
diff --git a/clippy_lints/src/casts/manual_dangling_ptr.rs b/clippy_lints/src/casts/manual_dangling_ptr.rs
index 61dfc0f..d9e88d6 100644
--- a/clippy_lints/src/casts/manual_dangling_ptr.rs
+++ b/clippy_lints/src/casts/manual_dangling_ptr.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::SpanRangeExt;
-use clippy_utils::{expr_or_init, path_def_id, paths, std_or_core};
+use clippy_utils::{expr_or_init, is_path_diagnostic_item, std_or_core, sym};
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, Ty, TyKind};
@@ -53,8 +53,7 @@
 
 fn is_align_of_call(cx: &LateContext<'_>, fun: &Expr<'_>, to: &Ty<'_>) -> bool {
     if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind
-        && let Some(fun_id) = path_def_id(cx, fun)
-        && paths::ALIGN_OF.matches(cx, fun_id)
+        && is_path_diagnostic_item(cx, fun, sym::mem_align_of)
         && let Some(args) = path.segments.last().and_then(|seg| seg.args)
         && let [GenericArg::Type(generic_ty)] = args.args
     {
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index daae9a8..37accff 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -878,7 +878,7 @@
             confusing_method_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to);
             fn_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to);
             fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to);
-            zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
+            zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir, self.msrv);
 
             if self.msrv.meets(cx, msrvs::MANUAL_DANGLING_PTR) {
                 manual_dangling_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 8e8c55c..010f09d 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -185,7 +185,7 @@
             Node::Expr(parent) if is_borrow_expr(cx, parent) && !is_in_allowed_macro(cx, parent) => {
                 MaybeParenOrBlock::Block
             },
-            Node::Expr(parent) if cast_expr.precedence() < parent.precedence() => MaybeParenOrBlock::Paren,
+            Node::Expr(parent) if cx.precedence(cast_expr) < cx.precedence(parent) => MaybeParenOrBlock::Paren,
             _ => MaybeParenOrBlock::Nothing,
         };
 
diff --git a/clippy_lints/src/casts/zero_ptr.rs b/clippy_lints/src/casts/zero_ptr.rs
index a34af6b..f4738e7 100644
--- a/clippy_lints/src/casts/zero_ptr.rs
+++ b/clippy_lints/src/casts/zero_ptr.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
 use rustc_errors::Applicability;
@@ -7,10 +8,10 @@
 
 use super::ZERO_PTR;
 
-pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) {
+pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>, msrv: Msrv) {
     if let TyKind::Ptr(ref mut_ty) = to.kind
         && is_integer_literal(from, 0)
-        && !is_in_const_context(cx)
+        && (!is_in_const_context(cx) || msrv.meets(cx, msrvs::PTR_NULL))
         && let Some(std_or_core) = std_or_core(cx)
     {
         let (msg, sugg_fn) = match mut_ty.mutbl {
diff --git a/clippy_lints/src/coerce_container_to_any.rs b/clippy_lints/src/coerce_container_to_any.rs
index 3311a35..6217fc4 100644
--- a/clippy_lints/src/coerce_container_to_any.rs
+++ b/clippy_lints/src/coerce_container_to_any.rs
@@ -43,7 +43,7 @@
     /// ```
     #[clippy::version = "1.88.0"]
     pub COERCE_CONTAINER_TO_ANY,
-    suspicious,
+    nursery,
     "coercing to `&dyn Any` when dereferencing could produce a `dyn Any` without coercion is usually not intended"
 }
 declare_lint_pass!(CoerceContainerToAny => [COERCE_CONTAINER_TO_ANY]);
diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs
index 5ef7266..2791869 100644
--- a/clippy_lints/src/copies.rs
+++ b/clippy_lints/src/copies.rs
@@ -11,7 +11,7 @@
 use core::iter;
 use core::ops::ControlFlow;
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind, intravisit};
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Node, Stmt, StmtKind, intravisit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::impl_lint_pass;
@@ -295,7 +295,7 @@
                 sugg,
                 Applicability::Unspecified,
             );
-            if !cx.typeck_results().expr_ty(expr).is_unit() {
+            if is_expr_parent_assignment(cx, expr) || !cx.typeck_results().expr_ty(expr).is_unit() {
                 diag.note("the end suggestion probably needs some adjustments to use the expression result correctly");
             }
         }
@@ -660,3 +660,17 @@
         );
     }
 }
+
+fn is_expr_parent_assignment(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let parent = cx.tcx.parent_hir_node(expr.hir_id);
+    if let Node::LetStmt(LetStmt { init: Some(e), .. })
+    | Node::Expr(Expr {
+        kind: ExprKind::Assign(_, e, _),
+        ..
+    }) = parent
+    {
+        return e.hir_id == expr.hir_id;
+    }
+
+    false
+}
diff --git a/clippy_lints/src/declare_clippy_lint.rs b/clippy_lints/src/declare_clippy_lint.rs
deleted file mode 100644
index 9f82f87..0000000
--- a/clippy_lints/src/declare_clippy_lint.rs
+++ /dev/null
@@ -1,168 +0,0 @@
-#[macro_export]
-#[allow(clippy::crate_in_macro_def)]
-macro_rules! declare_clippy_lint {
-    (@
-        $(#[doc = $lit:literal])*
-        pub $lint_name:ident,
-        $level:ident,
-        $lintcategory:expr,
-        $desc:literal,
-        $version_expr:expr,
-        $version_lit:literal
-        $(, $eval_always: literal)?
-    ) => {
-        rustc_session::declare_tool_lint! {
-            $(#[doc = $lit])*
-            #[clippy::version = $version_lit]
-            pub clippy::$lint_name,
-            $level,
-            $desc,
-            report_in_external_macro:true
-            $(, @eval_always = $eval_always)?
-        }
-
-        pub(crate) static ${concat($lint_name, _INFO)}: &'static crate::LintInfo = &crate::LintInfo {
-            lint: &$lint_name,
-            category:  $lintcategory,
-            explanation: concat!($($lit,"\n",)*),
-            location: concat!(file!(), "#L", line!()),
-            version: $version_expr
-        };
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        restriction,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Allow, crate::LintCategory::Restriction, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        style,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Warn, crate::LintCategory::Style, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        correctness,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Deny, crate::LintCategory::Correctness, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        perf,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Warn, crate::LintCategory::Perf, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        complexity,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Warn, crate::LintCategory::Complexity, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        suspicious,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        nursery,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Allow, crate::LintCategory::Nursery, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        pedantic,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-    (
-        $(#[doc = $lit:literal])*
-        #[clippy::version = $version:literal]
-        pub $lint_name:ident,
-        cargo,
-        $desc:literal
-        $(, @eval_always = $eval_always: literal)?
-    ) => {
-        declare_clippy_lint! {@
-            $(#[doc = $lit])*
-            pub $lint_name, Allow, crate::LintCategory::Cargo, $desc,
-            Some($version), $version
-            $(, $eval_always)?
-        }
-    };
-}
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 1e3907d..c3f8e02 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -2,7 +2,7 @@
 // Use that command to update this file and do not edit by hand.
 // Manual edits will be overwritten.
 
-pub static LINTS: &[&crate::LintInfo] = &[
+pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
     crate::absolute_paths::ABSOLUTE_PATHS_INFO,
     crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
     crate::approx_const::APPROX_CONSTANT_INFO,
@@ -112,6 +112,7 @@
     crate::disallowed_names::DISALLOWED_NAMES_INFO,
     crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
     crate::disallowed_types::DISALLOWED_TYPES_INFO,
+    crate::doc::DOC_BROKEN_LINK_INFO,
     crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS_INFO,
     crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO,
     crate::doc::DOC_LAZY_CONTINUATION_INFO,
@@ -590,6 +591,7 @@
     crate::operators::IMPOSSIBLE_COMPARISONS_INFO,
     crate::operators::INEFFECTIVE_BIT_MASK_INFO,
     crate::operators::INTEGER_DIVISION_INFO,
+    crate::operators::MANUAL_IS_MULTIPLE_OF_INFO,
     crate::operators::MANUAL_MIDPOINT_INFO,
     crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
     crate::operators::MODULO_ARITHMETIC_INFO,
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index cde9528..7463d7b 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -972,7 +972,7 @@
                 "&"
             };
 
-            let expr_str = if !expr_is_macro_call && is_ufcs && expr.precedence() < ExprPrecedence::Prefix {
+            let expr_str = if !expr_is_macro_call && is_ufcs && cx.precedence(expr) < ExprPrecedence::Prefix {
                 Cow::Owned(format!("({expr_str})"))
             } else {
                 expr_str
@@ -1015,10 +1015,10 @@
                         Node::Expr(e) => match e.kind {
                             ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
                             ExprKind::Call(..) => {
-                                expr.precedence() < ExprPrecedence::Unambiguous
+                                cx.precedence(expr) < ExprPrecedence::Unambiguous
                                     || matches!(expr.kind, ExprKind::Field(..))
                             },
-                            _ => expr.precedence() < e.precedence(),
+                            _ => cx.precedence(expr) < cx.precedence(e),
                         },
                         _ => false,
                     };
@@ -1066,7 +1066,7 @@
                         Mutability::Not => "&",
                         Mutability::Mut => "&mut ",
                     };
-                    (prefix, expr.precedence() < ExprPrecedence::Prefix)
+                    (prefix, cx.precedence(expr) < ExprPrecedence::Prefix)
                 },
                 None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
                 _ => ("", false),
@@ -1172,7 +1172,7 @@
                 },
                 Some(parent) if !parent.span.from_expansion() => {
                     // Double reference might be needed at this point.
-                    if parent.precedence() == ExprPrecedence::Unambiguous {
+                    if cx.precedence(parent) == ExprPrecedence::Unambiguous {
                         // Parentheses would be needed here, don't lint.
                         *outer_pat = None;
                     } else {
diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs
index 25b7099..37a1211 100644
--- a/clippy_lints/src/disallowed_macros.rs
+++ b/clippy_lints/src/disallowed_macros.rs
@@ -39,6 +39,9 @@
     ///     # When using an inline table, can add a `reason` for why the macro
     ///     # is disallowed.
     ///     { path = "serde::Serialize", reason = "no serializing" },
+    ///     # This would normally error if the path is incorrect, but with `allow-invalid` = `true`,
+    ///     # it will be silently ignored
+    ///     { path = "std::invalid_macro", reason = "use alternative instead", allow-invalid = true }
     /// ]
     /// ```
     /// ```no_run
diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs
index fb970e1..8c06743 100644
--- a/clippy_lints/src/disallowed_methods.rs
+++ b/clippy_lints/src/disallowed_methods.rs
@@ -34,6 +34,9 @@
     ///     { path = "std::vec::Vec::leak", reason = "no leaking memory" },
     ///     # Can also add a `replacement` that will be offered as a suggestion.
     ///     { path = "std::sync::Mutex::new", reason = "prefer faster & simpler non-poisonable mutex", replacement = "parking_lot::Mutex::new" },
+    ///     # This would normally error if the path is incorrect, but with `allow-invalid` = `true`,
+    ///     # it will be silently ignored
+    ///     { path = "std::fs::InvalidPath", reason = "use alternative instead", allow-invalid = true },
     /// ]
     /// ```
     ///
diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs
index d1a8590..cf964d4 100644
--- a/clippy_lints/src/disallowed_script_idents.rs
+++ b/clippy_lints/src/disallowed_script_idents.rs
@@ -89,6 +89,10 @@
             // Fast path for ascii-only idents.
             if !symbol_str.is_ascii()
                 && let Some(script) = symbol_str.chars().find_map(|c| {
+                    if c.is_ascii() {
+                        return None;
+                    }
+
                     c.script_extension()
                         .iter()
                         .find(|script| !self.whitelist.contains(script))
diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs
index 7875cdd..9a82327 100644
--- a/clippy_lints/src/disallowed_types.rs
+++ b/clippy_lints/src/disallowed_types.rs
@@ -35,6 +35,9 @@
     ///     { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" },
     ///     # Can also add a `replacement` that will be offered as a suggestion.
     ///     { path = "std::sync::Mutex", reason = "prefer faster & simpler non-poisonable mutex", replacement = "parking_lot::Mutex" },
+    ///     # This would normally error if the path is incorrect, but with `allow-invalid` = `true`,
+    ///     # it will be silently ignored
+    ///     { path = "std::invalid::Type", reason = "use alternative instead", allow-invalid = true }
     /// ]
     /// ```
     ///
diff --git a/clippy_lints/src/doc/broken_link.rs b/clippy_lints/src/doc/broken_link.rs
new file mode 100644
index 0000000..a97b807
--- /dev/null
+++ b/clippy_lints/src/doc/broken_link.rs
@@ -0,0 +1,83 @@
+use clippy_utils::diagnostics::span_lint;
+use pulldown_cmark::BrokenLink as PullDownBrokenLink;
+use rustc_lint::LateContext;
+use rustc_resolve::rustdoc::{DocFragment, source_span_for_markdown_range};
+use rustc_span::{BytePos, Pos, Span};
+
+use super::DOC_BROKEN_LINK;
+
+/// Scan and report broken link on documents.
+/// It ignores false positives detected by `pulldown_cmark`, and only
+/// warns users when the broken link is consider a URL.
+// NOTE: We don't check these other cases because
+// rustdoc itself will check and warn about it:
+// - When a link url is broken across multiple lines in the URL path part
+// - When a link tag is missing the close parenthesis character at the end.
+// - When a link has whitespace within the url link.
+pub fn check(cx: &LateContext<'_>, bl: &PullDownBrokenLink<'_>, doc: &str, fragments: &[DocFragment]) {
+    warn_if_broken_link(cx, bl, doc, fragments);
+}
+
+fn warn_if_broken_link(cx: &LateContext<'_>, bl: &PullDownBrokenLink<'_>, doc: &str, fragments: &[DocFragment]) {
+    if let Some(span) = source_span_for_markdown_range(cx.tcx, doc, &bl.span, fragments) {
+        let mut len = 0;
+
+        // grab raw link data
+        let (_, raw_link) = doc.split_at(bl.span.start);
+
+        // strip off link text part
+        let raw_link = match raw_link.split_once(']') {
+            None => return,
+            Some((prefix, suffix)) => {
+                len += prefix.len() + 1;
+                suffix
+            },
+        };
+
+        let raw_link = match raw_link.split_once('(') {
+            None => return,
+            Some((prefix, suffix)) => {
+                if !prefix.is_empty() {
+                    // there is text between ']' and '(' chars, so it is not a valid link
+                    return;
+                }
+                len += prefix.len() + 1;
+                suffix
+            },
+        };
+
+        if raw_link.starts_with("(http") {
+            // reduce chances of false positive reports
+            // by limiting this checking only to http/https links.
+            return;
+        }
+
+        for c in raw_link.chars() {
+            if c == ')' {
+                // it is a valid link
+                return;
+            }
+
+            if c == '\n' {
+                report_broken_link(cx, span, len);
+                break;
+            }
+
+            len += 1;
+        }
+    }
+}
+
+fn report_broken_link(cx: &LateContext<'_>, frag_span: Span, offset: usize) {
+    let start = frag_span.lo();
+    let end = start + BytePos::from_usize(offset);
+
+    let span = Span::new(start, end, frag_span.ctxt(), frag_span.parent());
+
+    span_lint(
+        cx,
+        DOC_BROKEN_LINK,
+        span,
+        "possible broken doc link: broken across multiple lines",
+    );
+}
diff --git a/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/clippy_lints/src/doc/doc_suspicious_footnotes.rs
index 289b6b9..3330cc5 100644
--- a/clippy_lints/src/doc/doc_suspicious_footnotes.rs
+++ b/clippy_lints/src/doc/doc_suspicious_footnotes.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_ast::attr::AttributeExt as _;
 use rustc_ast::token::CommentKind;
 use rustc_errors::Applicability;
 use rustc_hir::{AttrStyle, Attribute};
@@ -43,13 +44,15 @@
                 "looks like a footnote ref, but has no matching footnote",
                 |diag| {
                     if this_fragment.kind == DocFragmentKind::SugaredDoc {
-                        let (doc_attr, (_, doc_attr_comment_kind)) = attrs
+                        let (doc_attr, (_, doc_attr_comment_kind), attr_style) = attrs
                             .iter()
                             .filter(|attr| attr.span().overlaps(this_fragment.span))
                             .rev()
-                            .find_map(|attr| Some((attr, attr.doc_str_and_comment_kind()?)))
+                            .find_map(|attr| {
+                                Some((attr, attr.doc_str_and_comment_kind()?, attr.doc_resolution_scope()?))
+                            })
                             .unwrap();
-                        let (to_add, terminator) = match (doc_attr_comment_kind, doc_attr.style()) {
+                        let (to_add, terminator) = match (doc_attr_comment_kind, attr_style) {
                             (CommentKind::Line, AttrStyle::Outer) => ("\n///\n/// ", ""),
                             (CommentKind::Line, AttrStyle::Inner) => ("\n//!\n//! ", ""),
                             (CommentKind::Block, AttrStyle::Outer) => ("\n/** ", " */"),
diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs
index 9ee32fc..3033ac0 100644
--- a/clippy_lints/src/doc/missing_headers.rs
+++ b/clippy_lints/src/doc/missing_headers.rs
@@ -3,7 +3,7 @@
 use clippy_utils::macros::{is_panic, root_macro_call_first_node};
 use clippy_utils::ty::{get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item};
 use clippy_utils::visitors::for_each_expr;
-use clippy_utils::{fulfill_or_allowed, is_doc_hidden, method_chain_args, return_ty};
+use clippy_utils::{fulfill_or_allowed, is_doc_hidden, is_inside_always_const_context, method_chain_args, return_ty};
 use rustc_hir::{BodyId, FnSig, OwnerId, Safety};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -99,13 +99,16 @@
     let mut panic_span = None;
     let typeck = cx.tcx.typeck_body(body_id);
     for_each_expr(cx, cx.tcx.hir_body(body_id), |expr| {
+        if is_inside_always_const_context(cx.tcx, expr.hir_id) {
+            return ControlFlow::<!>::Continue(());
+        }
+
         if let Some(macro_call) = root_macro_call_first_node(cx, expr)
             && (is_panic(cx, macro_call.def_id)
                 || matches!(
                     cx.tcx.get_diagnostic_name(macro_call.def_id),
                     Some(sym::assert_macro | sym::assert_eq_macro | sym::assert_ne_macro)
                 ))
-            && !cx.tcx.hir_is_inside_const_context(expr.hir_id)
             && !fulfill_or_allowed(cx, MISSING_PANICS_DOC, [expr.hir_id])
             && panic_span.is_none()
         {
diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs
index e0fc2fd..1b6c48e 100644
--- a/clippy_lints/src/doc/mod.rs
+++ b/clippy_lints/src/doc/mod.rs
@@ -24,6 +24,7 @@
 use std::ops::Range;
 use url::Url;
 
+mod broken_link;
 mod doc_comment_double_space_linebreaks;
 mod doc_suspicious_footnotes;
 mod include_in_doc_without_cfg;
@@ -294,6 +295,34 @@
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks the doc comments have unbroken links, mostly caused
+    /// by bad formatted links such as broken across multiple lines.
+    ///
+    /// ### Why is this bad?
+    /// Because documentation generated by rustdoc will be broken
+    /// since expected links won't be links and just text.
+    ///
+    /// ### Examples
+    /// This link is broken:
+    /// ```no_run
+    /// /// [example of a bad link](https://
+    /// /// github.com/rust-lang/rust-clippy/)
+    /// pub fn do_something() {}
+    /// ```
+    ///
+    /// It shouldn't be broken across multiple lines to work:
+    /// ```no_run
+    /// /// [example of a good link](https://github.com/rust-lang/rust-clippy/)
+    /// pub fn do_something() {}
+    /// ```
+    #[clippy::version = "1.84.0"]
+    pub DOC_BROKEN_LINK,
+    pedantic,
+    "broken document link"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for the doc comments of publicly visible
     /// safe functions and traits and warns if there is a `# Safety` section.
     ///
@@ -656,6 +685,7 @@
 impl_lint_pass!(Documentation => [
     DOC_LINK_CODE,
     DOC_LINK_WITH_QUOTES,
+    DOC_BROKEN_LINK,
     DOC_MARKDOWN,
     DOC_NESTED_REFDEFS,
     MISSING_SAFETY_DOC,
@@ -786,9 +816,9 @@
 /// back in the various late lint pass methods if they need the final doc headers, like "Safety" or
 /// "Panics" sections.
 fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[Attribute]) -> Option<DocHeaders> {
-    /// We don't want the parser to choke on intra doc links. Since we don't
-    /// actually care about rendering them, just pretend that all broken links
-    /// point to a fake address.
+    // We don't want the parser to choke on intra doc links. Since we don't
+    // actually care about rendering them, just pretend that all broken links
+    // point to a fake address.
     #[expect(clippy::unnecessary_wraps)] // we're following a type signature
     fn fake_broken_link_callback<'a>(_: BrokenLink<'_>) -> Option<(CowStr<'a>, CowStr<'a>)> {
         Some(("fake".into(), "fake".into()))
@@ -828,14 +858,12 @@
         return Some(DocHeaders::default());
     }
 
-    let mut cb = fake_broken_link_callback;
-
     check_for_code_clusters(
         cx,
         pulldown_cmark::Parser::new_with_broken_link_callback(
             &doc,
             main_body_opts() - Options::ENABLE_SMART_PUNCTUATION,
-            Some(&mut cb),
+            Some(&mut fake_broken_link_callback),
         )
         .into_offset_iter(),
         &doc,
@@ -845,9 +873,17 @@
         },
     );
 
+    // NOTE: check_doc uses it own cb function,
+    // to avoid causing duplicated diagnostics for the broken link checker.
+    let mut full_fake_broken_link_callback = |bl: BrokenLink<'_>| -> Option<(CowStr<'_>, CowStr<'_>)> {
+        broken_link::check(cx, &bl, &doc, &fragments);
+        Some(("fake".into(), "fake".into()))
+    };
+
     // disable smart punctuation to pick up ['link'] more easily
     let opts = main_body_opts() - Options::ENABLE_SMART_PUNCTUATION;
-    let parser = pulldown_cmark::Parser::new_with_broken_link_callback(&doc, opts, Some(&mut cb));
+    let parser =
+        pulldown_cmark::Parser::new_with_broken_link_callback(&doc, opts, Some(&mut full_fake_broken_link_callback));
 
     Some(check_doc(
         cx,
diff --git a/clippy_lints/src/doc/needless_doctest_main.rs b/clippy_lints/src/doc/needless_doctest_main.rs
index 587ea63..74283d7 100644
--- a/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/clippy_lints/src/doc/needless_doctest_main.rs
@@ -42,9 +42,8 @@
                 let mut test_attr_spans = vec![];
                 let filename = FileName::anon_source_code(&code);
 
-                let fallback_bundle =
-                    rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
-                let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
+                let translator = rustc_driver::default_translator();
+                let emitter = HumanEmitter::new(Box::new(io::sink()), translator);
                 let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
                 #[expect(clippy::arc_with_non_send_sync)] // `Arc` is expected by with_dcx
                 let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
@@ -72,6 +71,7 @@
                                 if !ignore {
                                     get_test_spans(&item, *ident, &mut test_attr_spans);
                                 }
+
                                 let is_async = matches!(sig.header.coroutine_kind, Some(CoroutineKind::Async { .. }));
                                 let returns_nothing = match &sig.decl.output {
                                     FnRetTy::Default(..) => true,
@@ -90,9 +90,14 @@
                             // Another function was found; this case is ignored for needless_doctest_main
                             ItemKind::Fn(fn_) => {
                                 eligible = false;
-                                if !ignore {
-                                    get_test_spans(&item, fn_.ident, &mut test_attr_spans);
+                                if ignore {
+                                    // If ignore is active invalidating one lint,
+                                    // and we already found another function thus
+                                    // invalidating the other one, we have no
+                                    // business continuing.
+                                    return (false, test_attr_spans);
                                 }
+                                get_test_spans(&item, fn_.ident, &mut test_attr_spans);
                             },
                             // Tests with one of these items are ignored
                             ItemKind::Static(..)
@@ -123,6 +128,18 @@
 
     let trailing_whitespace = text.len() - text.trim_end().len();
 
+    // We currently only test for "fn main". Checking for the real
+    // entrypoint (with tcx.entry_fn(())) in each block would be unnecessarily
+    // expensive, as those are probably intended and relevant. Same goes for
+    // macros and other weird ways of declaring a main function.
+    //
+    // Also, as we only check for attribute names and don't do macro expansion,
+    // we can check only for #[test]
+
+    if !((text.contains("main") && text.contains("fn")) || text.contains("#[test]")) {
+        return;
+    }
+
     // Because of the global session, we need to create a new session in a different thread with
     // the edition we need.
     let text = text.to_owned();
diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs
index 0c5f8bb..3bd7485 100644
--- a/clippy_lints/src/empty_line_after.rs
+++ b/clippy_lints/src/empty_line_after.rs
@@ -10,7 +10,7 @@
 use rustc_lexer::TokenKind;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::impl_lint_pass;
-use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw};
+use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw, sym};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -129,10 +129,55 @@
     kind: StopKind,
     first: usize,
     last: usize,
+    name: Option<Symbol>,
 }
 
 impl Stop {
-    fn convert_to_inner(&self) -> (Span, String) {
+    fn is_outer_attr_only(&self) -> bool {
+        let Some(name) = self.name else {
+            return false;
+        };
+        // Check if the attribute only has effect when as an outer attribute
+        // The below attributes are collected from the builtin attributes of The Rust Reference
+        // https://doc.rust-lang.org/reference/attributes.html#r-attributes.builtin
+        // And the comments below are from compiler errors and warnings
+        matches!(
+            name,
+            // Cannot be used at crate level
+            sym::repr | sym::test | sym::derive | sym::automatically_derived | sym::path | sym::global_allocator |
+            // Only has an effect on macro definitions
+            sym::macro_export |
+            // Only be applied to trait definitions
+            sym::on_unimplemented |
+            // Only be placed on trait implementations
+            sym::do_not_recommend |
+            // Only has an effect on items
+            sym::ignore | sym::should_panic | sym::proc_macro | sym::proc_macro_derive | sym::proc_macro_attribute |
+            // Has no effect when applied to a module
+            sym::must_use |
+            // Should be applied to a foreign function or static
+            sym::link_name | sym::link_ordinal | sym::link_section |
+            // Should be applied to an `extern crate` item
+            sym::no_link |
+            // Should be applied to a free function, impl method or static
+            sym::export_name | sym::no_mangle |
+            // Should be applied to a `static` variable
+            sym::used |
+            // Should be applied to function or closure
+            sym::inline |
+            // Should be applied to a function definition
+            sym::cold | sym::target_feature | sym::track_caller | sym::instruction_set |
+            // Should be applied to a struct or enum
+            sym::non_exhaustive |
+            // Note: No any warning when it as an inner attribute, but it has no effect
+            sym::panic_handler
+        )
+    }
+
+    fn convert_to_inner(&self) -> Option<(Span, String)> {
+        if self.is_outer_attr_only() {
+            return None;
+        }
         let inner = match self.kind {
             // #![...]
             StopKind::Attr => InnerSpan::new(1, 1),
@@ -140,7 +185,7 @@
             //   ^      ^
             StopKind::Doc(_) => InnerSpan::new(2, 3),
         };
-        (self.span.from_inner(inner), "!".into())
+        Some((self.span.from_inner(inner), "!".into()))
     }
 
     fn comment_out(&self, cx: &EarlyContext<'_>, suggestions: &mut Vec<(Span, String)>) {
@@ -177,6 +222,7 @@
             },
             first: file.lookup_line(file.relative_position(lo))?,
             last: file.lookup_line(file.relative_position(hi))?,
+            name: attr.name(),
         })
     }
 }
@@ -356,6 +402,12 @@
         if let Some(parent) = self.items.iter().rev().nth(1)
             && (parent.kind == "module" || parent.kind == "crate")
             && parent.mod_items == Some(id)
+            && let suggestions = gaps
+                .iter()
+                .flat_map(|gap| gap.prev_chunk)
+                .filter_map(Stop::convert_to_inner)
+                .collect::<Vec<_>>()
+            && !suggestions.is_empty()
         {
             let desc = if parent.kind == "module" {
                 "parent module"
@@ -367,10 +419,7 @@
                     StopKind::Attr => format!("if the attribute should apply to the {desc} use an inner attribute"),
                     StopKind::Doc(_) => format!("if the comment should document the {desc} use an inner doc comment"),
                 },
-                gaps.iter()
-                    .flat_map(|gap| gap.prev_chunk)
-                    .map(Stop::convert_to_inner)
-                    .collect(),
+                suggestions,
                 Applicability::MaybeIncorrect,
             );
         }
@@ -425,6 +474,7 @@
                 first: line.line,
                 // last doesn't need to be accurate here, we don't compare it with anything
                 last: line.line,
+                name: None,
             });
         }
 
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 6ed7c87..0288747 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
 use clippy_utils::ty::get_type_diagnostic_name;
@@ -7,6 +7,7 @@
     get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id,
 };
 use rustc_abi::ExternAbi;
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_errors::Applicability;
 use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -108,14 +109,20 @@
         {
             let vec_crate = if is_no_std_crate(cx) { "alloc" } else { "std" };
             // replace `|| vec![]` with `Vec::new`
-            span_lint_and_sugg(
+            span_lint_hir_and_then(
                 cx,
                 REDUNDANT_CLOSURE,
+                expr.hir_id,
                 expr.span,
                 "redundant closure",
-                "replace the closure with `Vec::new`",
-                format!("{vec_crate}::vec::Vec::new"),
-                Applicability::MachineApplicable,
+                |diag| {
+                    diag.span_suggestion(
+                        expr.span,
+                        "replace the closure with `Vec::new`",
+                        format!("{vec_crate}::vec::Vec::new"),
+                        Applicability::MachineApplicable,
+                    );
+                },
             );
         }
         // skip `foo(|| macro!())`
@@ -155,7 +162,7 @@
             let sig = match callee_ty_adjusted.kind() {
                 ty::FnDef(def, _) => {
                     // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location`
-                    if cx.tcx.has_attr(*def, sym::track_caller) {
+                    if find_attr!(cx.tcx.get_all_attrs(*def), AttributeKind::TrackCaller(..)) {
                         return;
                     }
 
@@ -197,46 +204,53 @@
                 // For now ignore all callee types which reference a type parameter.
                 && !generic_args.types().any(|t| matches!(t.kind(), ty::Param(_)))
             {
-                span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
-                    if let Some(mut snippet) = snippet_opt(cx, callee.span) {
-                        if path_to_local(callee).is_some_and(|l| {
-                            // FIXME: Do we really need this `local_used_in` check?
-                            // Isn't it checking something like... `callee(callee)`?
-                            // If somehow this check is needed, add some test for it,
-                            // 'cuz currently nothing changes after deleting this check.
-                            local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
-                        }) {
-                            match cx
-                                .tcx
-                                .infer_ctxt()
-                                .build(cx.typing_mode())
-                                .err_ctxt()
-                                .type_implements_fn_trait(
-                                    cx.param_env,
-                                    Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
-                                    ty::PredicatePolarity::Positive,
-                                ) {
-                                // Mutable closure is used after current expr; we cannot consume it.
-                                Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
-                                Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
-                                    snippet = format!("&{snippet}");
-                                },
-                                _ => (),
+                span_lint_hir_and_then(
+                    cx,
+                    REDUNDANT_CLOSURE,
+                    expr.hir_id,
+                    expr.span,
+                    "redundant closure",
+                    |diag| {
+                        if let Some(mut snippet) = snippet_opt(cx, callee.span) {
+                            if path_to_local(callee).is_some_and(|l| {
+                                // FIXME: Do we really need this `local_used_in` check?
+                                // Isn't it checking something like... `callee(callee)`?
+                                // If somehow this check is needed, add some test for it,
+                                // 'cuz currently nothing changes after deleting this check.
+                                local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
+                            }) {
+                                match cx
+                                    .tcx
+                                    .infer_ctxt()
+                                    .build(cx.typing_mode())
+                                    .err_ctxt()
+                                    .type_implements_fn_trait(
+                                        cx.param_env,
+                                        Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
+                                        ty::PredicatePolarity::Positive,
+                                    ) {
+                                    // Mutable closure is used after current expr; we cannot consume it.
+                                    Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
+                                    Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
+                                        snippet = format!("&{snippet}");
+                                    },
+                                    _ => (),
+                                }
                             }
+                            diag.span_suggestion(
+                                expr.span,
+                                "replace the closure with the function itself",
+                                snippet,
+                                Applicability::MachineApplicable,
+                            );
                         }
-                        diag.span_suggestion(
-                            expr.span,
-                            "replace the closure with the function itself",
-                            snippet,
-                            Applicability::MachineApplicable,
-                        );
-                    }
-                });
+                    },
+                );
             }
         },
         ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => {
             if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id)
-                && !cx.tcx.has_attr(method_def_id, sym::track_caller)
+                && !find_attr!(cx.tcx.get_all_attrs(method_def_id), AttributeKind::TrackCaller(..))
                 && check_sig(closure_sig, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder())
             {
                 let mut app = Applicability::MachineApplicable;
@@ -244,9 +258,10 @@
                     Some(span) => format!("::{}", snippet_with_applicability(cx, span, "<..>", &mut app)),
                     None => String::new(),
                 };
-                span_lint_and_then(
+                span_lint_hir_and_then(
                     cx,
                     REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
+                    expr.hir_id,
                     expr.span,
                     "redundant closure",
                     |diag| {
diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs
index 1fb0e4d..86d9038 100644
--- a/clippy_lints/src/exhaustive_items.rs
+++ b/clippy_lints/src/exhaustive_items.rs
@@ -76,7 +76,7 @@
                 "exported enums should not be exhaustive",
                 [].as_slice(),
             ),
-            ItemKind::Struct(_, _, v) => (
+            ItemKind::Struct(_, _, v) if v.fields().iter().all(|f| f.default.is_none()) => (
                 EXHAUSTIVE_STRUCTS,
                 "exported structs should not be exhaustive",
                 v.fields(),
diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs
index 3c7e83b..b3c9e86 100644
--- a/clippy_lints/src/floating_point_arithmetic.rs
+++ b/clippy_lints/src/floating_point_arithmetic.rs
@@ -5,14 +5,13 @@
     eq_expr_value, get_parent_expr, higher, is_in_const_context, is_inherent_method_call, is_no_std_crate,
     numeric_literal, peel_blocks, sugg, sym,
 };
+use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::source_map::Spanned;
-
-use rustc_ast::ast;
 use std::f32::consts as f32_consts;
 use std::f64::consts as f64_consts;
 use sugg::Sugg;
diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs
index 7065583..d959981 100644
--- a/clippy_lints/src/functions/must_use.rs
+++ b/clippy_lints/src/functions/must_use.rs
@@ -14,6 +14,8 @@
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
+use rustc_attr_data_structures::{AttributeKind, find_attr};
+use rustc_span::Symbol;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 
 use core::ops::ControlFlow;
@@ -22,7 +24,7 @@
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     let attrs = cx.tcx.hir_attrs(item.hir_id());
-    let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
+    let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason));
     if let hir::ItemKind::Fn {
         ref sig,
         body: ref body_id,
@@ -31,9 +33,19 @@
     {
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-        if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
-        } else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
+        if let Some((attr_span, reason)) = attr {
+            check_needless_must_use(
+                cx,
+                sig.decl,
+                item.owner_id,
+                item.span,
+                fn_header_span,
+                *attr_span,
+                *reason,
+                attrs,
+                sig,
+            );
+        } else if is_public && !is_proc_macro(attrs) && !find_attr!(attrs, AttributeKind::NoMangle(..)) {
             check_must_use_candidate(
                 cx,
                 sig.decl,
@@ -52,9 +64,20 @@
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         let attrs = cx.tcx.hir_attrs(item.hir_id());
-        let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
-        if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
+        let attr =
+            find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason));
+        if let Some((attr_span, reason)) = attr {
+            check_needless_must_use(
+                cx,
+                sig.decl,
+                item.owner_id,
+                item.span,
+                fn_header_span,
+                *attr_span,
+                *reason,
+                attrs,
+                sig,
+            );
         } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id).is_none() {
             check_must_use_candidate(
                 cx,
@@ -75,9 +98,20 @@
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
 
         let attrs = cx.tcx.hir_attrs(item.hir_id());
-        let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
-        if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
+        let attr =
+            find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason));
+        if let Some((attr_span, reason)) = attr {
+            check_needless_must_use(
+                cx,
+                sig.decl,
+                item.owner_id,
+                item.span,
+                fn_header_span,
+                *attr_span,
+                *reason,
+                attrs,
+                sig,
+            );
         } else if let hir::TraitFn::Provided(eid) = *eid {
             let body = cx.tcx.hir_body(eid);
             if attr.is_none() && is_public && !is_proc_macro(attrs) {
@@ -103,7 +137,8 @@
     item_id: hir::OwnerId,
     item_span: Span,
     fn_header_span: Span,
-    attr: &Attribute,
+    attr_span: Span,
+    reason: Option<Symbol>,
     attrs: &[Attribute],
     sig: &FnSig<'_>,
 ) {
@@ -118,12 +153,7 @@
                 fn_header_span,
                 "this unit-returning function has a `#[must_use]` attribute",
                 |diag| {
-                    diag.span_suggestion(
-                        attr.span(),
-                        "remove the attribute",
-                        "",
-                        Applicability::MachineApplicable,
-                    );
+                    diag.span_suggestion(attr_span, "remove the attribute", "", Applicability::MachineApplicable);
                 },
             );
         } else {
@@ -137,11 +167,11 @@
                 MUST_USE_UNIT,
                 fn_header_span,
                 "this unit-returning function has a `#[must_use]` attribute",
-                Some(attr.span()),
+                Some(attr_span),
                 "remove `must_use`",
             );
         }
-    } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+    } else if reason.is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
         // Ignore async functions unless Future::Output type is a must_use type
         if sig.header.is_async() {
             let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs
index 45f9aa0..ab7a965 100644
--- a/clippy_lints/src/if_not_else.rs
+++ b/clippy_lints/src/if_not_else.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant};
+use clippy_utils::consts::is_zero_integer_const;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use clippy_utils::is_else_clause;
 use clippy_utils::source::{HasSession, indent_of, reindent_multiline, snippet};
@@ -48,13 +48,6 @@
 
 declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
 
-fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
-    if let Some(value) = ConstEvalCtxt::new(cx).eval_simple(expr) {
-        return Constant::Int(0) == value;
-    }
-    false
-}
-
 impl LateLintPass<'_> for IfNotElse {
     fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
         if let ExprKind::If(cond, cond_inner, Some(els)) = e.kind
@@ -68,7 +61,7 @@
                 ),
                 // Don't lint on `… != 0`, as these are likely to be bit tests.
                 // For example, `if foo & 0x0F00 != 0 { … } else { … }` is already in the "proper" order.
-                ExprKind::Binary(op, _, rhs) if op.node == BinOpKind::Ne && !is_zero_const(rhs, cx) => (
+                ExprKind::Binary(op, _, rhs) if op.node == BinOpKind::Ne && !is_zero_integer_const(cx, rhs) => (
                     "unnecessary `!=` operation",
                     "change to `==` and swap the blocks of the `if`/`else`",
                 ),
diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs
index da5ca5e..ffe6ad1 100644
--- a/clippy_lints/src/inline_fn_without_body.rs
+++ b/clippy_lints/src/inline_fn_without_body.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sugg::DiagExt;
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_errors::Applicability;
 use rustc_hir::{TraitFn, TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -32,15 +32,19 @@
 impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
         if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
-            && let Some(attr) = cx.tcx.hir_attrs(item.hir_id()).iter().find(|a| a.has_name(sym::inline))
+            && let Some(attr_span) = find_attr!(cx
+                    .tcx
+                    .hir_attrs(item.hir_id()),
+                    AttributeKind::Inline(_, span) => *span
+            )
         {
             span_lint_and_then(
                 cx,
                 INLINE_FN_WITHOUT_BODY,
-                attr.span(),
+                attr_span,
                 format!("use of `#[inline]` on trait method `{}` which has no body", item.ident),
                 |diag| {
-                    diag.suggest_remove_item(cx, attr.span(), "remove", Applicability::MachineApplicable);
+                    diag.suggest_remove_item(cx, attr_span, "remove", Applicability::MachineApplicable);
                 },
             );
         }
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index be9142b..96a6dee 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -59,10 +59,10 @@
 extern crate thin_vec;
 
 #[macro_use]
-mod declare_clippy_lint;
+extern crate clippy_utils;
 
 #[macro_use]
-extern crate clippy_utils;
+extern crate declare_clippy_lint;
 
 mod utils;
 
@@ -411,108 +411,9 @@
 use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation};
 use clippy_utils::macros::FormatArgsStorage;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_lint::{Lint, LintId};
+use rustc_lint::Lint;
 use utils::attr_collector::{AttrCollector, AttrStorage};
 
-#[derive(Default)]
-struct RegistrationGroups {
-    all: Vec<LintId>,
-    cargo: Vec<LintId>,
-    complexity: Vec<LintId>,
-    correctness: Vec<LintId>,
-    nursery: Vec<LintId>,
-    pedantic: Vec<LintId>,
-    perf: Vec<LintId>,
-    restriction: Vec<LintId>,
-    style: Vec<LintId>,
-    suspicious: Vec<LintId>,
-}
-
-impl RegistrationGroups {
-    #[rustfmt::skip]
-    fn register(self, store: &mut rustc_lint::LintStore) {
-        store.register_group(true, "clippy::all", Some("clippy_all"), self.all);
-        store.register_group(true, "clippy::cargo", Some("clippy_cargo"), self.cargo);
-        store.register_group(true, "clippy::complexity", Some("clippy_complexity"), self.complexity);
-        store.register_group(true, "clippy::correctness", Some("clippy_correctness"), self.correctness);
-        store.register_group(true, "clippy::nursery", Some("clippy_nursery"), self.nursery);
-        store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), self.pedantic);
-        store.register_group(true, "clippy::perf", Some("clippy_perf"), self.perf);
-        store.register_group(true, "clippy::restriction", Some("clippy_restriction"), self.restriction);
-        store.register_group(true, "clippy::style", Some("clippy_style"), self.style);
-        store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), self.suspicious);
-    }
-}
-
-#[derive(Copy, Clone, Debug)]
-pub(crate) enum LintCategory {
-    Cargo,
-    Complexity,
-    Correctness,
-    Nursery,
-    Pedantic,
-    Perf,
-    Restriction,
-    Style,
-    Suspicious,
-}
-
-#[allow(clippy::enum_glob_use)]
-use LintCategory::*;
-
-impl LintCategory {
-    fn is_all(self) -> bool {
-        matches!(self, Correctness | Suspicious | Style | Complexity | Perf)
-    }
-
-    fn group(self, groups: &mut RegistrationGroups) -> &mut Vec<LintId> {
-        match self {
-            Cargo => &mut groups.cargo,
-            Complexity => &mut groups.complexity,
-            Correctness => &mut groups.correctness,
-            Nursery => &mut groups.nursery,
-            Pedantic => &mut groups.pedantic,
-            Perf => &mut groups.perf,
-            Restriction => &mut groups.restriction,
-            Style => &mut groups.style,
-            Suspicious => &mut groups.suspicious,
-        }
-    }
-}
-
-pub struct LintInfo {
-    /// Double reference to maintain pointer equality
-    pub lint: &'static &'static Lint,
-    category: LintCategory,
-    pub explanation: &'static str,
-    /// e.g. `clippy_lints/src/absolute_paths.rs#43`
-    pub location: &'static str,
-    pub version: Option<&'static str>,
-}
-
-impl LintInfo {
-    /// Returns the lint name in lowercase without the `clippy::` prefix
-    #[allow(clippy::missing_panics_doc)]
-    pub fn name_lower(&self) -> String {
-        self.lint.name.strip_prefix("clippy::").unwrap().to_ascii_lowercase()
-    }
-
-    /// Returns the name of the lint's category in lowercase (`style`, `pedantic`)
-    pub fn category_str(&self) -> &'static str {
-        match self.category {
-            Cargo => "cargo",
-            Complexity => "complexity",
-            Correctness => "correctness",
-            Nursery => "nursery",
-            Pedantic => "pedantic",
-            Perf => "perf",
-            Restriction => "restriction",
-            Style => "style",
-            Suspicious => "suspicious",
-        }
-    }
-}
-
 pub fn explain(name: &str) -> i32 {
     let target = format!("clippy::{}", name.to_ascii_uppercase());
 
@@ -535,30 +436,11 @@
     }
 }
 
-fn register_categories(store: &mut rustc_lint::LintStore) {
-    let mut groups = RegistrationGroups::default();
-
-    for LintInfo { lint, category, .. } in declared_lints::LINTS {
-        if category.is_all() {
-            groups.all.push(LintId::of(lint));
-        }
-
-        category.group(&mut groups).push(LintId::of(lint));
-    }
-
-    let lints: Vec<&'static Lint> = declared_lints::LINTS.iter().map(|info| *info.lint).collect();
-
-    store.register_lints(&lints);
-    groups.register(store);
-}
-
 /// Register all lints and lint groups with the rustc lint store
 ///
 /// Used in `./src/driver.rs`.
 #[expect(clippy::too_many_lines)]
-pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
-    register_categories(store);
-
+pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     for (old_name, new_name) in deprecated_lints::RENAMED {
         store.register_renamed(old_name, new_name);
     }
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs
index 12719c4..d66771a 100644
--- a/clippy_lints/src/loops/single_element_loop.rs
+++ b/clippy_lints/src/loops/single_element_loop.rs
@@ -84,7 +84,7 @@
         if !prefix.is_empty()
             && (
                 // Precedence of internal expression is less than or equal to precedence of `&expr`.
-                arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
+                cx.precedence(arg_expression) <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
             )
         {
             arg_snip = format!("({arg_snip})").into();
diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs
index 0b3bec7..9ff82cd 100644
--- a/clippy_lints/src/manual_let_else.rs
+++ b/clippy_lints/src/manual_let_else.rs
@@ -13,7 +13,6 @@
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::{Arm, Expr, ExprKind, HirId, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LintContext};
-
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
 use std::slice;
diff --git a/clippy_lints/src/manual_option_as_slice.rs b/clippy_lints/src/manual_option_as_slice.rs
index b55c11f..922db17 100644
--- a/clippy_lints/src/manual_option_as_slice.rs
+++ b/clippy_lints/src/manual_option_as_slice.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
 use clippy_utils::msrvs::Msrv;
-use clippy_utils::{is_none_arm, msrvs, paths, peel_hir_expr_refs, sym};
+use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs, sym};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, Expr, ExprKind, LangItem, Pat, PatKind, QPath, is_range_literal};
@@ -220,5 +220,5 @@
 }
 
 fn is_slice_from_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    paths::SLICE_FROM_REF.matches_path(cx, expr)
+    clippy_utils::is_path_diagnostic_item(cx, expr, sym::slice_from_ref)
 }
diff --git a/clippy_lints/src/matches/manual_ok_err.rs b/clippy_lints/src/matches/manual_ok_err.rs
index 4959908..edbb556 100644
--- a/clippy_lints/src/matches/manual_ok_err.rs
+++ b/clippy_lints/src/matches/manual_ok_err.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, reindent_multiline};
 use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::option_arg_ty;
+use clippy_utils::ty::{option_arg_ty, peel_mid_ty_refs_is_mutable};
 use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res, peel_blocks, span_contains_comment};
-use rustc_ast::BindingMode;
+use rustc_ast::{BindingMode, Mutability};
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr};
 use rustc_hir::def::{DefKind, Res};
@@ -133,7 +133,21 @@
         Applicability::MachineApplicable
     };
     let scrut = Sugg::hir_with_applicability(cx, scrutinee, "..", &mut app).maybe_paren();
-    let sugg = format!("{scrut}.{method}()");
+
+    let scrutinee_ty = cx.typeck_results().expr_ty(scrutinee);
+    let (_, n_ref, mutability) = peel_mid_ty_refs_is_mutable(scrutinee_ty);
+    let prefix = if n_ref > 0 {
+        if mutability == Mutability::Mut {
+            ".as_mut()"
+        } else {
+            ".as_ref()"
+        }
+    } else {
+        ""
+    };
+
+    let sugg = format!("{scrut}{prefix}.{method}()");
+
     // If the expression being expanded is the `if …` part of an `else if …`, it must be blockified.
     let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
         && let ExprKind::If(_, _, Some(else_part)) = parent_expr.kind
diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs
index d090573..dbae71b 100644
--- a/clippy_lints/src/matches/manual_utils.rs
+++ b/clippy_lints/src/matches/manual_utils.rs
@@ -117,7 +117,7 @@
     // it's being passed by value.
     let scrutinee = peel_hir_expr_refs(scrutinee).0;
     let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
-    let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous {
+    let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && cx.precedence(scrutinee) < ExprPrecedence::Unambiguous {
         format!("({scrutinee_str})")
     } else {
         scrutinee_str.into()
diff --git a/clippy_lints/src/matches/match_wild_enum.rs b/clippy_lints/src/matches/match_wild_enum.rs
index 24b4a67..70a03ff 100644
--- a/clippy_lints/src/matches/match_wild_enum.rs
+++ b/clippy_lints/src/matches/match_wild_enum.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
 use rustc_errors::Applicability;
@@ -116,11 +117,12 @@
     let format_suggestion = |variant: &VariantDef| {
         format!(
             "{}{}{}{}",
-            if let Some(ident) = wildcard_ident {
-                format!("{} @ ", ident.name)
-            } else {
-                String::new()
-            },
+            wildcard_ident.map_or(String::new(), |ident| {
+                ident
+                    .span
+                    .get_source_text(cx)
+                    .map_or_else(|| format!("{} @ ", ident.name), |s| format!("{s} @ "))
+            }),
             if let CommonPrefixSearcher::Path(path_prefix) = path_prefix {
                 let mut s = String::new();
                 for seg in path_prefix {
@@ -138,7 +140,7 @@
                 Some(CtorKind::Fn) if variant.fields.len() == 1 => "(_)",
                 Some(CtorKind::Fn) => "(..)",
                 Some(CtorKind::Const) => "",
-                None => "{ .. }",
+                None => " { .. }",
             }
         )
     };
diff --git a/clippy_lints/src/methods/io_other_error.rs b/clippy_lints/src/methods/io_other_error.rs
index ec4b9c7..9276261 100644
--- a/clippy_lints/src/methods/io_other_error.rs
+++ b/clippy_lints/src/methods/io_other_error.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::{expr_or_init, paths};
+use clippy_utils::{expr_or_init, is_path_diagnostic_item, sym};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
@@ -10,8 +10,11 @@
         && !expr.span.from_expansion()
         && !error_kind.span.from_expansion()
         && let ExprKind::Path(QPath::TypeRelative(_, new_segment)) = path.kind
-        && paths::IO_ERROR_NEW.matches_path(cx, path)
-        && paths::IO_ERRORKIND_OTHER_CTOR.matches_path(cx, expr_or_init(cx, error_kind))
+        && is_path_diagnostic_item(cx, path, sym::io_error_new)
+        && let ExprKind::Path(QPath::Resolved(_, init_path)) = &expr_or_init(cx, error_kind).kind
+        && let [.., error_kind_ty, error_kind_variant] = init_path.segments
+        && cx.tcx.is_diagnostic_item(sym::io_errorkind, error_kind_ty.res.def_id())
+        && error_kind_variant.ident.name == sym::Other
         && msrv.meets(cx, msrvs::IO_ERROR_OTHER)
     {
         span_lint_and_then(
diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs
index 7bdd999..2139466 100644
--- a/clippy_lints/src/methods/or_fun_call.rs
+++ b/clippy_lints/src/methods/or_fun_call.rs
@@ -136,7 +136,7 @@
         fun_span: Option<Span>,
     ) -> bool {
         // (path, fn_has_argument, methods, suffix)
-        const KNOW_TYPES: [(Symbol, bool, &[Symbol], &str); 4] = [
+        const KNOW_TYPES: [(Symbol, bool, &[Symbol], &str); 5] = [
             (sym::BTreeEntry, false, &[sym::or_insert], "with"),
             (sym::HashMapEntry, false, &[sym::or_insert], "with"),
             (
@@ -145,16 +145,17 @@
                 &[sym::map_or, sym::ok_or, sym::or, sym::unwrap_or],
                 "else",
             ),
-            (sym::Result, true, &[sym::or, sym::unwrap_or], "else"),
+            (sym::Option, false, &[sym::get_or_insert], "with"),
+            (sym::Result, true, &[sym::map_or, sym::or, sym::unwrap_or], "else"),
         ];
 
         if KNOW_TYPES.iter().any(|k| k.2.contains(&name))
             && switch_to_lazy_eval(cx, arg)
             && !contains_return(arg)
             && let self_ty = cx.typeck_results().expr_ty(self_expr)
-            && let Some(&(_, fn_has_arguments, poss, suffix)) =
-                KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0))
-            && poss.contains(&name)
+            && let Some(&(_, fn_has_arguments, _, suffix)) = KNOW_TYPES
+                .iter()
+                .find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0) && i.2.contains(&name))
         {
             let ctxt = span.ctxt();
             let mut app = Applicability::HasPlaceholders;
diff --git a/clippy_lints/src/methods/swap_with_temporary.rs b/clippy_lints/src/methods/swap_with_temporary.rs
index de729fb..e378cbd 100644
--- a/clippy_lints/src/methods/swap_with_temporary.rs
+++ b/clippy_lints/src/methods/swap_with_temporary.rs
@@ -4,6 +4,7 @@
 use rustc_errors::{Applicability, Diag};
 use rustc_hir::{Expr, ExprKind, Node, QPath};
 use rustc_lint::LateContext;
+use rustc_middle::ty::adjustment::Adjust;
 use rustc_span::sym;
 
 use super::SWAP_WITH_TEMPORARY;
@@ -11,12 +12,12 @@
 const MSG_TEMPORARY: &str = "this expression returns a temporary value";
 const MSG_TEMPORARY_REFMUT: &str = "this is a mutable reference to a temporary value";
 
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>]) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, func: &Expr<'_>, args: &'tcx [Expr<'_>]) {
     if let ExprKind::Path(QPath::Resolved(_, func_path)) = func.kind
         && let Some(func_def_id) = func_path.res.opt_def_id()
         && cx.tcx.is_diagnostic_item(sym::mem_swap, func_def_id)
     {
-        match (ArgKind::new(&args[0]), ArgKind::new(&args[1])) {
+        match (ArgKind::new(cx, &args[0]), ArgKind::new(cx, &args[1])) {
             (ArgKind::RefMutToTemp(left_temp), ArgKind::RefMutToTemp(right_temp)) => {
                 emit_lint_useless(cx, expr, &args[0], &args[1], left_temp, right_temp);
             },
@@ -28,10 +29,10 @@
 }
 
 enum ArgKind<'tcx> {
-    // Mutable reference to a place, coming from a macro
-    RefMutToPlaceAsMacro(&'tcx Expr<'tcx>),
-    // Place behind a mutable reference
-    RefMutToPlace(&'tcx Expr<'tcx>),
+    // Mutable reference to a place, coming from a macro, and number of dereferences to use
+    RefMutToPlaceAsMacro(&'tcx Expr<'tcx>, usize),
+    // Place behind a mutable reference, and number of dereferences to use
+    RefMutToPlace(&'tcx Expr<'tcx>, usize),
     // Temporary value behind a mutable reference
     RefMutToTemp(&'tcx Expr<'tcx>),
     // Any other case
@@ -39,13 +40,29 @@
 }
 
 impl<'tcx> ArgKind<'tcx> {
-    fn new(arg: &'tcx Expr<'tcx>) -> Self {
-        if let ExprKind::AddrOf(BorrowKind::Ref, _, target) = arg.kind {
-            if target.is_syntactic_place_expr() {
+    /// Build a new `ArgKind` from `arg`. There must be no false positive when returning a
+    /// `ArgKind::RefMutToTemp` variant, as this may cause a spurious lint to be emitted.
+    fn new(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Self {
+        if let ExprKind::AddrOf(BorrowKind::Ref, _, target) = arg.kind
+            && let adjustments = cx.typeck_results().expr_adjustments(arg)
+            && adjustments
+                .first()
+                .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(None)))
+            && adjustments
+                .last()
+                .is_some_and(|adj| matches!(adj.kind, Adjust::Borrow(_)))
+        {
+            let extra_derefs = adjustments[1..adjustments.len() - 1]
+                .iter()
+                .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
+                .count();
+            // If a deref is used, `arg` might be a place expression. For example, a mutex guard
+            // would dereference into the mutex content which is probably not temporary.
+            if target.is_syntactic_place_expr() || extra_derefs > 0 {
                 if arg.span.from_expansion() {
-                    ArgKind::RefMutToPlaceAsMacro(arg)
+                    ArgKind::RefMutToPlaceAsMacro(arg, extra_derefs)
                 } else {
-                    ArgKind::RefMutToPlace(target)
+                    ArgKind::RefMutToPlace(target, extra_derefs)
                 }
             } else {
                 ArgKind::RefMutToTemp(target)
@@ -106,10 +123,15 @@
                 let mut applicability = Applicability::MachineApplicable;
                 let ctxt = expr.span.ctxt();
                 let assign_target = match target {
-                    ArgKind::Expr(target) | ArgKind::RefMutToPlaceAsMacro(target) => {
-                        Sugg::hir_with_context(cx, target, ctxt, "_", &mut applicability).deref()
-                    },
-                    ArgKind::RefMutToPlace(target) => Sugg::hir_with_context(cx, target, ctxt, "_", &mut applicability),
+                    ArgKind::Expr(target) => Sugg::hir_with_context(cx, target, ctxt, "_", &mut applicability).deref(),
+                    ArgKind::RefMutToPlaceAsMacro(arg, derefs) => (0..*derefs).fold(
+                        Sugg::hir_with_context(cx, arg, ctxt, "_", &mut applicability).deref(),
+                        |sugg, _| sugg.deref(),
+                    ),
+                    ArgKind::RefMutToPlace(target, derefs) => (0..*derefs).fold(
+                        Sugg::hir_with_context(cx, target, ctxt, "_", &mut applicability),
+                        |sugg, _| sugg.deref(),
+                    ),
                     ArgKind::RefMutToTemp(_) => unreachable!(),
                 };
                 let assign_source = Sugg::hir_with_context(cx, temp, ctxt, "_", &mut applicability);
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index fdccf1f..769526d 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -388,9 +388,11 @@
         && let (input, n_refs) = peel_middle_ty_refs(*input)
         && let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input)
         && let Some(sized_def_id) = cx.tcx.lang_items().sized_trait()
+        && let Some(meta_sized_def_id) = cx.tcx.lang_items().meta_sized_trait()
         && let [trait_predicate] = trait_predicates
             .iter()
             .filter(|trait_predicate| trait_predicate.def_id() != sized_def_id)
+            .filter(|trait_predicate| trait_predicate.def_id() != meta_sized_def_id)
             .collect::<Vec<_>>()[..]
         && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
         && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs
index 1f61317..25c95d2 100644
--- a/clippy_lints/src/missing_inline.rs
+++ b/clippy_lints/src/missing_inline.rs
@@ -1,10 +1,11 @@
 use clippy_utils::diagnostics::span_lint;
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_hir as hir;
 use rustc_hir::Attribute;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::AssocItemContainer;
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, sym};
+use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -64,8 +65,7 @@
 }
 
 fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[Attribute], sp: Span, desc: &'static str) {
-    let has_inline = attrs.iter().any(|a| a.has_name(sym::inline));
-    if !has_inline {
+    if !find_attr!(attrs, AttributeKind::Inline(..)) {
         span_lint(
             cx,
             MISSING_INLINE_IN_PUBLIC_ITEMS,
diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs
index 2efb55b..17d251a 100644
--- a/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -161,7 +161,7 @@
 ///   - `Copy` itself, or
 ///   - the only use of a mutable reference, or
 ///   - not a variable (created by a function call)
-#[expect(clippy::too_many_arguments)]
+#[expect(clippy::too_many_arguments, clippy::too_many_lines)]
 fn needless_borrow_count<'tcx>(
     cx: &LateContext<'tcx>,
     possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
@@ -174,6 +174,7 @@
 ) -> usize {
     let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait();
     let sized_trait_def_id = cx.tcx.lang_items().sized_trait();
+    let meta_sized_trait_def_id = cx.tcx.lang_items().meta_sized_trait();
     let drop_trait_def_id = cx.tcx.lang_items().drop_trait();
 
     let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity().skip_binder();
@@ -209,6 +210,7 @@
         .all(|trait_def_id| {
             Some(trait_def_id) == destruct_trait_def_id
                 || Some(trait_def_id) == sized_trait_def_id
+                || Some(trait_def_id) == meta_sized_trait_def_id
                 || cx.tcx.is_diagnostic_item(sym::Any, trait_def_id)
         })
     {
@@ -230,11 +232,11 @@
     let mut args_with_referent_ty = callee_args.to_vec();
 
     let mut check_reference_and_referent = |reference: &Expr<'tcx>, referent: &Expr<'tcx>| {
-        if let ExprKind::Field(base, _) = &referent.kind {
-            let base_ty = cx.typeck_results().expr_ty(base);
-            if drop_trait_def_id.is_some_and(|id| implements_trait(cx, base_ty, id, &[])) {
-                return false;
-            }
+        if let ExprKind::Field(base, _) = &referent.kind
+            && let base_ty = cx.typeck_results().expr_ty(base)
+            && drop_trait_def_id.is_some_and(|id| implements_trait(cx, base_ty, id, &[]))
+        {
+            return false;
         }
 
         let referent_ty = cx.typeck_results().expr_ty(referent);
diff --git a/clippy_lints/src/needless_parens_on_range_literals.rs b/clippy_lints/src/needless_parens_on_range_literals.rs
index 8a62106..021a115 100644
--- a/clippy_lints/src/needless_parens_on_range_literals.rs
+++ b/clippy_lints/src/needless_parens_on_range_literals.rs
@@ -5,7 +5,6 @@
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
-
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 9562346..c97ecce 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -116,13 +116,18 @@
         ];
 
         let sized_trait = need!(cx.tcx.lang_items().sized_trait());
+        let meta_sized_trait = need!(cx.tcx.lang_items().meta_sized_trait());
 
         let preds = traits::elaborate(cx.tcx, cx.param_env.caller_bounds().iter())
             .filter(|p| !p.is_global())
             .filter_map(|pred| {
                 // Note that we do not want to deal with qualified predicates here.
                 match pred.kind().no_bound_vars() {
-                    Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => Some(pred),
+                    Some(ty::ClauseKind::Trait(pred))
+                        if pred.def_id() != sized_trait && pred.def_id() != meta_sized_trait =>
+                    {
+                        Some(pred)
+                    },
                     _ => None,
                 }
             })
diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs
index 74c8142..442280f 100644
--- a/clippy_lints/src/neg_multiply.rs
+++ b/clippy_lints/src/neg_multiply.rs
@@ -64,7 +64,7 @@
     {
         let mut applicability = Applicability::MachineApplicable;
         let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
-        let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
+        let suggestion = if !from_macro && cx.precedence(exp) < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
             format!("-({snip})")
         } else {
             format!("-{snip}")
diff --git a/clippy_lints/src/no_mangle_with_rust_abi.rs b/clippy_lints/src/no_mangle_with_rust_abi.rs
index b71dde9..dee8efe 100644
--- a/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -1,8 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use rustc_abi::ExternAbi;
+use rustc_attr_data_structures::AttributeKind;
 use rustc_errors::Applicability;
-use rustc_hir::{Item, ItemKind};
+use rustc_hir::{Attribute, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::{BytePos, Pos};
@@ -44,8 +45,7 @@
             let mut app = Applicability::MaybeIncorrect;
             let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(ident.span.lo()), "..", &mut app);
             for attr in attrs {
-                if let Some(ident) = attr.ident()
-                    && ident.name == rustc_span::sym::no_mangle
+                if let Attribute::Parsed(AttributeKind::NoMangle(attr_span)) = attr
                     && fn_sig.header.abi == ExternAbi::Rust
                     && let Some((fn_attrs, _)) = fn_snippet.rsplit_once("fn")
                     && !fn_attrs.contains("extern")
@@ -54,7 +54,7 @@
                         .span
                         .with_lo(fn_sig.span.lo() + BytePos::from_usize(fn_attrs.len()))
                         .shrink_to_lo();
-                    let attr_snippet = snippet(cx, attr.span(), "..");
+                    let attr_snippet = snippet(cx, *attr_span, "..");
 
                     span_lint_and_then(
                         cx,
diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs
index a27c6aa..5f10e19 100644
--- a/clippy_lints/src/non_copy_const.rs
+++ b/clippy_lints/src/non_copy_const.rs
@@ -617,7 +617,7 @@
 
             // Then a type check. Note we only check the type here as the result
             // gets cached.
-            let ty = EarlyBinder::bind(typeck.expr_ty(src_expr)).instantiate(tcx, init_args);
+            let ty = typeck.expr_ty(src_expr);
             // Normalized as we need to check if this is an array later.
             let ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
             if self.is_ty_freeze(tcx, typing_env, ty).is_freeze() {
diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs
index e1fd095..3efbb89 100644
--- a/clippy_lints/src/operators/identity_op.rs
+++ b/clippy_lints/src/operators/identity_op.rs
@@ -1,12 +1,13 @@
-use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt, integer_const, is_zero_integer_const};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{clip, peel_hir_expr_refs, unsext};
+use clippy_utils::{ExprUseNode, clip, expr_use_ctxt, peel_hir_expr_refs, unsext};
 use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{BinOpKind, Expr, ExprKind, Node, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::Span;
+use rustc_span::{Span, kw};
 
 use super::IDENTITY_OP;
 
@@ -17,7 +18,7 @@
     left: &'tcx Expr<'_>,
     right: &'tcx Expr<'_>,
 ) {
-    if !is_allowed(cx, op, left, right) {
+    if !is_allowed(cx, expr, op, left, right) {
         return;
     }
 
@@ -165,14 +166,27 @@
     Parens::Needed
 }
 
-fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> bool {
+fn is_allowed<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    cmp: BinOpKind,
+    left: &Expr<'tcx>,
+    right: &Expr<'tcx>,
+) -> bool {
+    // Exclude case where the left or right side is associated function call returns a type which is
+    // `Self` that is not given explicitly, and the expression is not a let binding's init
+    // expression and the let binding has a type annotation, or a function's return value.
+    if (is_assoc_fn_without_type_instance(cx, left) || is_assoc_fn_without_type_instance(cx, right))
+        && !is_expr_used_with_type_annotation(cx, expr)
+    {
+        return false;
+    }
+
     // This lint applies to integers and their references
     cx.typeck_results().expr_ty(left).peel_refs().is_integral()
         && cx.typeck_results().expr_ty(right).peel_refs().is_integral()
         // `1 << 0` is a common pattern in bit manipulation code
-        && !(cmp == BinOpKind::Shl
-            && ConstEvalCtxt::new(cx).eval_simple(right) == Some(Constant::Int(0))
-            && ConstEvalCtxt::new(cx).eval_simple(left) == Some(Constant::Int(1)))
+        && !(cmp == BinOpKind::Shl && is_zero_integer_const(cx, right) && integer_const(cx, left) == Some(1))
 }
 
 fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span: Span, arg: Span) {
@@ -234,3 +248,47 @@
         applicability,
     );
 }
+
+fn is_expr_used_with_type_annotation<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
+    match expr_use_ctxt(cx, expr).use_node(cx) {
+        ExprUseNode::LetStmt(letstmt) => letstmt.ty.is_some(),
+        ExprUseNode::Return(_) => true,
+        _ => false,
+    }
+}
+
+/// Check if the expression is an associated function without a type instance.
+/// Example:
+/// ```
+/// trait Def {
+///     fn def() -> Self;
+/// }
+/// impl Def for usize {
+///     fn def() -> Self {
+///         0
+///     }
+/// }
+/// fn test() {
+///     let _ = 0usize + &Default::default();
+///     let _ = 0usize + &Def::def();
+/// }
+/// ```
+fn is_assoc_fn_without_type_instance<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
+    if let ExprKind::Call(func, _) = peel_hir_expr_refs(expr).0.kind
+        && let ExprKind::Path(QPath::Resolved(
+            // If it's not None, don't need to go further.
+            None,
+            Path {
+                res: Res::Def(DefKind::AssocFn, def_id),
+                ..
+            },
+        )) = func.kind
+        && let output_ty = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder().output()
+        && let ty::Param(ty::ParamTy {
+            name: kw::SelfUpper, ..
+        }) = output_ty.kind()
+    {
+        return true;
+    }
+    false
+}
diff --git a/clippy_lints/src/operators/manual_is_multiple_of.rs b/clippy_lints/src/operators/manual_is_multiple_of.rs
new file mode 100644
index 0000000..821178a
--- /dev/null
+++ b/clippy_lints/src/operators/manual_is_multiple_of.rs
@@ -0,0 +1,66 @@
+use clippy_utils::consts::is_zero_integer_const;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::sugg::Sugg;
+use rustc_ast::BinOpKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty;
+
+use super::MANUAL_IS_MULTIPLE_OF;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &Expr<'_>,
+    op: BinOpKind,
+    lhs: &'tcx Expr<'tcx>,
+    rhs: &'tcx Expr<'tcx>,
+    msrv: Msrv,
+) {
+    if msrv.meets(cx, msrvs::UNSIGNED_IS_MULTIPLE_OF)
+        && let Some(operand) = uint_compare_to_zero(cx, op, lhs, rhs)
+        && let ExprKind::Binary(operand_op, operand_left, operand_right) = operand.kind
+        && operand_op.node == BinOpKind::Rem
+    {
+        let mut app = Applicability::MachineApplicable;
+        let divisor = Sugg::hir_with_applicability(cx, operand_right, "_", &mut app);
+        span_lint_and_sugg(
+            cx,
+            MANUAL_IS_MULTIPLE_OF,
+            expr.span,
+            "manual implementation of `.is_multiple_of()`",
+            "replace with",
+            format!(
+                "{}{}.is_multiple_of({divisor})",
+                if op == BinOpKind::Eq { "" } else { "!" },
+                Sugg::hir_with_applicability(cx, operand_left, "_", &mut app).maybe_paren()
+            ),
+            app,
+        );
+    }
+}
+
+// If we have a `x == 0`, `x != 0` or `x > 0` (or the reverted ones), return the non-zero operand
+fn uint_compare_to_zero<'tcx>(
+    cx: &LateContext<'tcx>,
+    op: BinOpKind,
+    lhs: &'tcx Expr<'tcx>,
+    rhs: &'tcx Expr<'tcx>,
+) -> Option<&'tcx Expr<'tcx>> {
+    let operand = if matches!(lhs.kind, ExprKind::Binary(..))
+        && matches!(op, BinOpKind::Eq | BinOpKind::Ne | BinOpKind::Gt)
+        && is_zero_integer_const(cx, rhs)
+    {
+        lhs
+    } else if matches!(rhs.kind, ExprKind::Binary(..))
+        && matches!(op, BinOpKind::Eq | BinOpKind::Ne | BinOpKind::Lt)
+        && is_zero_integer_const(cx, lhs)
+    {
+        rhs
+    } else {
+        return None;
+    };
+
+    matches!(cx.typeck_results().expr_ty_adjusted(operand).kind(), ty::Uint(_)).then_some(operand)
+}
diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs
index 2f4e8e9..bdbbb34 100644
--- a/clippy_lints/src/operators/mod.rs
+++ b/clippy_lints/src/operators/mod.rs
@@ -11,6 +11,7 @@
 mod float_equality_without_abs;
 mod identity_op;
 mod integer_division;
+mod manual_is_multiple_of;
 mod manual_midpoint;
 mod misrefactored_assign_op;
 mod modulo_arithmetic;
@@ -830,12 +831,42 @@
     "manual implementation of `midpoint` which can overflow"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for manual implementation of `.is_multiple_of()` on
+    /// unsigned integer types.
+    ///
+    /// ### Why is this bad?
+    /// `a.is_multiple_of(b)` is a clearer way to check for divisibility
+    /// of `a` by `b`. This expression can never panic.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// # let (a, b) = (3u64, 4u64);
+    /// if a % b == 0 {
+    ///     println!("{a} is divisible by {b}");
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// # let (a, b) = (3u64, 4u64);
+    /// if a.is_multiple_of(b) {
+    ///     println!("{a} is divisible by {b}");
+    /// }
+    /// ```
+    #[clippy::version = "1.89.0"]
+    pub MANUAL_IS_MULTIPLE_OF,
+    complexity,
+    "manual implementation of `.is_multiple_of()`"
+}
+
 pub struct Operators {
     arithmetic_context: numeric_arithmetic::Context,
     verbose_bit_mask_threshold: u64,
     modulo_arithmetic_allow_comparison_to_zero: bool,
     msrv: Msrv,
 }
+
 impl Operators {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
@@ -874,6 +905,7 @@
     NEEDLESS_BITWISE_BOOL,
     SELF_ASSIGNMENT,
     MANUAL_MIDPOINT,
+    MANUAL_IS_MULTIPLE_OF,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Operators {
@@ -891,6 +923,7 @@
                     identity_op::check(cx, e, op.node, lhs, rhs);
                     needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
                     manual_midpoint::check(cx, e, op.node, lhs, rhs, self.msrv);
+                    manual_is_multiple_of::check(cx, e, op.node, lhs, rhs, self.msrv);
                 }
                 self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
                 bit_mask::check(cx, e, op.node, lhs, rhs);
diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs
index dadf49b..b8005df 100644
--- a/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/clippy_lints/src/pass_by_ref_or_value.rs
@@ -5,7 +5,7 @@
 use clippy_utils::{is_self, is_self_ty};
 use core::ops::ControlFlow;
 use rustc_abi::ExternAbi;
-use rustc_ast::attr;
+use rustc_attr_data_structures::{AttributeKind, InlineAttr, find_attr};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -270,11 +270,13 @@
                     return;
                 }
                 let attrs = cx.tcx.hir_attrs(hir_id);
+                if find_attr!(attrs, AttributeKind::Inline(InlineAttr::Always, _)) {
+                    return;
+                }
+
                 for a in attrs {
-                    if let Some(meta_items) = a.meta_item_list()
-                        && (a.has_name(sym::proc_macro_derive)
-                            || (a.has_name(sym::inline) && attr::list_contains_name(&meta_items, sym::always)))
-                    {
+                    // FIXME(jdonszelmann): make part of the find_attr above
+                    if a.has_name(sym::proc_macro_derive) {
                         return;
                     }
                 }
diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index c02e5e0..de12a25 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -142,6 +142,7 @@
         && let Some(ret) = find_let_else_ret_expression(els)
         && let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, ret)
         && !span_contains_comment(cx.tcx.sess.source_map(), els.span)
+        && !span_contains_cfg(cx, els.span)
     {
         let mut applicability = Applicability::MaybeIncorrect;
         let init_expr_str = Sugg::hir_with_applicability(cx, init_expr, "..", &mut applicability).maybe_paren();
diff --git a/clippy_lints/src/question_mark_used.rs b/clippy_lints/src/question_mark_used.rs
index 96ea485..7bbbd0d 100644
--- a/clippy_lints/src/question_mark_used.rs
+++ b/clippy_lints/src/question_mark_used.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-
 use clippy_utils::macros::span_is_local;
 use rustc_hir::{Expr, ExprKind, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/clippy_lints/src/read_zero_byte_vec.rs b/clippy_lints/src/read_zero_byte_vec.rs
index 6b1dc86..acd8404 100644
--- a/clippy_lints/src/read_zero_byte_vec.rs
+++ b/clippy_lints/src/read_zero_byte_vec.rs
@@ -3,11 +3,10 @@
 use clippy_utils::source::snippet;
 use clippy_utils::{get_enclosing_block, sym};
 
-use hir::{Expr, ExprKind, HirId, LetStmt, PatKind, PathSegment, QPath, StmtKind};
 use rustc_errors::Applicability;
-use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{Visitor, walk_expr};
+use rustc_hir::{self as hir, Expr, ExprKind, HirId, LetStmt, PatKind, PathSegment, QPath, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs
index 1117dea..324a05c 100644
--- a/clippy_lints/src/redundant_slicing.rs
+++ b/clippy_lints/src/redundant_slicing.rs
@@ -86,7 +86,7 @@
             let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
             let parent_expr = get_parent_expr(cx, expr);
             let needs_parens_for_prefix =
-                parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix);
+                parent_expr.is_some_and(|parent| cx.precedence(parent) > ExprPrecedence::Prefix);
 
             if expr_ty == indexed_ty {
                 if expr_ref_count > indexed_ref_count {
diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs
index 07ae92f..25929b8 100644
--- a/clippy_lints/src/return_self_not_must_use.rs
+++ b/clippy_lints/src/return_self_not_must_use.rs
@@ -1,12 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::{nth_arg, return_ty};
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, sym};
+use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -74,7 +75,10 @@
         // We only show this warning for public exported methods.
         && cx.effective_visibilities.is_exported(fn_def)
         // We don't want to emit this lint if the `#[must_use]` attribute is already there.
-        && !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
+        && !find_attr!(
+            cx.tcx.hir_attrs(owner_id.into()),
+            AttributeKind::MustUse { .. }
+        )
         && cx.tcx.visibility(fn_def.to_def_id()).is_public()
         && let ret_ty = return_ty(cx, owner_id)
         && let self_arg = nth_arg(cx, owner_id, 0)
diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs
index 54d09ff..dda2f8c 100644
--- a/clippy_lints/src/single_range_in_vec_init.rs
+++ b/clippy_lints/src/single_range_in_vec_init.rs
@@ -3,7 +3,7 @@
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_no_std_crate, paths};
+use clippy_utils::{is_no_std_crate, sym};
 use rustc_ast::{LitIntType, LitKind, UintTy};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr};
@@ -100,7 +100,7 @@
             && let Some(start_snippet) = start.span.get_source_text(cx)
             && let Some(end_snippet) = end.span.get_source_text(cx)
         {
-            let should_emit_every_value = if let Some(step_def_id) = paths::ITER_STEP.only(cx)
+            let should_emit_every_value = if let Some(step_def_id) = cx.tcx.get_diagnostic_item(sym::range_step)
                 && implements_trait(cx, ty, step_def_id, &[])
             {
                 true
diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs
index 7d7d74f..3e84754 100644
--- a/clippy_lints/src/to_digit_is_some.rs
+++ b/clippy_lints/src/to_digit_is_some.rs
@@ -2,7 +2,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_in_const_context, paths, sym};
+use clippy_utils::{is_in_const_context, is_path_diagnostic_item, sym};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
@@ -62,7 +62,7 @@
                     }
                 },
                 hir::ExprKind::Call(to_digits_call, [char_arg, radix_arg]) => {
-                    if paths::CHAR_TO_DIGIT.matches_path(cx, to_digits_call) {
+                    if is_path_diagnostic_item(cx, to_digits_call, sym::char_to_digit) {
                         Some((false, char_arg, radix_arg))
                     } else {
                         None
diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 0d5cf45..18897fb 100644
--- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -44,7 +44,7 @@
     };
 
     if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
-        && parent.precedence() > ExprPrecedence::Cast
+        && cx.precedence(parent) > ExprPrecedence::Cast
     {
         sugg = format!("({sugg})");
     }
diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs
index b839b6f..bd84209 100644
--- a/clippy_lints/src/unnested_or_patterns.rs
+++ b/clippy_lints/src/unnested_or_patterns.rs
@@ -128,7 +128,7 @@
     }
 
     impl MutVisitor for Visitor {
-        fn visit_pat(&mut self, pat: &mut P<Pat>) {
+        fn visit_pat(&mut self, pat: &mut Pat) {
             let is_inner = mem::replace(&mut self.is_inner, true);
             walk_pat(self, pat);
             let inner = match &mut pat.kind {
@@ -145,7 +145,7 @@
 fn insert_necessary_parens(pat: &mut P<Pat>) {
     struct Visitor;
     impl MutVisitor for Visitor {
-        fn visit_pat(&mut self, pat: &mut P<Pat>) {
+        fn visit_pat(&mut self, pat: &mut Pat) {
             use ast::BindingMode;
             walk_pat(self, pat);
             let target = match &mut pat.kind {
@@ -167,7 +167,7 @@
         changed: bool,
     }
     impl MutVisitor for Visitor {
-        fn visit_pat(&mut self, p: &mut P<Pat>) {
+        fn visit_pat(&mut self, p: &mut Pat) {
             // This is a bottom up transformation, so recurse first.
             walk_pat(self, p);
 
diff --git a/clippy_lints/src/useless_concat.rs b/clippy_lints/src/useless_concat.rs
index 1ed1fbb..96845ad 100644
--- a/clippy_lints/src/useless_concat.rs
+++ b/clippy_lints/src/useless_concat.rs
@@ -1,8 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::macros::macro_backtrace;
-use clippy_utils::paths::CONCAT;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::tokenize_with_text;
+use clippy_utils::{sym, tokenize_with_text};
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
@@ -43,7 +42,7 @@
             // Get the direct parent of the expression.
             && let Some(macro_call) = macro_backtrace(expr.span).next()
             // Check if the `concat` macro from the `core` library.
-            && CONCAT.matches(cx, macro_call.def_id)
+            && cx.tcx.is_diagnostic_item(sym::macro_concat, macro_call.def_id)
             // We get the original code to parse it.
             && let Some(original_code) = snippet_opt(cx, macro_call.span)
             // This check allows us to ensure that the code snippet:
diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml
index 615c099..73291aa 100644
--- a/clippy_utils/Cargo.toml
+++ b/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy_utils"
-version = "0.1.89"
+version = "0.1.90"
 edition = "2024"
 description = "Helpful tools for writing lints, provided as they are used in Clippy"
 repository = "https://github.com/rust-lang/rust-clippy"
diff --git a/clippy_utils/README.md b/clippy_utils/README.md
index 1aa16e3..649748d 100644
--- a/clippy_utils/README.md
+++ b/clippy_utils/README.md
@@ -8,7 +8,7 @@
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2025-06-12
+nightly-2025-06-26
 ```
 <!-- end autogenerated nightly -->
 
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 1ec5d11..aaa071f 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -958,3 +958,18 @@
         None
     }
 }
+
+/// If `expr` evaluates to an integer constant, return its value.
+pub fn integer_const(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
+    if let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_simple(expr) {
+        Some(value)
+    } else {
+        None
+    }
+}
+
+/// Check if `expr` evaluates to an integer constant of 0.
+#[inline]
+pub fn is_zero_integer_const(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    integer_const(cx, expr) == Some(0)
+}
diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs
index cd2098a..dc240dd 100644
--- a/clippy_utils/src/diagnostics.rs
+++ b/clippy_utils/src/diagnostics.rs
@@ -109,7 +109,7 @@
     });
 }
 
-/// Same as `span_lint` but with an extra `help` message.
+/// Same as [`span_lint`] but with an extra `help` message.
 ///
 /// Use this if you want to provide some general help but
 /// can't provide a specific machine applicable suggestion.
@@ -166,7 +166,7 @@
     });
 }
 
-/// Like `span_lint` but with a `note` section instead of a `help` message.
+/// Like [`span_lint`] but with a `note` section instead of a `help` message.
 ///
 /// The `note` message is presented separately from the main lint message
 /// and is attached to a specific span:
@@ -226,7 +226,7 @@
     });
 }
 
-/// Like `span_lint` but allows to add notes, help and suggestions using a closure.
+/// Like [`span_lint`] but allows to add notes, help and suggestions using a closure.
 ///
 /// If you need to customize your lint output a lot, use this function.
 /// If you change the signature, remember to update the internal lint `CollapsibleCalls`
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 7fa5222..a8b3341 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1886,7 +1886,7 @@
         _ => None,
     };
 
-    did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use))
+    did.is_some_and(|did| find_attr!(cx.tcx.get_all_attrs(did), AttributeKind::MustUse { .. }))
 }
 
 /// Checks if a function's body represents the identity function. Looks for bodies of the form:
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index a5e66ad..24ed4c3 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -24,7 +24,7 @@
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
     1,88,0 { LET_CHAINS }
-    1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT }
+    1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF }
     1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL }
     1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR }
     1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP }
@@ -42,6 +42,7 @@
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
     1,63,0 { CLONE_INTO, CONST_SLICE_FROM_REF }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN }
+    1,61,0 { CONST_FN_TRAIT_BOUND }
     1,60,0 { ABS_DIFF }
     1,59,0 { THREAD_LOCAL_CONST_INIT }
     1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
@@ -73,7 +74,7 @@
     1,28,0 { FROM_BOOL, REPEAT_WITH, SLICE_FROM_REF }
     1,27,0 { ITERATOR_TRY_FOLD }
     1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN }
-    1,24,0 { IS_ASCII_DIGIT }
+    1,24,0 { IS_ASCII_DIGIT, PTR_NULL }
     1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
     1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
     1,16,0 { STR_REPEAT }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index f37a609..8bbcb22 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -126,15 +126,6 @@
     macro_path: PathNS::Macro,
 }
 
-// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
-pub static ALIGN_OF: PathLookup = value_path!(core::mem::align_of);
-pub static CHAR_TO_DIGIT: PathLookup = value_path!(char::to_digit);
-pub static CONCAT: PathLookup = macro_path!(core::concat);
-pub static IO_ERROR_NEW: PathLookup = value_path!(std::io::Error::new);
-pub static IO_ERRORKIND_OTHER_CTOR: PathLookup = value_path!(std::io::ErrorKind::Other);
-pub static ITER_STEP: PathLookup = type_path!(core::iter::Step);
-pub static SLICE_FROM_REF: PathLookup = value_path!(core::slice::from_ref);
-
 // Paths in external crates
 pub static FUTURES_IO_ASYNCREADEXT: PathLookup = type_path!(futures_util::AsyncReadExt);
 pub static FUTURES_IO_ASYNCWRITEEXT: PathLookup = type_path!(futures_util::AsyncWriteExt);
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index e629012..be93f27 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -32,6 +32,21 @@
     for local in &body.local_decls {
         check_ty(cx, local.ty, local.source_info.span, msrv)?;
     }
+    if !msrv.meets(cx, msrvs::CONST_FN_TRAIT_BOUND)
+        && let Some(sized_did) = cx.tcx.lang_items().sized_trait()
+        && let Some(meta_sized_did) = cx.tcx.lang_items().meta_sized_trait()
+        && cx.tcx.param_env(def_id).caller_bounds().iter().any(|bound| {
+            bound.as_trait_clause().is_some_and(|clause| {
+                let did = clause.def_id();
+                did != sized_did && did != meta_sized_did
+            })
+        })
+    {
+        return Err((
+            body.span,
+            "non-`Sized` trait clause before `const_fn_trait_bound` is stabilized".into(),
+        ));
+    }
     // impl trait is gone in MIR, so check the return type manually
     check_ty(
         cx,
diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs
index 6974e65..7a24d07 100644
--- a/clippy_utils/src/sugg.rs
+++ b/clippy_utils/src/sugg.rs
@@ -494,7 +494,17 @@
 /// operators have the same
 /// precedence.
 pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
-    Sugg::MaybeParen(format!("{op}{}", expr.maybe_paren()).into())
+    // If the `expr` starts with `op` already, do not add wrap it in
+    // parentheses.
+    let expr = if let Sugg::MaybeParen(ref sugg) = expr
+        && !has_enclosing_paren(sugg)
+        && sugg.starts_with(op)
+    {
+        expr
+    } else {
+        expr.maybe_paren()
+    };
+    Sugg::MaybeParen(format!("{op}{expr}").into())
 }
 
 /// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
@@ -1016,6 +1026,16 @@
         let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into());
         assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_paren().to_string());
     }
+
+    #[test]
+    fn unop_parenthesize() {
+        let sugg = Sugg::NonParen("x".into()).mut_addr();
+        assert_eq!("&mut x", sugg.to_string());
+        let sugg = sugg.mut_addr();
+        assert_eq!("&mut &mut x", sugg.to_string());
+        assert_eq!("(&mut &mut x)", sugg.maybe_paren().to_string());
+    }
+
     #[test]
     fn not_op() {
         use ast::BinOpKind::{Add, And, Eq, Ge, Gt, Le, Lt, Ne, Or};
diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs
index a544954..8a8218c 100644
--- a/clippy_utils/src/sym.rs
+++ b/clippy_utils/src/sym.rs
@@ -46,7 +46,6 @@
     DOUBLE_QUOTE: "\"",
     Deserialize,
     EarlyLintPass,
-    ErrorKind,
     IntoIter,
     Itertools,
     LF: "\n",
@@ -65,7 +64,6 @@
     RegexBuilder,
     RegexSet,
     Start,
-    Step,
     Symbol,
     SyntaxContext,
     TBD,
@@ -76,7 +74,6 @@
     Visitor,
     Weak,
     abs,
-    align_of,
     ambiguous_glob_reexports,
     append,
     arg,
@@ -159,7 +156,6 @@
     from_ne_bytes,
     from_ptr,
     from_raw,
-    from_ref,
     from_str,
     from_str_radix,
     fs,
@@ -167,6 +163,7 @@
     futures_util,
     get,
     get_mut,
+    get_or_insert,
     get_or_insert_with,
     get_unchecked,
     get_unchecked_mut,
@@ -217,7 +214,6 @@
     max_by_key,
     max_value,
     maximum,
-    mem,
     min,
     min_by,
     min_by_key,
diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs
index 1f0a0f2..bffbcf0 100644
--- a/clippy_utils/src/ty/mod.rs
+++ b/clippy_utils/src/ty/mod.rs
@@ -6,6 +6,7 @@
 use itertools::Itertools;
 use rustc_abi::VariantIdx;
 use rustc_ast::ast::Mutability;
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -20,8 +21,8 @@
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{
     self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef,
-    GenericParamDefKind, IntTy, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
-    TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
+    GenericParamDefKind, IntTy, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+    TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
@@ -326,8 +327,8 @@
 // Returns whether the type has #[must_use] attribute
 pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.kind() {
-        ty::Adt(adt, _) => cx.tcx.has_attr(adt.did(), sym::must_use),
-        ty::Foreign(did) => cx.tcx.has_attr(*did, sym::must_use),
+        ty::Adt(adt, _) => find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::MustUse { .. }),
+        ty::Foreign(did) => find_attr!(cx.tcx.get_all_attrs(*did), AttributeKind::MustUse { .. }),
         ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => {
             // for the Array case we don't need to care for the len == 0 case
             // because we don't want to lint functions returning empty arrays
@@ -337,7 +338,10 @@
         ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() {
                 if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
-                    && cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use)
+                    && find_attr!(
+                        cx.tcx.get_all_attrs(trait_predicate.trait_ref.def_id),
+                        AttributeKind::MustUse { .. }
+                    )
                 {
                     return true;
                 }
@@ -347,7 +351,7 @@
         ty::Dynamic(binder, _, _) => {
             for predicate in *binder {
                 if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
-                    && cx.tcx.has_attr(trait_ref.def_id, sym::must_use)
+                    && find_attr!(cx.tcx.get_all_attrs(trait_ref.def_id), AttributeKind::MustUse { .. })
                 {
                     return true;
                 }
@@ -853,7 +857,7 @@
                 ControlFlow::Continue(())
             }
         }
-        fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result {
+        fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result {
             self.index += 1;
             let res = t.super_visit_with(self);
             self.index -= 1;
diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml
new file mode 100644
index 0000000..bd6b4df
--- /dev/null
+++ b/declare_clippy_lint/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "declare_clippy_lint"
+version = "0.1.90"
+edition = "2024"
+repository = "https://github.com/rust-lang/rust-clippy"
+license = "MIT OR Apache-2.0"
+
+[package.metadata.rust-analyzer]
+# This crate uses #[feature(rustc_private)]
+rustc_private = true
diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs
new file mode 100644
index 0000000..f7d9c64
--- /dev/null
+++ b/declare_clippy_lint/src/lib.rs
@@ -0,0 +1,280 @@
+#![feature(macro_metavar_expr_concat, rustc_private)]
+
+extern crate rustc_lint;
+
+use rustc_lint::{Lint, LintId, LintStore};
+
+// Needed by `declare_clippy_lint!`.
+pub extern crate rustc_session;
+
+#[derive(Default)]
+pub struct LintListBuilder {
+    lints: Vec<&'static Lint>,
+    all: Vec<LintId>,
+    cargo: Vec<LintId>,
+    complexity: Vec<LintId>,
+    correctness: Vec<LintId>,
+    nursery: Vec<LintId>,
+    pedantic: Vec<LintId>,
+    perf: Vec<LintId>,
+    restriction: Vec<LintId>,
+    style: Vec<LintId>,
+    suspicious: Vec<LintId>,
+}
+impl LintListBuilder {
+    pub fn insert(&mut self, lints: &[&LintInfo]) {
+        #[allow(clippy::enum_glob_use)]
+        use LintCategory::*;
+
+        self.lints.extend(lints.iter().map(|&x| x.lint));
+        for &&LintInfo { lint, category, .. } in lints {
+            let (all, cat) = match category {
+                Complexity => (Some(&mut self.all), &mut self.complexity),
+                Correctness => (Some(&mut self.all), &mut self.correctness),
+                Perf => (Some(&mut self.all), &mut self.perf),
+                Style => (Some(&mut self.all), &mut self.style),
+                Suspicious => (Some(&mut self.all), &mut self.suspicious),
+                Cargo => (None, &mut self.cargo),
+                Nursery => (None, &mut self.nursery),
+                Pedantic => (None, &mut self.pedantic),
+                Restriction => (None, &mut self.restriction),
+            };
+            if let Some(all) = all {
+                all.push(LintId::of(lint));
+            }
+            cat.push(LintId::of(lint));
+        }
+    }
+
+    pub fn register(self, store: &mut LintStore) {
+        store.register_lints(&self.lints);
+        store.register_group(true, "clippy::all", Some("clippy_all"), self.all);
+        store.register_group(true, "clippy::cargo", Some("clippy_cargo"), self.cargo);
+        store.register_group(true, "clippy::complexity", Some("clippy_complexity"), self.complexity);
+        store.register_group(
+            true,
+            "clippy::correctness",
+            Some("clippy_correctness"),
+            self.correctness,
+        );
+        store.register_group(true, "clippy::nursery", Some("clippy_nursery"), self.nursery);
+        store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), self.pedantic);
+        store.register_group(true, "clippy::perf", Some("clippy_perf"), self.perf);
+        store.register_group(
+            true,
+            "clippy::restriction",
+            Some("clippy_restriction"),
+            self.restriction,
+        );
+        store.register_group(true, "clippy::style", Some("clippy_style"), self.style);
+        store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), self.suspicious);
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum LintCategory {
+    Cargo,
+    Complexity,
+    Correctness,
+    Nursery,
+    Pedantic,
+    Perf,
+    Restriction,
+    Style,
+    Suspicious,
+}
+impl LintCategory {
+    #[must_use]
+    pub fn name(self) -> &'static str {
+        match self {
+            Self::Cargo => "cargo",
+            Self::Complexity => "complexity",
+            Self::Correctness => "correctness",
+            Self::Nursery => "nursery",
+            Self::Pedantic => "pedantic",
+            Self::Perf => "perf",
+            Self::Restriction => "restriction",
+            Self::Style => "style",
+            Self::Suspicious => "suspicious",
+        }
+    }
+}
+
+pub struct LintInfo {
+    pub lint: &'static Lint,
+    pub category: LintCategory,
+    pub explanation: &'static str,
+    /// e.g. `clippy_lints/src/absolute_paths.rs#43`
+    pub location: &'static str,
+    pub version: &'static str,
+}
+
+impl LintInfo {
+    /// Returns the lint name in lowercase without the `clippy::` prefix
+    #[must_use]
+    #[expect(clippy::missing_panics_doc)]
+    pub fn name_lower(&self) -> String {
+        self.lint.name.strip_prefix("clippy::").unwrap().to_ascii_lowercase()
+    }
+}
+
+#[macro_export]
+macro_rules! declare_clippy_lint_inner {
+    (
+        $(#[doc = $docs:literal])*
+        #[clippy::version = $version:literal]
+        $vis:vis $lint_name:ident,
+        $level:ident,
+        $category:ident,
+        $desc:literal
+        $(, @eval_always = $eval_always:literal)?
+    ) => {
+        $crate::rustc_session::declare_tool_lint! {
+            $(#[doc = $docs])*
+            #[clippy::version = $version]
+            $vis clippy::$lint_name,
+            $level,
+            $desc,
+            report_in_external_macro:true
+            $(, @eval_always = $eval_always)?
+        }
+
+        pub(crate) static ${concat($lint_name, _INFO)}: &'static $crate::LintInfo = &$crate::LintInfo {
+            lint: $lint_name,
+            category: $crate::LintCategory::$category,
+            explanation: concat!($($docs,"\n",)*),
+            location: concat!(file!(), "#L", line!()),
+            version: $version,
+        };
+    };
+}
+
+#[macro_export]
+macro_rules! declare_clippy_lint {
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        correctness,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Deny,
+            Correctness,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        complexity,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Warn,
+            Complexity,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        perf,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Warn,
+            Perf,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        style,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Warn,
+            Style,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        suspicious,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Warn,
+            Suspicious,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        cargo,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Allow,
+            Cargo,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        nursery,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Allow,
+            Nursery,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        pedantic,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Allow,
+            Pedantic,
+            $($rest)*
+        }
+    };
+    (
+        $(#[$($meta:tt)*])*
+        $vis:vis $lint_name:ident,
+        restriction,
+        $($rest:tt)*
+    ) => {
+        $crate::declare_clippy_lint_inner! {
+            $(#[$($meta)*])*
+            $vis $lint_name,
+            Allow,
+            Restriction,
+            $($rest)*
+        }
+    };
+}
diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index 8418383..eb390ee 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -45,7 +45,7 @@
 
 #[must_use]
 pub fn target_dir() -> String {
-    env::var("CARGO_TARGET_DIR").unwrap_or("target".to_owned())
+    env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| "target".to_owned())
 }
 
 fn lintcheck_sources() -> String {
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 3fc5a12..124756a 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2025-06-12"
+channel = "nightly-2025-06-26"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
diff --git a/src/driver.rs b/src/driver.rs
index 37adb14..c4076cb 100644
--- a/src/driver.rs
+++ b/src/driver.rs
@@ -13,7 +13,13 @@
 extern crate rustc_session;
 extern crate rustc_span;
 
+// See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
+// about jemalloc.
+#[cfg(feature = "jemalloc")]
+extern crate tikv_jemalloc_sys as jemalloc_sys;
+
 use clippy_utils::sym;
+use declare_clippy_lint::LintListBuilder;
 use rustc_interface::interface;
 use rustc_session::EarlyDiagCtxt;
 use rustc_session::config::ErrorOutputType;
@@ -151,8 +157,13 @@
                 (previous)(sess, lint_store);
             }
 
+            let mut list_builder = LintListBuilder::default();
+            list_builder.insert(clippy_lints::declared_lints::LINTS);
+            list_builder.register(lint_store);
+
             let conf = clippy_config::Conf::read(sess, &conf_path);
-            clippy_lints::register_lints(lint_store, conf);
+            clippy_lints::register_lint_passes(lint_store, conf);
+
             #[cfg(feature = "internal")]
             clippy_lints_internal::register_lints(lint_store);
         }));
@@ -181,6 +192,36 @@
 #[allow(clippy::too_many_lines)]
 #[allow(clippy::ignored_unit_patterns)]
 pub fn main() {
+    // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
+    // about jemalloc.
+    #[cfg(feature = "jemalloc")]
+    {
+        use std::os::raw::{c_int, c_void};
+
+        #[used]
+        static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc;
+        #[used]
+        static _F2: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int = jemalloc_sys::posix_memalign;
+        #[used]
+        static _F3: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::aligned_alloc;
+        #[used]
+        static _F4: unsafe extern "C" fn(usize) -> *mut c_void = jemalloc_sys::malloc;
+        #[used]
+        static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc;
+        #[used]
+        static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free;
+
+        #[cfg(target_os = "macos")]
+        {
+            unsafe extern "C" {
+                fn _rjem_je_zone_register();
+            }
+
+            #[used]
+            static _F7: unsafe extern "C" fn() = _rjem_je_zone_register;
+        }
+    }
+
     let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
 
     rustc_driver::init_rustc_env_logger(&early_dcx);
diff --git a/src/main.rs b/src/main.rs
index c9853e5..3c2eec1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -107,7 +107,7 @@
     }
 
     fn into_std_cmd(self) -> Command {
-        let mut cmd = Command::new(env::var("CARGO").unwrap_or("cargo".into()));
+        let mut cmd = Command::new(env::var("CARGO").unwrap_or_else(|_| "cargo".into()));
         let clippy_args: String = self
             .clippy_args
             .iter()
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 99a0125..cefe654 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -7,9 +7,9 @@
 use cargo_metadata::Message;
 use cargo_metadata::diagnostic::{Applicability, Diagnostic};
 use clippy_config::ClippyConfiguration;
-use clippy_lints::LintInfo;
 use clippy_lints::declared_lints::LINTS;
 use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED};
+use declare_clippy_lint::LintInfo;
 use pulldown_cmark::{Options, Parser, html};
 use serde::Deserialize;
 use test_utils::IS_RUSTC_TEST_SUITE;
@@ -568,10 +568,10 @@
         Self {
             id: name,
             id_location: Some(lint.location),
-            group: lint.category_str(),
+            group: lint.category.name(),
             level: lint.lint.default_level.as_str(),
             docs,
-            version: lint.version.unwrap(),
+            version: lint.version,
             applicability,
         }
     }
diff --git a/tests/dogfood.rs b/tests/dogfood.rs
index 4ac2bd5..3896168 100644
--- a/tests/dogfood.rs
+++ b/tests/dogfood.rs
@@ -40,6 +40,7 @@
         "clippy_lints",
         "clippy_utils",
         "clippy_config",
+        "declare_clippy_lint",
         "lintcheck",
         "rustc_tools_util",
     ] {
diff --git a/tests/ui/author/macro_in_closure.stdout b/tests/ui/author/macro_in_closure.stdout
index 5f8a4ce..49595e2 100644
--- a/tests/ui/author/macro_in_closure.stdout
+++ b/tests/ui/author/macro_in_closure.stdout
@@ -9,28 +9,35 @@
     && let ExprKind::Call(func, args) = e.kind
     && paths::STD_IO_STDIO__PRINT.matches_path(cx, func) // Add the path to `clippy_utils::paths` if needed
     && args.len() == 1
-    && let ExprKind::Call(func1, args1) = args[0].kind
-    && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
-    && args1.len() == 2
+    && let ExprKind::Block(block1, None) = args[0].kind
+    && block1.stmts.len() == 1
+    && let StmtKind::Let(local1) = block1.stmts[0].kind
+    && let Some(init1) = local1.init
+    && let ExprKind::Array(elements) = init1.kind
+    && elements.len() == 1
+    && let ExprKind::Call(func1, args1) = elements[0].kind
+    && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
+    && args1.len() == 1
     && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
-    && let ExprKind::Array(elements) = inner.kind
-    && elements.len() == 2
-    && let ExprKind::Lit(ref lit) = elements[0].kind
+    && let PatKind::Binding(BindingMode::NONE, _, name, None) = local1.pat.kind
+    && name.as_str() == "args"
+    && let Some(trailing_expr) = block1.expr
+    && let ExprKind::Call(func2, args2) = trailing_expr.kind
+    && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
+    && args2.len() == 2
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args2[0].kind
+    && let ExprKind::Array(elements1) = inner1.kind
+    && elements1.len() == 2
+    && let ExprKind::Lit(ref lit) = elements1[0].kind
     && let LitKind::Str(s, _) = lit.node
     && s.as_str() == ""
-    && let ExprKind::Lit(ref lit1) = elements[1].kind
+    && let ExprKind::Lit(ref lit1) = elements1[1].kind
     && let LitKind::Str(s1, _) = lit1.node
     && s1.as_str() == "\n"
-    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
-    && let ExprKind::Array(elements1) = inner1.kind
-    && elements1.len() == 1
-    && let ExprKind::Call(func2, args2) = elements1[0].kind
-    && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
-    && args2.len() == 1
-    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[1].kind
     && block.expr.is_none()
-    && let PatKind::Binding(BindingMode::NONE, _, name, None) = local.pat.kind
-    && name.as_str() == "print_text"
+    && let PatKind::Binding(BindingMode::NONE, _, name1, None) = local.pat.kind
+    && name1.as_str() == "print_text"
 {
     // report your lint here
 }
diff --git a/tests/ui/author/macro_in_loop.stdout b/tests/ui/author/macro_in_loop.stdout
index ecc2525..4fc7b49 100644
--- a/tests/ui/author/macro_in_loop.stdout
+++ b/tests/ui/author/macro_in_loop.stdout
@@ -19,25 +19,32 @@
     && let ExprKind::Call(func, args) = e1.kind
     && paths::STD_IO_STDIO__PRINT.matches_path(cx, func) // Add the path to `clippy_utils::paths` if needed
     && args.len() == 1
-    && let ExprKind::Call(func1, args1) = args[0].kind
-    && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
-    && args1.len() == 2
+    && let ExprKind::Block(block2, None) = args[0].kind
+    && block2.stmts.len() == 1
+    && let StmtKind::Let(local) = block2.stmts[0].kind
+    && let Some(init) = local.init
+    && let ExprKind::Array(elements) = init.kind
+    && elements.len() == 1
+    && let ExprKind::Call(func1, args1) = elements[0].kind
+    && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed
+    && args1.len() == 1
     && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind
-    && let ExprKind::Array(elements) = inner.kind
-    && elements.len() == 2
-    && let ExprKind::Lit(ref lit2) = elements[0].kind
+    && let PatKind::Binding(BindingMode::NONE, _, name1, None) = local.pat.kind
+    && name1.as_str() == "args"
+    && let Some(trailing_expr) = block2.expr
+    && let ExprKind::Call(func2, args2) = trailing_expr.kind
+    && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
+    && args2.len() == 2
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args2[0].kind
+    && let ExprKind::Array(elements1) = inner1.kind
+    && elements1.len() == 2
+    && let ExprKind::Lit(ref lit2) = elements1[0].kind
     && let LitKind::Str(s, _) = lit2.node
     && s.as_str() == ""
-    && let ExprKind::Lit(ref lit3) = elements[1].kind
+    && let ExprKind::Lit(ref lit3) = elements1[1].kind
     && let LitKind::Str(s1, _) = lit3.node
     && s1.as_str() == "\n"
-    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind
-    && let ExprKind::Array(elements1) = inner1.kind
-    && elements1.len() == 1
-    && let ExprKind::Call(func2, args2) = elements1[0].kind
-    && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed
-    && args2.len() == 1
-    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind
+    && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[1].kind
     && block1.expr.is_none()
     && block.expr.is_none()
 {
diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed
index 765dd75..6d06fcc 100644
--- a/tests/ui/borrow_deref_ref.fixed
+++ b/tests/ui/borrow_deref_ref.fixed
@@ -124,3 +124,50 @@
         //~^ borrow_deref_ref
     }
 }
+
+fn issue_14934() {
+    let x: &'static str = "x";
+    let y = "y".to_string();
+    {
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*x; // Do not lint
+        *x = &*y;
+    }
+    {
+        let mut x = x;
+        //~^ borrow_deref_ref
+        x = &*y;
+    }
+    {
+        #[expect(clippy::toplevel_ref_arg, clippy::needless_borrow)]
+        let ref x = x;
+        //~^ borrow_deref_ref
+    }
+    {
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = std::convert::identity(x);
+        //~^ borrow_deref_ref
+        *x = &*y;
+    }
+    {
+        #[derive(Clone)]
+        struct S(&'static str);
+        let s = S("foo");
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*s.0; // Do not lint
+        *x = "bar";
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = s.clone().0;
+        //~^ borrow_deref_ref
+        *x = "bar";
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*std::convert::identity(&s).0;
+        *x = "bar";
+    }
+    {
+        let y = &1;
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = { y };
+        //~^ borrow_deref_ref
+    }
+}
diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs
index 8ee66bf..b43f4c9 100644
--- a/tests/ui/borrow_deref_ref.rs
+++ b/tests/ui/borrow_deref_ref.rs
@@ -124,3 +124,50 @@
         //~^ borrow_deref_ref
     }
 }
+
+fn issue_14934() {
+    let x: &'static str = "x";
+    let y = "y".to_string();
+    {
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*x; // Do not lint
+        *x = &*y;
+    }
+    {
+        let mut x = &*x;
+        //~^ borrow_deref_ref
+        x = &*y;
+    }
+    {
+        #[expect(clippy::toplevel_ref_arg, clippy::needless_borrow)]
+        let ref x = &*x;
+        //~^ borrow_deref_ref
+    }
+    {
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*std::convert::identity(x);
+        //~^ borrow_deref_ref
+        *x = &*y;
+    }
+    {
+        #[derive(Clone)]
+        struct S(&'static str);
+        let s = S("foo");
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*s.0; // Do not lint
+        *x = "bar";
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*s.clone().0;
+        //~^ borrow_deref_ref
+        *x = "bar";
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = &*std::convert::identity(&s).0;
+        *x = "bar";
+    }
+    {
+        let y = &1;
+        #[expect(clippy::toplevel_ref_arg)]
+        let ref mut x = { &*y };
+        //~^ borrow_deref_ref
+    }
+}
diff --git a/tests/ui/borrow_deref_ref.stderr b/tests/ui/borrow_deref_ref.stderr
index 3d55da2..3a1f968 100644
--- a/tests/ui/borrow_deref_ref.stderr
+++ b/tests/ui/borrow_deref_ref.stderr
@@ -25,5 +25,35 @@
 LL |         (&*s).foo();
    |         ^^^^^ help: if you would like to reborrow, try removing `&*`: `s`
 
-error: aborting due to 4 previous errors
+error: deref on an immutable reference
+  --> tests/ui/borrow_deref_ref.rs:137:21
+   |
+LL |         let mut x = &*x;
+   |                     ^^^ help: if you would like to reborrow, try removing `&*`: `x`
+
+error: deref on an immutable reference
+  --> tests/ui/borrow_deref_ref.rs:143:21
+   |
+LL |         let ref x = &*x;
+   |                     ^^^ help: if you would like to reborrow, try removing `&*`: `x`
+
+error: deref on an immutable reference
+  --> tests/ui/borrow_deref_ref.rs:148:25
+   |
+LL |         let ref mut x = &*std::convert::identity(x);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `std::convert::identity(x)`
+
+error: deref on an immutable reference
+  --> tests/ui/borrow_deref_ref.rs:160:25
+   |
+LL |         let ref mut x = &*s.clone().0;
+   |                         ^^^^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `s.clone().0`
+
+error: deref on an immutable reference
+  --> tests/ui/borrow_deref_ref.rs:170:27
+   |
+LL |         let ref mut x = { &*y };
+   |                           ^^^ help: if you would like to reborrow, try removing `&*`: `y`
+
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/borrow_interior_mutable_const.rs b/tests/ui/borrow_interior_mutable_const.rs
index 0f439f7..674450a 100644
--- a/tests/ui/borrow_interior_mutable_const.rs
+++ b/tests/ui/borrow_interior_mutable_const.rs
@@ -218,4 +218,20 @@
         let _ = &S::VALUE.1; //~ borrow_interior_mutable_const
         let _ = &S::VALUE.2;
     }
+    {
+        pub struct Foo<T, const N: usize>(pub Entry<N>, pub T);
+
+        pub struct Entry<const N: usize>(pub Cell<[u32; N]>);
+
+        impl<const N: usize> Entry<N> {
+            const INIT: Self = Self(Cell::new([42; N]));
+        }
+
+        impl<T, const N: usize> Foo<T, N> {
+            pub fn make_foo(v: T) -> Self {
+                // Used to ICE due to incorrect instantiation.
+                Foo(Entry::INIT, v)
+            }
+        }
+    }
 }
diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed
index 80000f5..ed00494 100644
--- a/tests/ui/box_default.fixed
+++ b/tests/ui/box_default.fixed
@@ -126,7 +126,7 @@
     impl Bar for Foo {}
 
     fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
-        if i % 2 == 0 {
+        if i.is_multiple_of(2) {
             Some(Box::new(Foo::default()))
         } else {
             None
diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs
index 4681016..801d92f 100644
--- a/tests/ui/box_default.rs
+++ b/tests/ui/box_default.rs
@@ -126,7 +126,7 @@
     impl Bar for Foo {}
 
     fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
-        if i % 2 == 0 {
+        if i.is_multiple_of(2) {
             Some(Box::new(Foo::default()))
         } else {
             None
diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.rs b/tests/ui/branches_sharing_code/shared_at_bottom.rs
index 922d304..fa322dc 100644
--- a/tests/ui/branches_sharing_code/shared_at_bottom.rs
+++ b/tests/ui/branches_sharing_code/shared_at_bottom.rs
@@ -276,3 +276,27 @@
         }
     }
 }
+
+fn issue15004() {
+    let a = 12u32;
+    let b = 13u32;
+    let mut c = 8u32;
+
+    let mut result = if b > a {
+        c += 1;
+        0
+    } else {
+        c += 2;
+        0
+        //~^ branches_sharing_code
+    };
+
+    result = if b > a {
+        c += 1;
+        1
+    } else {
+        c += 2;
+        1
+        //~^ branches_sharing_code
+    };
+}
diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_bottom.stderr
index f437db8..1c470fb 100644
--- a/tests/ui/branches_sharing_code/shared_at_bottom.stderr
+++ b/tests/ui/branches_sharing_code/shared_at_bottom.stderr
@@ -172,5 +172,35 @@
 LL +         let y = 1;
    |
 
-error: aborting due to 10 previous errors
+error: all if blocks contain the same code at the end
+  --> tests/ui/branches_sharing_code/shared_at_bottom.rs:290:5
+   |
+LL | /         0
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: the end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving these statements after the if
+   |
+LL ~     }
+LL ~     0;
+   |
+
+error: all if blocks contain the same code at the end
+  --> tests/ui/branches_sharing_code/shared_at_bottom.rs:299:5
+   |
+LL | /         1
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: the end suggestion probably needs some adjustments to use the expression result correctly
+help: consider moving these statements after the if
+   |
+LL ~     }
+LL ~     1;
+   |
+
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/cast_size.32bit.stderr b/tests/ui/cast_size.32bit.stderr
index cb1620e..5811cb3 100644
--- a/tests/ui/cast_size.32bit.stderr
+++ b/tests/ui/cast_size.32bit.stderr
@@ -177,6 +177,14 @@
 LL |     9_999_999_999_999_999usize as f64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: casting `usize` to `u16` may truncate the value
+  --> tests/ui/cast_size.rs:71:20
+   |
+LL |     const N: u16 = M as u16;
+   |                    ^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
 error: literal out of range for `usize`
   --> tests/ui/cast_size.rs:63:5
    |
@@ -186,5 +194,5 @@
    = note: the literal `9_999_999_999_999_999usize` does not fit into the type `usize` whose range is `0..=4294967295`
    = note: `#[deny(overflowing_literals)]` on by default
 
-error: aborting due to 19 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/tests/ui/cast_size.64bit.stderr b/tests/ui/cast_size.64bit.stderr
index b6000a5..ba14195 100644
--- a/tests/ui/cast_size.64bit.stderr
+++ b/tests/ui/cast_size.64bit.stderr
@@ -177,5 +177,13 @@
 LL |     9_999_999_999_999_999usize as f64;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 18 previous errors
+error: casting `usize` to `u16` may truncate the value
+  --> tests/ui/cast_size.rs:71:20
+   |
+LL |     const N: u16 = M as u16;
+   |                    ^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs
index e5bef2a..ecc5866 100644
--- a/tests/ui/cast_size.rs
+++ b/tests/ui/cast_size.rs
@@ -65,3 +65,9 @@
     //~[32bit]^^ ERROR: literal out of range for `usize`
     // 999_999_999_999_999_999_999_999_999_999u128 as f128;
 }
+
+fn issue15163() {
+    const M: usize = 100;
+    const N: u16 = M as u16;
+    //~^ cast_possible_truncation
+}
diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs
index 40f40f7..5c13d86 100644
--- a/tests/ui/def_id_nocore.rs
+++ b/tests/ui/def_id_nocore.rs
@@ -7,8 +7,14 @@
 #[link(name = "c")]
 unsafe extern "C" {}
 
+#[lang = "pointee_sized"]
+pub trait PointeeSized {}
+
+#[lang = "meta_sized"]
+pub trait MetaSized: PointeeSized {}
+
 #[lang = "sized"]
-pub trait Sized {}
+pub trait Sized: MetaSized {}
 #[lang = "copy"]
 pub trait Copy {}
 #[lang = "freeze"]
diff --git a/tests/ui/def_id_nocore.stderr b/tests/ui/def_id_nocore.stderr
index 2718217..175dd07 100644
--- a/tests/ui/def_id_nocore.stderr
+++ b/tests/ui/def_id_nocore.stderr
@@ -1,5 +1,5 @@
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> tests/ui/def_id_nocore.rs:27:19
+  --> tests/ui/def_id_nocore.rs:33:19
    |
 LL |     pub fn as_ref(self) -> &'static str {
    |                   ^^^^
diff --git a/tests/ui/disallowed_script_idents.rs b/tests/ui/disallowed_script_idents.rs
index 08fd1d9..dae3800 100644
--- a/tests/ui/disallowed_script_idents.rs
+++ b/tests/ui/disallowed_script_idents.rs
@@ -15,3 +15,17 @@
     let カウンタ = 10;
     //~^ disallowed_script_idents
 }
+
+fn issue15116() {
+    const ÄÖÜ: u8 = 0;
+    const _ÄÖÜ: u8 = 0;
+    const Ä_ÖÜ: u8 = 0;
+    const ÄÖ_Ü: u8 = 0;
+    const ÄÖÜ_: u8 = 0;
+    let äöüß = 1;
+    let _äöüß = 1;
+    let ä_öüß = 1;
+    let äö_üß = 1;
+    let äöü_ß = 1;
+    let äöüß_ = 1;
+}
diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs
index 21396cb..8c32176 100644
--- a/tests/ui/doc/needless_doctest_main.rs
+++ b/tests/ui/doc/needless_doctest_main.rs
@@ -1,5 +1,3 @@
-//@ check-pass
-
 #![warn(clippy::needless_doctest_main)]
 //! issue 10491:
 //! ```rust,no_test
@@ -19,6 +17,100 @@
 /// ```
 fn foo() {}
 
+#[rustfmt::skip]
+/// Description
+/// ```rust
+/// fn main() {
+//~^ error: needless `fn main` in doctest
+///     let a = 0;
+/// }
+/// ```
+fn mulpipulpi() {}
+
+#[rustfmt::skip]
+/// With a `#[no_main]`
+/// ```rust
+/// #[no_main]
+/// fn a() {
+///     let _ = 0;
+/// }
+/// ```
+fn pulpimulpi() {}
+
+// Without a `#[no_main]` attribute
+/// ```rust
+/// fn a() {
+///     let _ = 0;
+/// }
+/// ```
+fn plumilupi() {}
+
+#[rustfmt::skip]
+/// Additional function, shouldn't trigger
+/// ```rust
+/// fn additional_function() {
+///     let _ = 0;
+///     // Thus `fn main` is actually relevant!
+/// }
+/// fn main() {
+///     let _ = 0;
+/// }
+/// ```
+fn mlupipupi() {}
+
+#[rustfmt::skip]
+/// Additional function AFTER main, shouldn't trigger
+/// ```rust
+/// fn main() {
+///     let _ = 0;
+/// }
+/// fn additional_function() {
+///     let _ = 0;
+///     // Thus `fn main` is actually relevant!
+/// }
+/// ```
+fn lumpimupli() {}
+
+#[rustfmt::skip]
+/// Ignore code block, should not lint at all
+/// ```rust, ignore
+/// fn main() {
+//~^ error: needless `fn main` in doctest
+///     // Hi!
+///     let _ = 0;
+/// }
+/// ```
+fn mpulpilumi() {}
+
+#[rustfmt::skip]
+/// Spaces in weird positions (including an \u{A0} after `main`)
+/// ```rust
+/// fn     main (){
+//~^ error: needless `fn main` in doctest
+///     let _ = 0;
+/// }
+/// ```
+fn plumpiplupi() {}
+
+/// 4 Functions, this should not lint because there are several function
+///
+/// ```rust
+/// fn a() {let _ = 0; }
+/// fn b() {let _ = 0; }
+/// fn main() { let _ = 0; }
+/// fn d() { let _ = 0; }
+/// ```
+fn pulmipulmip() {}
+
+/// 3 Functions but main is first, should also not lint
+///
+///```rust
+/// fn main() { let _ = 0; }
+/// fn b() { let _ = 0; }
+/// fn c() { let _ = 0; }
+/// ```
+fn pmuplimulip() {}
+
 fn main() {}
 
 fn issue8244() -> Result<(), ()> {
diff --git a/tests/ui/doc/needless_doctest_main.stderr b/tests/ui/doc/needless_doctest_main.stderr
new file mode 100644
index 0000000..dd5474c
--- /dev/null
+++ b/tests/ui/doc/needless_doctest_main.stderr
@@ -0,0 +1,36 @@
+error: needless `fn main` in doctest
+  --> tests/ui/doc/needless_doctest_main.rs:23:5
+   |
+LL |   /// fn main() {
+   |  _____^
+LL | |
+LL | | ///     let a = 0;
+LL | | /// }
+   | |_____^
+   |
+   = note: `-D clippy::needless-doctest-main` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::needless_doctest_main)]`
+
+error: needless `fn main` in doctest
+  --> tests/ui/doc/needless_doctest_main.rs:77:5
+   |
+LL |   /// fn main() {
+   |  _____^
+LL | |
+LL | | ///     // Hi!
+LL | | ///     let _ = 0;
+LL | | /// }
+   | |_____^
+
+error: needless `fn main` in doctest
+  --> tests/ui/doc/needless_doctest_main.rs:88:5
+   |
+LL |   /// fn     main (){
+   |  _____^
+LL | |
+LL | | ///     let _ = 0;
+LL | | /// }
+   | |_____^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/doc_broken_link.rs b/tests/ui/doc_broken_link.rs
new file mode 100644
index 0000000..7d9c0ef
--- /dev/null
+++ b/tests/ui/doc_broken_link.rs
@@ -0,0 +1,72 @@
+#![warn(clippy::doc_broken_link)]
+
+fn main() {}
+
+pub struct FakeType {}
+
+/// This might be considered a link false positive
+/// and should be ignored by this lint rule:
+/// Example of referencing some code with brackets [FakeType].
+pub fn doc_ignore_link_false_positive_1() {}
+
+/// This might be considered a link false positive
+/// and should be ignored by this lint rule:
+/// [`FakeType`]. Continue text after brackets,
+/// then (something in
+/// parenthesis).
+pub fn doc_ignore_link_false_positive_2() {}
+
+/// Test valid link, whole link single line.
+/// [doc valid link](https://test.fake/doc_valid_link)
+pub fn doc_valid_link() {}
+
+/// Test valid link, whole link single line but it has special chars such as brackets and
+/// parenthesis. [doc invalid link url invalid char](https://test.fake/doc_valid_link_url_invalid_char?foo[bar]=1&bar(foo)=2)
+pub fn doc_valid_link_url_invalid_char() {}
+
+/// Test valid link, text tag broken across multiple lines.
+/// [doc valid link broken
+/// text](https://test.fake/doc_valid_link_broken_text)
+pub fn doc_valid_link_broken_text() {}
+
+/// Test valid link, url tag broken across multiple lines, but
+/// the whole url part in a single line.
+/// [doc valid link broken url tag two lines first](https://test.fake/doc_valid_link_broken_url_tag_two_lines_first
+/// )
+pub fn doc_valid_link_broken_url_tag_two_lines_first() {}
+
+/// Test valid link, url tag broken across multiple lines, but
+/// the whole url part in a single line.
+/// [doc valid link broken url tag two lines second](
+/// https://test.fake/doc_valid_link_broken_url_tag_two_lines_second)
+pub fn doc_valid_link_broken_url_tag_two_lines_second() {}
+
+/// Test valid link, url tag broken across multiple lines, but
+/// the whole url part in a single line, but the closing pharentesis
+/// in a third line.
+/// [doc valid link broken url tag three lines](
+/// https://test.fake/doc_valid_link_broken_url_tag_three_lines
+/// )
+pub fn doc_valid_link_broken_url_tag_three_lines() {}
+
+/// Test invalid link, url part broken across multiple lines.
+/// [doc invalid link broken url scheme part](https://
+/// test.fake/doc_invalid_link_broken_url_scheme_part)
+//~^^ ERROR: possible broken doc link: broken across multiple lines
+pub fn doc_invalid_link_broken_url_scheme_part() {}
+
+/// Test invalid link, url part broken across multiple lines.
+/// [doc invalid link broken url host part](https://test
+/// .fake/doc_invalid_link_broken_url_host_part)
+//~^^ ERROR: possible broken doc link: broken across multiple lines
+pub fn doc_invalid_link_broken_url_host_part() {}
+
+/// Test invalid link, for multiple urls in the same block of comment.
+/// There is a [fist link - invalid](https://test
+/// .fake) then it continues
+//~^^ ERROR: possible broken doc link: broken across multiple lines
+/// with a [second link - valid](https://test.fake/doc_valid_link) and another [third link - invalid](https://test
+/// .fake). It ends with another
+//~^^ ERROR: possible broken doc link: broken across multiple lines
+/// line of comment.
+pub fn doc_multiple_invalid_link_broken_url() {}
diff --git a/tests/ui/doc_broken_link.stderr b/tests/ui/doc_broken_link.stderr
new file mode 100644
index 0000000..179ed97
--- /dev/null
+++ b/tests/ui/doc_broken_link.stderr
@@ -0,0 +1,29 @@
+error: possible broken doc link: broken across multiple lines
+  --> tests/ui/doc_broken_link.rs:53:5
+   |
+LL | /// [doc invalid link broken url scheme part](https://
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::doc-broken-link` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::doc_broken_link)]`
+
+error: possible broken doc link: broken across multiple lines
+  --> tests/ui/doc_broken_link.rs:59:5
+   |
+LL | /// [doc invalid link broken url host part](https://test
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: possible broken doc link: broken across multiple lines
+  --> tests/ui/doc_broken_link.rs:65:16
+   |
+LL | /// There is a [fist link - invalid](https://test
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: possible broken doc link: broken across multiple lines
+  --> tests/ui/doc_broken_link.rs:68:80
+   |
+LL | /// with a [second link - valid](https://test.fake/doc_valid_link) and another [third link - invalid](https://test
+   |                                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/empty_line_after/outer_attribute.1.fixed b/tests/ui/empty_line_after/outer_attribute.1.fixed
index 36d80a2..e36e3c2 100644
--- a/tests/ui/empty_line_after/outer_attribute.1.fixed
+++ b/tests/ui/empty_line_after/outer_attribute.1.fixed
@@ -105,4 +105,13 @@
 ")]
 pub struct Args;
 
+mod issue_14980 {
+    //~v empty_line_after_outer_attr
+    #[repr(align(536870912))]
+    enum Aligned {
+        Zero = 0,
+        One = 1,
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.2.fixed b/tests/ui/empty_line_after/outer_attribute.2.fixed
index 0e8e412..b0908fc 100644
--- a/tests/ui/empty_line_after/outer_attribute.2.fixed
+++ b/tests/ui/empty_line_after/outer_attribute.2.fixed
@@ -108,4 +108,13 @@
 ")]
 pub struct Args;
 
+mod issue_14980 {
+    //~v empty_line_after_outer_attr
+    #[repr(align(536870912))]
+    enum Aligned {
+        Zero = 0,
+        One = 1,
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.rs b/tests/ui/empty_line_after/outer_attribute.rs
index 1295088..4ae113c 100644
--- a/tests/ui/empty_line_after/outer_attribute.rs
+++ b/tests/ui/empty_line_after/outer_attribute.rs
@@ -116,4 +116,14 @@
 ")]
 pub struct Args;
 
+mod issue_14980 {
+    //~v empty_line_after_outer_attr
+    #[repr(align(536870912))]
+
+    enum Aligned {
+        Zero = 0,
+        One = 1,
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/empty_line_after/outer_attribute.stderr b/tests/ui/empty_line_after/outer_attribute.stderr
index 519ba6e..331bc7c 100644
--- a/tests/ui/empty_line_after/outer_attribute.stderr
+++ b/tests/ui/empty_line_after/outer_attribute.stderr
@@ -111,5 +111,16 @@
    |
    = help: if the empty lines are unintentional, remove them
 
-error: aborting due to 9 previous errors
+error: empty line after outer attribute
+  --> tests/ui/empty_line_after/outer_attribute.rs:121:5
+   |
+LL | /     #[repr(align(536870912))]
+LL | |
+   | |_^
+LL |       enum Aligned {
+   |       ------------ the attribute applies to this enum
+   |
+   = help: if the empty line is unintentional, remove it
+
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed
index 0ba631f..c93b83f 100644
--- a/tests/ui/eta.fixed
+++ b/tests/ui/eta.fixed
@@ -543,3 +543,21 @@
         //~^ redundant_closure
     }
 }
+
+fn issue_14789() {
+    _ = Some(1u8).map(
+        #[expect(clippy::redundant_closure)]
+        |a| foo(a),
+    );
+
+    _ = Some("foo").map(
+        #[expect(clippy::redundant_closure_for_method_calls)]
+        |s| s.to_owned(),
+    );
+
+    let _: Vec<u8> = None.map_or_else(
+        #[expect(clippy::redundant_closure)]
+        || vec![],
+        std::convert::identity,
+    );
+}
diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs
index 4d8b29d..273c8b2 100644
--- a/tests/ui/eta.rs
+++ b/tests/ui/eta.rs
@@ -543,3 +543,21 @@
         //~^ redundant_closure
     }
 }
+
+fn issue_14789() {
+    _ = Some(1u8).map(
+        #[expect(clippy::redundant_closure)]
+        |a| foo(a),
+    );
+
+    _ = Some("foo").map(
+        #[expect(clippy::redundant_closure_for_method_calls)]
+        |s| s.to_owned(),
+    );
+
+    let _: Vec<u8> = None.map_or_else(
+        #[expect(clippy::redundant_closure)]
+        || vec![],
+        std::convert::identity,
+    );
+}
diff --git a/tests/ui/exhaustive_items.fixed b/tests/ui/exhaustive_items.fixed
index 79c74ae..3b2f33d 100644
--- a/tests/ui/exhaustive_items.fixed
+++ b/tests/ui/exhaustive_items.fixed
@@ -1,3 +1,4 @@
+#![feature(default_field_values)]
 #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
 #![allow(unused)]
 
@@ -90,3 +91,9 @@
         pub bar: String,
     }
 }
+
+pub mod issue14992 {
+    pub struct A {
+        pub a: isize = 42,
+    }
+}
diff --git a/tests/ui/exhaustive_items.rs b/tests/ui/exhaustive_items.rs
index 4e851f4..b0a6a71 100644
--- a/tests/ui/exhaustive_items.rs
+++ b/tests/ui/exhaustive_items.rs
@@ -1,3 +1,4 @@
+#![feature(default_field_values)]
 #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
 #![allow(unused)]
 
@@ -87,3 +88,9 @@
         pub bar: String,
     }
 }
+
+pub mod issue14992 {
+    pub struct A {
+        pub a: isize = 42,
+    }
+}
diff --git a/tests/ui/exhaustive_items.stderr b/tests/ui/exhaustive_items.stderr
index c92c8a9..55928fa 100644
--- a/tests/ui/exhaustive_items.stderr
+++ b/tests/ui/exhaustive_items.stderr
@@ -1,5 +1,5 @@
 error: exported enums should not be exhaustive
-  --> tests/ui/exhaustive_items.rs:9:5
+  --> tests/ui/exhaustive_items.rs:10:5
    |
 LL | /     pub enum Exhaustive {
 LL | |
@@ -11,7 +11,7 @@
    | |_____^
    |
 note: the lint level is defined here
-  --> tests/ui/exhaustive_items.rs:1:9
+  --> tests/ui/exhaustive_items.rs:2:9
    |
 LL | #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@
    |
 
 error: exported enums should not be exhaustive
-  --> tests/ui/exhaustive_items.rs:19:5
+  --> tests/ui/exhaustive_items.rs:20:5
    |
 LL | /     pub enum ExhaustiveWithAttrs {
 LL | |
@@ -40,7 +40,7 @@
    |
 
 error: exported structs should not be exhaustive
-  --> tests/ui/exhaustive_items.rs:55:5
+  --> tests/ui/exhaustive_items.rs:56:5
    |
 LL | /     pub struct Exhaustive {
 LL | |
@@ -50,7 +50,7 @@
    | |_____^
    |
 note: the lint level is defined here
-  --> tests/ui/exhaustive_items.rs:1:35
+  --> tests/ui/exhaustive_items.rs:2:35
    |
 LL | #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/identity_op.fixed b/tests/ui/identity_op.fixed
index a1b5560..4e14e1a 100644
--- a/tests/ui/identity_op.fixed
+++ b/tests/ui/identity_op.fixed
@@ -312,3 +312,49 @@
     let _: u64 = 1u64 + ((x as i32 + y as i32) as u64);
     //~^ identity_op
 }
+
+fn issue_14932() {
+    let _ = 0usize + &Default::default(); // no error
+
+    0usize + &Default::default(); // no error
+
+    <usize as Default>::default();
+    //~^ identity_op
+
+    let _ = usize::default();
+    //~^ identity_op
+
+    let _n: usize = Default::default();
+    //~^ identity_op
+}
+
+// Expr's type can be inferred by the function's return type
+fn issue_14932_2() -> usize {
+    Default::default()
+    //~^ identity_op
+}
+
+trait Def {
+    fn def() -> Self;
+}
+
+impl Def for usize {
+    fn def() -> Self {
+        0
+    }
+}
+
+fn issue_14932_3() {
+    let _ = 0usize + &Def::def(); // no error
+
+    0usize + &Def::def(); // no error
+
+    <usize as Def>::def();
+    //~^ identity_op
+
+    let _ = usize::def();
+    //~^ identity_op
+
+    let _n: usize = Def::def();
+    //~^ identity_op
+}
diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs
index f603e10..ebbef57 100644
--- a/tests/ui/identity_op.rs
+++ b/tests/ui/identity_op.rs
@@ -312,3 +312,49 @@
     let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64);
     //~^ identity_op
 }
+
+fn issue_14932() {
+    let _ = 0usize + &Default::default(); // no error
+
+    0usize + &Default::default(); // no error
+
+    0usize + &<usize as Default>::default();
+    //~^ identity_op
+
+    let _ = 0usize + &usize::default();
+    //~^ identity_op
+
+    let _n: usize = 0usize + &Default::default();
+    //~^ identity_op
+}
+
+// Expr's type can be inferred by the function's return type
+fn issue_14932_2() -> usize {
+    0usize + &Default::default()
+    //~^ identity_op
+}
+
+trait Def {
+    fn def() -> Self;
+}
+
+impl Def for usize {
+    fn def() -> Self {
+        0
+    }
+}
+
+fn issue_14932_3() {
+    let _ = 0usize + &Def::def(); // no error
+
+    0usize + &Def::def(); // no error
+
+    0usize + &<usize as Def>::def();
+    //~^ identity_op
+
+    let _ = 0usize + &usize::def();
+    //~^ identity_op
+
+    let _n: usize = 0usize + &Def::def();
+    //~^ identity_op
+}
diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr
index 8f9c2b6..24fa5db 100644
--- a/tests/ui/identity_op.stderr
+++ b/tests/ui/identity_op.stderr
@@ -379,5 +379,47 @@
 LL |     let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x as i32 + y as i32) as u64)`
 
-error: aborting due to 63 previous errors
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:321:5
+   |
+LL |     0usize + &<usize as Default>::default();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `<usize as Default>::default()`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:324:13
+   |
+LL |     let _ = 0usize + &usize::default();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `usize::default()`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:327:21
+   |
+LL |     let _n: usize = 0usize + &Default::default();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `Default::default()`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:333:5
+   |
+LL |     0usize + &Default::default()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `Default::default()`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:352:5
+   |
+LL |     0usize + &<usize as Def>::def();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `<usize as Def>::def()`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:355:13
+   |
+LL |     let _ = 0usize + &usize::def();
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `usize::def()`
+
+error: this operation has no effect
+  --> tests/ui/identity_op.rs:358:21
+   |
+LL |     let _n: usize = 0usize + &Def::def();
+   |                     ^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `Def::def()`
+
+error: aborting due to 70 previous errors
 
diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs
index 002a791..701a865 100644
--- a/tests/ui/infinite_iter.rs
+++ b/tests/ui/infinite_iter.rs
@@ -38,7 +38,7 @@
     //~^ infinite_iter
 
     // infinite iter
-    (0_u64..).filter(|x| x % 2 == 0).last();
+    (0_u64..).filter(|x| x.is_multiple_of(2)).last();
     //~^ infinite_iter
 
     // not an infinite, because ranges are double-ended
diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr
index 47133a2..b9e7c00 100644
--- a/tests/ui/infinite_iter.stderr
+++ b/tests/ui/infinite_iter.stderr
@@ -42,8 +42,8 @@
 error: infinite iteration detected
   --> tests/ui/infinite_iter.rs:41:5
    |
-LL |     (0_u64..).filter(|x| x % 2 == 0).last();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     (0_u64..).filter(|x| x.is_multiple_of(2)).last();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: possible infinite iteration detected
   --> tests/ui/infinite_iter.rs:53:5
diff --git a/tests/ui/iter_kv_map.fixed b/tests/ui/iter_kv_map.fixed
index 874f749..b18dda3 100644
--- a/tests/ui/iter_kv_map.fixed
+++ b/tests/ui/iter_kv_map.fixed
@@ -30,15 +30,19 @@
 
     let _ = map.clone().values().collect::<Vec<_>>();
     //~^ iter_kv_map
-    let _ = map.keys().filter(|x| *x % 2 == 0).count();
+    let _ = map.keys().filter(|x| x.is_multiple_of(2)).count();
     //~^ iter_kv_map
 
     // Don't lint
-    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+    let _ = map
+        .iter()
+        .filter(|(_, val)| val.is_multiple_of(2))
+        .map(|(key, _)| key)
+        .count();
     let _ = map.iter().map(get_key).collect::<Vec<_>>();
 
     // Linting the following could be an improvement to the lint
-    // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+    // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count();
 
     // Lint
     let _ = map.keys().map(|key| key * 9).count();
@@ -84,15 +88,19 @@
 
     let _ = map.clone().values().collect::<Vec<_>>();
     //~^ iter_kv_map
-    let _ = map.keys().filter(|x| *x % 2 == 0).count();
+    let _ = map.keys().filter(|x| x.is_multiple_of(2)).count();
     //~^ iter_kv_map
 
     // Don't lint
-    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+    let _ = map
+        .iter()
+        .filter(|(_, val)| val.is_multiple_of(2))
+        .map(|(key, _)| key)
+        .count();
     let _ = map.iter().map(get_key).collect::<Vec<_>>();
 
     // Linting the following could be an improvement to the lint
-    // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+    // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count();
 
     // Lint
     let _ = map.keys().map(|key| key * 9).count();
diff --git a/tests/ui/iter_kv_map.rs b/tests/ui/iter_kv_map.rs
index f570e3c..729e4e8 100644
--- a/tests/ui/iter_kv_map.rs
+++ b/tests/ui/iter_kv_map.rs
@@ -30,15 +30,19 @@
 
     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
     //~^ iter_kv_map
-    let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+    let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count();
     //~^ iter_kv_map
 
     // Don't lint
-    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+    let _ = map
+        .iter()
+        .filter(|(_, val)| val.is_multiple_of(2))
+        .map(|(key, _)| key)
+        .count();
     let _ = map.iter().map(get_key).collect::<Vec<_>>();
 
     // Linting the following could be an improvement to the lint
-    // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+    // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count();
 
     // Lint
     let _ = map.iter().map(|(key, _value)| key * 9).count();
@@ -86,15 +90,19 @@
 
     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
     //~^ iter_kv_map
-    let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+    let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count();
     //~^ iter_kv_map
 
     // Don't lint
-    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+    let _ = map
+        .iter()
+        .filter(|(_, val)| val.is_multiple_of(2))
+        .map(|(key, _)| key)
+        .count();
     let _ = map.iter().map(get_key).collect::<Vec<_>>();
 
     // Linting the following could be an improvement to the lint
-    // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+    // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count();
 
     // Lint
     let _ = map.iter().map(|(key, _value)| key * 9).count();
diff --git a/tests/ui/iter_kv_map.stderr b/tests/ui/iter_kv_map.stderr
index 31ee76c..8f73541 100644
--- a/tests/ui/iter_kv_map.stderr
+++ b/tests/ui/iter_kv_map.stderr
@@ -52,29 +52,29 @@
 error: iterating on a map's keys
   --> tests/ui/iter_kv_map.rs:33:13
    |
-LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:44:13
+  --> tests/ui/iter_kv_map.rs:48:13
    |
 LL |     let _ = map.iter().map(|(key, _value)| key * 9).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:46:13
+  --> tests/ui/iter_kv_map.rs:50:13
    |
 LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:50:13
+  --> tests/ui/iter_kv_map.rs:54:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:54:13
+  --> tests/ui/iter_kv_map.rs:58:13
    |
 LL |       let _ = map
    |  _____________^
@@ -97,85 +97,85 @@
    |
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:65:13
+  --> tests/ui/iter_kv_map.rs:69:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:70:13
+  --> tests/ui/iter_kv_map.rs:74:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:72:13
+  --> tests/ui/iter_kv_map.rs:76:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:74:13
+  --> tests/ui/iter_kv_map.rs:78:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:77:13
+  --> tests/ui/iter_kv_map.rs:81:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:79:13
+  --> tests/ui/iter_kv_map.rs:83:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:82:13
+  --> tests/ui/iter_kv_map.rs:86:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:84:13
+  --> tests/ui/iter_kv_map.rs:88:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:87:13
+  --> tests/ui/iter_kv_map.rs:91:13
    |
 LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:89:13
+  --> tests/ui/iter_kv_map.rs:93:13
    |
-LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:100:13
+  --> tests/ui/iter_kv_map.rs:108:13
    |
 LL |     let _ = map.iter().map(|(key, _value)| key * 9).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:102:13
+  --> tests/ui/iter_kv_map.rs:110:13
    |
 LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:106:13
+  --> tests/ui/iter_kv_map.rs:114:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:110:13
+  --> tests/ui/iter_kv_map.rs:118:13
    |
 LL |       let _ = map
    |  _____________^
@@ -198,73 +198,73 @@
    |
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:121:13
+  --> tests/ui/iter_kv_map.rs:129:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:137:13
+  --> tests/ui/iter_kv_map.rs:145:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:140:13
+  --> tests/ui/iter_kv_map.rs:148:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:143:13
+  --> tests/ui/iter_kv_map.rs:151:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:152:13
+  --> tests/ui/iter_kv_map.rs:160:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:155:13
+  --> tests/ui/iter_kv_map.rs:163:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:158:13
+  --> tests/ui/iter_kv_map.rs:166:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:161:13
+  --> tests/ui/iter_kv_map.rs:169:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
 
 error: iterating on a map's keys
-  --> tests/ui/iter_kv_map.rs:164:13
+  --> tests/ui/iter_kv_map.rs:172:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:167:13
+  --> tests/ui/iter_kv_map.rs:175:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:170:13
+  --> tests/ui/iter_kv_map.rs:178:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's values
-  --> tests/ui/iter_kv_map.rs:185:13
+  --> tests/ui/iter_kv_map.rs:193:13
    |
 LL |     let _ = map.as_ref().iter().map(|(_, v)| v).copied().collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.as_ref().values()`
diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs
index 3ed124f..132f145 100644
--- a/tests/ui/large_stack_frames.rs
+++ b/tests/ui/large_stack_frames.rs
@@ -1,8 +1,7 @@
 //@ normalize-stderr-test: "\b10000(08|16|32)\b" -> "100$$PTR"
 //@ normalize-stderr-test: "\b2500(060|120)\b" -> "250$$PTR"
-#![allow(unused, incomplete_features)]
+#![allow(unused)]
 #![warn(clippy::large_stack_frames)]
-#![feature(unsized_locals)]
 
 use std::hint::black_box;
 
@@ -11,11 +10,6 @@
     black_box(&x);
 }
 
-fn unsized_local() {
-    let x: dyn std::fmt::Display = *(Box::new(1) as Box<dyn std::fmt::Display>);
-    black_box(&x);
-}
-
 struct ArrayDefault<const N: usize>([u8; N]);
 
 impl<const N: usize> Default for ArrayDefault<N> {
diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr
index 0ff49e9..79482e6 100644
--- a/tests/ui/large_stack_frames.stderr
+++ b/tests/ui/large_stack_frames.stderr
@@ -1,5 +1,5 @@
 error: this function may allocate 250$PTR bytes on the stack
-  --> tests/ui/large_stack_frames.rs:27:4
+  --> tests/ui/large_stack_frames.rs:21:4
    |
 LL | fn many_small_arrays() {
    |    ^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@
    = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]`
 
 error: this function may allocate 1000000 bytes on the stack
-  --> tests/ui/large_stack_frames.rs:38:4
+  --> tests/ui/large_stack_frames.rs:32:4
    |
 LL | fn large_return_value() -> ArrayDefault<1_000_000> {
    |    ^^^^^^^^^^^^^^^^^^      ----------------------- this is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>`
@@ -21,7 +21,7 @@
    = note: 1000000 bytes is larger than Clippy's configured `stack-size-threshold` of 512000
 
 error: this function may allocate 100$PTR bytes on the stack
-  --> tests/ui/large_stack_frames.rs:44:4
+  --> tests/ui/large_stack_frames.rs:38:4
    |
 LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) {
    |    ^^^^^^^^^^^^ - `x` is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>`
@@ -29,7 +29,7 @@
    = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000
 
 error: this function may allocate 100$PTR bytes on the stack
-  --> tests/ui/large_stack_frames.rs:51:13
+  --> tests/ui/large_stack_frames.rs:45:13
    |
 LL |     let f = || black_box(&[0u8; 1_000_000]);
    |             ^^^^^^^^^^^^^^----------------^
diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed
index 5e7a2ad..304eace 100644
--- a/tests/ui/let_unit.fixed
+++ b/tests/ui/let_unit.fixed
@@ -61,7 +61,7 @@
         //~^ let_unit_value
         .into_iter()
         .map(|i| i * 2)
-        .filter(|i| i % 2 == 0)
+        .filter(|i| i.is_multiple_of(2))
         .map(|_| ())
         .next()
         .unwrap();
diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs
index 7b06f69..a02cb34 100644
--- a/tests/ui/let_unit.rs
+++ b/tests/ui/let_unit.rs
@@ -61,7 +61,7 @@
         //~^ let_unit_value
         .into_iter()
         .map(|i| i * 2)
-        .filter(|i| i % 2 == 0)
+        .filter(|i| i.is_multiple_of(2))
         .map(|_| ())
         .next()
         .unwrap();
diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr
index d7d01d3..d743110 100644
--- a/tests/ui/let_unit.stderr
+++ b/tests/ui/let_unit.stderr
@@ -25,7 +25,7 @@
 LL +
 LL +         .into_iter()
 LL +         .map(|i| i * 2)
-LL +         .filter(|i| i % 2 == 0)
+LL +         .filter(|i| i.is_multiple_of(2))
 LL +         .map(|_| ())
 LL +         .next()
 LL +         .unwrap();
diff --git a/tests/ui/manual_contains.fixed b/tests/ui/manual_contains.fixed
index d26c948..18171f0 100644
--- a/tests/ui/manual_contains.fixed
+++ b/tests/ui/manual_contains.fixed
@@ -58,7 +58,7 @@
 
     let vec: Vec<u32> = vec![1, 2, 3, 4, 5, 6];
     let values = &vec[..];
-    let _ = values.iter().any(|&v| v % 2 == 0);
+    let _ = values.iter().any(|&v| v.is_multiple_of(2));
     let _ = values.iter().any(|&v| v * 2 == 6);
     let _ = values.iter().any(|&v| v == v);
     let _ = values.iter().any(|&v| 4 == 4);
diff --git a/tests/ui/manual_contains.rs b/tests/ui/manual_contains.rs
index fe67d2e..918f4d6 100644
--- a/tests/ui/manual_contains.rs
+++ b/tests/ui/manual_contains.rs
@@ -58,7 +58,7 @@
 
     let vec: Vec<u32> = vec![1, 2, 3, 4, 5, 6];
     let values = &vec[..];
-    let _ = values.iter().any(|&v| v % 2 == 0);
+    let _ = values.iter().any(|&v| v.is_multiple_of(2));
     let _ = values.iter().any(|&v| v * 2 == 6);
     let _ = values.iter().any(|&v| v == v);
     let _ = values.iter().any(|&v| 4 == 4);
diff --git a/tests/ui/manual_find_fixable.fixed b/tests/ui/manual_find_fixable.fixed
index 01b3eba..c69b0cb 100644
--- a/tests/ui/manual_find_fixable.fixed
+++ b/tests/ui/manual_find_fixable.fixed
@@ -11,7 +11,7 @@
 }
 
 fn with_pat(arr: Vec<(u32, u32)>) -> Option<u32> {
-    arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)
+    arr.into_iter().map(|(a, _)| a).find(|&a| a.is_multiple_of(2))
 }
 
 struct Data {
@@ -63,7 +63,7 @@
 
 fn with_else(arr: Vec<u32>) -> Option<u32> {
     for el in arr {
-        if el % 2 == 0 {
+        if el.is_multiple_of(2) {
             return Some(el);
         } else {
             println!("{}", el);
diff --git a/tests/ui/manual_find_fixable.rs b/tests/ui/manual_find_fixable.rs
index ce62a4b..db7092f 100644
--- a/tests/ui/manual_find_fixable.rs
+++ b/tests/ui/manual_find_fixable.rs
@@ -19,7 +19,7 @@
 fn with_pat(arr: Vec<(u32, u32)>) -> Option<u32> {
     for (a, _) in arr {
         //~^ manual_find
-        if a % 2 == 0 {
+        if a.is_multiple_of(2) {
             return Some(a);
         }
     }
@@ -111,7 +111,7 @@
 
 fn with_else(arr: Vec<u32>) -> Option<u32> {
     for el in arr {
-        if el % 2 == 0 {
+        if el.is_multiple_of(2) {
             return Some(el);
         } else {
             println!("{}", el);
diff --git a/tests/ui/manual_find_fixable.stderr b/tests/ui/manual_find_fixable.stderr
index 020635d..0c05c0d 100644
--- a/tests/ui/manual_find_fixable.stderr
+++ b/tests/ui/manual_find_fixable.stderr
@@ -17,11 +17,11 @@
    |
 LL | /     for (a, _) in arr {
 LL | |
-LL | |         if a % 2 == 0 {
+LL | |         if a.is_multiple_of(2) {
 LL | |             return Some(a);
 ...  |
 LL | |     None
-   | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)`
+   | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a.is_multiple_of(2))`
 
 error: manual implementation of `Iterator::find`
   --> tests/ui/manual_find_fixable.rs:34:5
diff --git a/tests/ui/manual_inspect.fixed b/tests/ui/manual_inspect.fixed
index 9b768db..00a1915 100644
--- a/tests/ui/manual_inspect.fixed
+++ b/tests/ui/manual_inspect.fixed
@@ -154,7 +154,6 @@
     });
 
     let _ = [0]
-        //~^ suspicious_map
         .into_iter()
         .inspect(|&x| {
             //~^ manual_inspect
diff --git a/tests/ui/manual_inspect.rs b/tests/ui/manual_inspect.rs
index e679636..b3b1713 100644
--- a/tests/ui/manual_inspect.rs
+++ b/tests/ui/manual_inspect.rs
@@ -165,7 +165,6 @@
     });
 
     let _ = [0]
-        //~^ suspicious_map
         .into_iter()
         .map(|x| {
             //~^ manual_inspect
diff --git a/tests/ui/manual_inspect.stderr b/tests/ui/manual_inspect.stderr
index 78b085f..70c00c1 100644
--- a/tests/ui/manual_inspect.stderr
+++ b/tests/ui/manual_inspect.stderr
@@ -157,25 +157,8 @@
 LL ~         println!("{}", x);
    |
 
-error: this call to `map()` won't have an effect on the call to `count()`
-  --> tests/ui/manual_inspect.rs:167:13
-   |
-LL |       let _ = [0]
-   |  _____________^
-LL | |
-LL | |         .into_iter()
-LL | |         .map(|x| {
-...  |
-LL | |         })
-LL | |         .count();
-   | |________________^
-   |
-   = help: make sure you did not confuse `map` with `filter`, `for_each` or `inspect`
-   = note: `-D clippy::suspicious-map` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::suspicious_map)]`
-
 error: using `map` over `inspect`
-  --> tests/ui/manual_inspect.rs:170:10
+  --> tests/ui/manual_inspect.rs:169:10
    |
 LL |         .map(|x| {
    |          ^^^
@@ -188,7 +171,7 @@
    |
 
 error: using `map` over `inspect`
-  --> tests/ui/manual_inspect.rs:203:30
+  --> tests/ui/manual_inspect.rs:202:30
    |
 LL |     if let Some(x) = Some(1).map(|x| { println!("{x}");
    |                              ^^^
@@ -200,5 +183,5 @@
 LL ~          }) {
    |
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/tests/ui/manual_is_multiple_of.fixed b/tests/ui/manual_is_multiple_of.fixed
new file mode 100644
index 0000000..6735b99
--- /dev/null
+++ b/tests/ui/manual_is_multiple_of.fixed
@@ -0,0 +1,25 @@
+//@aux-build: proc_macros.rs
+#![warn(clippy::manual_is_multiple_of)]
+
+fn main() {}
+
+#[clippy::msrv = "1.87"]
+fn f(a: u64, b: u64) {
+    let _ = a.is_multiple_of(b); //~ manual_is_multiple_of
+    let _ = (a + 1).is_multiple_of(b + 1); //~ manual_is_multiple_of
+    let _ = !a.is_multiple_of(b); //~ manual_is_multiple_of
+    let _ = !(a + 1).is_multiple_of(b + 1); //~ manual_is_multiple_of
+
+    let _ = !a.is_multiple_of(b); //~ manual_is_multiple_of
+    let _ = !a.is_multiple_of(b); //~ manual_is_multiple_of
+
+    proc_macros::external! {
+        let a: u64 = 23424;
+        let _ = a % 4096 == 0;
+    }
+}
+
+#[clippy::msrv = "1.86"]
+fn g(a: u64, b: u64) {
+    let _ = a % b == 0;
+}
diff --git a/tests/ui/manual_is_multiple_of.rs b/tests/ui/manual_is_multiple_of.rs
new file mode 100644
index 0000000..00b638e
--- /dev/null
+++ b/tests/ui/manual_is_multiple_of.rs
@@ -0,0 +1,25 @@
+//@aux-build: proc_macros.rs
+#![warn(clippy::manual_is_multiple_of)]
+
+fn main() {}
+
+#[clippy::msrv = "1.87"]
+fn f(a: u64, b: u64) {
+    let _ = a % b == 0; //~ manual_is_multiple_of
+    let _ = (a + 1) % (b + 1) == 0; //~ manual_is_multiple_of
+    let _ = a % b != 0; //~ manual_is_multiple_of
+    let _ = (a + 1) % (b + 1) != 0; //~ manual_is_multiple_of
+
+    let _ = a % b > 0; //~ manual_is_multiple_of
+    let _ = 0 < a % b; //~ manual_is_multiple_of
+
+    proc_macros::external! {
+        let a: u64 = 23424;
+        let _ = a % 4096 == 0;
+    }
+}
+
+#[clippy::msrv = "1.86"]
+fn g(a: u64, b: u64) {
+    let _ = a % b == 0;
+}
diff --git a/tests/ui/manual_is_multiple_of.stderr b/tests/ui/manual_is_multiple_of.stderr
new file mode 100644
index 0000000..0b1ae70
--- /dev/null
+++ b/tests/ui/manual_is_multiple_of.stderr
@@ -0,0 +1,41 @@
+error: manual implementation of `.is_multiple_of()`
+  --> tests/ui/manual_is_multiple_of.rs:8:13
+   |
+LL |     let _ = a % b == 0;
+   |             ^^^^^^^^^^ help: replace with: `a.is_multiple_of(b)`
+   |
+   = note: `-D clippy::manual-is-multiple-of` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_is_multiple_of)]`
+
+error: manual implementation of `.is_multiple_of()`
+  --> tests/ui/manual_is_multiple_of.rs:9:13
+   |
+LL |     let _ = (a + 1) % (b + 1) == 0;
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(a + 1).is_multiple_of(b + 1)`
+
+error: manual implementation of `.is_multiple_of()`
+  --> tests/ui/manual_is_multiple_of.rs:10:13
+   |
+LL |     let _ = a % b != 0;
+   |             ^^^^^^^^^^ help: replace with: `!a.is_multiple_of(b)`
+
+error: manual implementation of `.is_multiple_of()`
+  --> tests/ui/manual_is_multiple_of.rs:11:13
+   |
+LL |     let _ = (a + 1) % (b + 1) != 0;
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `!(a + 1).is_multiple_of(b + 1)`
+
+error: manual implementation of `.is_multiple_of()`
+  --> tests/ui/manual_is_multiple_of.rs:13:13
+   |
+LL |     let _ = a % b > 0;
+   |             ^^^^^^^^^ help: replace with: `!a.is_multiple_of(b)`
+
+error: manual implementation of `.is_multiple_of()`
+  --> tests/ui/manual_is_multiple_of.rs:14:13
+   |
+LL |     let _ = 0 < a % b;
+   |             ^^^^^^^^^ help: replace with: `!a.is_multiple_of(b)`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/manual_is_variant_and.fixed b/tests/ui/manual_is_variant_and.fixed
index 18a7218..6425f32 100644
--- a/tests/ui/manual_is_variant_and.fixed
+++ b/tests/ui/manual_is_variant_and.fixed
@@ -77,7 +77,7 @@
     let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
 
     // Should not lint.
-    let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true);
+    let _ = Foo::<u32>(0).map(|x| x.is_multiple_of(2)) == Some(true);
     let _ = Some(2).map(|x| x % 2 == 0) != foo();
     let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true));
     let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
@@ -96,11 +96,11 @@
     });
     let _ = res.is_ok_and(|x| x > 1);
 
-    let _ = Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    let _ = Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2));
     //~^ manual_is_variant_and
-    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2));
     //~^ manual_is_variant_and
-    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0);
+    let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2));
     //~^ manual_is_variant_and
 
     // won't fix because the return type of the closure is not `bool`
diff --git a/tests/ui/manual_is_variant_and.rs b/tests/ui/manual_is_variant_and.rs
index a92f7c0..e069e97 100644
--- a/tests/ui/manual_is_variant_and.rs
+++ b/tests/ui/manual_is_variant_and.rs
@@ -83,7 +83,7 @@
     let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
 
     // Should not lint.
-    let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true);
+    let _ = Foo::<u32>(0).map(|x| x.is_multiple_of(2)) == Some(true);
     let _ = Some(2).map(|x| x % 2 == 0) != foo();
     let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true));
     let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true);
@@ -105,11 +105,11 @@
     //~^ manual_is_variant_and
         .unwrap_or_default();
 
-    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true);
+    let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) == Ok(true);
     //~^ manual_is_variant_and
-    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+    let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true);
     //~^ manual_is_variant_and
-    let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
+    let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true);
     //~^ manual_is_variant_and
 
     // won't fix because the return type of the closure is not `bool`
diff --git a/tests/ui/manual_is_variant_and.stderr b/tests/ui/manual_is_variant_and.stderr
index 1fb437a..f770319 100644
--- a/tests/ui/manual_is_variant_and.stderr
+++ b/tests/ui/manual_is_variant_and.stderr
@@ -105,20 +105,20 @@
 error: called `.map() == Ok()`
   --> tests/ui/manual_is_variant_and.rs:108:13
    |
-LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) == Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2))`
 
 error: called `.map() != Ok()`
   --> tests/ui/manual_is_variant_and.rs:110:13
    |
-LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2))`
 
 error: called `.map() != Ok()`
   --> tests/ui/manual_is_variant_and.rs:112:13
    |
-LL |     let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)`
+LL |     let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2))`
 
 error: called `map(<f>).unwrap_or_default()` on a `Result` value
   --> tests/ui/manual_is_variant_and.rs:119:18
diff --git a/tests/ui/manual_ok_err.fixed b/tests/ui/manual_ok_err.fixed
index e6f799a..9b70ce0 100644
--- a/tests/ui/manual_ok_err.fixed
+++ b/tests/ui/manual_ok_err.fixed
@@ -103,3 +103,27 @@
     };
     //~^^^^^ manual_ok_err
 }
+
+mod issue15051 {
+    struct Container {
+        field: Result<bool, ()>,
+    }
+
+    #[allow(clippy::needless_borrow)]
+    fn with_addr_of(x: &Container) -> Option<&bool> {
+        (&x.field).as_ref().ok()
+    }
+
+    fn from_fn(x: &Container) -> Option<&bool> {
+        let result_with_ref = || &x.field;
+        result_with_ref().as_ref().ok()
+    }
+
+    fn result_with_ref_mut(x: &mut Container) -> &mut Result<bool, ()> {
+        &mut x.field
+    }
+
+    fn from_fn_mut(x: &mut Container) -> Option<&mut bool> {
+        result_with_ref_mut(x).as_mut().ok()
+    }
+}
diff --git a/tests/ui/manual_ok_err.rs b/tests/ui/manual_ok_err.rs
index 972b2c4..dee9046 100644
--- a/tests/ui/manual_ok_err.rs
+++ b/tests/ui/manual_ok_err.rs
@@ -141,3 +141,39 @@
     };
     //~^^^^^ manual_ok_err
 }
+
+mod issue15051 {
+    struct Container {
+        field: Result<bool, ()>,
+    }
+
+    #[allow(clippy::needless_borrow)]
+    fn with_addr_of(x: &Container) -> Option<&bool> {
+        match &x.field {
+            //~^ manual_ok_err
+            Ok(panel) => Some(panel),
+            Err(_) => None,
+        }
+    }
+
+    fn from_fn(x: &Container) -> Option<&bool> {
+        let result_with_ref = || &x.field;
+        match result_with_ref() {
+            //~^ manual_ok_err
+            Ok(panel) => Some(panel),
+            Err(_) => None,
+        }
+    }
+
+    fn result_with_ref_mut(x: &mut Container) -> &mut Result<bool, ()> {
+        &mut x.field
+    }
+
+    fn from_fn_mut(x: &mut Container) -> Option<&mut bool> {
+        match result_with_ref_mut(x) {
+            //~^ manual_ok_err
+            Ok(panel) => Some(panel),
+            Err(_) => None,
+        }
+    }
+}
diff --git a/tests/ui/manual_ok_err.stderr b/tests/ui/manual_ok_err.stderr
index 040e170..448fbff 100644
--- a/tests/ui/manual_ok_err.stderr
+++ b/tests/ui/manual_ok_err.stderr
@@ -111,5 +111,35 @@
 LL ~     };
    |
 
-error: aborting due to 9 previous errors
+error: manual implementation of `ok`
+  --> tests/ui/manual_ok_err.rs:152:9
+   |
+LL | /         match &x.field {
+LL | |
+LL | |             Ok(panel) => Some(panel),
+LL | |             Err(_) => None,
+LL | |         }
+   | |_________^ help: replace with: `(&x.field).as_ref().ok()`
+
+error: manual implementation of `ok`
+  --> tests/ui/manual_ok_err.rs:161:9
+   |
+LL | /         match result_with_ref() {
+LL | |
+LL | |             Ok(panel) => Some(panel),
+LL | |             Err(_) => None,
+LL | |         }
+   | |_________^ help: replace with: `result_with_ref().as_ref().ok()`
+
+error: manual implementation of `ok`
+  --> tests/ui/manual_ok_err.rs:173:9
+   |
+LL | /         match result_with_ref_mut(x) {
+LL | |
+LL | |             Ok(panel) => Some(panel),
+LL | |             Err(_) => None,
+LL | |         }
+   | |_________^ help: replace with: `result_with_ref_mut(x).as_mut().ok()`
+
+error: aborting due to 12 previous errors
 
diff --git a/tests/ui/missing_const_for_fn/const_trait.fixed b/tests/ui/missing_const_for_fn/const_trait.fixed
index 7e0d4fc..f1d5579 100644
--- a/tests/ui/missing_const_for_fn/const_trait.fixed
+++ b/tests/ui/missing_const_for_fn/const_trait.fixed
@@ -25,7 +25,7 @@
     0u64.method();
 }
 
-// False negative, see FIXME comment in `clipy_utils::qualify_min_const`
+// False negative, see FIXME comment in `clippy_utils::qualify_min_const_fn`
 fn could_be_const_but_does_not_trigger<T>(t: T)
 where
     T: const ConstTrait,
diff --git a/tests/ui/missing_const_for_fn/const_trait.rs b/tests/ui/missing_const_for_fn/const_trait.rs
index 439da46..d495759 100644
--- a/tests/ui/missing_const_for_fn/const_trait.rs
+++ b/tests/ui/missing_const_for_fn/const_trait.rs
@@ -25,7 +25,7 @@
     0u64.method();
 }
 
-// False negative, see FIXME comment in `clipy_utils::qualify_min_const`
+// False negative, see FIXME comment in `clippy_utils::qualify_min_const_fn`
 fn could_be_const_but_does_not_trigger<T>(t: T)
 where
     T: const ConstTrait,
diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed
index 65eb2d5..95bf63e 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.fixed
+++ b/tests/ui/missing_const_for_fn/could_be_const.fixed
@@ -221,3 +221,60 @@
     //~^ missing_const_for_fn
     *x += 1;
 }
+
+mod issue_15079 {
+    pub trait Trait {}
+
+    pub struct Struct<T: Trait> {
+        _t: Option<T>,
+    }
+
+    impl<T: Trait> Struct<T> {
+        #[clippy::msrv = "1.60"]
+        pub fn new_1_60() -> Self {
+            Self { _t: None }
+        }
+
+        #[clippy::msrv = "1.61"]
+        pub const fn new_1_61() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+    }
+
+    pub struct S2<T> {
+        _t: Option<T>,
+    }
+
+    impl<T> S2<T> {
+        #[clippy::msrv = "1.60"]
+        pub const fn new_1_60() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+
+        #[clippy::msrv = "1.61"]
+        pub const fn new_1_61() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+    }
+
+    pub struct S3<T: ?Sized + 'static> {
+        _t: Option<&'static T>,
+    }
+
+    impl<T: ?Sized + 'static> S3<T> {
+        #[clippy::msrv = "1.60"]
+        pub const fn new_1_60() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+
+        #[clippy::msrv = "1.61"]
+        pub const fn new_1_61() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+    }
+}
diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs
index 3690d2f..8290be6 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -221,3 +221,60 @@
     //~^ missing_const_for_fn
     *x += 1;
 }
+
+mod issue_15079 {
+    pub trait Trait {}
+
+    pub struct Struct<T: Trait> {
+        _t: Option<T>,
+    }
+
+    impl<T: Trait> Struct<T> {
+        #[clippy::msrv = "1.60"]
+        pub fn new_1_60() -> Self {
+            Self { _t: None }
+        }
+
+        #[clippy::msrv = "1.61"]
+        pub fn new_1_61() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+    }
+
+    pub struct S2<T> {
+        _t: Option<T>,
+    }
+
+    impl<T> S2<T> {
+        #[clippy::msrv = "1.60"]
+        pub fn new_1_60() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+
+        #[clippy::msrv = "1.61"]
+        pub fn new_1_61() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+    }
+
+    pub struct S3<T: ?Sized + 'static> {
+        _t: Option<&'static T>,
+    }
+
+    impl<T: ?Sized + 'static> S3<T> {
+        #[clippy::msrv = "1.60"]
+        pub fn new_1_60() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+
+        #[clippy::msrv = "1.61"]
+        pub fn new_1_61() -> Self {
+            //~^ missing_const_for_fn
+            Self { _t: None }
+        }
+    }
+}
diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr
index 10e07d1..17cbc43 100644
--- a/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -332,5 +332,75 @@
 LL | const fn mut_add(x: &mut i32) {
    | +++++
 
-error: aborting due to 25 previous errors
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:239:9
+   |
+LL | /         pub fn new_1_61() -> Self {
+LL | |
+LL | |             Self { _t: None }
+LL | |         }
+   | |_________^
+   |
+help: make the function `const`
+   |
+LL |         pub const fn new_1_61() -> Self {
+   |             +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:251:9
+   |
+LL | /         pub fn new_1_60() -> Self {
+LL | |
+LL | |             Self { _t: None }
+LL | |         }
+   | |_________^
+   |
+help: make the function `const`
+   |
+LL |         pub const fn new_1_60() -> Self {
+   |             +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:257:9
+   |
+LL | /         pub fn new_1_61() -> Self {
+LL | |
+LL | |             Self { _t: None }
+LL | |         }
+   | |_________^
+   |
+help: make the function `const`
+   |
+LL |         pub const fn new_1_61() -> Self {
+   |             +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:269:9
+   |
+LL | /         pub fn new_1_60() -> Self {
+LL | |
+LL | |             Self { _t: None }
+LL | |         }
+   | |_________^
+   |
+help: make the function `const`
+   |
+LL |         pub const fn new_1_60() -> Self {
+   |             +++++
+
+error: this could be a `const fn`
+  --> tests/ui/missing_const_for_fn/could_be_const.rs:275:9
+   |
+LL | /         pub fn new_1_61() -> Self {
+LL | |
+LL | |             Self { _t: None }
+LL | |         }
+   | |_________^
+   |
+help: make the function `const`
+   |
+LL |         pub const fn new_1_61() -> Self {
+   |             +++++
+
+error: aborting due to 30 previous errors
 
diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs
index ffdae85..d016e09 100644
--- a/tests/ui/missing_panics_doc.rs
+++ b/tests/ui/missing_panics_doc.rs
@@ -250,3 +250,31 @@
         }
     }
 }
+
+/// This needs documenting
+pub fn unwrap_expect_etc_in_const() {
+    let a = const { std::num::NonZeroUsize::new(1).unwrap() };
+    // This should still pass the lint even if it is guaranteed to panic at compile-time
+    let b = const { std::num::NonZeroUsize::new(0).unwrap() };
+}
+
+/// This needs documenting
+pub const fn unwrap_expect_etc_in_const_fn_fails() {
+    //~^ missing_panics_doc
+    let a = std::num::NonZeroUsize::new(1).unwrap();
+}
+
+/// This needs documenting
+pub const fn assert_in_const_fn_fails() {
+    //~^ missing_panics_doc
+    let x = 0;
+    if x == 0 {
+        panic!();
+    }
+}
+
+/// This needs documenting
+pub const fn in_const_fn<const N: usize>(n: usize) {
+    //~^ missing_panics_doc
+    assert!(N > n);
+}
diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr
index 7f0acf8..85a0091 100644
--- a/tests/ui/missing_panics_doc.stderr
+++ b/tests/ui/missing_panics_doc.stderr
@@ -180,5 +180,41 @@
 LL |         *v.last().expect("passed an empty thing")
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 15 previous errors
+error: docs for function which may panic missing `# Panics` section
+  --> tests/ui/missing_panics_doc.rs:262:1
+   |
+LL | pub const fn unwrap_expect_etc_in_const_fn_fails() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> tests/ui/missing_panics_doc.rs:264:13
+   |
+LL |     let a = std::num::NonZeroUsize::new(1).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> tests/ui/missing_panics_doc.rs:268:1
+   |
+LL | pub const fn assert_in_const_fn_fails() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> tests/ui/missing_panics_doc.rs:272:9
+   |
+LL |         panic!();
+   |         ^^^^^^^^
+
+error: docs for function which may panic missing `# Panics` section
+  --> tests/ui/missing_panics_doc.rs:277:1
+   |
+LL | pub const fn in_const_fn<const N: usize>(n: usize) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first possible panic found here
+  --> tests/ui/missing_panics_doc.rs:279:5
+   |
+LL |     assert!(N > n);
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 18 previous errors
 
diff --git a/tests/ui/nonminimal_bool.stderr b/tests/ui/nonminimal_bool.stderr
index 0e3e4cf..ecb82a2 100644
--- a/tests/ui/nonminimal_bool.stderr
+++ b/tests/ui/nonminimal_bool.stderr
@@ -179,7 +179,7 @@
   --> tests/ui/nonminimal_bool.rs:186:8
    |
 LL |     if !b != true {}
-   |        ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)`
+   |        ^^^^^^^^^^ help: try simplifying it as shown: `!!b`
 
 error: this boolean expression can be simplified
   --> tests/ui/nonminimal_bool.rs:189:8
@@ -209,7 +209,7 @@
   --> tests/ui/nonminimal_bool.rs:193:8
    |
 LL |     if true != !b {}
-   |        ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)`
+   |        ^^^^^^^^^^ help: try simplifying it as shown: `!!b`
 
 error: this boolean expression can be simplified
   --> tests/ui/nonminimal_bool.rs:196:8
diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed
index a1119d7..34f3e04 100644
--- a/tests/ui/or_fun_call.fixed
+++ b/tests/ui/or_fun_call.fixed
@@ -5,6 +5,7 @@
     clippy::uninlined_format_args,
     clippy::unnecessary_wraps,
     clippy::unnecessary_literal_unwrap,
+    clippy::unnecessary_result_map_or_else,
     clippy::useless_vec
 )]
 
@@ -409,4 +410,33 @@
     //~^ or_fun_call
 }
 
+mod result_map_or {
+    fn g() -> i32 {
+        3
+    }
+
+    fn f(n: i32) -> i32 {
+        n
+    }
+
+    fn test_map_or() {
+        let x: Result<i32, ()> = Ok(4);
+        let _ = x.map_or_else(|_| g(), |v| v);
+        //~^ or_fun_call
+        let _ = x.map_or_else(|_| g(), f);
+        //~^ or_fun_call
+        let _ = x.map_or(0, f);
+    }
+}
+
+fn test_option_get_or_insert() {
+    // assume that this is slow call
+    fn g() -> u8 {
+        99
+    }
+    let mut x = Some(42_u8);
+    let _ = x.get_or_insert_with(g);
+    //~^ or_fun_call
+}
+
 fn main() {}
diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs
index a7cd632..dc57bd6 100644
--- a/tests/ui/or_fun_call.rs
+++ b/tests/ui/or_fun_call.rs
@@ -5,6 +5,7 @@
     clippy::uninlined_format_args,
     clippy::unnecessary_wraps,
     clippy::unnecessary_literal_unwrap,
+    clippy::unnecessary_result_map_or_else,
     clippy::useless_vec
 )]
 
@@ -409,4 +410,33 @@
     //~^ or_fun_call
 }
 
+mod result_map_or {
+    fn g() -> i32 {
+        3
+    }
+
+    fn f(n: i32) -> i32 {
+        n
+    }
+
+    fn test_map_or() {
+        let x: Result<i32, ()> = Ok(4);
+        let _ = x.map_or(g(), |v| v);
+        //~^ or_fun_call
+        let _ = x.map_or(g(), f);
+        //~^ or_fun_call
+        let _ = x.map_or(0, f);
+    }
+}
+
+fn test_option_get_or_insert() {
+    // assume that this is slow call
+    fn g() -> u8 {
+        99
+    }
+    let mut x = Some(42_u8);
+    let _ = x.get_or_insert(g());
+    //~^ or_fun_call
+}
+
 fn main() {}
diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr
index 35bda7e..0f159fe 100644
--- a/tests/ui/or_fun_call.stderr
+++ b/tests/ui/or_fun_call.stderr
@@ -1,5 +1,5 @@
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:52:22
+  --> tests/ui/or_fun_call.rs:53:22
    |
 LL |     with_constructor.unwrap_or(make());
    |                      ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(make)`
@@ -8,7 +8,7 @@
    = help: to override `-D warnings` add `#[allow(clippy::or_fun_call)]`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:56:14
+  --> tests/ui/or_fun_call.rs:57:14
    |
 LL |     with_new.unwrap_or(Vec::new());
    |              ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
@@ -17,199 +17,199 @@
    = help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:60:21
+  --> tests/ui/or_fun_call.rs:61:21
    |
 LL |     with_const_args.unwrap_or(Vec::with_capacity(12));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Vec::with_capacity(12))`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:64:14
+  --> tests/ui/or_fun_call.rs:65:14
    |
 LL |     with_err.unwrap_or(make());
    |              ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| make())`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:68:19
+  --> tests/ui/or_fun_call.rs:69:19
    |
 LL |     with_err_args.unwrap_or(Vec::with_capacity(12));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:72:24
+  --> tests/ui/or_fun_call.rs:73:24
    |
 LL |     with_default_trait.unwrap_or(Default::default());
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:76:23
+  --> tests/ui/or_fun_call.rs:77:23
    |
 LL |     with_default_type.unwrap_or(u64::default());
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:80:18
+  --> tests/ui/or_fun_call.rs:81:18
    |
 LL |     self_default.unwrap_or(<FakeDefault>::default());
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(<FakeDefault>::default)`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:84:18
+  --> tests/ui/or_fun_call.rs:85:18
    |
 LL |     real_default.unwrap_or(<FakeDefault as Default>::default());
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:88:14
+  --> tests/ui/or_fun_call.rs:89:14
    |
 LL |     with_vec.unwrap_or(vec![]);
    |              ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:92:21
+  --> tests/ui/or_fun_call.rs:93:21
    |
 LL |     without_default.unwrap_or(Foo::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)`
 
 error: use of `or_insert` to construct default value
-  --> tests/ui/or_fun_call.rs:96:19
+  --> tests/ui/or_fun_call.rs:97:19
    |
 LL |     map.entry(42).or_insert(String::new());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `or_insert` to construct default value
-  --> tests/ui/or_fun_call.rs:100:23
+  --> tests/ui/or_fun_call.rs:101:23
    |
 LL |     map_vec.entry(42).or_insert(vec![]);
    |                       ^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `or_insert` to construct default value
-  --> tests/ui/or_fun_call.rs:104:21
+  --> tests/ui/or_fun_call.rs:105:21
    |
 LL |     btree.entry(42).or_insert(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `or_insert` to construct default value
-  --> tests/ui/or_fun_call.rs:108:25
+  --> tests/ui/or_fun_call.rs:109:25
    |
 LL |     btree_vec.entry(42).or_insert(vec![]);
    |                         ^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:112:21
+  --> tests/ui/or_fun_call.rs:113:21
    |
 LL |     let _ = stringy.unwrap_or(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `ok_or`
-  --> tests/ui/or_fun_call.rs:117:17
+  --> tests/ui/or_fun_call.rs:118:17
    |
 LL |     let _ = opt.ok_or(format!("{} world.", hello));
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ok_or_else(|| format!("{} world.", hello))`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:122:21
+  --> tests/ui/or_fun_call.rs:123:21
    |
 LL |     let _ = Some(1).unwrap_or(map[&1]);
    |                     ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:125:21
+  --> tests/ui/or_fun_call.rs:126:21
    |
 LL |     let _ = Some(1).unwrap_or(map[&1]);
    |                     ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])`
 
 error: function call inside of `or`
-  --> tests/ui/or_fun_call.rs:150:35
+  --> tests/ui/or_fun_call.rs:151:35
    |
 LL |     let _ = Some("a".to_string()).or(Some("b".to_string()));
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:193:18
+  --> tests/ui/or_fun_call.rs:194:18
    |
 LL |             None.unwrap_or(ptr_to_ref(s));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:201:14
+  --> tests/ui/or_fun_call.rs:202:14
    |
 LL |         None.unwrap_or(unsafe { ptr_to_ref(s) });
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:204:14
+  --> tests/ui/or_fun_call.rs:205:14
    |
 LL |         None.unwrap_or( unsafe { ptr_to_ref(s) }    );
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
 
 error: function call inside of `map_or`
-  --> tests/ui/or_fun_call.rs:280:25
+  --> tests/ui/or_fun_call.rs:281:25
    |
 LL |         let _ = Some(4).map_or(g(), |v| v);
    |                         ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)`
 
 error: function call inside of `map_or`
-  --> tests/ui/or_fun_call.rs:282:25
+  --> tests/ui/or_fun_call.rs:283:25
    |
 LL |         let _ = Some(4).map_or(g(), f);
    |                         ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:314:18
+  --> tests/ui/or_fun_call.rs:315:18
    |
 LL |         with_new.unwrap_or_else(Vec::new);
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:318:28
+  --> tests/ui/or_fun_call.rs:319:28
    |
 LL |         with_default_trait.unwrap_or_else(Default::default);
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:322:27
+  --> tests/ui/or_fun_call.rs:323:27
    |
 LL |         with_default_type.unwrap_or_else(u64::default);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:326:22
+  --> tests/ui/or_fun_call.rs:327:22
    |
 LL |         real_default.unwrap_or_else(<FakeDefault as Default>::default);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: use of `or_insert_with` to construct default value
-  --> tests/ui/or_fun_call.rs:330:23
+  --> tests/ui/or_fun_call.rs:331:23
    |
 LL |         map.entry(42).or_insert_with(String::new);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `or_insert_with` to construct default value
-  --> tests/ui/or_fun_call.rs:334:25
+  --> tests/ui/or_fun_call.rs:335:25
    |
 LL |         btree.entry(42).or_insert_with(String::new);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
 
 error: use of `unwrap_or_else` to construct default value
-  --> tests/ui/or_fun_call.rs:338:25
+  --> tests/ui/or_fun_call.rs:339:25
    |
 LL |         let _ = stringy.unwrap_or_else(String::new);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:380:17
+  --> tests/ui/or_fun_call.rs:381:17
    |
 LL |     let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
    |                 ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:385:17
+  --> tests/ui/or_fun_call.rs:386:17
    |
 LL |     let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
    |                 ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:390:17
+  --> tests/ui/or_fun_call.rs:391:17
    |
 LL |       let _ = opt.unwrap_or({
    |  _________________^
@@ -229,22 +229,40 @@
    |
 
 error: function call inside of `map_or`
-  --> tests/ui/or_fun_call.rs:396:17
+  --> tests/ui/or_fun_call.rs:397:17
    |
 LL |     let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)`
 
 error: use of `unwrap_or` to construct default value
-  --> tests/ui/or_fun_call.rs:401:17
+  --> tests/ui/or_fun_call.rs:402:17
    |
 LL |     let _ = opt.unwrap_or({ i32::default() });
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
 
 error: function call inside of `unwrap_or`
-  --> tests/ui/or_fun_call.rs:408:21
+  --> tests/ui/or_fun_call.rs:409:21
    |
 LL |     let _ = opt_foo.unwrap_or(Foo { val: String::default() });
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })`
 
-error: aborting due to 38 previous errors
+error: function call inside of `map_or`
+  --> tests/ui/or_fun_call.rs:424:19
+   |
+LL |         let _ = x.map_or(g(), |v| v);
+   |                   ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), |v| v)`
+
+error: function call inside of `map_or`
+  --> tests/ui/or_fun_call.rs:426:19
+   |
+LL |         let _ = x.map_or(g(), f);
+   |                   ^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), f)`
+
+error: function call inside of `get_or_insert`
+  --> tests/ui/or_fun_call.rs:438:15
+   |
+LL |     let _ = x.get_or_insert(g());
+   |               ^^^^^^^^^^^^^^^^^^ help: try: `get_or_insert_with(g)`
+
+error: aborting due to 41 previous errors
 
diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed
index 60dc1c1..8d6f5fb 100644
--- a/tests/ui/question_mark.fixed
+++ b/tests/ui/question_mark.fixed
@@ -453,3 +453,15 @@
 
     None
 }
+
+fn issue_13642(x: Option<i32>) -> Option<()> {
+    let Some(x) = x else {
+        #[cfg(false)]
+        panic!();
+
+        #[cfg(true)]
+        return None;
+    };
+
+    None
+}
diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs
index 99d0122..f13eee2 100644
--- a/tests/ui/question_mark.rs
+++ b/tests/ui/question_mark.rs
@@ -549,3 +549,15 @@
 
     None
 }
+
+fn issue_13642(x: Option<i32>) -> Option<()> {
+    let Some(x) = x else {
+        #[cfg(false)]
+        panic!();
+
+        #[cfg(true)]
+        return None;
+    };
+
+    None
+}
diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs
index 2588445..0888019 100644
--- a/tests/ui/single_range_in_vec_init.rs
+++ b/tests/ui/single_range_in_vec_init.rs
@@ -2,7 +2,6 @@
 //@no-rustfix: overlapping suggestions
 #![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec, unused)]
 #![warn(clippy::single_range_in_vec_init)]
-#![feature(generic_arg_infer)]
 
 #[macro_use]
 extern crate proc_macros;
diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr
index a99127a..b21338e 100644
--- a/tests/ui/single_range_in_vec_init.stderr
+++ b/tests/ui/single_range_in_vec_init.stderr
@@ -1,5 +1,5 @@
 error: an array of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:26:5
+  --> tests/ui/single_range_in_vec_init.rs:25:5
    |
 LL |     [0..200];
    |     ^^^^^^^^
@@ -18,7 +18,7 @@
    |
 
 error: a `Vec` of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:28:5
+  --> tests/ui/single_range_in_vec_init.rs:27:5
    |
 LL |     vec![0..200];
    |     ^^^^^^^^^^^^
@@ -35,7 +35,7 @@
    |
 
 error: an array of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:30:5
+  --> tests/ui/single_range_in_vec_init.rs:29:5
    |
 LL |     [0u8..200];
    |     ^^^^^^^^^^
@@ -52,7 +52,7 @@
    |
 
 error: an array of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:32:5
+  --> tests/ui/single_range_in_vec_init.rs:31:5
    |
 LL |     [0usize..200];
    |     ^^^^^^^^^^^^^
@@ -69,7 +69,7 @@
    |
 
 error: an array of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:34:5
+  --> tests/ui/single_range_in_vec_init.rs:33:5
    |
 LL |     [0..200usize];
    |     ^^^^^^^^^^^^^
@@ -86,7 +86,7 @@
    |
 
 error: a `Vec` of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:36:5
+  --> tests/ui/single_range_in_vec_init.rs:35:5
    |
 LL |     vec![0u8..200];
    |     ^^^^^^^^^^^^^^
@@ -103,7 +103,7 @@
    |
 
 error: a `Vec` of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:38:5
+  --> tests/ui/single_range_in_vec_init.rs:37:5
    |
 LL |     vec![0usize..200];
    |     ^^^^^^^^^^^^^^^^^
@@ -120,7 +120,7 @@
    |
 
 error: a `Vec` of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:40:5
+  --> tests/ui/single_range_in_vec_init.rs:39:5
    |
 LL |     vec![0..200usize];
    |     ^^^^^^^^^^^^^^^^^
@@ -137,7 +137,7 @@
    |
 
 error: an array of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:43:5
+  --> tests/ui/single_range_in_vec_init.rs:42:5
    |
 LL |     [0..200isize];
    |     ^^^^^^^^^^^^^
@@ -149,7 +149,7 @@
    |
 
 error: a `Vec` of `Range` that is only one element
-  --> tests/ui/single_range_in_vec_init.rs:45:5
+  --> tests/ui/single_range_in_vec_init.rs:44:5
    |
 LL |     vec![0..200isize];
    |     ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/swap_with_temporary.fixed b/tests/ui/swap_with_temporary.fixed
index 4007d99..4b4b0d4 100644
--- a/tests/ui/swap_with_temporary.fixed
+++ b/tests/ui/swap_with_temporary.fixed
@@ -72,3 +72,49 @@
     swap(&mut s.t, v.get_mut(0).unwrap());
     swap(w.unwrap(), &mut s.t);
 }
+
+fn issue15166() {
+    use std::sync::Mutex;
+
+    struct A {
+        thing: Mutex<Vec<u8>>,
+    }
+
+    impl A {
+        fn a(&self) {
+            let mut new_vec = vec![42];
+            // Do not lint here, as neither `new_vec` nor the result of `.lock().unwrap()` are temporaries
+            swap(&mut new_vec, &mut self.thing.lock().unwrap());
+            for v in new_vec {
+                // Do something with v
+            }
+            // Here `vec![42]` is temporary though, and a proper dereference will have to be used in the fix
+            *self.thing.lock().unwrap() = vec![42];
+            //~^ ERROR: swapping with a temporary value is inefficient
+        }
+    }
+}
+
+fn multiple_deref() {
+    let mut v1 = &mut &mut &mut vec![42];
+    ***v1 = vec![];
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    struct Wrapper<T: ?Sized>(T);
+    impl<T: ?Sized> std::ops::Deref for Wrapper<T> {
+        type Target = T;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T: ?Sized> std::ops::DerefMut for Wrapper<T> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            &mut self.0
+        }
+    }
+
+    use std::sync::Mutex;
+    let mut v1 = Mutex::new(Wrapper(Wrapper(vec![42])));
+    ***v1.lock().unwrap() = vec![];
+    //~^ ERROR: swapping with a temporary value is inefficient
+}
diff --git a/tests/ui/swap_with_temporary.rs b/tests/ui/swap_with_temporary.rs
index d403c08..8e35e61 100644
--- a/tests/ui/swap_with_temporary.rs
+++ b/tests/ui/swap_with_temporary.rs
@@ -72,3 +72,49 @@
     swap(&mut s.t, v.get_mut(0).unwrap());
     swap(w.unwrap(), &mut s.t);
 }
+
+fn issue15166() {
+    use std::sync::Mutex;
+
+    struct A {
+        thing: Mutex<Vec<u8>>,
+    }
+
+    impl A {
+        fn a(&self) {
+            let mut new_vec = vec![42];
+            // Do not lint here, as neither `new_vec` nor the result of `.lock().unwrap()` are temporaries
+            swap(&mut new_vec, &mut self.thing.lock().unwrap());
+            for v in new_vec {
+                // Do something with v
+            }
+            // Here `vec![42]` is temporary though, and a proper dereference will have to be used in the fix
+            swap(&mut vec![42], &mut self.thing.lock().unwrap());
+            //~^ ERROR: swapping with a temporary value is inefficient
+        }
+    }
+}
+
+fn multiple_deref() {
+    let mut v1 = &mut &mut &mut vec![42];
+    swap(&mut ***v1, &mut vec![]);
+    //~^ ERROR: swapping with a temporary value is inefficient
+
+    struct Wrapper<T: ?Sized>(T);
+    impl<T: ?Sized> std::ops::Deref for Wrapper<T> {
+        type Target = T;
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<T: ?Sized> std::ops::DerefMut for Wrapper<T> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            &mut self.0
+        }
+    }
+
+    use std::sync::Mutex;
+    let mut v1 = Mutex::new(Wrapper(Wrapper(vec![42])));
+    swap(&mut vec![], &mut v1.lock().unwrap());
+    //~^ ERROR: swapping with a temporary value is inefficient
+}
diff --git a/tests/ui/swap_with_temporary.stderr b/tests/ui/swap_with_temporary.stderr
index 5935577..5ca4fcc 100644
--- a/tests/ui/swap_with_temporary.stderr
+++ b/tests/ui/swap_with_temporary.stderr
@@ -96,5 +96,41 @@
 LL |     swap(mac!(refmut y), &mut func());
    |                               ^^^^^^
 
-error: aborting due to 8 previous errors
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:92:13
+   |
+LL |             swap(&mut vec![42], &mut self.thing.lock().unwrap());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*self.thing.lock().unwrap() = vec![42]`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:92:23
+   |
+LL |             swap(&mut vec![42], &mut self.thing.lock().unwrap());
+   |                       ^^^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:100:5
+   |
+LL |     swap(&mut ***v1, &mut vec![]);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `***v1 = vec![]`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:100:27
+   |
+LL |     swap(&mut ***v1, &mut vec![]);
+   |                           ^^^^^^
+
+error: swapping with a temporary value is inefficient
+  --> tests/ui/swap_with_temporary.rs:118:5
+   |
+LL |     swap(&mut vec![], &mut v1.lock().unwrap());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `***v1.lock().unwrap() = vec![]`
+   |
+note: this expression returns a temporary value
+  --> tests/ui/swap_with_temporary.rs:118:15
+   |
+LL |     swap(&mut vec![], &mut v1.lock().unwrap());
+   |               ^^^^^^
+
+error: aborting due to 11 previous errors
 
diff --git a/tests/ui/unnecessary_os_str_debug_formatting.rs b/tests/ui/unnecessary_os_str_debug_formatting.rs
index 6652efd..66590be 100644
--- a/tests/ui/unnecessary_os_str_debug_formatting.rs
+++ b/tests/ui/unnecessary_os_str_debug_formatting.rs
@@ -21,3 +21,16 @@
     let _: String = format!("{:?}", os_str); //~ unnecessary_debug_formatting
     let _: String = format!("{:?}", os_string); //~ unnecessary_debug_formatting
 }
+
+#[clippy::msrv = "1.86"]
+fn msrv_1_86() {
+    let os_str = OsStr::new("test");
+    println!("{:?}", os_str);
+}
+
+#[clippy::msrv = "1.87"]
+fn msrv_1_87() {
+    let os_str = OsStr::new("test");
+    println!("{:?}", os_str);
+    //~^ unnecessary_debug_formatting
+}
diff --git a/tests/ui/unnecessary_os_str_debug_formatting.stderr b/tests/ui/unnecessary_os_str_debug_formatting.stderr
index 382e59b..f04d2d5 100644
--- a/tests/ui/unnecessary_os_str_debug_formatting.stderr
+++ b/tests/ui/unnecessary_os_str_debug_formatting.stderr
@@ -54,5 +54,14 @@
    = help: use `Display` formatting and change this to `os_string.display()`
    = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
 
-error: aborting due to 6 previous errors
+error: unnecessary `Debug` formatting in `println!` args
+  --> tests/ui/unnecessary_os_str_debug_formatting.rs:34:22
+   |
+LL |     println!("{:?}", os_str);
+   |                      ^^^^^^
+   |
+   = help: use `Display` formatting and change this to `os_str.display()`
+   = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed
+
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/wildcard_enum_match_arm.fixed b/tests/ui/wildcard_enum_match_arm.fixed
index 141ff6e..5f738a2 100644
--- a/tests/ui/wildcard_enum_match_arm.fixed
+++ b/tests/ui/wildcard_enum_match_arm.fixed
@@ -91,6 +91,21 @@
     }
 
     {
+        pub enum Enum {
+            A,
+            B,
+            C(u8),
+            D(u8, u8),
+            E { e: u8 },
+        };
+        match Enum::A {
+            Enum::A => (),
+            Enum::B | Enum::C(_) | Enum::D(..) | Enum::E { .. } => (),
+            //~^ wildcard_enum_match_arm
+        }
+    }
+
+    {
         #![allow(clippy::manual_non_exhaustive)]
         pub enum Enum {
             A,
@@ -105,3 +120,17 @@
         }
     }
 }
+
+fn issue15091() {
+    enum Foo {
+        A,
+        B,
+        C,
+    }
+
+    match Foo::A {
+        Foo::A => {},
+        r#type @ Foo::B | r#type @ Foo::C => {},
+        //~^ wildcard_enum_match_arm
+    }
+}
diff --git a/tests/ui/wildcard_enum_match_arm.rs b/tests/ui/wildcard_enum_match_arm.rs
index a13684e..4bc4bfd 100644
--- a/tests/ui/wildcard_enum_match_arm.rs
+++ b/tests/ui/wildcard_enum_match_arm.rs
@@ -91,6 +91,21 @@
     }
 
     {
+        pub enum Enum {
+            A,
+            B,
+            C(u8),
+            D(u8, u8),
+            E { e: u8 },
+        };
+        match Enum::A {
+            Enum::A => (),
+            _ => (),
+            //~^ wildcard_enum_match_arm
+        }
+    }
+
+    {
         #![allow(clippy::manual_non_exhaustive)]
         pub enum Enum {
             A,
@@ -105,3 +120,17 @@
         }
     }
 }
+
+fn issue15091() {
+    enum Foo {
+        A,
+        B,
+        C,
+    }
+
+    match Foo::A {
+        Foo::A => {},
+        r#type => {},
+        //~^ wildcard_enum_match_arm
+    }
+}
diff --git a/tests/ui/wildcard_enum_match_arm.stderr b/tests/ui/wildcard_enum_match_arm.stderr
index 088c6b7..d092998 100644
--- a/tests/ui/wildcard_enum_match_arm.stderr
+++ b/tests/ui/wildcard_enum_match_arm.stderr
@@ -38,7 +38,19 @@
   --> tests/ui/wildcard_enum_match_arm.rs:103:13
    |
 LL |             _ => (),
+   |             ^ help: try: `Enum::B | Enum::C(_) | Enum::D(..) | Enum::E { .. }`
+
+error: wildcard match will also match any future added variants
+  --> tests/ui/wildcard_enum_match_arm.rs:118:13
+   |
+LL |             _ => (),
    |             ^ help: try: `Enum::B | Enum::__Private`
 
-error: aborting due to 6 previous errors
+error: wildcard match will also match any future added variants
+  --> tests/ui/wildcard_enum_match_arm.rs:133:9
+   |
+LL |         r#type => {},
+   |         ^^^^^^ help: try: `r#type @ Foo::B | r#type @ Foo::C`
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/zero_ptr.fixed b/tests/ui/zero_ptr.fixed
index f2375d5..f9d9d2d 100644
--- a/tests/ui/zero_ptr.fixed
+++ b/tests/ui/zero_ptr.fixed
@@ -16,3 +16,11 @@
     let z = 0;
     let _ = z as *const usize; // this is currently not caught
 }
+
+const fn in_const_context() {
+    #[clippy::msrv = "1.23"]
+    let _: *const usize = 0 as *const _;
+    #[clippy::msrv = "1.24"]
+    let _: *const usize = std::ptr::null();
+    //~^ zero_ptr
+}
diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs
index ee01e42..41455fe 100644
--- a/tests/ui/zero_ptr.rs
+++ b/tests/ui/zero_ptr.rs
@@ -16,3 +16,11 @@
     let z = 0;
     let _ = z as *const usize; // this is currently not caught
 }
+
+const fn in_const_context() {
+    #[clippy::msrv = "1.23"]
+    let _: *const usize = 0 as *const _;
+    #[clippy::msrv = "1.24"]
+    let _: *const usize = 0 as *const _;
+    //~^ zero_ptr
+}
diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr
index 8dc781f..81269de 100644
--- a/tests/ui/zero_ptr.stderr
+++ b/tests/ui/zero_ptr.stderr
@@ -31,5 +31,11 @@
 LL |     foo(0 as *const _, 0 as *mut _);
    |                        ^^^^^^^^^^^ help: try: `std::ptr::null_mut()`
 
-error: aborting due to 5 previous errors
+error: `0 as *const _` detected
+  --> tests/ui/zero_ptr.rs:24:27
+   |
+LL |     let _: *const usize = 0 as *const _;
+   |                           ^^^^^^^^^^^^^ help: try: `std::ptr::null()`
+
+error: aborting due to 6 previous errors
 
diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs
index f6fc235..b017938 100644
--- a/tests/versioncheck.rs
+++ b/tests/versioncheck.rs
@@ -27,6 +27,7 @@
         "clippy_config/Cargo.toml",
         "clippy_lints/Cargo.toml",
         "clippy_utils/Cargo.toml",
+        "declare_clippy_lint/Cargo.toml",
     ];
 
     for path in paths {
diff --git a/triagebot.toml b/triagebot.toml
index 16557a4..4f37075 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -17,6 +17,9 @@
 
 [issue-links]
 
+[mentions."clippy_lints/src/doc"]
+cc = ["@notriddle"]
+
 # Prevents mentions in commits to avoid users being spammed
 [no-mentions]
 
diff --git a/util/versions.py b/util/versions.py
index fee0d29..6e06d77 100755
--- a/util/versions.py
+++ b/util/versions.py
@@ -6,11 +6,11 @@
 import sys
 
 def key(v):
-    if v == "master":
-        return sys.maxsize
     if v == "stable":
-        return sys.maxsize - 1
+        return sys.maxsize 
     if v == "beta":
+        return sys.maxsize - 1
+    if v == "master":
         return sys.maxsize - 2
     if v == "pre-1.29.0":
         return -1