]> git.lizzy.rs Git - rust.git/commitdiff
Merge commit '7f27e2e74ef957baa382dc05cf08df6368165c74' into clippyup
authorPhilipp Krones <hello@philkrones.com>
Thu, 12 Jan 2023 18:48:13 +0000 (19:48 +0100)
committerPhilipp Krones <hello@philkrones.com>
Thu, 12 Jan 2023 18:48:13 +0000 (19:48 +0100)
84 files changed:
1  2 
src/tools/clippy/.github/driver.sh
src/tools/clippy/CHANGELOG.md
src/tools/clippy/book/src/installation.md
src/tools/clippy/clippy_dev/src/lib.rs
src/tools/clippy/clippy_lints/src/box_default.rs
src/tools/clippy/clippy_lints/src/copies.rs
src/tools/clippy/clippy_lints/src/dbg_macro.rs
src/tools/clippy/clippy_lints/src/declared_lints.rs
src/tools/clippy/clippy_lints/src/default.rs
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/derivable_impls.rs
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
src/tools/clippy/clippy_lints/src/methods/filter_map.rs
src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
src/tools/clippy/clippy_lints/src/mutex_atomic.rs
src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
src/tools/clippy/clippy_lints/src/ranges.rs
src/tools/clippy/clippy_lints/src/redundant_clone.rs
src/tools/clippy/clippy_lints/src/renamed_lints.rs
src/tools/clippy/clippy_lints/src/returns.rs
src/tools/clippy/clippy_lints/src/types/mod.rs
src/tools/clippy/clippy_lints/src/unused_self.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
src/tools/clippy/clippy_utils/src/msrvs.rs
src/tools/clippy/clippy_utils/src/paths.rs
src/tools/clippy/clippy_utils/src/visitors.rs
src/tools/clippy/rust-toolchain
src/tools/clippy/src/driver.rs
src/tools/clippy/tests/integration.rs
src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
src/tools/clippy/tests/ui/arithmetic_side_effects.rs
src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
src/tools/clippy/tests/ui/box_default.fixed
src/tools/clippy/tests/ui/box_default.rs
src/tools/clippy/tests/ui/box_default.stderr
src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
src/tools/clippy/tests/ui/clone_on_copy.stderr
src/tools/clippy/tests/ui/dbg_macro.stderr
src/tools/clippy/tests/ui/default_trait_access.fixed
src/tools/clippy/tests/ui/default_trait_access.stderr
src/tools/clippy/tests/ui/derivable_impls.fixed
src/tools/clippy/tests/ui/derivable_impls.rs
src/tools/clippy/tests/ui/derivable_impls.stderr
src/tools/clippy/tests/ui/derive.rs
src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs
src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
src/tools/clippy/tests/ui/drop_ref.rs
src/tools/clippy/tests/ui/drop_ref.stderr
src/tools/clippy/tests/ui/field_reassign_with_default.rs
src/tools/clippy/tests/ui/iter_kv_map.fixed
src/tools/clippy/tests/ui/iter_kv_map.rs
src/tools/clippy/tests/ui/iter_kv_map.stderr
src/tools/clippy/tests/ui/needless_borrow.fixed
src/tools/clippy/tests/ui/needless_borrow.rs
src/tools/clippy/tests/ui/needless_borrow.stderr
src/tools/clippy/tests/ui/needless_return.fixed
src/tools/clippy/tests/ui/needless_return.rs
src/tools/clippy/tests/ui/needless_return.stderr
src/tools/clippy/tests/ui/redundant_clone.fixed
src/tools/clippy/tests/ui/redundant_clone.rs
src/tools/clippy/tests/ui/redundant_clone.stderr
src/tools/clippy/tests/ui/rename.fixed
src/tools/clippy/tests/ui/rename.rs
src/tools/clippy/tests/ui/rename.stderr
src/tools/clippy/tests/ui/single_element_loop.fixed
src/tools/clippy/tests/ui/single_element_loop.rs
src/tools/clippy/tests/ui/single_element_loop.stderr
src/tools/clippy/tests/ui/suspicious_to_owned.stderr
src/tools/clippy/tests/ui/unnecessary_clone.stderr
src/tools/clippy/tests/ui/unused_self.rs
src/tools/clippy/tests/ui/unused_self.stderr

index 6ff189fc85926e61a2349bc3e6bc5fe370738204,0000000000000000000000000000000000000000..798782340ee7d1581425c994f73573cdcd01fb76
mode 100644,000000..100644
--- /dev/null
@@@ -1,39 -1,0 +1,46 @@@
 +#!/bin/bash
 +
 +set -ex
 +
 +# Check sysroot handling
 +sysroot=$(./target/debug/clippy-driver --print sysroot)
 +test "$sysroot" = "$(rustc --print sysroot)"
 +
 +if [[ ${OS} == "Windows" ]]; then
 +      desired_sysroot=C:/tmp
 +else
 +      desired_sysroot=/tmp
 +fi
 +sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot)
 +test "$sysroot" = $desired_sysroot
 +
 +sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot)
 +test "$sysroot" = $desired_sysroot
 +
++# Check that the --sysroot argument is only passed once (SYSROOT is ignored)
++(
++    cd rustc_tools_util
++    touch src/lib.rs
++    SYSROOT=/tmp RUSTFLAGS="--sysroot=$(rustc --print sysroot)" ../target/debug/cargo-clippy clippy --verbose
++)
++
 +# Make sure this isn't set - clippy-driver should cope without it
 +unset CARGO_MANIFEST_DIR
 +
 +# Run a lint and make sure it produces the expected output. It's also expected to exit with code 1
 +# FIXME: How to match the clippy invocation in compile-test.rs?
 +./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
 +sed -e "s,tests/ui,\$DIR," -e "/= help/d" double_neg.stderr >normalized.stderr
 +diff -u normalized.stderr tests/ui/double_neg.stderr
 +
 +# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
 +SYSROOT=$(rustc --print sysroot)
 +diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
 +
 +echo "fn main() {}" >target/driver_test.rs
 +# we can't run 2 rustcs on the same file at the same time
 +CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc)
 +RUSTC=$(rustc ./target/driver_test.rs)
 +diff -u <($CLIPPY) <($RUSTC)
 +
 +# TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR
index 02f3188f8be08209dfb700b07c7ceffe2ebd7670,0000000000000000000000000000000000000000..8e31e8f0d9815083d09b9fe971c471871e41248d
mode 100644,000000..100644
--- /dev/null
@@@ -1,4699 -1,0 +1,4700 @@@
 +# Changelog
 +
 +All notable changes to this project will be documented in this file.
 +See [Changelog Update](book/src/development/infrastructure/changelog_update.md) if you want to update this
 +document.
 +
 +## Unreleased / Beta / In Rust Nightly
 +
 +[4f142aa1...master](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...master)
 +
 +## Rust 1.66
 +
 +Current stable, released 2022-12-15
 +
 +[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
 +
 +### New Lints
 +
 +* [`manual_clamp`]
 +  [#9484](https://github.com/rust-lang/rust-clippy/pull/9484)
 +* [`missing_trait_methods`]
 +  [#9670](https://github.com/rust-lang/rust-clippy/pull/9670)
 +* [`unused_format_specs`]
 +  [#9637](https://github.com/rust-lang/rust-clippy/pull/9637)
 +* [`iter_kv_map`]
 +  [#9409](https://github.com/rust-lang/rust-clippy/pull/9409)
 +* [`manual_filter`]
 +  [#9451](https://github.com/rust-lang/rust-clippy/pull/9451)
 +* [`box_default`]
 +  [#9511](https://github.com/rust-lang/rust-clippy/pull/9511)
 +* [`implicit_saturating_add`]
 +  [#9549](https://github.com/rust-lang/rust-clippy/pull/9549)
 +* [`as_ptr_cast_mut`]
 +  [#9572](https://github.com/rust-lang/rust-clippy/pull/9572)
 +* [`disallowed_macros`]
 +  [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
 +* [`partial_pub_fields`]
 +  [#9658](https://github.com/rust-lang/rust-clippy/pull/9658)
 +* [`uninlined_format_args`]
 +  [#9233](https://github.com/rust-lang/rust-clippy/pull/9233)
 +* [`cast_nan_to_int`]
 +  [#9617](https://github.com/rust-lang/rust-clippy/pull/9617)
 +
 +### Moves and Deprecations
 +
 +* `positional_named_format_parameters` was uplifted to rustc under the new name
 +  `named_arguments_used_positionally`
 +  [#8518](https://github.com/rust-lang/rust-clippy/pull/8518)
 +* Moved [`implicit_saturating_sub`] to `style` (Now warn-by-default)
 +  [#9584](https://github.com/rust-lang/rust-clippy/pull/9584)
 +* Moved `derive_partial_eq_without_eq` to `nursery` (now allow-by-default)
 +  [#9536](https://github.com/rust-lang/rust-clippy/pull/9536)
 +
 +### Enhancements
 +
 +* [`nonstandard_macro_braces`]: Now includes `matches!()` in the default lint config
 +  [#9471](https://github.com/rust-lang/rust-clippy/pull/9471)
 +* [`suboptimal_flops`]: Now supports multiplication and subtraction operations
 +  [#9581](https://github.com/rust-lang/rust-clippy/pull/9581)
 +* [`arithmetic_side_effects`]: Now detects cases with literals behind references
 +  [#9587](https://github.com/rust-lang/rust-clippy/pull/9587)
 +* [`upper_case_acronyms`]: Now also checks enum names
 +  [#9580](https://github.com/rust-lang/rust-clippy/pull/9580)
 +* [`needless_borrowed_reference`]: Now lints nested patterns
 +  [#9573](https://github.com/rust-lang/rust-clippy/pull/9573)
 +* [`unnecessary_cast`]: Now works for non-trivial non-literal expressions
 +  [#9576](https://github.com/rust-lang/rust-clippy/pull/9576)
 +* [`arithmetic_side_effects`]: Now detects operations with custom types
 +  [#9559](https://github.com/rust-lang/rust-clippy/pull/9559)
 +* [`disallowed_methods`], [`disallowed_types`]: Not correctly lints types, functions and macros
 +  with the same path
 +  [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
 +* [`self_named_module_files`], [`mod_module_files`]: Now take remapped path prefixes into account
 +  [#9475](https://github.com/rust-lang/rust-clippy/pull/9475)
 +* [`bool_to_int_with_if`]: Now detects the inverse if case
 +  [#9476](https://github.com/rust-lang/rust-clippy/pull/9476)
 +
 +### False Positive Fixes
 +
 +* [`arithmetic_side_effects`]: Now allows operations that can't overflow
 +  [#9474](https://github.com/rust-lang/rust-clippy/pull/9474)
 +* [`unnecessary_lazy_evaluations`]: No longer lints in external macros
 +  [#9486](https://github.com/rust-lang/rust-clippy/pull/9486)
 +* [`needless_borrow`], [`explicit_auto_deref`]: No longer lint on unions that require the reference
 +  [#9490](https://github.com/rust-lang/rust-clippy/pull/9490)
 +* [`almost_complete_letter_range`]: No longer lints in external macros
 +  [#9467](https://github.com/rust-lang/rust-clippy/pull/9467)
 +* [`drop_copy`]: No longer lints on idiomatic cases in match arms 
 +  [#9491](https://github.com/rust-lang/rust-clippy/pull/9491)
 +* [`question_mark`]: No longer lints in const context
 +  [#9487](https://github.com/rust-lang/rust-clippy/pull/9487)
 +* [`collapsible_if`]: Suggestion now work in macros
 +  [#9410](https://github.com/rust-lang/rust-clippy/pull/9410)
 +* [`std_instead_of_core`]: No longer triggers on unstable modules
 +  [#9545](https://github.com/rust-lang/rust-clippy/pull/9545)
 +* [`unused_peekable`]: No longer lints, if the peak is done in a closure or function
 +  [#9465](https://github.com/rust-lang/rust-clippy/pull/9465)
 +* [`useless_attribute`]: No longer lints on `#[allow]` attributes for [`unsafe_removed_from_name`]
 +  [#9593](https://github.com/rust-lang/rust-clippy/pull/9593)
 +* [`unnecessary_lazy_evaluations`]: No longer suggest switching to early evaluation when type has
 +  custom `Drop` implementation
 +  [#9551](https://github.com/rust-lang/rust-clippy/pull/9551)
 +* [`unnecessary_cast`]: No longer lints on negative hexadecimal literals when cast as floats
 +  [#9609](https://github.com/rust-lang/rust-clippy/pull/9609)
 +* [`use_self`]: No longer lints in proc macros
 +  [#9454](https://github.com/rust-lang/rust-clippy/pull/9454)
 +* [`never_loop`]: Now takes `let ... else` statements into consideration.
 +  [#9496](https://github.com/rust-lang/rust-clippy/pull/9496)
 +* [`default_numeric_fallback`]: Now ignores constants
 +  [#9636](https://github.com/rust-lang/rust-clippy/pull/9636)
 +* [`uninit_vec`]: No longer lints `Vec::set_len(0)`
 +  [#9519](https://github.com/rust-lang/rust-clippy/pull/9519)
 +* [`arithmetic_side_effects`]: Now ignores references to integer types
 +  [#9507](https://github.com/rust-lang/rust-clippy/pull/9507)
 +* [`large_stack_arrays`]: No longer lints inside static items
 +  [#9466](https://github.com/rust-lang/rust-clippy/pull/9466)
 +* [`ref_option_ref`]: No longer lints if the inner reference is mutable
 +  [#9684](https://github.com/rust-lang/rust-clippy/pull/9684)
 +* [`ptr_arg`]: No longer lints if the argument is used as an incomplete trait object
 +  [#9645](https://github.com/rust-lang/rust-clippy/pull/9645)
 +* [`should_implement_trait`]: Now also works for `default` methods
 +  [#9546](https://github.com/rust-lang/rust-clippy/pull/9546)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`derivable_impls`]: The suggestion is now machine applicable
 +  [#9429](https://github.com/rust-lang/rust-clippy/pull/9429)
 +* [`match_single_binding`]: The suggestion now handles scrutinies with side effects better
 +  [#9601](https://github.com/rust-lang/rust-clippy/pull/9601)
 +* [`zero_prefixed_literal`]: Only suggests using octal numbers, if this is possible
 +  [#9652](https://github.com/rust-lang/rust-clippy/pull/9652)
 +* [`rc_buffer`]: The suggestion is no longer machine applicable to avoid semantic changes
 +  [#9633](https://github.com/rust-lang/rust-clippy/pull/9633)
 +* [`print_literal`], [`write_literal`], [`uninlined_format_args`]: The suggestion now ignores
 +  comments after the macro call.
 +  [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
 +* [`expect_fun_call`]:Improved the suggestion for `format!` calls with captured variables
 +  [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
 +* [`nonstandard_macro_braces`]: The suggestion is now machine applicable and will no longer
 +  replace brackets inside the macro argument.
 +  [#9499](https://github.com/rust-lang/rust-clippy/pull/9499)
 +* [`from_over_into`]: The suggestion is now a machine applicable and contains explanations
 +  [#9649](https://github.com/rust-lang/rust-clippy/pull/9649)
 +* [`needless_return`]: The automatic suggestion now removes all required semicolons
 +  [#9497](https://github.com/rust-lang/rust-clippy/pull/9497)
 +* [`to_string_in_format_args`]: The suggestion now keeps parenthesis around values
 +  [#9590](https://github.com/rust-lang/rust-clippy/pull/9590)
 +* [`manual_assert`]: The suggestion now preserves comments
 +  [#9479](https://github.com/rust-lang/rust-clippy/pull/9479)
 +* [`redundant_allocation`]: The suggestion applicability is now marked `MaybeIncorrect` to
 +  avoid semantic changes
 +  [#9634](https://github.com/rust-lang/rust-clippy/pull/9634)
 +* [`assertions_on_result_states`]: The suggestion has been corrected, for cases where the
 +  `assert!` is not in a statement.
 +  [#9453](https://github.com/rust-lang/rust-clippy/pull/9453)
 +* [`nonminimal_bool`]: The suggestion no longer expands macros
 +  [#9457](https://github.com/rust-lang/rust-clippy/pull/9457)
 +* [`collapsible_match`]: Now specifies field names, when a struct is destructed
 +  [#9685](https://github.com/rust-lang/rust-clippy/pull/9685)
 +* [`unnecessary_cast`]: The suggestion now adds parenthesis for negative numbers
 +  [#9577](https://github.com/rust-lang/rust-clippy/pull/9577)
 +* [`redundant_closure`]: The suggestion now works for `impl FnMut` arguments
 +  [#9556](https://github.com/rust-lang/rust-clippy/pull/9556)
 +
 +### ICE Fixes
 +
 +* [`unnecessary_to_owned`]: Avoid ICEs in favor of false negatives if information is missing
 +  [#9505](https://github.com/rust-lang/rust-clippy/pull/9505)
 +* [`manual_range_contains`]: No longer ICEs on values behind references
 +  [#9627](https://github.com/rust-lang/rust-clippy/pull/9627)
 +* [`needless_pass_by_value`]: No longer ICEs on unsized `dyn Fn` arguments
 +  [#9531](https://github.com/rust-lang/rust-clippy/pull/9531)
 +* `*_interior_mutable_const` lints: no longer ICE on const unions containing `!Freeze` types
 +  [#9539](https://github.com/rust-lang/rust-clippy/pull/9539)
 +
 +### Others
 +
 +* Released `rustc_tools_util` for version information on `Crates.io`. (Further adjustments will
 +  not be published as part of this changelog)
 +
 +## Rust 1.65
 +
 +Released 2022-11-03
 +
 +[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523)
 +
 +### Important Changes
 +
 +* Clippy now has an `--explain <LINT>` command to show the lint description in the console
 +  [#8952](https://github.com/rust-lang/rust-clippy/pull/8952)
 +
 +### New Lints
 +
 +* [`unused_peekable`]
 +  [#9258](https://github.com/rust-lang/rust-clippy/pull/9258)
 +* [`collapsible_str_replace`]
 +  [#9269](https://github.com/rust-lang/rust-clippy/pull/9269)
 +* [`manual_string_new`]
 +  [#9295](https://github.com/rust-lang/rust-clippy/pull/9295)
 +* [`iter_on_empty_collections`]
 +  [#9187](https://github.com/rust-lang/rust-clippy/pull/9187)
 +* [`iter_on_single_items`]
 +  [#9187](https://github.com/rust-lang/rust-clippy/pull/9187)
 +* [`bool_to_int_with_if`]
 +  [#9412](https://github.com/rust-lang/rust-clippy/pull/9412)
 +* [`multi_assignments`]
 +  [#9379](https://github.com/rust-lang/rust-clippy/pull/9379)
 +* [`result_large_err`]
 +  [#9373](https://github.com/rust-lang/rust-clippy/pull/9373)
 +* [`partialeq_to_none`]
 +  [#9288](https://github.com/rust-lang/rust-clippy/pull/9288)
 +* [`suspicious_to_owned`]
 +  [#8984](https://github.com/rust-lang/rust-clippy/pull/8984)
 +* [`cast_slice_from_raw_parts`]
 +  [#9247](https://github.com/rust-lang/rust-clippy/pull/9247)
 +* [`manual_instant_elapsed`]
 +  [#9264](https://github.com/rust-lang/rust-clippy/pull/9264)
 +
 +### Moves and Deprecations
 +
 +* Moved [`significant_drop_in_scrutinee`] to `nursery` (now allow-by-default)
 +  [#9302](https://github.com/rust-lang/rust-clippy/pull/9302)
 +* Rename `logic_bug` to [`overly_complex_bool_expr`]
 +  [#9306](https://github.com/rust-lang/rust-clippy/pull/9306)
 +* Rename `arithmetic` to [`arithmetic_side_effects`]
 +  [#9443](https://github.com/rust-lang/rust-clippy/pull/9443)
 +* Moved [`only_used_in_recursion`] to complexity (now warn-by-default)
 +  [#8804](https://github.com/rust-lang/rust-clippy/pull/8804)
 +* Moved [`assertions_on_result_states`] to restriction (now allow-by-default)
 +  [#9273](https://github.com/rust-lang/rust-clippy/pull/9273)
 +* Renamed `blacklisted_name` to [`disallowed_names`]
 +  [#8974](https://github.com/rust-lang/rust-clippy/pull/8974)
 +
 +### Enhancements
 +
 +* [`option_if_let_else`]: Now also checks for match expressions
 +  [#8696](https://github.com/rust-lang/rust-clippy/pull/8696)
 +* [`explicit_auto_deref`]: Now lints on implicit returns in closures
 +  [#9126](https://github.com/rust-lang/rust-clippy/pull/9126)
 +* [`needless_borrow`]: Now considers trait implementations
 +  [#9136](https://github.com/rust-lang/rust-clippy/pull/9136)
 +* [`suboptimal_flops`], [`imprecise_flops`]: Now lint on constant expressions
 +  [#9404](https://github.com/rust-lang/rust-clippy/pull/9404)
 +* [`if_let_mutex`]: Now detects mutex behind references and warns about deadlocks
 +  [#9318](https://github.com/rust-lang/rust-clippy/pull/9318)
 +
 +### False Positive Fixes
 +
 +* [`unit_arg`] [`default_trait_access`] [`missing_docs_in_private_items`]: No longer
 +  trigger in code generated from proc-macros
 +  [#8694](https://github.com/rust-lang/rust-clippy/pull/8694)
 +* [`unwrap_used`]: Now lints uses of `unwrap_err`
 +  [#9338](https://github.com/rust-lang/rust-clippy/pull/9338)
 +* [`expect_used`]: Now lints uses of `expect_err`
 +  [#9338](https://github.com/rust-lang/rust-clippy/pull/9338)
 +* [`transmute_undefined_repr`]: Now longer lints if the first field is compatible
 +  with the other type
 +  [#9287](https://github.com/rust-lang/rust-clippy/pull/9287)
 +* [`unnecessary_to_owned`]: No longer lints, if type change cased errors in
 +  the caller function
 +  [#9424](https://github.com/rust-lang/rust-clippy/pull/9424)
 +* [`match_like_matches_macro`]: No longer lints, if there are comments inside the
 +  match expression
 +  [#9276](https://github.com/rust-lang/rust-clippy/pull/9276)
 +* [`partialeq_to_none`]: No longer trigger in code generated from macros
 +  [#9389](https://github.com/rust-lang/rust-clippy/pull/9389)
 +* [`arithmetic_side_effects`]: No longer lints expressions that only use literals
 +  [#9365](https://github.com/rust-lang/rust-clippy/pull/9365)
 +* [`explicit_auto_deref`]: Now ignores references on block expressions when the type
 +  is `Sized`, on `dyn Trait` returns and when the suggestion is non-trivial
 +  [#9126](https://github.com/rust-lang/rust-clippy/pull/9126)
 +* [`trait_duplication_in_bounds`]: Now better tracks bounds to avoid false positives
 +  [#9167](https://github.com/rust-lang/rust-clippy/pull/9167)
 +* [`format_in_format_args`]: Now suggests cases where the result is formatted again
 +  [#9349](https://github.com/rust-lang/rust-clippy/pull/9349)
 +* [`only_used_in_recursion`]: No longer lints on function without recursions and
 +  takes external functions into account
 +  [#8804](https://github.com/rust-lang/rust-clippy/pull/8804)
 +* [`missing_const_for_fn`]: No longer lints in proc-macros
 +  [#9308](https://github.com/rust-lang/rust-clippy/pull/9308)
 +* [`non_ascii_literal`]: Allow non-ascii comments in tests and make sure `#[allow]`
 +  attributes work in tests
 +  [#9327](https://github.com/rust-lang/rust-clippy/pull/9327)
 +* [`question_mark`]: No longer lint `if let`s with subpatterns
 +  [#9348](https://github.com/rust-lang/rust-clippy/pull/9348)
 +* [`needless_collect`]: No longer lints in loops
 +  [#8992](https://github.com/rust-lang/rust-clippy/pull/8992)
 +* [`mut_mutex_lock`]: No longer lints if the mutex is behind an immutable reference
 +  [#9418](https://github.com/rust-lang/rust-clippy/pull/9418)
 +* [`needless_return`]: Now ignores returns with arguments
 +  [#9381](https://github.com/rust-lang/rust-clippy/pull/9381)
 +* [`range_plus_one`], [`range_minus_one`]: Now ignores code with macros
 +  [#9446](https://github.com/rust-lang/rust-clippy/pull/9446)
 +* [`assertions_on_result_states`]: No longer lints on the unit type
 +  [#9273](https://github.com/rust-lang/rust-clippy/pull/9273)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`unwrap_or_else_default`]: Now suggests `unwrap_or_default()` for empty strings
 +  [#9421](https://github.com/rust-lang/rust-clippy/pull/9421)
 +* [`if_then_some_else_none`]: Now also suggests `bool::then_some`
 +  [#9289](https://github.com/rust-lang/rust-clippy/pull/9289)
 +* [`redundant_closure_call`]: The suggestion now works for async closures
 +  [#9053](https://github.com/rust-lang/rust-clippy/pull/9053)
 +* [`suboptimal_flops`]: Now suggests parenthesis when they are required
 +  [#9394](https://github.com/rust-lang/rust-clippy/pull/9394)
 +* [`case_sensitive_file_extension_comparisons`]: Now suggests `map_or(..)` instead of `map(..).unwrap_or`
 +  [#9341](https://github.com/rust-lang/rust-clippy/pull/9341)
 +* Deprecated configuration values can now be updated automatically
 +  [#9252](https://github.com/rust-lang/rust-clippy/pull/9252)
 +* [`or_fun_call`]: Now suggest `Entry::or_default` for `Entry::or_insert(Default::default())`
 +  [#9342](https://github.com/rust-lang/rust-clippy/pull/9342)
 +* [`unwrap_used`]: Only suggests `expect` if [`expect_used`] is allowed
 +  [#9223](https://github.com/rust-lang/rust-clippy/pull/9223)
 +
 +### ICE Fixes
 +
 +* Fix ICE in [`useless_format`] for literals
 +  [#9406](https://github.com/rust-lang/rust-clippy/pull/9406)
 +* Fix infinite loop in [`vec_init_then_push`]
 +  [#9441](https://github.com/rust-lang/rust-clippy/pull/9441)
 +* Fix ICE when reading literals with weird proc-macro spans
 +  [#9303](https://github.com/rust-lang/rust-clippy/pull/9303)
 +
 +## Rust 1.64
 +
 +Released 2022-09-22
 +
 +[d7b5cbf0...3c7e7dbc](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...3c7e7dbc)
 +
 +### New Lints
 +
 +* [`arithmetic_side_effects`]
 +  [#9130](https://github.com/rust-lang/rust-clippy/pull/9130)
 +* [`invalid_utf8_in_unchecked`]
 +  [#9105](https://github.com/rust-lang/rust-clippy/pull/9105)
 +* [`assertions_on_result_states`]
 +  [#9225](https://github.com/rust-lang/rust-clippy/pull/9225)
 +* [`manual_find`]
 +  [#8649](https://github.com/rust-lang/rust-clippy/pull/8649)
 +* [`manual_retain`]
 +  [#8972](https://github.com/rust-lang/rust-clippy/pull/8972)
 +* [`default_instead_of_iter_empty`]
 +  [#8989](https://github.com/rust-lang/rust-clippy/pull/8989)
 +* [`manual_rem_euclid`]
 +  [#9031](https://github.com/rust-lang/rust-clippy/pull/9031)
 +* [`obfuscated_if_else`]
 +  [#9148](https://github.com/rust-lang/rust-clippy/pull/9148)
 +* [`std_instead_of_core`]
 +  [#9103](https://github.com/rust-lang/rust-clippy/pull/9103)
 +* [`std_instead_of_alloc`]
 +  [#9103](https://github.com/rust-lang/rust-clippy/pull/9103)
 +* [`alloc_instead_of_core`]
 +  [#9103](https://github.com/rust-lang/rust-clippy/pull/9103)
 +* [`explicit_auto_deref`]
 +  [#8355](https://github.com/rust-lang/rust-clippy/pull/8355)
 +
 +
 +### Moves and Deprecations
 +
 +* Moved [`format_push_string`] to `restriction` (now allow-by-default)
 +  [#9161](https://github.com/rust-lang/rust-clippy/pull/9161)
 +
 +### Enhancements
 +
 +* [`significant_drop_in_scrutinee`]: Now gives more context in the lint message
 +  [#8981](https://github.com/rust-lang/rust-clippy/pull/8981)
 +* [`single_match`], [`single_match_else`]: Now catches more `Option` cases
 +  [#8985](https://github.com/rust-lang/rust-clippy/pull/8985)
 +* [`unused_async`]: Now works for async methods
 +  [#9025](https://github.com/rust-lang/rust-clippy/pull/9025)
 +* [`manual_filter_map`], [`manual_find_map`]: Now lint more expressions
 +  [#8958](https://github.com/rust-lang/rust-clippy/pull/8958)
 +* [`question_mark`]: Now works for simple `if let` expressions
 +  [#8356](https://github.com/rust-lang/rust-clippy/pull/8356)
 +* [`undocumented_unsafe_blocks`]: Now finds comments before the start of closures
 +  [#9117](https://github.com/rust-lang/rust-clippy/pull/9117)
 +* [`trait_duplication_in_bounds`]: Now catches duplicate bounds in where clauses
 +  [#8703](https://github.com/rust-lang/rust-clippy/pull/8703)
 +* [`shadow_reuse`], [`shadow_same`], [`shadow_unrelated`]: Now lint in const blocks
 +  [#9124](https://github.com/rust-lang/rust-clippy/pull/9124)
 +* [`slow_vector_initialization`]: Now detects cases with `vec.capacity()`
 +  [#8953](https://github.com/rust-lang/rust-clippy/pull/8953)
 +* [`unused_self`]: Now respects the `avoid-breaking-exported-api` config option
 +  [#9199](https://github.com/rust-lang/rust-clippy/pull/9199)
 +* [`box_collection`]: Now supports all std collections
 +  [#9170](https://github.com/rust-lang/rust-clippy/pull/9170)
 +
 +### False Positive Fixes
 +
 +* [`significant_drop_in_scrutinee`]: Now ignores calls to `IntoIterator::into_iter`
 +  [#9140](https://github.com/rust-lang/rust-clippy/pull/9140)
 +* [`while_let_loop`]: Now ignores cases when the significant drop order would change
 +  [#8981](https://github.com/rust-lang/rust-clippy/pull/8981)
 +* [`branches_sharing_code`]: Now ignores cases where moved variables have a significant
 +  drop or variable modifications can affect the conditions
 +  [#9138](https://github.com/rust-lang/rust-clippy/pull/9138)
 +* [`let_underscore_lock`]: Now ignores bindings that aren't locked
 +  [#8990](https://github.com/rust-lang/rust-clippy/pull/8990)
 +* [`trivially_copy_pass_by_ref`]: Now tracks lifetimes and ignores cases where unsafe
 +  pointers are used
 +  [#8639](https://github.com/rust-lang/rust-clippy/pull/8639)
 +* [`let_unit_value`]: No longer ignores `#[allow]` attributes on the value
 +  [#9082](https://github.com/rust-lang/rust-clippy/pull/9082)
 +* [`declare_interior_mutable_const`]: Now ignores the `thread_local!` macro
 +  [#9015](https://github.com/rust-lang/rust-clippy/pull/9015)
 +* [`if_same_then_else`]: Now ignores branches with `todo!` and `unimplemented!`
 +  [#9006](https://github.com/rust-lang/rust-clippy/pull/9006)
 +* [`enum_variant_names`]: Now ignores names with `_` prefixes
 +  [#9032](https://github.com/rust-lang/rust-clippy/pull/9032)
 +* [`let_unit_value`]: Now ignores cases, where the unit type is manually specified
 +  [#9056](https://github.com/rust-lang/rust-clippy/pull/9056)
 +* [`match_same_arms`]: Now ignores branches with `todo!`
 +  [#9207](https://github.com/rust-lang/rust-clippy/pull/9207)
 +* [`assign_op_pattern`]: Ignores cases that break borrowing rules
 +  [#9214](https://github.com/rust-lang/rust-clippy/pull/9214)
 +* [`extra_unused_lifetimes`]: No longer triggers in derive macros
 +  [#9037](https://github.com/rust-lang/rust-clippy/pull/9037)
 +* [`mismatching_type_param_order`]: Now ignores complicated generic parameters
 +  [#9146](https://github.com/rust-lang/rust-clippy/pull/9146)
 +* [`equatable_if_let`]: No longer lints in macros
 +  [#9074](https://github.com/rust-lang/rust-clippy/pull/9074)
 +* [`new_without_default`]: Now ignores generics and lifetime parameters on `fn new`
 +  [#9115](https://github.com/rust-lang/rust-clippy/pull/9115)
 +* [`needless_borrow`]: Now ignores cases that result in the execution of different traits
 +  [#9096](https://github.com/rust-lang/rust-clippy/pull/9096)
 +* [`declare_interior_mutable_const`]: No longer triggers in thread-local initializers
 +  [#9246](https://github.com/rust-lang/rust-clippy/pull/9246)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`type_repetition_in_bounds`]: The suggestion now works with maybe bounds
 +  [#9132](https://github.com/rust-lang/rust-clippy/pull/9132)
 +* [`transmute_ptr_to_ref`]: Now suggests `pointer::cast` when possible
 +  [#8939](https://github.com/rust-lang/rust-clippy/pull/8939)
 +* [`useless_format`]: Now suggests the correct variable name
 +  [#9237](https://github.com/rust-lang/rust-clippy/pull/9237)
 +* [`or_fun_call`]: The lint emission will now only span over the `unwrap_or` call
 +  [#9144](https://github.com/rust-lang/rust-clippy/pull/9144)
 +* [`neg_multiply`]: Now suggests adding parentheses around suggestion if needed
 +  [#9026](https://github.com/rust-lang/rust-clippy/pull/9026)
 +* [`unnecessary_lazy_evaluations`]: Now suggest for `bool::then_some` for lazy evaluation
 +  [#9099](https://github.com/rust-lang/rust-clippy/pull/9099)
 +* [`manual_flatten`]: Improved message for long code snippets
 +  [#9156](https://github.com/rust-lang/rust-clippy/pull/9156)
 +* [`explicit_counter_loop`]: The suggestion is now machine applicable
 +  [#9149](https://github.com/rust-lang/rust-clippy/pull/9149)
 +* [`needless_borrow`]: Now keeps parentheses around fields, when needed
 +  [#9210](https://github.com/rust-lang/rust-clippy/pull/9210)
 +* [`while_let_on_iterator`]: The suggestion now works in `FnOnce` closures
 +  [#9134](https://github.com/rust-lang/rust-clippy/pull/9134)
 +
 +### ICE Fixes
 +
 +* Fix ICEs related to `#![feature(generic_const_exprs)]` usage
 +  [#9241](https://github.com/rust-lang/rust-clippy/pull/9241)
 +* Fix ICEs related to reference lints
 +  [#9093](https://github.com/rust-lang/rust-clippy/pull/9093)
 +* [`question_mark`]: Fix ICE on zero field tuple structs
 +  [#9244](https://github.com/rust-lang/rust-clippy/pull/9244)
 +
 +### Documentation Improvements
 +
 +* [`needless_option_take`]: Now includes a "What it does" and "Why is this bad?" section.
 +  [#9022](https://github.com/rust-lang/rust-clippy/pull/9022)
 +
 +### Others
 +
 +* Using `--cap-lints=allow` and only `--force-warn`ing some will now work with Clippy's driver
 +  [#9036](https://github.com/rust-lang/rust-clippy/pull/9036)
 +* Clippy now tries to read the `rust-version` from `Cargo.toml` to identify the
 +  minimum supported rust version
 +  [#8774](https://github.com/rust-lang/rust-clippy/pull/8774)
 +
 +## Rust 1.63
 +
 +Released 2022-08-11
 +
 +[7c21f91b...d7b5cbf0](https://github.com/rust-lang/rust-clippy/compare/7c21f91b...d7b5cbf0)
 +
 +### New Lints
 +
 +* [`borrow_deref_ref`]
 +  [#7930](https://github.com/rust-lang/rust-clippy/pull/7930)
 +* [`doc_link_with_quotes`]
 +  [#8385](https://github.com/rust-lang/rust-clippy/pull/8385)
 +* [`no_effect_replace`]
 +  [#8754](https://github.com/rust-lang/rust-clippy/pull/8754)
 +* [`rc_clone_in_vec_init`]
 +  [#8769](https://github.com/rust-lang/rust-clippy/pull/8769)
 +* [`derive_partial_eq_without_eq`]
 +  [#8796](https://github.com/rust-lang/rust-clippy/pull/8796)
 +* [`mismatching_type_param_order`]
 +  [#8831](https://github.com/rust-lang/rust-clippy/pull/8831)
 +* [`duplicate_mod`] [#8832](https://github.com/rust-lang/rust-clippy/pull/8832)
 +* [`unused_rounding`]
 +  [#8866](https://github.com/rust-lang/rust-clippy/pull/8866)
 +* [`get_first`] [#8882](https://github.com/rust-lang/rust-clippy/pull/8882)
 +* [`swap_ptr_to_ref`]
 +  [#8916](https://github.com/rust-lang/rust-clippy/pull/8916)
 +* [`almost_complete_letter_range`]
 +  [#8918](https://github.com/rust-lang/rust-clippy/pull/8918)
 +* [`needless_parens_on_range_literals`]
 +  [#8933](https://github.com/rust-lang/rust-clippy/pull/8933)
 +* [`as_underscore`] [#8934](https://github.com/rust-lang/rust-clippy/pull/8934)
 +
 +### Moves and Deprecations
 +
 +* Rename `eval_order_dependence` to [`mixed_read_write_in_expression`], move to
 +  `nursery` [#8621](https://github.com/rust-lang/rust-clippy/pull/8621)
 +
 +### Enhancements
 +
 +* [`undocumented_unsafe_blocks`]: Now also lints on unsafe trait implementations
 +  [#8761](https://github.com/rust-lang/rust-clippy/pull/8761)
 +* [`empty_line_after_outer_attr`]: Now also lints on argumentless macros
 +  [#8790](https://github.com/rust-lang/rust-clippy/pull/8790)
 +* [`expect_used`]: Now can be disabled in tests with the `allow-expect-in-tests`
 +  option [#8802](https://github.com/rust-lang/rust-clippy/pull/8802)
 +* [`unwrap_used`]: Now can be disabled in tests with the `allow-unwrap-in-tests`
 +  option [#8802](https://github.com/rust-lang/rust-clippy/pull/8802)
 +* [`disallowed_methods`]: Now also lints indirect usages
 +  [#8852](https://github.com/rust-lang/rust-clippy/pull/8852)
 +* [`get_last_with_len`]: Now also lints `VecDeque` and any deref to slice
 +  [#8862](https://github.com/rust-lang/rust-clippy/pull/8862)
 +* [`manual_range_contains`]: Now also lints on chains of `&&` and `||`
 +  [#8884](https://github.com/rust-lang/rust-clippy/pull/8884)
 +* [`rc_clone_in_vec_init`]: Now also lints on `Weak`
 +  [#8885](https://github.com/rust-lang/rust-clippy/pull/8885)
 +* [`dbg_macro`]: Introduce `allow-dbg-in-tests` config option
 +  [#8897](https://github.com/rust-lang/rust-clippy/pull/8897)
 +* [`use_self`]: Now also lints on `TupleStruct` and `Struct` patterns
 +  [#8899](https://github.com/rust-lang/rust-clippy/pull/8899)
 +* [`manual_find_map`] and [`manual_filter_map`]: Now also lints on more complex
 +  method chains inside `map`
 +  [#8930](https://github.com/rust-lang/rust-clippy/pull/8930)
 +* [`needless_return`]: Now also lints on macro expressions in return statements
 +  [#8932](https://github.com/rust-lang/rust-clippy/pull/8932)
 +* [`doc_markdown`]: Users can now indicate, that the `doc-valid-idents` config
 +  should extend the default and not replace it
 +  [#8944](https://github.com/rust-lang/rust-clippy/pull/8944)
 +* [`disallowed_names`]: Users can now indicate, that the `disallowed-names`
 +  config should extend the default and not replace it
 +  [#8944](https://github.com/rust-lang/rust-clippy/pull/8944)
 +* [`never_loop`]: Now checks for `continue` in struct expression
 +  [#9002](https://github.com/rust-lang/rust-clippy/pull/9002)
 +
 +### False Positive Fixes
 +
 +* [`useless_transmute`]: No longer lints on types with erased regions
 +  [#8564](https://github.com/rust-lang/rust-clippy/pull/8564)
 +* [`vec_init_then_push`]: No longer lints when further extended
 +  [#8699](https://github.com/rust-lang/rust-clippy/pull/8699)
 +* [`cmp_owned`]: No longer lints on `From::from` for `Copy` types
 +  [#8807](https://github.com/rust-lang/rust-clippy/pull/8807)
 +* [`redundant_allocation`]: No longer lints on fat pointers that would become
 +  thin pointers [#8813](https://github.com/rust-lang/rust-clippy/pull/8813)
 +* [`derive_partial_eq_without_eq`]:
 +    * Handle differing predicates applied by `#[derive(PartialEq)]` and
 +      `#[derive(Eq)]`
 +      [#8869](https://github.com/rust-lang/rust-clippy/pull/8869)
 +    * No longer lints on non-public types and better handles generics
 +      [#8950](https://github.com/rust-lang/rust-clippy/pull/8950)
 +* [`empty_line_after_outer_attr`]: No longer lints empty lines in inner
 +  string values [#8892](https://github.com/rust-lang/rust-clippy/pull/8892)
 +* [`branches_sharing_code`]: No longer lints when using different binding names
 +  [#8901](https://github.com/rust-lang/rust-clippy/pull/8901)
 +* [`significant_drop_in_scrutinee`]: No longer lints on Try `?` and `await`
 +  desugared expressions [#8902](https://github.com/rust-lang/rust-clippy/pull/8902)
 +* [`checked_conversions`]: No longer lints in `const` contexts
 +  [#8907](https://github.com/rust-lang/rust-clippy/pull/8907)
 +* [`iter_overeager_cloned`]: No longer lints on `.cloned().flatten()` when
 +  `T::Item` doesn't implement `IntoIterator`
 +  [#8960](https://github.com/rust-lang/rust-clippy/pull/8960)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`vec_init_then_push`]: Suggest to remove `mut` binding when possible
 +  [#8699](https://github.com/rust-lang/rust-clippy/pull/8699)
 +* [`manual_range_contains`]: Fix suggestion for integers with different signs
 +  [#8763](https://github.com/rust-lang/rust-clippy/pull/8763)
 +* [`identity_op`]: Add parenthesis to suggestions where required
 +  [#8786](https://github.com/rust-lang/rust-clippy/pull/8786)
 +* [`cast_lossless`]: No longer gives wrong suggestion on `usize`/`isize`->`f64`
 +  [#8778](https://github.com/rust-lang/rust-clippy/pull/8778)
 +* [`rc_clone_in_vec_init`]: Add suggestion
 +  [#8814](https://github.com/rust-lang/rust-clippy/pull/8814)
 +* The "unknown field" error messages for config files now wraps the field names
 +  [#8823](https://github.com/rust-lang/rust-clippy/pull/8823)
 +* [`cast_abs_to_unsigned`]: Do not remove cast if it's required
 +  [#8876](https://github.com/rust-lang/rust-clippy/pull/8876)
 +* [`significant_drop_in_scrutinee`]: Improve lint message for types that are not
 +  references and not trivially clone-able
 +  [#8902](https://github.com/rust-lang/rust-clippy/pull/8902)
 +* [`for_loops_over_fallibles`]: Now suggests the correct variant of `iter()`,
 +  `iter_mut()` or `into_iter()`
 +  [#8941](https://github.com/rust-lang/rust-clippy/pull/8941)
 +
 +### ICE Fixes
 +
 +* Fix ICE in [`let_unit_value`] when calling a `static`/`const` callable type
 +  [#8835](https://github.com/rust-lang/rust-clippy/pull/8835)
 +* Fix ICEs on callable `static`/`const`s
 +  [#8896](https://github.com/rust-lang/rust-clippy/pull/8896)
 +* [`needless_late_init`]
 +  [#8912](https://github.com/rust-lang/rust-clippy/pull/8912)
 +* Fix ICE in shadow lints
 +  [#8913](https://github.com/rust-lang/rust-clippy/pull/8913)
 +
 +### Documentation Improvements
 +
 +* Clippy has a [Book](https://doc.rust-lang.org/nightly/clippy/) now!
 +  [#7359](https://github.com/rust-lang/rust-clippy/pull/7359)
 +* Add a *copy lint name*-button to Clippy's lint list
 +  [#8839](https://github.com/rust-lang/rust-clippy/pull/8839)
 +* Display past names of renamed lints on Clippy's lint list
 +  [#8843](https://github.com/rust-lang/rust-clippy/pull/8843)
 +* Add the ability to show the lint output in the lint list
 +  [#8947](https://github.com/rust-lang/rust-clippy/pull/8947)
 +
 +## Rust 1.62
 +
 +Released 2022-06-30
 +
 +[d0cf3481...7c21f91b](https://github.com/rust-lang/rust-clippy/compare/d0cf3481...7c21f91b)
 +
 +### New Lints
 +
 +* [`large_include_file`]
 +  [#8727](https://github.com/rust-lang/rust-clippy/pull/8727)
 +* [`cast_abs_to_unsigned`]
 +  [#8635](https://github.com/rust-lang/rust-clippy/pull/8635)
 +* [`err_expect`]
 +  [#8606](https://github.com/rust-lang/rust-clippy/pull/8606)
 +* [`unnecessary_owned_empty_strings`]
 +  [#8660](https://github.com/rust-lang/rust-clippy/pull/8660)
 +* [`empty_structs_with_brackets`]
 +  [#8594](https://github.com/rust-lang/rust-clippy/pull/8594)
 +* [`crate_in_macro_def`]
 +  [#8576](https://github.com/rust-lang/rust-clippy/pull/8576)
 +* [`needless_option_take`]
 +  [#8665](https://github.com/rust-lang/rust-clippy/pull/8665)
 +* [`bytes_count_to_len`]
 +  [#8711](https://github.com/rust-lang/rust-clippy/pull/8711)
 +* [`is_digit_ascii_radix`]
 +  [#8624](https://github.com/rust-lang/rust-clippy/pull/8624)
 +* [`await_holding_invalid_type`]
 +  [#8707](https://github.com/rust-lang/rust-clippy/pull/8707)
 +* [`trim_split_whitespace`]
 +  [#8575](https://github.com/rust-lang/rust-clippy/pull/8575)
 +* [`pub_use`]
 +  [#8670](https://github.com/rust-lang/rust-clippy/pull/8670)
 +* [`format_push_string`]
 +  [#8626](https://github.com/rust-lang/rust-clippy/pull/8626)
 +* [`empty_drop`]
 +  [#8571](https://github.com/rust-lang/rust-clippy/pull/8571)
 +* [`drop_non_drop`]
 +  [#8630](https://github.com/rust-lang/rust-clippy/pull/8630)
 +* [`forget_non_drop`]
 +  [#8630](https://github.com/rust-lang/rust-clippy/pull/8630)
 +
 +### Moves and Deprecations
 +
 +* Move [`only_used_in_recursion`] to `nursery` (now allow-by-default)
 +  [#8783](https://github.com/rust-lang/rust-clippy/pull/8783)
 +* Move [`stable_sort_primitive`] to `pedantic` (now allow-by-default)
 +  [#8716](https://github.com/rust-lang/rust-clippy/pull/8716)
 +
 +### Enhancements
 +
 +* Remove overlap between [`manual_split_once`] and [`needless_splitn`]
 +  [#8631](https://github.com/rust-lang/rust-clippy/pull/8631)
 +* [`map_identity`]: Now checks for needless `map_err`
 +  [#8487](https://github.com/rust-lang/rust-clippy/pull/8487)
 +* [`extra_unused_lifetimes`]: Now checks for impl lifetimes
 +  [#8737](https://github.com/rust-lang/rust-clippy/pull/8737)
 +* [`cast_possible_truncation`]: Now catches more cases with larger shift or divide operations
 +  [#8687](https://github.com/rust-lang/rust-clippy/pull/8687)
 +* [`identity_op`]: Now checks for modulo expressions
 +  [#8519](https://github.com/rust-lang/rust-clippy/pull/8519)
 +* [`panic`]: No longer lint in constant context
 +  [#8592](https://github.com/rust-lang/rust-clippy/pull/8592)
 +* [`manual_split_once`]: Now lints manual iteration of `splitn`
 +  [#8717](https://github.com/rust-lang/rust-clippy/pull/8717)
 +* [`self_named_module_files`], [`mod_module_files`]: Now handle relative module paths
 +  [#8611](https://github.com/rust-lang/rust-clippy/pull/8611)
 +* [`unsound_collection_transmute`]: Now has better size and alignment checks
 +  [#8648](https://github.com/rust-lang/rust-clippy/pull/8648)
 +* [`unnested_or_patterns`]: Ignore cases, where the suggestion would be longer
 +  [#8619](https://github.com/rust-lang/rust-clippy/pull/8619)
 +
 +### False Positive Fixes
 +
 +* [`rest_pat_in_fully_bound_structs`]: Now ignores structs marked with `#[non_exhaustive]`
 +  [#8690](https://github.com/rust-lang/rust-clippy/pull/8690)
 +* [`needless_late_init`]: No longer lints `if let` statements, `let mut` bindings or instances that
 +  changes the drop order significantly
 +  [#8617](https://github.com/rust-lang/rust-clippy/pull/8617)
 +* [`unnecessary_cast`]: No longer lints to casts to aliased or non-primitive types
 +  [#8596](https://github.com/rust-lang/rust-clippy/pull/8596)
 +* [`init_numbered_fields`]: No longer lints type aliases
 +  [#8780](https://github.com/rust-lang/rust-clippy/pull/8780)
 +* [`needless_option_as_deref`]: No longer lints for `as_deref_mut` on `Option` values that can't be moved
 +  [#8646](https://github.com/rust-lang/rust-clippy/pull/8646)
 +* [`mistyped_literal_suffixes`]: Now ignores float literals without an exponent
 +  [#8742](https://github.com/rust-lang/rust-clippy/pull/8742)
 +* [`undocumented_unsafe_blocks`]: Now ignores unsafe blocks from proc-macros and works better for sub-expressions
 +  [#8450](https://github.com/rust-lang/rust-clippy/pull/8450)
 +* [`same_functions_in_if_condition`]: Now allows different constants, even if they have the same value
 +  [#8673](https://github.com/rust-lang/rust-clippy/pull/8673)
 +* [`needless_match`]: Now checks for more complex types and ignores type coercion
 +  [#8549](https://github.com/rust-lang/rust-clippy/pull/8549)
 +* [`assertions_on_constants`]: Now ignores constants from `cfg!` macros
 +  [#8614](https://github.com/rust-lang/rust-clippy/pull/8614)
 +* [`indexing_slicing`]: Fix false positives with constant indices in
 +  [#8588](https://github.com/rust-lang/rust-clippy/pull/8588)
 +* [`iter_with_drain`]: Now ignores iterator references
 +  [#8668](https://github.com/rust-lang/rust-clippy/pull/8668)
 +* [`useless_attribute`]: Now allows [`redundant_pub_crate`] on `use` items
 +  [#8743](https://github.com/rust-lang/rust-clippy/pull/8743)
 +* [`cast_ptr_alignment`]: Now ignores expressions, when used for unaligned reads and writes
 +  [#8632](https://github.com/rust-lang/rust-clippy/pull/8632)
 +* [`wrong_self_convention`]: Now allows `&mut self` and no self as arguments for `is_*` methods
 +  [#8738](https://github.com/rust-lang/rust-clippy/pull/8738)
 +* [`mut_from_ref`]: Only lint in unsafe code
 +  [#8647](https://github.com/rust-lang/rust-clippy/pull/8647)
 +* [`redundant_pub_crate`]: Now allows macro exports
 +  [#8736](https://github.com/rust-lang/rust-clippy/pull/8736)
 +* [`needless_match`]: Ignores cases where the else block expression is different
 +  [#8700](https://github.com/rust-lang/rust-clippy/pull/8700)
 +* [`transmute_int_to_char`]: Now allows transmutations in `const` code
 +  [#8610](https://github.com/rust-lang/rust-clippy/pull/8610)
 +* [`manual_non_exhaustive`]: Ignores cases, where the enum value is used
 +  [#8645](https://github.com/rust-lang/rust-clippy/pull/8645)
 +* [`redundant_closure`]: Now ignores coerced closure
 +  [#8431](https://github.com/rust-lang/rust-clippy/pull/8431)
 +* [`identity_op`]: Is now ignored in cases where extra brackets would be needed
 +  [#8730](https://github.com/rust-lang/rust-clippy/pull/8730)
 +* [`let_unit_value`]: Now ignores cases which are used for type inference
 +  [#8563](https://github.com/rust-lang/rust-clippy/pull/8563)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`manual_split_once`]: Fixed incorrect suggestions for single result accesses
 +  [#8631](https://github.com/rust-lang/rust-clippy/pull/8631)
 +* [`bytes_nth`]: Fix typos in the diagnostic message
 +  [#8403](https://github.com/rust-lang/rust-clippy/pull/8403)
 +* [`mistyped_literal_suffixes`]: Now suggests the correct integer types
 +  [#8742](https://github.com/rust-lang/rust-clippy/pull/8742)
 +* [`unnecessary_to_owned`]: Fixed suggestion based on the configured msrv
 +  [#8692](https://github.com/rust-lang/rust-clippy/pull/8692)
 +* [`single_element_loop`]: Improve lint for Edition 2021 arrays
 +  [#8616](https://github.com/rust-lang/rust-clippy/pull/8616)
 +* [`manual_bits`]: Now includes a cast for proper type conversion, when needed
 +  [#8677](https://github.com/rust-lang/rust-clippy/pull/8677)
 +* [`option_map_unit_fn`], [`result_map_unit_fn`]: Fix some incorrect suggestions
 +  [#8584](https://github.com/rust-lang/rust-clippy/pull/8584)
 +* [`collapsible_else_if`]: Add whitespace in suggestion
 +  [#8729](https://github.com/rust-lang/rust-clippy/pull/8729)
 +* [`transmute_bytes_to_str`]: Now suggest `from_utf8_unchecked` in `const` context
 +  [#8612](https://github.com/rust-lang/rust-clippy/pull/8612)
 +* [`map_clone`]: Improve message and suggestion based on the msrv
 +  [#8688](https://github.com/rust-lang/rust-clippy/pull/8688)
 +* [`needless_late_init`]: Now shows the `let` statement where it was first initialized
 +  [#8779](https://github.com/rust-lang/rust-clippy/pull/8779)
 +
 +### ICE Fixes
 +
 +* [`only_used_in_recursion`]
 +  [#8691](https://github.com/rust-lang/rust-clippy/pull/8691)
 +* [`cast_slice_different_sizes`]
 +  [#8720](https://github.com/rust-lang/rust-clippy/pull/8720)
 +* [`iter_overeager_cloned`]
 +  [#8602](https://github.com/rust-lang/rust-clippy/pull/8602)
 +* [`undocumented_unsafe_blocks`]
 +  [#8686](https://github.com/rust-lang/rust-clippy/pull/8686)
 +
 +## Rust 1.61
 +
 +Released 2022-05-19
 +
 +[57b3c4b...d0cf3481](https://github.com/rust-lang/rust-clippy/compare/57b3c4b...d0cf3481)
 +
 +### New Lints
 +
 +* [`only_used_in_recursion`]
 +  [#8422](https://github.com/rust-lang/rust-clippy/pull/8422)
 +* [`cast_enum_truncation`]
 +  [#8381](https://github.com/rust-lang/rust-clippy/pull/8381)
 +* [`missing_spin_loop`]
 +  [#8174](https://github.com/rust-lang/rust-clippy/pull/8174)
 +* [`deref_by_slicing`]
 +  [#8218](https://github.com/rust-lang/rust-clippy/pull/8218)
 +* [`needless_match`]
 +  [#8471](https://github.com/rust-lang/rust-clippy/pull/8471)
 +* [`allow_attributes_without_reason`] (Requires `#![feature(lint_reasons)]`)
 +  [#8504](https://github.com/rust-lang/rust-clippy/pull/8504)
 +* [`print_in_format_impl`]
 +  [#8253](https://github.com/rust-lang/rust-clippy/pull/8253)
 +* [`unnecessary_find_map`]
 +  [#8489](https://github.com/rust-lang/rust-clippy/pull/8489)
 +* [`or_then_unwrap`]
 +  [#8561](https://github.com/rust-lang/rust-clippy/pull/8561)
 +* [`unnecessary_join`]
 +  [#8579](https://github.com/rust-lang/rust-clippy/pull/8579)
 +* [`iter_with_drain`]
 +  [#8483](https://github.com/rust-lang/rust-clippy/pull/8483)
 +* [`cast_enum_constructor`]
 +  [#8562](https://github.com/rust-lang/rust-clippy/pull/8562)
 +* [`cast_slice_different_sizes`]
 +  [#8445](https://github.com/rust-lang/rust-clippy/pull/8445)
 +
 +### Moves and Deprecations
 +
 +* Moved [`transmute_undefined_repr`] to `nursery` (now allow-by-default)
 +  [#8432](https://github.com/rust-lang/rust-clippy/pull/8432)
 +* Moved [`try_err`] to `restriction`
 +  [#8544](https://github.com/rust-lang/rust-clippy/pull/8544)
 +* Move [`iter_with_drain`] to `nursery`
 +  [#8541](https://github.com/rust-lang/rust-clippy/pull/8541)
 +* Renamed `to_string_in_display` to [`recursive_format_impl`]
 +  [#8188](https://github.com/rust-lang/rust-clippy/pull/8188)
 +
 +### Enhancements
 +
 +* [`dbg_macro`]: The lint level can now be set with crate attributes and works inside macros
 +  [#8411](https://github.com/rust-lang/rust-clippy/pull/8411)
 +* [`ptr_as_ptr`]: Now works inside macros
 +  [#8442](https://github.com/rust-lang/rust-clippy/pull/8442)
 +* [`use_self`]: Now works for variants in match expressions
 +  [#8456](https://github.com/rust-lang/rust-clippy/pull/8456)
 +* [`await_holding_lock`]: Now lints for `parking_lot::{Mutex, RwLock}`
 +  [#8419](https://github.com/rust-lang/rust-clippy/pull/8419)
 +* [`recursive_format_impl`]: Now checks for format calls on `self`
 +  [#8188](https://github.com/rust-lang/rust-clippy/pull/8188)
 +
 +### False Positive Fixes
 +
 +* [`new_without_default`]: No longer lints for `new()` methods with `#[doc(hidden)]`
 +  [#8472](https://github.com/rust-lang/rust-clippy/pull/8472)
 +* [`transmute_undefined_repr`]: No longer lints for single field structs with `#[repr(C)]`,
 +  generic parameters, wide pointers, unions, tuples and allow several forms of type erasure
 +  [#8425](https://github.com/rust-lang/rust-clippy/pull/8425)
 +  [#8553](https://github.com/rust-lang/rust-clippy/pull/8553)
 +  [#8440](https://github.com/rust-lang/rust-clippy/pull/8440)
 +  [#8547](https://github.com/rust-lang/rust-clippy/pull/8547)
 +* [`match_single_binding`], [`match_same_arms`], [`match_as_ref`], [`match_bool`]: No longer
 +  lint `match` expressions with `cfg`ed arms
 +  [#8443](https://github.com/rust-lang/rust-clippy/pull/8443)
 +* [`single_component_path_imports`]: No longer lint on macros
 +  [#8537](https://github.com/rust-lang/rust-clippy/pull/8537)
 +* [`ptr_arg`]: Allow `&mut` arguments for `Cow<_>`
 +  [#8552](https://github.com/rust-lang/rust-clippy/pull/8552)
 +* [`needless_borrow`]: No longer lints for method calls
 +  [#8441](https://github.com/rust-lang/rust-clippy/pull/8441)
 +* [`match_same_arms`]: Now ensures that interposing arm patterns don't overlap
 +  [#8232](https://github.com/rust-lang/rust-clippy/pull/8232)
 +* [`default_trait_access`]: Now allows `Default::default` in update expressions
 +  [#8433](https://github.com/rust-lang/rust-clippy/pull/8433)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`redundant_slicing`]: Fixed suggestion for a method calls
 +  [#8218](https://github.com/rust-lang/rust-clippy/pull/8218)
 +* [`map_flatten`]: Long suggestions will now be split up into two help messages
 +  [#8520](https://github.com/rust-lang/rust-clippy/pull/8520)
 +* [`unnecessary_lazy_evaluations`]: Now shows suggestions for longer code snippets
 +  [#8543](https://github.com/rust-lang/rust-clippy/pull/8543)
 +* [`unnecessary_sort_by`]: Now suggests `Reverse` including the path
 +  [#8462](https://github.com/rust-lang/rust-clippy/pull/8462)
 +* [`search_is_some`]: More suggestions are now `MachineApplicable`
 +  [#8536](https://github.com/rust-lang/rust-clippy/pull/8536)
 +
 +### Documentation Improvements
 +
 +* [`new_without_default`]: Document `pub` requirement for the struct and fields
 +  [#8429](https://github.com/rust-lang/rust-clippy/pull/8429)
 +
 +## Rust 1.60
 +
 +Released 2022-04-07
 +
 +[0eff589...57b3c4b](https://github.com/rust-lang/rust-clippy/compare/0eff589...57b3c4b)
 +
 +### New Lints
 +
 +* [`single_char_lifetime_names`]
 +  [#8236](https://github.com/rust-lang/rust-clippy/pull/8236)
 +* [`iter_overeager_cloned`]
 +  [#8203](https://github.com/rust-lang/rust-clippy/pull/8203)
 +* [`transmute_undefined_repr`]
 +  [#8398](https://github.com/rust-lang/rust-clippy/pull/8398)
 +* [`default_union_representation`]
 +  [#8289](https://github.com/rust-lang/rust-clippy/pull/8289)
 +* [`manual_bits`]
 +  [#8213](https://github.com/rust-lang/rust-clippy/pull/8213)
 +* [`borrow_as_ptr`]
 +  [#8210](https://github.com/rust-lang/rust-clippy/pull/8210)
 +
 +### Moves and Deprecations
 +
 +* Moved [`disallowed_methods`] and [`disallowed_types`] to `style` (now warn-by-default)
 +  [#8261](https://github.com/rust-lang/rust-clippy/pull/8261)
 +* Rename `ref_in_deref` to [`needless_borrow`]
 +  [#8217](https://github.com/rust-lang/rust-clippy/pull/8217)
 +* Moved [`mutex_atomic`] to `nursery` (now allow-by-default)
 +  [#8260](https://github.com/rust-lang/rust-clippy/pull/8260)
 +
 +### Enhancements
 +
 +* [`ptr_arg`]: Now takes the argument usage into account and lints for mutable references
 +  [#8271](https://github.com/rust-lang/rust-clippy/pull/8271)
 +* [`unused_io_amount`]: Now supports async read and write traits
 +  [#8179](https://github.com/rust-lang/rust-clippy/pull/8179)
 +* [`while_let_on_iterator`]: Improved detection to catch more cases
 +  [#8221](https://github.com/rust-lang/rust-clippy/pull/8221)
 +* [`trait_duplication_in_bounds`]: Now covers trait functions with `Self` bounds
 +  [#8252](https://github.com/rust-lang/rust-clippy/pull/8252)
 +* [`unwrap_used`]: Now works for `.get(i).unwrap()` and `.get_mut(i).unwrap()`
 +  [#8372](https://github.com/rust-lang/rust-clippy/pull/8372)
 +* [`map_clone`]: The suggestion takes `msrv` into account
 +  [#8280](https://github.com/rust-lang/rust-clippy/pull/8280)
 +* [`manual_bits`] and [`borrow_as_ptr`]: Now track the `clippy::msrv` attribute
 +  [#8280](https://github.com/rust-lang/rust-clippy/pull/8280)
 +* [`disallowed_methods`]: Now works for methods on primitive types
 +  [#8112](https://github.com/rust-lang/rust-clippy/pull/8112)
 +* [`not_unsafe_ptr_arg_deref`]: Now works for type aliases
 +  [#8273](https://github.com/rust-lang/rust-clippy/pull/8273)
 +* [`needless_question_mark`]: Now works for async functions
 +  [#8311](https://github.com/rust-lang/rust-clippy/pull/8311)
 +* [`iter_not_returning_iterator`]: Now handles type projections
 +  [#8228](https://github.com/rust-lang/rust-clippy/pull/8228)
 +* [`wrong_self_convention`]: Now detects wrong `self` references in more cases
 +  [#8208](https://github.com/rust-lang/rust-clippy/pull/8208)
 +* [`single_match`]: Now works for `match` statements with tuples
 +  [#8322](https://github.com/rust-lang/rust-clippy/pull/8322)
 +
 +### False Positive Fixes
 +
 +* [`erasing_op`]: No longer triggers if the output type changes
 +  [#8204](https://github.com/rust-lang/rust-clippy/pull/8204)
 +* [`if_same_then_else`]: No longer triggers for `if let` statements
 +  [#8297](https://github.com/rust-lang/rust-clippy/pull/8297)
 +* [`manual_memcpy`]: No longer lints on `VecDeque`
 +  [#8226](https://github.com/rust-lang/rust-clippy/pull/8226)
 +* [`trait_duplication_in_bounds`]: Now takes path segments into account
 +  [#8315](https://github.com/rust-lang/rust-clippy/pull/8315)
 +* [`deref_addrof`]: No longer lints when the dereference or borrow occurs in different a context
 +  [#8268](https://github.com/rust-lang/rust-clippy/pull/8268)
 +* [`type_repetition_in_bounds`]: Now checks for full equality to prevent false positives
 +  [#8224](https://github.com/rust-lang/rust-clippy/pull/8224)
 +* [`ptr_arg`]: No longer lint for mutable references in traits
 +  [#8369](https://github.com/rust-lang/rust-clippy/pull/8369)
 +* [`implicit_clone`]: No longer lints for double references
 +  [#8231](https://github.com/rust-lang/rust-clippy/pull/8231)
 +* [`needless_lifetimes`]: No longer lints lifetimes for explicit `self` types
 +  [#8278](https://github.com/rust-lang/rust-clippy/pull/8278)
 +* [`op_ref`]: No longer lints in `BinOp` impl if that can cause recursion
 +  [#8298](https://github.com/rust-lang/rust-clippy/pull/8298)
 +* [`enum_variant_names`]: No longer triggers for empty variant names
 +  [#8329](https://github.com/rust-lang/rust-clippy/pull/8329)
 +* [`redundant_closure`]: No longer lints for `Arc<T>` or `Rc<T>`
 +  [#8193](https://github.com/rust-lang/rust-clippy/pull/8193)
 +* [`iter_not_returning_iterator`]: No longer lints on trait implementations but therefore on trait definitions
 +  [#8228](https://github.com/rust-lang/rust-clippy/pull/8228)
 +* [`single_match`]: No longer lints on exhaustive enum patterns without a wildcard
 +  [#8322](https://github.com/rust-lang/rust-clippy/pull/8322)
 +* [`manual_swap`]: No longer lints on cases that involve automatic dereferences
 +  [#8220](https://github.com/rust-lang/rust-clippy/pull/8220)
 +* [`useless_format`]: Now works for implicit named arguments
 +  [#8295](https://github.com/rust-lang/rust-clippy/pull/8295)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`needless_borrow`]: Prevent mutable borrows being moved and suggest removing the borrow on method calls
 +  [#8217](https://github.com/rust-lang/rust-clippy/pull/8217)
 +* [`chars_next_cmp`]: Correctly escapes the suggestion
 +  [#8376](https://github.com/rust-lang/rust-clippy/pull/8376)
 +* [`explicit_write`]: Add suggestions for `write!`s with format arguments
 +  [#8365](https://github.com/rust-lang/rust-clippy/pull/8365)
 +* [`manual_memcpy`]: Suggests `copy_from_slice` when applicable
 +  [#8226](https://github.com/rust-lang/rust-clippy/pull/8226)
 +* [`or_fun_call`]: Improved suggestion display for long arguments
 +  [#8292](https://github.com/rust-lang/rust-clippy/pull/8292)
 +* [`unnecessary_cast`]: Now correctly includes the sign
 +  [#8350](https://github.com/rust-lang/rust-clippy/pull/8350)
 +* [`cmp_owned`]: No longer flips the comparison order
 +  [#8299](https://github.com/rust-lang/rust-clippy/pull/8299)
 +* [`explicit_counter_loop`]: Now correctly suggests `iter()` on references
 +  [#8382](https://github.com/rust-lang/rust-clippy/pull/8382)
 +
 +### ICE Fixes
 +
 +* [`manual_split_once`]
 +  [#8250](https://github.com/rust-lang/rust-clippy/pull/8250)
 +
 +### Documentation Improvements
 +
 +* [`map_flatten`]: Add documentation for the `Option` type
 +  [#8354](https://github.com/rust-lang/rust-clippy/pull/8354)
 +* Document that Clippy's driver might use a different code generation than rustc
 +  [#8037](https://github.com/rust-lang/rust-clippy/pull/8037)
 +* Clippy's lint list will now automatically focus the search box
 +  [#8343](https://github.com/rust-lang/rust-clippy/pull/8343)
 +
 +### Others
 +
 +* Clippy now warns if we find multiple Clippy config files exist
 +  [#8326](https://github.com/rust-lang/rust-clippy/pull/8326)
 +
 +## Rust 1.59
 +
 +Released 2022-02-24
 +
 +[e181011...0eff589](https://github.com/rust-lang/rust-clippy/compare/e181011...0eff589)
 +
 +### New Lints
 +
 +* [`index_refutable_slice`]
 +  [#7643](https://github.com/rust-lang/rust-clippy/pull/7643)
 +* [`needless_splitn`]
 +  [#7896](https://github.com/rust-lang/rust-clippy/pull/7896)
 +* [`unnecessary_to_owned`]
 +  [#7978](https://github.com/rust-lang/rust-clippy/pull/7978)
 +* [`needless_late_init`]
 +  [#7995](https://github.com/rust-lang/rust-clippy/pull/7995)
 +* [`octal_escapes`] [#8007](https://github.com/rust-lang/rust-clippy/pull/8007)
 +* [`return_self_not_must_use`]
 +  [#8071](https://github.com/rust-lang/rust-clippy/pull/8071)
 +* [`init_numbered_fields`]
 +  [#8170](https://github.com/rust-lang/rust-clippy/pull/8170)
 +
 +### Moves and Deprecations
 +
 +* Move `if_then_panic` to `pedantic` and rename to [`manual_assert`] (now
 +  allow-by-default) [#7810](https://github.com/rust-lang/rust-clippy/pull/7810)
 +* Rename `disallow_type` to [`disallowed_types`] and `disallowed_method` to
 +  [`disallowed_methods`]
 +  [#7984](https://github.com/rust-lang/rust-clippy/pull/7984)
 +* Move [`map_flatten`] to `complexity` (now warn-by-default)
 +  [#8054](https://github.com/rust-lang/rust-clippy/pull/8054)
 +
 +### Enhancements
 +
 +* [`match_overlapping_arm`]: Fix false negative where after included ranges,
 +  overlapping ranges weren't linted anymore
 +  [#7909](https://github.com/rust-lang/rust-clippy/pull/7909)
 +* [`deprecated_cfg_attr`]: Now takes the specified MSRV into account
 +  [#7944](https://github.com/rust-lang/rust-clippy/pull/7944)
 +* [`cast_lossless`]: Now also lints for `bool` to integer casts
 +  [#7948](https://github.com/rust-lang/rust-clippy/pull/7948)
 +* [`let_underscore_lock`]: Also emit lints for the `parking_lot` crate
 +  [#7957](https://github.com/rust-lang/rust-clippy/pull/7957)
 +* [`needless_borrow`]
 +  [#7977](https://github.com/rust-lang/rust-clippy/pull/7977)
 +    * Lint when a borrow is auto-dereffed more than once
 +    * Lint in the trailing expression of a block for a match arm
 +* [`strlen_on_c_strings`]
 +  [8001](https://github.com/rust-lang/rust-clippy/pull/8001)
 +    * Lint when used without a fully-qualified path
 +    * Suggest removing the surrounding unsafe block when possible
 +* [`non_ascii_literal`]: Now also lints on `char`s, not just `string`s
 +  [#8034](https://github.com/rust-lang/rust-clippy/pull/8034)
 +* [`single_char_pattern`]: Now also lints on `split_inclusive`, `split_once`,
 +  `rsplit_once`, `replace`, and `replacen`
 +  [#8077](https://github.com/rust-lang/rust-clippy/pull/8077)
 +* [`unwrap_or_else_default`]: Now also lints on `std` constructors like
 +  `Vec::new`, `HashSet::new`, and `HashMap::new`
 +  [#8163](https://github.com/rust-lang/rust-clippy/pull/8163)
 +* [`shadow_reuse`]: Now also lints on shadowed `if let` bindings, instead of
 +  [`shadow_unrelated`]
 +  [#8165](https://github.com/rust-lang/rust-clippy/pull/8165)
 +
 +### False Positive Fixes
 +
 +* [`or_fun_call`], [`unnecessary_lazy_evaluations`]: Improve heuristics, so that
 +  cheap functions (e.g. calling `.len()` on a `Vec`) won't get linted anymore
 +  [#7639](https://github.com/rust-lang/rust-clippy/pull/7639)
 +* [`manual_split_once`]: No longer suggests code changing the original behavior
 +  [#7896](https://github.com/rust-lang/rust-clippy/pull/7896)
 +* Don't show [`no_effect`] or [`unnecessary_operation`] warning for unit struct
 +  implementing `FnOnce`
 +  [#7898](https://github.com/rust-lang/rust-clippy/pull/7898)
 +* [`semicolon_if_nothing_returned`]: Fixed a bug, where the lint wrongly
 +  triggered on `let-else` statements
 +  [#7955](https://github.com/rust-lang/rust-clippy/pull/7955)
 +* [`if_then_some_else_none`]: No longer lints if there is an early return
 +  [#7980](https://github.com/rust-lang/rust-clippy/pull/7980)
 +* [`needless_collect`]: No longer suggests removal of `collect` when removal
 +  would create code requiring mutably borrowing a value multiple times
 +  [#7982](https://github.com/rust-lang/rust-clippy/pull/7982)
 +* [`shadow_same`]: Fix false positive for `async` function's params
 +  [#7997](https://github.com/rust-lang/rust-clippy/pull/7997)
 +* [`suboptimal_flops`]: No longer triggers in constant functions
 +  [#8009](https://github.com/rust-lang/rust-clippy/pull/8009)
 +* [`type_complexity`]: No longer lints on associated types in traits
 +  [#8030](https://github.com/rust-lang/rust-clippy/pull/8030)
 +* [`question_mark`]: No longer lints if returned object is not local
 +  [#8080](https://github.com/rust-lang/rust-clippy/pull/8080)
 +* [`option_if_let_else`]: No longer lint on complex sub-patterns
 +  [#8086](https://github.com/rust-lang/rust-clippy/pull/8086)
 +* [`blocks_in_if_conditions`]: No longer lints on empty closures
 +  [#8100](https://github.com/rust-lang/rust-clippy/pull/8100)
 +* [`enum_variant_names`]: No longer lint when first prefix is only a substring
 +  of a camel-case word
 +  [#8127](https://github.com/rust-lang/rust-clippy/pull/8127)
 +* [`identity_op`]: Only lint on integral operands
 +  [#8183](https://github.com/rust-lang/rust-clippy/pull/8183)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`search_is_some`]: Fix suggestion for `any()` not taking item by reference
 +  [#7463](https://github.com/rust-lang/rust-clippy/pull/7463)
 +* [`almost_swapped`]: Now detects if there is a `no_std` or `no_core` attribute
 +  and adapts the suggestion accordingly
 +  [#7877](https://github.com/rust-lang/rust-clippy/pull/7877)
 +* [`redundant_pattern_matching`]: Fix suggestion for deref expressions
 +  [#7949](https://github.com/rust-lang/rust-clippy/pull/7949)
 +* [`explicit_counter_loop`]: Now also produces a suggestion for non-`usize`
 +  types [#7950](https://github.com/rust-lang/rust-clippy/pull/7950)
 +* [`manual_map`]: Fix suggestion when used with unsafe functions and blocks
 +  [#7968](https://github.com/rust-lang/rust-clippy/pull/7968)
 +* [`option_map_or_none`]: Suggest `map` over `and_then` when possible
 +  [#7971](https://github.com/rust-lang/rust-clippy/pull/7971)
 +* [`option_if_let_else`]: No longer expands macros in the suggestion
 +  [#7974](https://github.com/rust-lang/rust-clippy/pull/7974)
 +* [`iter_cloned_collect`]: Suggest `copied` over `cloned` when possible
 +  [#8006](https://github.com/rust-lang/rust-clippy/pull/8006)
 +* [`doc_markdown`]: No longer uses inline hints to improve readability of
 +  suggestion [#8011](https://github.com/rust-lang/rust-clippy/pull/8011)
 +* [`needless_question_mark`]: Now better explains the suggestion
 +  [#8028](https://github.com/rust-lang/rust-clippy/pull/8028)
 +* [`single_char_pattern`]: Escape backslash `\` in suggestion
 +  [#8067](https://github.com/rust-lang/rust-clippy/pull/8067)
 +* [`needless_bool`]: Suggest `a != b` over `!(a == b)`
 +  [#8117](https://github.com/rust-lang/rust-clippy/pull/8117)
 +* [`iter_skip_next`]: Suggest to add a `mut` if it is necessary in order to
 +  apply this lints suggestion
 +  [#8133](https://github.com/rust-lang/rust-clippy/pull/8133)
 +* [`neg_multiply`]: Now produces a suggestion
 +  [#8144](https://github.com/rust-lang/rust-clippy/pull/8144)
 +* [`needless_return`]: Now suggests the unit type `()` over an empty block `{}`
 +  in match arms [#8185](https://github.com/rust-lang/rust-clippy/pull/8185)
 +* [`suboptimal_flops`]: Now gives a syntactically correct suggestion for
 +  `to_radians` and `to_degrees`
 +  [#8187](https://github.com/rust-lang/rust-clippy/pull/8187)
 +
 +### ICE Fixes
 +
 +* [`undocumented_unsafe_blocks`]
 +  [#7945](https://github.com/rust-lang/rust-clippy/pull/7945)
 +  [#7988](https://github.com/rust-lang/rust-clippy/pull/7988)
 +* [`unnecessary_cast`]
 +  [#8167](https://github.com/rust-lang/rust-clippy/pull/8167)
 +
 +### Documentation Improvements
 +
 +* [`print_stdout`], [`print_stderr`], [`dbg_macro`]: Document how the lint level
 +  can be changed crate-wide
 +  [#8040](https://github.com/rust-lang/rust-clippy/pull/8040)
 +* Added a note to the `README` that config changes don't apply to already
 +  compiled code [#8175](https://github.com/rust-lang/rust-clippy/pull/8175)
 +
 +### Others
 +
 +* [Clippy's lint
 +  list](https://rust-lang.github.io/rust-clippy/master/index.html) now displays
 +  the version a lint was added. :tada:
 +  [#7813](https://github.com/rust-lang/rust-clippy/pull/7813)
 +* New and improved issue templates
 +  [#8032](https://github.com/rust-lang/rust-clippy/pull/8032)
 +* _Dev:_ Add `cargo dev lint` command, to run your modified Clippy version on a
 +  file [#7917](https://github.com/rust-lang/rust-clippy/pull/7917)
 +
 +## Rust 1.58
 +
 +Released 2022-01-13
 +
 +[00e31fa...e181011](https://github.com/rust-lang/rust-clippy/compare/00e31fa...e181011)
 +
 +### Rust 1.58.1
 +
 +* Move [`non_send_fields_in_send_ty`] to `nursery` (now allow-by-default)
 +  [#8075](https://github.com/rust-lang/rust-clippy/pull/8075)
 +* [`useless_format`]: Handle implicit named arguments
 +  [#8295](https://github.com/rust-lang/rust-clippy/pull/8295)
 +
 +### New lints
 +
 +* [`transmute_num_to_bytes`]
 +  [#7805](https://github.com/rust-lang/rust-clippy/pull/7805)
 +* [`match_str_case_mismatch`]
 +  [#7806](https://github.com/rust-lang/rust-clippy/pull/7806)
 +* [`format_in_format_args`], [`to_string_in_format_args`]
 +  [#7743](https://github.com/rust-lang/rust-clippy/pull/7743)
 +* [`uninit_vec`]
 +  [#7682](https://github.com/rust-lang/rust-clippy/pull/7682)
 +* [`fn_to_numeric_cast_any`]
 +  [#7705](https://github.com/rust-lang/rust-clippy/pull/7705)
 +* [`undocumented_unsafe_blocks`]
 +  [#7748](https://github.com/rust-lang/rust-clippy/pull/7748)
 +* [`trailing_empty_array`]
 +  [#7838](https://github.com/rust-lang/rust-clippy/pull/7838)
 +* [`string_slice`]
 +  [#7878](https://github.com/rust-lang/rust-clippy/pull/7878)
 +
 +### Moves or deprecations of lints
 +
 +* Move [`non_send_fields_in_send_ty`] to `suspicious`
 +  [#7874](https://github.com/rust-lang/rust-clippy/pull/7874)
 +* Move [`non_ascii_literal`] to `restriction`
 +  [#7907](https://github.com/rust-lang/rust-clippy/pull/7907)
 +
 +### Changes that expand what code existing lints cover
 +
 +* [`question_mark`] now covers `Result`
 +  [#7840](https://github.com/rust-lang/rust-clippy/pull/7840)
 +* Make [`useless_format`] recognize bare `format!("")`
 +  [#7801](https://github.com/rust-lang/rust-clippy/pull/7801)
 +* Lint on underscored variables with no side effects in [`no_effect`]
 +  [#7775](https://github.com/rust-lang/rust-clippy/pull/7775)
 +* Expand [`match_ref_pats`] to check for multiple reference patterns
 +  [#7800](https://github.com/rust-lang/rust-clippy/pull/7800)
 +
 +### False positive fixes
 +
 +* Fix false positive of [`implicit_saturating_sub`] with `else` clause
 +  [#7832](https://github.com/rust-lang/rust-clippy/pull/7832)
 +* Fix [`question_mark`] when there is call in conditional predicate
 +  [#7860](https://github.com/rust-lang/rust-clippy/pull/7860)
 +* [`mut_mut`] no longer lints when type is defined in external macros
 +  [#7795](https://github.com/rust-lang/rust-clippy/pull/7795)
 +* Avoid [`eq_op`] in test functions
 +  [#7811](https://github.com/rust-lang/rust-clippy/pull/7811)
 +* [`cast_possible_truncation`] no longer lints when cast is coming from `signum`
 +  method call [#7850](https://github.com/rust-lang/rust-clippy/pull/7850)
 +* [`match_str_case_mismatch`] no longer lints on uncased characters
 +  [#7865](https://github.com/rust-lang/rust-clippy/pull/7865)
 +* [`ptr_arg`] no longer lints references to type aliases
 +  [#7890](https://github.com/rust-lang/rust-clippy/pull/7890)
 +* [`missing_safety_doc`] now also accepts "implementation safety" headers
 +  [#7856](https://github.com/rust-lang/rust-clippy/pull/7856)
 +* [`missing_safety_doc`] no longer lints if any parent has `#[doc(hidden)]`
 +  attribute [#7849](https://github.com/rust-lang/rust-clippy/pull/7849)
 +* [`if_not_else`] now ignores else-if statements
 +  [#7895](https://github.com/rust-lang/rust-clippy/pull/7895)
 +* Avoid linting [`cast_possible_truncation`] on bit-reducing operations
 +  [#7819](https://github.com/rust-lang/rust-clippy/pull/7819)
 +* Avoid linting [`field_reassign_with_default`] when `Drop` and `Copy` are
 +  involved [#7794](https://github.com/rust-lang/rust-clippy/pull/7794)
 +* [`unnecessary_sort_by`] now checks if argument implements `Ord` trait
 +  [#7824](https://github.com/rust-lang/rust-clippy/pull/7824)
 +* Fix false positive in [`match_overlapping_arm`]
 +  [#7847](https://github.com/rust-lang/rust-clippy/pull/7847)
 +* Prevent [`needless_lifetimes`] false positive in `async` function definition
 +  [#7901](https://github.com/rust-lang/rust-clippy/pull/7901)
 +
 +### Suggestion fixes/improvements
 +
 +* Keep an initial `::` when [`doc_markdown`] suggests to use ticks
 +  [#7916](https://github.com/rust-lang/rust-clippy/pull/7916)
 +* Add a machine applicable suggestion for the [`doc_markdown`] missing backticks
 +  lint [#7904](https://github.com/rust-lang/rust-clippy/pull/7904)
 +* [`equatable_if_let`] no longer expands macros in the suggestion
 +  [#7788](https://github.com/rust-lang/rust-clippy/pull/7788)
 +* Make [`shadow_reuse`] suggestion less verbose
 +  [#7782](https://github.com/rust-lang/rust-clippy/pull/7782)
 +
 +### ICE fixes
 +
 +* Fix ICE in [`enum_variant_names`]
 +  [#7873](https://github.com/rust-lang/rust-clippy/pull/7873)
 +* Fix ICE in [`undocumented_unsafe_blocks`]
 +  [#7891](https://github.com/rust-lang/rust-clippy/pull/7891)
 +
 +### Documentation improvements
 +
 +* Fixed naive doc formatting for `#[must_use]` lints ([`must_use_unit`],
 +  [`double_must_use`], [`must_use_candidate`], [`let_underscore_must_use`])
 +  [#7827](https://github.com/rust-lang/rust-clippy/pull/7827)
 +* Fix typo in example for [`match_result_ok`]
 +  [#7815](https://github.com/rust-lang/rust-clippy/pull/7815)
 +
 +### Others
 +
 +* Allow giving reasons for [`disallowed_types`]
 +  [#7791](https://github.com/rust-lang/rust-clippy/pull/7791)
 +* Fix [`manual_assert`] and [`match_wild_err_arm`] for `#![no_std]` and Rust
 +  2021. [#7851](https://github.com/rust-lang/rust-clippy/pull/7851)
 +* Fix regression in [`semicolon_if_nothing_returned`] on macros containing while
 +  loops [#7789](https://github.com/rust-lang/rust-clippy/pull/7789)
 +* Added a new configuration `literal-suffix-style` to enforce a certain style
 +  writing [`unseparated_literal_suffix`]
 +  [#7726](https://github.com/rust-lang/rust-clippy/pull/7726)
 +
 +## Rust 1.57
 +
 +Released 2021-12-02
 +
 +[7bfc26e...00e31fa](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...00e31fa)
 +
 +### New Lints
 +
 +* [`negative_feature_names`]
 +  [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
 +* [`redundant_feature_names`]
 +  [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
 +* [`mod_module_files`]
 +  [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
 +* [`self_named_module_files`]
 +  [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
 +* [`manual_split_once`]
 +  [#7565](https://github.com/rust-lang/rust-clippy/pull/7565)
 +* [`derivable_impls`]
 +  [#7570](https://github.com/rust-lang/rust-clippy/pull/7570)
 +* [`needless_option_as_deref`]
 +  [#7596](https://github.com/rust-lang/rust-clippy/pull/7596)
 +* [`iter_not_returning_iterator`]
 +  [#7610](https://github.com/rust-lang/rust-clippy/pull/7610)
 +* [`same_name_method`]
 +  [#7653](https://github.com/rust-lang/rust-clippy/pull/7653)
 +* [`manual_assert`] [#7669](https://github.com/rust-lang/rust-clippy/pull/7669)
 +* [`non_send_fields_in_send_ty`]
 +  [#7709](https://github.com/rust-lang/rust-clippy/pull/7709)
 +* [`equatable_if_let`]
 +  [#7762](https://github.com/rust-lang/rust-clippy/pull/7762)
 +
 +### Moves and Deprecations
 +
 +* Move [`shadow_unrelated`] to `restriction`
 +  [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
 +* Move [`option_if_let_else`] to `nursery`
 +  [#7568](https://github.com/rust-lang/rust-clippy/pull/7568)
 +* Move [`branches_sharing_code`] to `nursery`
 +  [#7595](https://github.com/rust-lang/rust-clippy/pull/7595)
 +* Rename `if_let_some_result` to [`match_result_ok`] which now also handles
 +  `while let` cases [#7608](https://github.com/rust-lang/rust-clippy/pull/7608)
 +* Move [`many_single_char_names`] to `pedantic`
 +  [#7671](https://github.com/rust-lang/rust-clippy/pull/7671)
 +* Move [`float_cmp`] to `pedantic`
 +  [#7692](https://github.com/rust-lang/rust-clippy/pull/7692)
 +* Rename `box_vec` to [`box_collection`] and lint on more general cases
 +  [#7693](https://github.com/rust-lang/rust-clippy/pull/7693)
 +* Uplift `invalid_atomic_ordering` to rustc
 +  [rust-lang/rust#84039](https://github.com/rust-lang/rust/pull/84039)
 +
 +### Enhancements
 +
 +* Rewrite the `shadow*` lints, so that they find a lot more shadows and are not
 +  limited to certain patterns
 +  [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
 +* The `avoid-breaking-exported-api` configuration now also works for
 +  [`box_collection`], [`redundant_allocation`], [`rc_buffer`], [`vec_box`],
 +  [`option_option`], [`linkedlist`], [`rc_mutex`]
 +  [#7560](https://github.com/rust-lang/rust-clippy/pull/7560)
 +* [`unnecessary_unwrap`]: Now also checks for `expect`s
 +  [#7584](https://github.com/rust-lang/rust-clippy/pull/7584)
 +* [`disallowed_methods`]: Allow adding a reason that will be displayed with the
 +  lint message
 +  [#7621](https://github.com/rust-lang/rust-clippy/pull/7621)
 +* [`approx_constant`]: Now checks the MSRV for `LOG10_2` and `LOG2_10`
 +  [#7629](https://github.com/rust-lang/rust-clippy/pull/7629)
 +* [`approx_constant`]: Add `TAU`
 +  [#7642](https://github.com/rust-lang/rust-clippy/pull/7642)
 +* [`needless_borrow`]: Now also lints on needless mutable borrows
 +  [#7657](https://github.com/rust-lang/rust-clippy/pull/7657)
 +* [`missing_safety_doc`]: Now also lints on unsafe traits
 +  [#7734](https://github.com/rust-lang/rust-clippy/pull/7734)
 +
 +### False Positive Fixes
 +
 +* [`manual_map`]: No longer lints when the option is borrowed in the match and
 +  also consumed in the arm
 +  [#7531](https://github.com/rust-lang/rust-clippy/pull/7531)
 +* [`filter_next`]: No longer lints if `filter` method is not the
 +  `Iterator::filter` method
 +  [#7562](https://github.com/rust-lang/rust-clippy/pull/7562)
 +* [`manual_flatten`]: No longer lints if expression is used after `if let`
 +  [#7566](https://github.com/rust-lang/rust-clippy/pull/7566)
 +* [`option_if_let_else`]: Multiple fixes
 +  [#7573](https://github.com/rust-lang/rust-clippy/pull/7573)
 +    * `break` and `continue` statements local to the would-be closure are
 +      allowed
 +    * Don't lint in const contexts
 +    * Don't lint when yield expressions are used
 +    * Don't lint when the captures made by the would-be closure conflict with
 +      the other branch
 +    * Don't lint when a field of a local is used when the type could be
 +      potentially moved from
 +    * In some cases, don't lint when scrutinee expression conflicts with the
 +      captures of the would-be closure
 +* [`redundant_allocation`]: No longer lints on `Box<Box<dyn T>>` which replaces
 +  wide pointers with thin pointers
 +  [#7592](https://github.com/rust-lang/rust-clippy/pull/7592)
 +* [`bool_assert_comparison`]: No longer lints on types that do not implement the
 +  `Not` trait with `Output = bool`
 +  [#7605](https://github.com/rust-lang/rust-clippy/pull/7605)
 +* [`mut_range_bound`]: No longer lints on range bound mutations, that are
 +  immediately followed by a `break;`
 +  [#7607](https://github.com/rust-lang/rust-clippy/pull/7607)
 +* [`mutable_key_type`]: Improve accuracy and document remaining false positives
 +  and false negatives
 +  [#7640](https://github.com/rust-lang/rust-clippy/pull/7640)
 +* [`redundant_closure`]: Rewrite the lint to fix various false positives and
 +  false negatives [#7661](https://github.com/rust-lang/rust-clippy/pull/7661)
 +* [`large_enum_variant`]: No longer wrongly identifies the second largest
 +  variant [#7677](https://github.com/rust-lang/rust-clippy/pull/7677)
 +* [`needless_return`]: No longer lints on let-else expressions
 +  [#7685](https://github.com/rust-lang/rust-clippy/pull/7685)
 +* [`suspicious_else_formatting`]: No longer lints in proc-macros
 +  [#7707](https://github.com/rust-lang/rust-clippy/pull/7707)
 +* [`excessive_precision`]: No longer lints when in some cases the float was
 +  already written in the shortest form
 +  [#7722](https://github.com/rust-lang/rust-clippy/pull/7722)
 +* [`doc_markdown`]: No longer lints on intra-doc links
 +  [#7772](https://github.com/rust-lang/rust-clippy/pull/7772)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`unnecessary_operation`]: Recommend using an `assert!` instead of using a
 +  function call in an indexing operation
 +  [#7453](https://github.com/rust-lang/rust-clippy/pull/7453)
 +* [`manual_split_once`]: Produce semantically equivalent suggestion when
 +  `rsplitn` is used [#7663](https://github.com/rust-lang/rust-clippy/pull/7663)
 +* [`while_let_on_iterator`]: Produce correct suggestion when using `&mut`
 +  [#7690](https://github.com/rust-lang/rust-clippy/pull/7690)
 +* [`manual_assert`]: No better handles complex conditions
 +  [#7741](https://github.com/rust-lang/rust-clippy/pull/7741)
 +* Correctly handle signs in exponents in numeric literals lints
 +  [#7747](https://github.com/rust-lang/rust-clippy/pull/7747)
 +* [`suspicious_map`]: Now also suggests to use `inspect` as an alternative
 +  [#7770](https://github.com/rust-lang/rust-clippy/pull/7770)
 +* Drop exponent from suggestion if it is 0 in numeric literals lints
 +  [#7774](https://github.com/rust-lang/rust-clippy/pull/7774)
 +
 +### ICE Fixes
 +
 +* [`implicit_hasher`]
 +  [#7761](https://github.com/rust-lang/rust-clippy/pull/7761)
 +
 +### Others
 +
 +* Clippy now uses the 2021
 +  [Edition!](https://www.youtube.com/watch?v=q0aNduqb2Ro)
 +  [#7664](https://github.com/rust-lang/rust-clippy/pull/7664)
 +
 +## Rust 1.56
 +
 +Released 2021-10-21
 +
 +[74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e)
 +
 +### New Lints
 +
 +* [`unwrap_or_else_default`]
 +  [#7516](https://github.com/rust-lang/rust-clippy/pull/7516)
 +
 +### Enhancements
 +
 +* [`needless_continue`]: Now also lints in `loop { continue; }` case
 +  [#7477](https://github.com/rust-lang/rust-clippy/pull/7477)
 +* [`disallowed_types`]: Now also primitive types can be disallowed
 +  [#7488](https://github.com/rust-lang/rust-clippy/pull/7488)
 +* [`manual_swap`]: Now also lints on xor swaps
 +  [#7506](https://github.com/rust-lang/rust-clippy/pull/7506)
 +* [`map_flatten`]: Now also lints on the `Result` type
 +  [#7522](https://github.com/rust-lang/rust-clippy/pull/7522)
 +* [`no_effect`]: Now also lints on inclusive ranges
 +  [#7556](https://github.com/rust-lang/rust-clippy/pull/7556)
 +
 +### False Positive Fixes
 +
 +* [`nonstandard_macro_braces`]: No longer lints on similar named nested macros
 +  [#7478](https://github.com/rust-lang/rust-clippy/pull/7478)
 +* [`too_many_lines`]: No longer lints in closures to avoid duplicated diagnostics
 +  [#7534](https://github.com/rust-lang/rust-clippy/pull/7534)
 +* [`similar_names`]: No longer complains about `iter` and `item` being too
 +  similar [#7546](https://github.com/rust-lang/rust-clippy/pull/7546)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`similar_names`]: No longer suggests to insert or add an underscore as a fix
 +  [#7221](https://github.com/rust-lang/rust-clippy/pull/7221)
 +* [`new_without_default`]: No longer shows the full qualified type path when
 +  suggesting adding a `Default` implementation
 +  [#7493](https://github.com/rust-lang/rust-clippy/pull/7493)
 +* [`while_let_on_iterator`]: Now suggests re-borrowing mutable references
 +  [#7520](https://github.com/rust-lang/rust-clippy/pull/7520)
 +* [`extend_with_drain`]: Improve code suggestion for mutable and immutable
 +  references [#7533](https://github.com/rust-lang/rust-clippy/pull/7533)
 +* [`trivially_copy_pass_by_ref`]: Now properly handles `Self` type
 +  [#7535](https://github.com/rust-lang/rust-clippy/pull/7535)
 +* [`never_loop`]: Now suggests using `if let` instead of a `for` loop when
 +  applicable [#7541](https://github.com/rust-lang/rust-clippy/pull/7541)
 +
 +### Documentation Improvements
 +
 +* Clippy now uses a lint to generate its lint documentation. [Lints all the way
 +  down](https://en.wikipedia.org/wiki/Turtles_all_the_way_down).
 +  [#7502](https://github.com/rust-lang/rust-clippy/pull/7502)
 +* Reworked Clippy's website:
 +  [#7172](https://github.com/rust-lang/rust-clippy/issues/7172)
 +  [#7279](https://github.com/rust-lang/rust-clippy/pull/7279)
 +  * Added applicability information about lints
 +  * Added a link to jump into the implementation
 +  * Improved loading times
 +  * Adapted some styling
 +* `cargo clippy --help` now also explains the `--fix` and `--no-deps` flag
 +  [#7492](https://github.com/rust-lang/rust-clippy/pull/7492)
 +* [`unnested_or_patterns`]: Removed `or_patterns` feature gate in the code
 +  example [#7507](https://github.com/rust-lang/rust-clippy/pull/7507)
 +
 +## Rust 1.55
 +
 +Released 2021-09-09
 +
 +[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
 +
 +### Important Changes
 +
 +* Stabilized `cargo clippy --fix` :tada:
 +  [#7405](https://github.com/rust-lang/rust-clippy/pull/7405)
 +
 +### New Lints
 +
 +* [`rc_mutex`]
 +  [#7316](https://github.com/rust-lang/rust-clippy/pull/7316)
 +* [`nonstandard_macro_braces`]
 +  [#7299](https://github.com/rust-lang/rust-clippy/pull/7299)
 +* [`strlen_on_c_strings`]
 +  [#7243](https://github.com/rust-lang/rust-clippy/pull/7243)
 +* [`self_named_constructors`]
 +  [#7403](https://github.com/rust-lang/rust-clippy/pull/7403)
 +* [`disallowed_script_idents`]
 +  [#7400](https://github.com/rust-lang/rust-clippy/pull/7400)
 +* [`disallowed_types`]
 +  [#7315](https://github.com/rust-lang/rust-clippy/pull/7315)
 +* [`missing_enforced_import_renames`]
 +  [#7300](https://github.com/rust-lang/rust-clippy/pull/7300)
 +* [`extend_with_drain`]
 +  [#7270](https://github.com/rust-lang/rust-clippy/pull/7270)
 +
 +### Moves and Deprecations
 +
 +* Moved [`from_iter_instead_of_collect`] to `pedantic`
 +  [#7375](https://github.com/rust-lang/rust-clippy/pull/7375)
 +* Added `suspicious` as a new lint group for *code that is most likely wrong or useless*
 +  [#7350](https://github.com/rust-lang/rust-clippy/pull/7350)
 +  * Moved [`blanket_clippy_restriction_lints`] to `suspicious`
 +  * Moved [`empty_loop`] to `suspicious`
 +  * Moved [`eval_order_dependence`] to `suspicious`
 +  * Moved [`float_equality_without_abs`] to `suspicious`
 +  * Moved [`for_loops_over_fallibles`] to `suspicious`
 +  * Moved [`misrefactored_assign_op`] to `suspicious`
 +  * Moved [`mut_range_bound`] to `suspicious`
 +  * Moved [`mutable_key_type`] to `suspicious`
 +  * Moved [`suspicious_arithmetic_impl`] to `suspicious`
 +  * Moved [`suspicious_assignment_formatting`] to `suspicious`
 +  * Moved [`suspicious_else_formatting`] to `suspicious`
 +  * Moved [`suspicious_map`] to `suspicious`
 +  * Moved [`suspicious_op_assign_impl`] to `suspicious`
 +  * Moved [`suspicious_unary_op_formatting`] to `suspicious`
 +
 +### Enhancements
 +
 +* [`while_let_on_iterator`]: Now suggests `&mut iter` inside closures
 +  [#7262](https://github.com/rust-lang/rust-clippy/pull/7262)
 +* [`doc_markdown`]:
 +  * Now detects unbalanced ticks
 +    [#7357](https://github.com/rust-lang/rust-clippy/pull/7357)
 +  * Add `FreeBSD` to the default configuration as an allowed identifier
 +    [#7334](https://github.com/rust-lang/rust-clippy/pull/7334)
 +* [`wildcard_enum_match_arm`], [`match_wildcard_for_single_variants`]: Now allows wildcards for enums with unstable
 +  or hidden variants
 +  [#7407](https://github.com/rust-lang/rust-clippy/pull/7407)
 +* [`redundant_allocation`]: Now additionally supports the `Arc<>` type
 +  [#7308](https://github.com/rust-lang/rust-clippy/pull/7308)
 +* [`disallowed_names`]: Now allows disallowed names in test code
 +  [#7379](https://github.com/rust-lang/rust-clippy/pull/7379)
 +* [`redundant_closure`]: Suggests `&mut` for `FnMut`
 +  [#7437](https://github.com/rust-lang/rust-clippy/pull/7437)
 +* [`disallowed_methods`], [`disallowed_types`]: The configuration values `disallowed-method` and `disallowed-type`
 +  no longer require fully qualified paths
 +  [#7345](https://github.com/rust-lang/rust-clippy/pull/7345)
 +* [`zst_offset`]: Fixed lint invocation after it was accidentally suppressed
 +  [#7396](https://github.com/rust-lang/rust-clippy/pull/7396)
 +
 +### False Positive Fixes
 +
 +* [`default_numeric_fallback`]: No longer lints on float literals as function arguments
 +  [#7446](https://github.com/rust-lang/rust-clippy/pull/7446)
 +* [`use_self`]: No longer lints on type parameters
 +  [#7288](https://github.com/rust-lang/rust-clippy/pull/7288)
 +* [`unimplemented`]: Now ignores the `assert` and `debug_assert` macros
 +  [#7439](https://github.com/rust-lang/rust-clippy/pull/7439)
 +* [`branches_sharing_code`]: Now always checks for block expressions
 +  [#7462](https://github.com/rust-lang/rust-clippy/pull/7462)
 +* [`field_reassign_with_default`]: No longer triggers in macros
 +  [#7160](https://github.com/rust-lang/rust-clippy/pull/7160)
 +* [`redundant_clone`]: No longer lints on required clones for borrowed data
 +  [#7346](https://github.com/rust-lang/rust-clippy/pull/7346)
 +* [`default_numeric_fallback`]: No longer triggers in external macros
 +  [#7325](https://github.com/rust-lang/rust-clippy/pull/7325)
 +* [`needless_bool`]: No longer lints in macros
 +  [#7442](https://github.com/rust-lang/rust-clippy/pull/7442)
 +* [`useless_format`]: No longer triggers when additional text is being appended
 +  [#7442](https://github.com/rust-lang/rust-clippy/pull/7442)
 +* [`assertions_on_constants`]: `cfg!(...)` is no longer considered to be a constant
 +  [#7319](https://github.com/rust-lang/rust-clippy/pull/7319)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`needless_collect`]: Now show correct lint messages for shadowed values
 +  [#7289](https://github.com/rust-lang/rust-clippy/pull/7289)
 +* [`wrong_pub_self_convention`]: The deprecated message now suggest the correct configuration value
 +  [#7382](https://github.com/rust-lang/rust-clippy/pull/7382)
 +* [`semicolon_if_nothing_returned`]: Allow missing semicolon in blocks with only one expression
 +  [#7326](https://github.com/rust-lang/rust-clippy/pull/7326)
 +
 +### ICE Fixes
 +
 +* [`zero_sized_map_values`]
 +  [#7470](https://github.com/rust-lang/rust-clippy/pull/7470)
 +* [`redundant_pattern_matching`]
 +  [#7471](https://github.com/rust-lang/rust-clippy/pull/7471)
 +* [`modulo_one`]
 +  [#7473](https://github.com/rust-lang/rust-clippy/pull/7473)
 +* [`use_self`]
 +  [#7428](https://github.com/rust-lang/rust-clippy/pull/7428)
 +
 +## Rust 1.54
 +
 +Released 2021-07-29
 +
 +[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf)
 +
 +### New Lints
 +
 +- [`ref_binding_to_reference`]
 +  [#7105](https://github.com/rust-lang/rust-clippy/pull/7105)
 +- [`needless_bitwise_bool`]
 +  [#7133](https://github.com/rust-lang/rust-clippy/pull/7133)
 +- [`unused_async`] [#7225](https://github.com/rust-lang/rust-clippy/pull/7225)
 +- [`manual_str_repeat`]
 +  [#7265](https://github.com/rust-lang/rust-clippy/pull/7265)
 +- [`suspicious_splitn`]
 +  [#7292](https://github.com/rust-lang/rust-clippy/pull/7292)
 +
 +### Moves and Deprecations
 +
 +- Deprecate `pub_enum_variant_names` and `wrong_pub_self_convention` in favor of
 +  the new `avoid-breaking-exported-api` config option (see
 +  [Enhancements](#1-54-enhancements))
 +  [#7187](https://github.com/rust-lang/rust-clippy/pull/7187)
 +- Move [`inconsistent_struct_constructor`] to `pedantic`
 +  [#7193](https://github.com/rust-lang/rust-clippy/pull/7193)
 +- Move [`needless_borrow`] to `style` (now warn-by-default)
 +  [#7254](https://github.com/rust-lang/rust-clippy/pull/7254)
 +- Move [`suspicious_operation_groupings`] to `nursery`
 +  [#7266](https://github.com/rust-lang/rust-clippy/pull/7266)
 +- Move [`semicolon_if_nothing_returned`] to `pedantic`
 +  [#7268](https://github.com/rust-lang/rust-clippy/pull/7268)
 +
 +### Enhancements <a name="1-54-enhancements"></a>
 +
 +- [`while_let_on_iterator`]: Now also lints in nested loops
 +  [#6966](https://github.com/rust-lang/rust-clippy/pull/6966)
 +- [`single_char_pattern`]: Now also lints on `strip_prefix` and `strip_suffix`
 +  [#7156](https://github.com/rust-lang/rust-clippy/pull/7156)
 +- [`needless_collect`]: Now also lints on assignments with type annotations
 +  [#7163](https://github.com/rust-lang/rust-clippy/pull/7163)
 +- [`if_then_some_else_none`]: Now works with the MSRV config
 +  [#7177](https://github.com/rust-lang/rust-clippy/pull/7177)
 +- Add `avoid-breaking-exported-api` config option for the lints
 +  [`enum_variant_names`], [`large_types_passed_by_value`],
 +  [`trivially_copy_pass_by_ref`], [`unnecessary_wraps`],
 +  [`upper_case_acronyms`], and [`wrong_self_convention`]. We recommend to set
 +  this configuration option to `false` before a major release (1.0/2.0/...) to
 +  clean up the API [#7187](https://github.com/rust-lang/rust-clippy/pull/7187)
 +- [`needless_collect`]: Now lints on even more data structures
 +  [#7188](https://github.com/rust-lang/rust-clippy/pull/7188)
 +- [`missing_docs_in_private_items`]: No longer sees `#[<name> = "<value>"]` like
 +  attributes as sufficient documentation
 +  [#7281](https://github.com/rust-lang/rust-clippy/pull/7281)
 +- [`needless_collect`], [`short_circuit_statement`], [`unnecessary_operation`]:
 +  Now work as expected when used with `allow`
 +  [#7282](https://github.com/rust-lang/rust-clippy/pull/7282)
 +
 +### False Positive Fixes
 +
 +- [`implicit_return`]: Now takes all diverging functions in account to avoid
 +  false positives [#6951](https://github.com/rust-lang/rust-clippy/pull/6951)
 +- [`while_let_on_iterator`]: No longer lints when the iterator is a struct field
 +  and the struct is used in the loop
 +  [#6966](https://github.com/rust-lang/rust-clippy/pull/6966)
 +- [`multiple_inherent_impl`]: No longer lints with generic arguments
 +  [#7089](https://github.com/rust-lang/rust-clippy/pull/7089)
 +- [`comparison_chain`]: No longer lints in a `const` context
 +  [#7118](https://github.com/rust-lang/rust-clippy/pull/7118)
 +- [`while_immutable_condition`]: Fix false positive where mutation in the loop
 +  variable wasn't picked up
 +  [#7144](https://github.com/rust-lang/rust-clippy/pull/7144)
 +- [`default_trait_access`]: No longer lints in macros
 +  [#7150](https://github.com/rust-lang/rust-clippy/pull/7150)
 +- [`needless_question_mark`]: No longer lints when the inner value is implicitly
 +  dereferenced [#7165](https://github.com/rust-lang/rust-clippy/pull/7165)
 +- [`unused_unit`]: No longer lints when multiple macro contexts are involved
 +  [#7167](https://github.com/rust-lang/rust-clippy/pull/7167)
 +- [`eval_order_dependence`]: Fix false positive in async context
 +  [#7174](https://github.com/rust-lang/rust-clippy/pull/7174)
 +- [`unnecessary_filter_map`]: No longer lints if the `filter_map` changes the
 +  type [#7175](https://github.com/rust-lang/rust-clippy/pull/7175)
 +- [`wrong_self_convention`]: No longer lints in trait implementations of
 +  non-`Copy` types [#7182](https://github.com/rust-lang/rust-clippy/pull/7182)
 +- [`suboptimal_flops`]: No longer lints on `powi(2)`
 +  [#7201](https://github.com/rust-lang/rust-clippy/pull/7201)
 +- [`wrong_self_convention`]: No longer lints if there is no implicit `self`
 +  [#7215](https://github.com/rust-lang/rust-clippy/pull/7215)
 +- [`option_if_let_else`]: No longer lints on `else if let` pattern
 +  [#7216](https://github.com/rust-lang/rust-clippy/pull/7216)
 +- [`use_self`], [`useless_conversion`]: Fix false positives when generic
 +  arguments are involved
 +  [#7223](https://github.com/rust-lang/rust-clippy/pull/7223)
 +- [`manual_unwrap_or`]: Fix false positive with deref coercion
 +  [#7233](https://github.com/rust-lang/rust-clippy/pull/7233)
 +- [`similar_names`]: No longer lints on `wparam`/`lparam`
 +  [#7255](https://github.com/rust-lang/rust-clippy/pull/7255)
 +- [`redundant_closure`]: No longer lints on using the `vec![]` macro in a
 +  closure [#7263](https://github.com/rust-lang/rust-clippy/pull/7263)
 +
 +### Suggestion Fixes/Improvements
 +
 +- [`implicit_return`]
 +  [#6951](https://github.com/rust-lang/rust-clippy/pull/6951)
 +    - Fix suggestion for async functions
 +    - Improve suggestion with macros
 +    - Suggest to change `break` to `return` when appropriate
 +- [`while_let_on_iterator`]: Now suggests `&mut iter` when necessary
 +  [#6966](https://github.com/rust-lang/rust-clippy/pull/6966)
 +- [`match_single_binding`]: Improve suggestion when match scrutinee has side
 +  effects [#7095](https://github.com/rust-lang/rust-clippy/pull/7095)
 +- [`needless_borrow`]: Now suggests to also change usage sites as needed
 +  [#7105](https://github.com/rust-lang/rust-clippy/pull/7105)
 +- [`write_with_newline`]: Improve suggestion when only `\n` is written to the
 +  buffer [#7183](https://github.com/rust-lang/rust-clippy/pull/7183)
 +- [`from_iter_instead_of_collect`]: The suggestion is now auto applicable also
 +  when a `<_ as Trait>::_` is involved
 +  [#7264](https://github.com/rust-lang/rust-clippy/pull/7264)
 +- [`not_unsafe_ptr_arg_deref`]: Improved error message
 +  [#7294](https://github.com/rust-lang/rust-clippy/pull/7294)
 +
 +### ICE Fixes
 +
 +- Fix ICE when running Clippy on `libstd`
 +  [#7140](https://github.com/rust-lang/rust-clippy/pull/7140)
 +- [`implicit_return`]
 +  [#7242](https://github.com/rust-lang/rust-clippy/pull/7242)
 +
 +## Rust 1.53
 +
 +Released 2021-06-17
 +
 +[6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c)
 +
 +### New Lints
 +
 +* [`option_filter_map`]
 +  [#6342](https://github.com/rust-lang/rust-clippy/pull/6342)
 +* [`branches_sharing_code`]
 +  [#6463](https://github.com/rust-lang/rust-clippy/pull/6463)
 +* [`needless_for_each`]
 +  [#6706](https://github.com/rust-lang/rust-clippy/pull/6706)
 +* [`if_then_some_else_none`]
 +  [#6859](https://github.com/rust-lang/rust-clippy/pull/6859)
 +* [`non_octal_unix_permissions`]
 +  [#7001](https://github.com/rust-lang/rust-clippy/pull/7001)
 +* [`unnecessary_self_imports`]
 +  [#7072](https://github.com/rust-lang/rust-clippy/pull/7072)
 +* [`bool_assert_comparison`]
 +  [#7083](https://github.com/rust-lang/rust-clippy/pull/7083)
 +* [`cloned_instead_of_copied`]
 +  [#7098](https://github.com/rust-lang/rust-clippy/pull/7098)
 +* [`flat_map_option`]
 +  [#7101](https://github.com/rust-lang/rust-clippy/pull/7101)
 +
 +### Moves and Deprecations
 +
 +* Deprecate [`filter_map`] lint
 +  [#7059](https://github.com/rust-lang/rust-clippy/pull/7059)
 +* Move [`transmute_ptr_to_ptr`] to `pedantic`
 +  [#7102](https://github.com/rust-lang/rust-clippy/pull/7102)
 +
 +### Enhancements
 +
 +* [`mem_replace_with_default`]: Also lint on common std constructors
 +  [#6820](https://github.com/rust-lang/rust-clippy/pull/6820)
 +* [`wrong_self_convention`]: Also lint on `to_*_mut` methods
 +  [#6828](https://github.com/rust-lang/rust-clippy/pull/6828)
 +* [`wildcard_enum_match_arm`], [`match_wildcard_for_single_variants`]:
 +  [#6863](https://github.com/rust-lang/rust-clippy/pull/6863)
 +    * Attempt to find a common path prefix in suggestion
 +    * Don't lint on `Option` and `Result`
 +    * Consider `Self` prefix
 +* [`explicit_deref_methods`]: Also lint on chained `deref` calls
 +  [#6865](https://github.com/rust-lang/rust-clippy/pull/6865)
 +* [`or_fun_call`]: Also lint on `unsafe` blocks
 +  [#6928](https://github.com/rust-lang/rust-clippy/pull/6928)
 +* [`vec_box`], [`linkedlist`], [`option_option`]: Also lint in `const` and
 +  `static` items [#6938](https://github.com/rust-lang/rust-clippy/pull/6938)
 +* [`search_is_some`]: Also check for `is_none`
 +  [#6942](https://github.com/rust-lang/rust-clippy/pull/6942)
 +* [`string_lit_as_bytes`]: Also lint on `into_bytes`
 +  [#6959](https://github.com/rust-lang/rust-clippy/pull/6959)
 +* [`len_without_is_empty`]: Also lint if function signatures of `len` and
 +  `is_empty` don't match
 +  [#6980](https://github.com/rust-lang/rust-clippy/pull/6980)
 +* [`redundant_pattern_matching`]: Also lint if the pattern is a `&` pattern
 +  [#6991](https://github.com/rust-lang/rust-clippy/pull/6991)
 +* [`clone_on_copy`]: Also lint on chained method calls taking `self` by value
 +  [#7000](https://github.com/rust-lang/rust-clippy/pull/7000)
 +* [`missing_panics_doc`]: Also lint on `assert_eq!` and `assert_ne!`
 +  [#7029](https://github.com/rust-lang/rust-clippy/pull/7029)
 +* [`needless_return`]: Also lint in `async` functions
 +  [#7067](https://github.com/rust-lang/rust-clippy/pull/7067)
 +* [`unused_io_amount`]: Also lint on expressions like `_.read().ok()?`
 +  [#7100](https://github.com/rust-lang/rust-clippy/pull/7100)
 +* [`iter_cloned_collect`]: Also lint on large arrays, since const-generics are
 +  now stable [#7138](https://github.com/rust-lang/rust-clippy/pull/7138)
 +
 +### False Positive Fixes
 +
 +* [`upper_case_acronyms`]: No longer lints on public items
 +  [#6805](https://github.com/rust-lang/rust-clippy/pull/6805)
 +* [`suspicious_map`]: No longer lints when side effects may occur inside the
 +  `map` call [#6831](https://github.com/rust-lang/rust-clippy/pull/6831)
 +* [`manual_map`], [`manual_unwrap_or`]: No longer lints in `const` functions
 +  [#6917](https://github.com/rust-lang/rust-clippy/pull/6917)
 +* [`wrong_self_convention`]: Now respects `Copy` types
 +  [#6924](https://github.com/rust-lang/rust-clippy/pull/6924)
 +* [`needless_question_mark`]: No longer lints if the `?` and the `Some(..)` come
 +  from different macro contexts [#6935](https://github.com/rust-lang/rust-clippy/pull/6935)
 +* [`map_entry`]: Better detect if the entry API can be used
 +  [#6937](https://github.com/rust-lang/rust-clippy/pull/6937)
 +* [`or_fun_call`]: No longer lints on some `len` function calls
 +  [#6950](https://github.com/rust-lang/rust-clippy/pull/6950)
 +* [`new_ret_no_self`]: No longer lints when `Self` is returned with different
 +  generic arguments [#6952](https://github.com/rust-lang/rust-clippy/pull/6952)
 +* [`upper_case_acronyms`]: No longer lints on public items
 +  [#6981](https://github.com/rust-lang/rust-clippy/pull/6981)
 +* [`explicit_into_iter_loop`]: Only lint when `into_iter` is an implementation
 +  of `IntoIterator` [#6982](https://github.com/rust-lang/rust-clippy/pull/6982)
 +* [`expl_impl_clone_on_copy`]: Take generic constraints into account before
 +  suggesting to use `derive` instead
 +  [#6993](https://github.com/rust-lang/rust-clippy/pull/6993)
 +* [`missing_panics_doc`]: No longer lints when only debug-assertions are used
 +  [#6996](https://github.com/rust-lang/rust-clippy/pull/6996)
 +* [`clone_on_copy`]: Only lint when using the `Clone` trait
 +  [#7000](https://github.com/rust-lang/rust-clippy/pull/7000)
 +* [`wrong_self_convention`]: No longer lints inside a trait implementation
 +  [#7002](https://github.com/rust-lang/rust-clippy/pull/7002)
 +* [`redundant_clone`]: No longer lints when the cloned value is modified while
 +  the clone is in use
 +  [#7011](https://github.com/rust-lang/rust-clippy/pull/7011)
 +* [`same_item_push`]: No longer lints if the `Vec` is used in the loop body
 +  [#7018](https://github.com/rust-lang/rust-clippy/pull/7018)
 +* [`cargo_common_metadata`]: Remove author requirement
 +  [#7026](https://github.com/rust-lang/rust-clippy/pull/7026)
 +* [`panic_in_result_fn`]: No longer lints on `debug_assert` family
 +  [#7060](https://github.com/rust-lang/rust-clippy/pull/7060)
 +* [`panic`]: No longer wrongfully lints on `debug_assert` with message
 +  [#7063](https://github.com/rust-lang/rust-clippy/pull/7063)
 +* [`wrong_self_convention`]: No longer lints in trait implementations where no
 +  `self` is involved [#7064](https://github.com/rust-lang/rust-clippy/pull/7064)
 +* [`missing_const_for_fn`]: No longer lints when unstable `const` function is
 +  involved [#7076](https://github.com/rust-lang/rust-clippy/pull/7076)
 +* [`suspicious_else_formatting`]: Allow Allman style braces
 +  [#7087](https://github.com/rust-lang/rust-clippy/pull/7087)
 +* [`inconsistent_struct_constructor`]: No longer lints in macros
 +  [#7097](https://github.com/rust-lang/rust-clippy/pull/7097)
 +* [`single_component_path_imports`]: No longer lints on macro re-exports
 +  [#7120](https://github.com/rust-lang/rust-clippy/pull/7120)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`redundant_pattern_matching`]: Add a note when applying this lint would
 +  change the drop order
 +  [#6568](https://github.com/rust-lang/rust-clippy/pull/6568)
 +* [`write_literal`], [`print_literal`]: Add auto-applicable suggestion
 +  [#6821](https://github.com/rust-lang/rust-clippy/pull/6821)
 +* [`manual_map`]: Fix suggestion for complex `if let ... else` chains
 +  [#6856](https://github.com/rust-lang/rust-clippy/pull/6856)
 +* [`inconsistent_struct_constructor`]: Make lint description and message clearer
 +  [#6892](https://github.com/rust-lang/rust-clippy/pull/6892)
 +* [`map_entry`]: Now suggests `or_insert`, `insert_with` or `match _.entry(_)`
 +  as appropriate [#6937](https://github.com/rust-lang/rust-clippy/pull/6937)
 +* [`manual_flatten`]: Suggest to insert `copied` if necessary
 +  [#6962](https://github.com/rust-lang/rust-clippy/pull/6962)
 +* [`redundant_slicing`]: Fix suggestion when a re-borrow might be required or
 +  when the value is from a macro call
 +  [#6975](https://github.com/rust-lang/rust-clippy/pull/6975)
 +* [`match_wildcard_for_single_variants`]: Fix suggestion for hidden variant
 +  [#6988](https://github.com/rust-lang/rust-clippy/pull/6988)
 +* [`clone_on_copy`]: Correct suggestion when the cloned value is a macro call
 +  [#7000](https://github.com/rust-lang/rust-clippy/pull/7000)
 +* [`manual_map`]: Fix suggestion at the end of an if chain
 +  [#7004](https://github.com/rust-lang/rust-clippy/pull/7004)
 +* Fix needless parenthesis output in multiple lint suggestions
 +  [#7013](https://github.com/rust-lang/rust-clippy/pull/7013)
 +* [`needless_collect`]: Better explanation in the lint message
 +  [#7020](https://github.com/rust-lang/rust-clippy/pull/7020)
 +* [`useless_vec`]: Now considers mutability
 +  [#7036](https://github.com/rust-lang/rust-clippy/pull/7036)
 +* [`useless_format`]: Wrap the content in braces if necessary
 +  [#7092](https://github.com/rust-lang/rust-clippy/pull/7092)
 +* [`single_match`]: Don't suggest an equality check for types which don't
 +  implement `PartialEq`
 +  [#7093](https://github.com/rust-lang/rust-clippy/pull/7093)
 +* [`from_over_into`]: Mention type in help message
 +  [#7099](https://github.com/rust-lang/rust-clippy/pull/7099)
 +* [`manual_unwrap_or`]: Fix invalid code suggestion due to a macro call
 +  [#7136](https://github.com/rust-lang/rust-clippy/pull/7136)
 +
 +### ICE Fixes
 +
 +* [`macro_use_imports`]
 +  [#7022](https://github.com/rust-lang/rust-clippy/pull/7022)
 +* [`missing_panics_doc`]
 +  [#7034](https://github.com/rust-lang/rust-clippy/pull/7034)
 +* [`tabs_in_doc_comments`]
 +  [#7039](https://github.com/rust-lang/rust-clippy/pull/7039)
 +* [`missing_const_for_fn`]
 +  [#7128](https://github.com/rust-lang/rust-clippy/pull/7128)
 +
 +### Others
 +
 +* [Clippy's lint
 +  list](https://rust-lang.github.io/rust-clippy/master/index.html) now supports
 +  themes [#7030](https://github.com/rust-lang/rust-clippy/pull/7030)
 +* Lints that were uplifted to `rustc` now mention the new `rustc` name in the
 +  deprecation warning
 +  [#7056](https://github.com/rust-lang/rust-clippy/pull/7056)
 +
 +## Rust 1.52
 +
 +Released 2021-05-06
 +
 +[3e41797...6ed6f1e](https://github.com/rust-lang/rust-clippy/compare/3e41797...6ed6f1e)
 +
 +### New Lints
 +
 +* [`from_str_radix_10`]
 +  [#6717](https://github.com/rust-lang/rust-clippy/pull/6717)
 +* [`implicit_clone`]
 +  [#6730](https://github.com/rust-lang/rust-clippy/pull/6730)
 +* [`semicolon_if_nothing_returned`]
 +  [#6681](https://github.com/rust-lang/rust-clippy/pull/6681)
 +* [`manual_flatten`]
 +  [#6646](https://github.com/rust-lang/rust-clippy/pull/6646)
 +* [`inconsistent_struct_constructor`]
 +  [#6769](https://github.com/rust-lang/rust-clippy/pull/6769)
 +* [`iter_count`]
 +  [#6791](https://github.com/rust-lang/rust-clippy/pull/6791)
 +* [`default_numeric_fallback`]
 +  [#6662](https://github.com/rust-lang/rust-clippy/pull/6662)
 +* [`bytes_nth`]
 +  [#6695](https://github.com/rust-lang/rust-clippy/pull/6695)
 +* [`filter_map_identity`]
 +  [#6685](https://github.com/rust-lang/rust-clippy/pull/6685)
 +* [`manual_map`]
 +  [#6573](https://github.com/rust-lang/rust-clippy/pull/6573)
 +
 +### Moves and Deprecations
 +
 +* Moved [`upper_case_acronyms`] to `pedantic`
 +  [#6775](https://github.com/rust-lang/rust-clippy/pull/6775)
 +* Moved [`manual_map`] to `nursery`
 +  [#6796](https://github.com/rust-lang/rust-clippy/pull/6796)
 +* Moved [`unnecessary_wraps`] to `pedantic`
 +  [#6765](https://github.com/rust-lang/rust-clippy/pull/6765)
 +* Moved [`trivial_regex`] to `nursery`
 +  [#6696](https://github.com/rust-lang/rust-clippy/pull/6696)
 +* Moved [`naive_bytecount`] to `pedantic`
 +  [#6825](https://github.com/rust-lang/rust-clippy/pull/6825)
 +* Moved [`upper_case_acronyms`] to `style`
 +  [#6788](https://github.com/rust-lang/rust-clippy/pull/6788)
 +* Moved [`manual_map`] to `style`
 +  [#6801](https://github.com/rust-lang/rust-clippy/pull/6801)
 +
 +### Enhancements
 +
 +* [`disallowed_methods`]: Now supports functions in addition to methods
 +  [#6674](https://github.com/rust-lang/rust-clippy/pull/6674)
 +* [`upper_case_acronyms`]: Added a new configuration `upper-case-acronyms-aggressive` to
 +  trigger the lint if there is more than one uppercase character next to each other
 +  [#6788](https://github.com/rust-lang/rust-clippy/pull/6788)
 +* [`collapsible_match`]: Now supports block comparison with different value names
 +  [#6754](https://github.com/rust-lang/rust-clippy/pull/6754)
 +* [`unnecessary_wraps`]: Will now suggest removing unnecessary wrapped return unit type, like `Option<()>`
 +  [#6665](https://github.com/rust-lang/rust-clippy/pull/6665)
 +* Improved value usage detection in closures
 +  [#6698](https://github.com/rust-lang/rust-clippy/pull/6698)
 +
 +### False Positive Fixes
 +
 +* [`use_self`]: No longer lints in macros
 +  [#6833](https://github.com/rust-lang/rust-clippy/pull/6833)
 +* [`use_self`]: Fixed multiple false positives for: generics, associated types and derive implementations
 +  [#6179](https://github.com/rust-lang/rust-clippy/pull/6179)
 +* [`missing_inline_in_public_items`]: No longer lints for procedural macros
 +  [#6814](https://github.com/rust-lang/rust-clippy/pull/6814)
 +* [`inherent_to_string`]: No longer lints on functions with function generics
 +  [#6771](https://github.com/rust-lang/rust-clippy/pull/6771)
 +* [`doc_markdown`]: Add `OpenDNS` to the default configuration as an allowed identifier
 +  [#6783](https://github.com/rust-lang/rust-clippy/pull/6783)
 +* [`missing_panics_doc`]: No longer lints on [`unreachable!`](https://doc.rust-lang.org/std/macro.unreachable.html)
 +  [#6700](https://github.com/rust-lang/rust-clippy/pull/6700)
 +* [`collapsible_if`]: No longer lints on if statements with attributes
 +  [#6701](https://github.com/rust-lang/rust-clippy/pull/6701)
 +* [`match_same_arms`]: Only considers empty blocks as equal if the tokens contained are the same
 +  [#6843](https://github.com/rust-lang/rust-clippy/pull/6843)
 +* [`redundant_closure`]: Now ignores macros
 +  [#6871](https://github.com/rust-lang/rust-clippy/pull/6871)
 +* [`manual_map`]: Fixed false positives when control flow statements like `return`, `break` etc. are used
 +  [#6801](https://github.com/rust-lang/rust-clippy/pull/6801)
 +* [`vec_init_then_push`]: Fixed false positives for loops and if statements
 +  [#6697](https://github.com/rust-lang/rust-clippy/pull/6697)
 +* [`len_without_is_empty`]: Will now consider multiple impl blocks and `#[allow]` on
 +  the `len` method as well as the type definition.
 +  [#6853](https://github.com/rust-lang/rust-clippy/pull/6853)
 +* [`let_underscore_drop`]: Only lints on types which implement `Drop`
 +  [#6682](https://github.com/rust-lang/rust-clippy/pull/6682)
 +* [`unit_arg`]: No longer lints on unit arguments when they come from a path expression.
 +  [#6601](https://github.com/rust-lang/rust-clippy/pull/6601)
 +* [`cargo_common_metadata`]: No longer lints if
 +  [`publish = false`](https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field)
 +  is defined in the manifest
 +  [#6650](https://github.com/rust-lang/rust-clippy/pull/6650)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`collapsible_match`]: Fixed lint message capitalization
 +  [#6766](https://github.com/rust-lang/rust-clippy/pull/6766)
 +* [`or_fun_call`]: Improved suggestions for `or_insert(vec![])`
 +  [#6790](https://github.com/rust-lang/rust-clippy/pull/6790)
 +* [`manual_map`]: No longer expands macros in the suggestions
 +  [#6801](https://github.com/rust-lang/rust-clippy/pull/6801)
 +* Aligned Clippy's lint messages with the rustc dev guide
 +  [#6787](https://github.com/rust-lang/rust-clippy/pull/6787)
 +
 +### ICE Fixes
 +
 +* [`zero_sized_map_values`]
 +  [#6866](https://github.com/rust-lang/rust-clippy/pull/6866)
 +
 +### Documentation Improvements
 +
 +* [`useless_format`]: Improved the documentation example
 +  [#6854](https://github.com/rust-lang/rust-clippy/pull/6854)
 +* Clippy's [`README.md`]: Includes a new subsection on running Clippy as a rustc wrapper
 +  [#6782](https://github.com/rust-lang/rust-clippy/pull/6782)
 +
 +### Others
 +* Running `cargo clippy` after `cargo check` now works as expected
 +  (`cargo clippy` and `cargo check` no longer shares the same build cache)
 +  [#6687](https://github.com/rust-lang/rust-clippy/pull/6687)
 +* Cargo now re-runs Clippy if arguments after `--` provided to `cargo clippy` are changed.
 +  [#6834](https://github.com/rust-lang/rust-clippy/pull/6834)
 +* Extracted Clippy's `utils` module into the new `clippy_utils` crate
 +  [#6756](https://github.com/rust-lang/rust-clippy/pull/6756)
 +* Clippy lintcheck tool improvements
 +  [#6800](https://github.com/rust-lang/rust-clippy/pull/6800)
 +  [#6735](https://github.com/rust-lang/rust-clippy/pull/6735)
 +  [#6764](https://github.com/rust-lang/rust-clippy/pull/6764)
 +  [#6708](https://github.com/rust-lang/rust-clippy/pull/6708)
 +  [#6780](https://github.com/rust-lang/rust-clippy/pull/6780)
 +  [#6686](https://github.com/rust-lang/rust-clippy/pull/6686)
 +
 +## Rust 1.51
 +
 +Released 2021-03-25
 +
 +[4911ab1...3e41797](https://github.com/rust-lang/rust-clippy/compare/4911ab1...3e41797)
 +
 +### New Lints
 +
 +* [`upper_case_acronyms`]
 +  [#6475](https://github.com/rust-lang/rust-clippy/pull/6475)
 +* [`from_over_into`] [#6476](https://github.com/rust-lang/rust-clippy/pull/6476)
 +* [`case_sensitive_file_extension_comparisons`]
 +  [#6500](https://github.com/rust-lang/rust-clippy/pull/6500)
 +* [`needless_question_mark`]
 +  [#6507](https://github.com/rust-lang/rust-clippy/pull/6507)
 +* [`missing_panics_doc`]
 +  [#6523](https://github.com/rust-lang/rust-clippy/pull/6523)
 +* [`redundant_slicing`]
 +  [#6528](https://github.com/rust-lang/rust-clippy/pull/6528)
 +* [`vec_init_then_push`]
 +  [#6538](https://github.com/rust-lang/rust-clippy/pull/6538)
 +* [`ptr_as_ptr`] [#6542](https://github.com/rust-lang/rust-clippy/pull/6542)
 +* [`collapsible_else_if`] (split out from `collapsible_if`)
 +  [#6544](https://github.com/rust-lang/rust-clippy/pull/6544)
 +* [`inspect_for_each`] [#6577](https://github.com/rust-lang/rust-clippy/pull/6577)
 +* [`manual_filter_map`]
 +  [#6591](https://github.com/rust-lang/rust-clippy/pull/6591)
 +* [`exhaustive_enums`]
 +  [#6617](https://github.com/rust-lang/rust-clippy/pull/6617)
 +* [`exhaustive_structs`]
 +  [#6617](https://github.com/rust-lang/rust-clippy/pull/6617)
 +
 +### Moves and Deprecations
 +
 +* Replace [`find_map`] with [`manual_find_map`]
 +  [#6591](https://github.com/rust-lang/rust-clippy/pull/6591)
 +* `unknown_clippy_lints` Now integrated in the `unknown_lints` rustc lint
 +  [#6653](https://github.com/rust-lang/rust-clippy/pull/6653)
 +
 +### Enhancements
 +
 +* [`ptr_arg`] Now also suggests to use `&Path` instead of `&PathBuf`
 +  [#6506](https://github.com/rust-lang/rust-clippy/pull/6506)
 +* [`cast_ptr_alignment`] Also lint when the `pointer::cast` method is used
 +  [#6557](https://github.com/rust-lang/rust-clippy/pull/6557)
 +* [`collapsible_match`] Now also deals with `&` and `*` operators in the `match`
 +  scrutinee [#6619](https://github.com/rust-lang/rust-clippy/pull/6619)
 +
 +### False Positive Fixes
 +
 +* [`similar_names`] Ignore underscore prefixed names
 +  [#6403](https://github.com/rust-lang/rust-clippy/pull/6403)
 +* [`print_literal`] and [`write_literal`] No longer lint numeric literals
 +  [#6408](https://github.com/rust-lang/rust-clippy/pull/6408)
 +* [`large_enum_variant`] No longer lints in external macros
 +  [#6485](https://github.com/rust-lang/rust-clippy/pull/6485)
 +* [`empty_enum`] Only lint if `never_type` feature is enabled
 +  [#6513](https://github.com/rust-lang/rust-clippy/pull/6513)
 +* [`field_reassign_with_default`] No longer lints in macros
 +  [#6553](https://github.com/rust-lang/rust-clippy/pull/6553)
 +* [`size_of_in_element_count`] No longer lints when dividing by element size
 +  [#6578](https://github.com/rust-lang/rust-clippy/pull/6578)
 +* [`needless_return`] No longer lints in macros
 +  [#6586](https://github.com/rust-lang/rust-clippy/pull/6586)
 +* [`match_overlapping_arm`] No longer lint when first arm is completely included
 +  in second arm [#6603](https://github.com/rust-lang/rust-clippy/pull/6603)
 +* [`doc_markdown`] Add `WebGL` to the default configuration as an allowed
 +  identifier [#6605](https://github.com/rust-lang/rust-clippy/pull/6605)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`field_reassign_with_default`] Don't expand macro in lint suggestion
 +  [#6531](https://github.com/rust-lang/rust-clippy/pull/6531)
 +* [`match_like_matches_macro`] Strip references in suggestion
 +  [#6532](https://github.com/rust-lang/rust-clippy/pull/6532)
 +* [`single_match`] Suggest `if` over `if let` when possible
 +  [#6574](https://github.com/rust-lang/rust-clippy/pull/6574)
 +* `ref_in_deref` Use parentheses correctly in suggestion
 +  [#6609](https://github.com/rust-lang/rust-clippy/pull/6609)
 +* [`stable_sort_primitive`] Clarify error message
 +  [#6611](https://github.com/rust-lang/rust-clippy/pull/6611)
 +
 +### ICE Fixes
 +
 +* [`zero_sized_map_values`]
 +  [#6582](https://github.com/rust-lang/rust-clippy/pull/6582)
 +
 +### Documentation Improvements
 +
 +* Improve search performance on the Clippy website and make it possible to
 +  directly search for lints on the GitHub issue tracker
 +  [#6483](https://github.com/rust-lang/rust-clippy/pull/6483)
 +* Clean up `README.md` by removing outdated paragraph
 +  [#6488](https://github.com/rust-lang/rust-clippy/pull/6488)
 +* [`await_holding_refcell_ref`] and [`await_holding_lock`]
 +  [#6585](https://github.com/rust-lang/rust-clippy/pull/6585)
 +* [`as_conversions`] [#6608](https://github.com/rust-lang/rust-clippy/pull/6608)
 +
 +### Others
 +
 +* Clippy now has a [Roadmap] for 2021. If you like to get involved in a bigger
 +  project, take a look at the [Roadmap project page]. All issues listed there
 +  are actively mentored
 +  [#6462](https://github.com/rust-lang/rust-clippy/pull/6462)
 +* The Clippy version number now corresponds to the Rust version number
 +  [#6526](https://github.com/rust-lang/rust-clippy/pull/6526)
 +* Fix oversight which caused Clippy to lint deps in some environments, where
 +  `CLIPPY_TESTS=true` was set somewhere
 +  [#6575](https://github.com/rust-lang/rust-clippy/pull/6575)
 +* Add `cargo dev-lintcheck` tool to the Clippy Dev Tool
 +  [#6469](https://github.com/rust-lang/rust-clippy/pull/6469)
 +
 +[Roadmap]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/proposals/roadmap-2021.md
 +[Roadmap project page]: https://github.com/rust-lang/rust-clippy/projects/3
 +
 +## Rust 1.50
 +
 +Released 2021-02-11
 +
 +[b20d4c1...4bd77a1](https://github.com/rust-lang/rust-clippy/compare/b20d4c1...4bd77a1)
 +
 +### New Lints
 +
 +* [`suspicious_operation_groupings`] [#6086](https://github.com/rust-lang/rust-clippy/pull/6086)
 +* [`size_of_in_element_count`] [#6394](https://github.com/rust-lang/rust-clippy/pull/6394)
 +* [`unnecessary_wraps`] [#6070](https://github.com/rust-lang/rust-clippy/pull/6070)
 +* [`let_underscore_drop`] [#6305](https://github.com/rust-lang/rust-clippy/pull/6305)
 +* [`collapsible_match`] [#6402](https://github.com/rust-lang/rust-clippy/pull/6402)
 +* [`redundant_else`] [#6330](https://github.com/rust-lang/rust-clippy/pull/6330)
 +* [`zero_sized_map_values`] [#6218](https://github.com/rust-lang/rust-clippy/pull/6218)
 +* [`print_stderr`] [#6367](https://github.com/rust-lang/rust-clippy/pull/6367)
 +* [`string_from_utf8_as_bytes`] [#6134](https://github.com/rust-lang/rust-clippy/pull/6134)
 +
 +### Moves and Deprecations
 +
 +* Previously deprecated [`str_to_string`] and [`string_to_string`] have been un-deprecated
 +  as `restriction` lints [#6333](https://github.com/rust-lang/rust-clippy/pull/6333)
 +* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panics`
 +  [#6351](https://github.com/rust-lang/rust-clippy/pull/6351)
 +* Move [`map_err_ignore`] to `restriction`
 +  [#6416](https://github.com/rust-lang/rust-clippy/pull/6416)
 +* Move [`await_holding_refcell_ref`] to `pedantic`
 +  [#6354](https://github.com/rust-lang/rust-clippy/pull/6354)
 +* Move [`await_holding_lock`] to `pedantic`
 +  [#6354](https://github.com/rust-lang/rust-clippy/pull/6354)
 +
 +### Enhancements
 +
 +* Add the `unreadable-literal-lint-fractions` configuration to disable
 +  the `unreadable_literal` lint for fractions
 +  [#6421](https://github.com/rust-lang/rust-clippy/pull/6421)
 +* [`clone_on_copy`]: Now shows the type in the lint message
 +  [#6443](https://github.com/rust-lang/rust-clippy/pull/6443)
 +* [`redundant_pattern_matching`]: Now also lints on `std::task::Poll`
 +  [#6339](https://github.com/rust-lang/rust-clippy/pull/6339)
 +* [`redundant_pattern_matching`]: Additionally also lints on `std::net::IpAddr`
 +  [#6377](https://github.com/rust-lang/rust-clippy/pull/6377)
 +* [`search_is_some`]: Now suggests `contains` instead of `find(foo).is_some()`
 +  [#6119](https://github.com/rust-lang/rust-clippy/pull/6119)
 +* [`clone_double_ref`]: Now prints the reference type in the lint message
 +  [#6442](https://github.com/rust-lang/rust-clippy/pull/6442)
 +* [`modulo_one`]: Now also lints on -1.
 +  [#6360](https://github.com/rust-lang/rust-clippy/pull/6360)
 +* [`empty_loop`]: Now lints no_std crates, too
 +  [#6205](https://github.com/rust-lang/rust-clippy/pull/6205)
 +* [`or_fun_call`]: Now also lints when indexing `HashMap` or `BTreeMap`
 +  [#6267](https://github.com/rust-lang/rust-clippy/pull/6267)
 +* [`wrong_self_convention`]: Now also lints in trait definitions
 +  [#6316](https://github.com/rust-lang/rust-clippy/pull/6316)
 +* [`needless_borrow`]: Print the type in the lint message
 +  [#6449](https://github.com/rust-lang/rust-clippy/pull/6449)
 +
 +[msrv_readme]: https://github.com/rust-lang/rust-clippy#specifying-the-minimum-supported-rust-version
 +
 +### False Positive Fixes
 +
 +* [`manual_range_contains`]: No longer lints in `const fn`
 +  [#6382](https://github.com/rust-lang/rust-clippy/pull/6382)
 +* [`unnecessary_lazy_evaluations`]: No longer lints if closure argument is used
 +  [#6370](https://github.com/rust-lang/rust-clippy/pull/6370)
 +* [`match_single_binding`]: Now ignores cases with `#[cfg()]` macros
 +  [#6435](https://github.com/rust-lang/rust-clippy/pull/6435)
 +* [`match_like_matches_macro`]: No longer lints on arms with attributes
 +  [#6290](https://github.com/rust-lang/rust-clippy/pull/6290)
 +* [`map_clone`]: No longer lints with deref and clone
 +  [#6269](https://github.com/rust-lang/rust-clippy/pull/6269)
 +* [`map_clone`]: No longer lints in the case of &mut
 +  [#6301](https://github.com/rust-lang/rust-clippy/pull/6301)
 +* [`needless_update`]: Now ignores `non_exhaustive` structs
 +  [#6464](https://github.com/rust-lang/rust-clippy/pull/6464)
 +* [`needless_collect`]: No longer lints when a collect is needed multiple times
 +  [#6313](https://github.com/rust-lang/rust-clippy/pull/6313)
 +* [`unnecessary_cast`] No longer lints cfg-dependent types
 +  [#6369](https://github.com/rust-lang/rust-clippy/pull/6369)
 +* [`declare_interior_mutable_const`] and [`borrow_interior_mutable_const`]:
 +  Both now ignore enums with frozen variants
 +  [#6110](https://github.com/rust-lang/rust-clippy/pull/6110)
 +* [`field_reassign_with_default`] No longer lint for private fields
 +  [#6537](https://github.com/rust-lang/rust-clippy/pull/6537)
 +
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`vec_box`]: Provide correct type scope suggestion
 +  [#6271](https://github.com/rust-lang/rust-clippy/pull/6271)
 +* [`manual_range_contains`]: Give correct suggestion when using floats
 +  [#6320](https://github.com/rust-lang/rust-clippy/pull/6320)
 +* [`unnecessary_lazy_evaluations`]: Don't always mark suggestion as MachineApplicable
 +  [#6272](https://github.com/rust-lang/rust-clippy/pull/6272)
 +* [`manual_async_fn`]: Improve suggestion formatting
 +  [#6294](https://github.com/rust-lang/rust-clippy/pull/6294)
 +* [`unnecessary_cast`]: Fix incorrectly formatted float literal suggestion
 +  [#6362](https://github.com/rust-lang/rust-clippy/pull/6362)
 +
 +### ICE Fixes
 +
 +* Fix a crash in [`from_iter_instead_of_collect`]
 +  [#6304](https://github.com/rust-lang/rust-clippy/pull/6304)
 +* Fix a silent crash when parsing doc comments in [`needless_doctest_main`]
 +  [#6458](https://github.com/rust-lang/rust-clippy/pull/6458)
 +
 +### Documentation Improvements
 +
 +* The lint website search has been improved ([#6477](https://github.com/rust-lang/rust-clippy/pull/6477)):
 +  * Searching for lints with dashes and spaces is possible now. For example
 +    `missing-errors-doc` and `missing errors doc` are now valid aliases for lint names
 +  * Improved fuzzy search in lint descriptions
 +* Various README improvements
 +  [#6287](https://github.com/rust-lang/rust-clippy/pull/6287)
 +* Add known problems to [`comparison_chain`] documentation
 +  [#6390](https://github.com/rust-lang/rust-clippy/pull/6390)
 +* Fix example used in [`cargo_common_metadata`]
 +  [#6293](https://github.com/rust-lang/rust-clippy/pull/6293)
 +* Improve [`map_clone`] documentation
 +  [#6340](https://github.com/rust-lang/rust-clippy/pull/6340)
 +
 +### Others
 +
 +* You can now tell Clippy about the MSRV your project supports. Please refer to
 +  the specific README section to learn more about MSRV support [here][msrv_readme]
 +  [#6201](https://github.com/rust-lang/rust-clippy/pull/6201)
 +* Add `--no-deps` option to avoid running on path dependencies in workspaces
 +  [#6188](https://github.com/rust-lang/rust-clippy/pull/6188)
 +
 +## Rust 1.49
 +
 +Released 2020-12-31
 +
 +[e636b88...b20d4c1](https://github.com/rust-lang/rust-clippy/compare/e636b88...b20d4c1)
 +
 +### New Lints
 +
 +* [`field_reassign_with_default`] [#5911](https://github.com/rust-lang/rust-clippy/pull/5911)
 +* [`await_holding_refcell_ref`] [#6029](https://github.com/rust-lang/rust-clippy/pull/6029)
 +* [`disallowed_methods`] [#6081](https://github.com/rust-lang/rust-clippy/pull/6081)
 +* [`inline_asm_x86_att_syntax`] [#6092](https://github.com/rust-lang/rust-clippy/pull/6092)
 +* [`inline_asm_x86_intel_syntax`] [#6092](https://github.com/rust-lang/rust-clippy/pull/6092)
 +* [`from_iter_instead_of_collect`] [#6101](https://github.com/rust-lang/rust-clippy/pull/6101)
 +* [`mut_mutex_lock`] [#6103](https://github.com/rust-lang/rust-clippy/pull/6103)
 +* [`single_element_loop`] [#6109](https://github.com/rust-lang/rust-clippy/pull/6109)
 +* [`manual_unwrap_or`] [#6123](https://github.com/rust-lang/rust-clippy/pull/6123)
 +* [`large_types_passed_by_value`] [#6135](https://github.com/rust-lang/rust-clippy/pull/6135)
 +* [`result_unit_err`] [#6157](https://github.com/rust-lang/rust-clippy/pull/6157)
 +* [`ref_option_ref`] [#6165](https://github.com/rust-lang/rust-clippy/pull/6165)
 +* [`manual_range_contains`] [#6177](https://github.com/rust-lang/rust-clippy/pull/6177)
 +* [`unusual_byte_groupings`] [#6183](https://github.com/rust-lang/rust-clippy/pull/6183)
 +* [`comparison_to_empty`] [#6226](https://github.com/rust-lang/rust-clippy/pull/6226)
 +* [`map_collect_result_unit`] [#6227](https://github.com/rust-lang/rust-clippy/pull/6227)
 +* [`manual_ok_or`] [#6233](https://github.com/rust-lang/rust-clippy/pull/6233)
 +
 +### Moves and Deprecations
 +
 +* Rename `single_char_push_str` to [`single_char_add_str`]
 +  [#6037](https://github.com/rust-lang/rust-clippy/pull/6037)
 +* Rename `zero_width_space` to [`invisible_characters`]
 +  [#6105](https://github.com/rust-lang/rust-clippy/pull/6105)
 +* Deprecate `drop_bounds` (uplifted)
 +  [#6111](https://github.com/rust-lang/rust-clippy/pull/6111)
 +* Move [`string_lit_as_bytes`] to `nursery`
 +  [#6117](https://github.com/rust-lang/rust-clippy/pull/6117)
 +* Move [`rc_buffer`] to `restriction`
 +  [#6128](https://github.com/rust-lang/rust-clippy/pull/6128)
 +
 +### Enhancements
 +
 +* [`manual_memcpy`]: Also lint when there are loop counters (and produce a
 +  reliable suggestion)
 +  [#5727](https://github.com/rust-lang/rust-clippy/pull/5727)
 +* [`single_char_add_str`]: Also lint on `String::insert_str`
 +  [#6037](https://github.com/rust-lang/rust-clippy/pull/6037)
 +* [`invisible_characters`]: Also lint the characters `\u{AD}` and `\u{2060}`
 +  [#6105](https://github.com/rust-lang/rust-clippy/pull/6105)
 +* [`eq_op`]: Also lint on the `assert_*!` macro family
 +  [#6167](https://github.com/rust-lang/rust-clippy/pull/6167)
 +* [`items_after_statements`]: Also lint in local macro expansions
 +  [#6176](https://github.com/rust-lang/rust-clippy/pull/6176)
 +* [`unnecessary_cast`]: Also lint casts on integer and float literals
 +  [#6187](https://github.com/rust-lang/rust-clippy/pull/6187)
 +* [`manual_unwrap_or`]: Also lint `Result::unwrap_or`
 +  [#6190](https://github.com/rust-lang/rust-clippy/pull/6190)
 +* [`match_like_matches_macro`]: Also lint when `match` has more than two arms
 +  [#6216](https://github.com/rust-lang/rust-clippy/pull/6216)
 +* [`integer_arithmetic`]: Better handle `/` an `%` operators
 +  [#6229](https://github.com/rust-lang/rust-clippy/pull/6229)
 +
 +### False Positive Fixes
 +
 +* [`needless_lifetimes`]: Bail out if the function has a `where` clause with the
 +  lifetime [#5978](https://github.com/rust-lang/rust-clippy/pull/5978)
 +* [`explicit_counter_loop`]: No longer lints, when loop counter is used after it
 +  is incremented [#6076](https://github.com/rust-lang/rust-clippy/pull/6076)
 +* [`or_fun_call`]: Revert changes addressing the handling of `const fn`
 +  [#6077](https://github.com/rust-lang/rust-clippy/pull/6077)
 +* [`needless_range_loop`]: No longer lints, when the iterable is used in the
 +  range [#6102](https://github.com/rust-lang/rust-clippy/pull/6102)
 +* [`inconsistent_digit_grouping`]: Fix bug when using floating point exponent
 +  [#6104](https://github.com/rust-lang/rust-clippy/pull/6104)
 +* [`mistyped_literal_suffixes`]: No longer lints on the fractional part of a
 +  float (e.g. `713.32_64`)
 +  [#6114](https://github.com/rust-lang/rust-clippy/pull/6114)
 +* [`invalid_regex`]: No longer lint on unicode characters within `bytes::Regex`
 +  [#6132](https://github.com/rust-lang/rust-clippy/pull/6132)
 +* [`boxed_local`]: No longer lints on `extern fn` arguments
 +  [#6133](https://github.com/rust-lang/rust-clippy/pull/6133)
 +* [`needless_lifetimes`]: Fix regression, where lifetime is used in `where`
 +  clause [#6198](https://github.com/rust-lang/rust-clippy/pull/6198)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`unnecessary_sort_by`]: Avoid dereferencing the suggested closure parameter
 +  [#6078](https://github.com/rust-lang/rust-clippy/pull/6078)
 +* [`needless_arbitrary_self_type`]: Correctly handle expanded code
 +  [#6093](https://github.com/rust-lang/rust-clippy/pull/6093)
 +* [`useless_format`]: Preserve raw strings in suggestion
 +  [#6151](https://github.com/rust-lang/rust-clippy/pull/6151)
 +* [`empty_loop`]: Suggest alternatives
 +  [#6162](https://github.com/rust-lang/rust-clippy/pull/6162)
 +* [`borrowed_box`]: Correctly add parentheses in suggestion
 +  [#6200](https://github.com/rust-lang/rust-clippy/pull/6200)
 +* [`unused_unit`]: Improve suggestion formatting
 +  [#6247](https://github.com/rust-lang/rust-clippy/pull/6247)
 +
 +### Documentation Improvements
 +
 +* Some doc improvements:
 +    * [`rc_buffer`] [#6090](https://github.com/rust-lang/rust-clippy/pull/6090)
 +    * [`empty_loop`] [#6162](https://github.com/rust-lang/rust-clippy/pull/6162)
 +* [`doc_markdown`]: Document problematic link text style
 +  [#6107](https://github.com/rust-lang/rust-clippy/pull/6107)
 +
 +## Rust 1.48
 +
 +Released 2020-11-19
 +
 +[09bd400...e636b88](https://github.com/rust-lang/rust-clippy/compare/09bd400...e636b88)
 +
 +### New lints
 +
 +* [`self_assignment`] [#5894](https://github.com/rust-lang/rust-clippy/pull/5894)
 +* [`unnecessary_lazy_evaluations`] [#5720](https://github.com/rust-lang/rust-clippy/pull/5720)
 +* [`manual_strip`] [#6038](https://github.com/rust-lang/rust-clippy/pull/6038)
 +* [`map_err_ignore`] [#5998](https://github.com/rust-lang/rust-clippy/pull/5998)
 +* [`rc_buffer`] [#6044](https://github.com/rust-lang/rust-clippy/pull/6044)
 +* `to_string_in_display` [#5831](https://github.com/rust-lang/rust-clippy/pull/5831)
 +* `single_char_push_str` [#5881](https://github.com/rust-lang/rust-clippy/pull/5881)
 +
 +### Moves and Deprecations
 +
 +* Downgrade [`verbose_bit_mask`] to pedantic
 +  [#6036](https://github.com/rust-lang/rust-clippy/pull/6036)
 +
 +### Enhancements
 +
 +* Extend [`precedence`] to handle chains of methods combined with unary negation
 +  [#5928](https://github.com/rust-lang/rust-clippy/pull/5928)
 +* [`useless_vec`]: add a configuration value for the maximum allowed size on the stack
 +  [#5907](https://github.com/rust-lang/rust-clippy/pull/5907)
 +* [`suspicious_arithmetic_impl`]: extend to implementations of `BitAnd`, `BitOr`, `BitXor`, `Rem`, `Shl`, and `Shr`
 +  [#5884](https://github.com/rust-lang/rust-clippy/pull/5884)
 +* `invalid_atomic_ordering`: detect misuse of `compare_exchange`, `compare_exchange_weak`, and `fetch_update`
 +  [#6025](https://github.com/rust-lang/rust-clippy/pull/6025)
 +* Avoid [`redundant_pattern_matching`] triggering in macros
 +  [#6069](https://github.com/rust-lang/rust-clippy/pull/6069)
 +* [`option_if_let_else`]: distinguish pure from impure `else` expressions
 +  [#5937](https://github.com/rust-lang/rust-clippy/pull/5937)
 +* [`needless_doctest_main`]: parse doctests instead of using textual search
 +  [#5912](https://github.com/rust-lang/rust-clippy/pull/5912)
 +* [`wildcard_imports`]: allow `prelude` to appear in any segment of an import
 +  [#5929](https://github.com/rust-lang/rust-clippy/pull/5929)
 +* Re-enable [`len_zero`] for ranges now that `range_is_empty` is stable
 +  [#5961](https://github.com/rust-lang/rust-clippy/pull/5961)
 +* [`option_as_ref_deref`]: catch fully-qualified calls to `Deref::deref` and `DerefMut::deref_mut`
 +  [#5933](https://github.com/rust-lang/rust-clippy/pull/5933)
 +
 +### False Positive Fixes
 +
 +* [`useless_attribute`]: permit allowing [`wildcard_imports`] and [`enum_glob_use`]
 +  [#5994](https://github.com/rust-lang/rust-clippy/pull/5994)
 +* [`transmute_ptr_to_ptr`]: avoid suggesting dereferencing raw pointers in const contexts
 +  [#5999](https://github.com/rust-lang/rust-clippy/pull/5999)
 +* [`redundant_closure_call`]: take into account usages of the closure in nested functions and closures
 +  [#5920](https://github.com/rust-lang/rust-clippy/pull/5920)
 +* Fix false positive in [`borrow_interior_mutable_const`] when referencing a field behind a pointer
 +  [#5949](https://github.com/rust-lang/rust-clippy/pull/5949)
 +* [`doc_markdown`]: allow using "GraphQL" without backticks
 +  [#5996](https://github.com/rust-lang/rust-clippy/pull/5996)
 +* `to_string_in_display`: avoid linting when calling `to_string()` on anything that is not `self`
 +  [#5971](https://github.com/rust-lang/rust-clippy/pull/5971)
 +* [`indexing_slicing`] and [`out_of_bounds_indexing`] treat references to arrays as arrays
 +  [#6034](https://github.com/rust-lang/rust-clippy/pull/6034)
 +* [`should_implement_trait`]: ignore methods with lifetime parameters
 +  [#5725](https://github.com/rust-lang/rust-clippy/pull/5725)
 +* [`needless_return`]: avoid linting if a temporary borrows a local variable
 +  [#5903](https://github.com/rust-lang/rust-clippy/pull/5903)
 +* Restrict [`unnecessary_sort_by`] to non-reference, Copy types
 +  [#6006](https://github.com/rust-lang/rust-clippy/pull/6006)
 +* Avoid suggesting `from_bits`/`to_bits` in const contexts in [`transmute_int_to_float`]
 +  [#5919](https://github.com/rust-lang/rust-clippy/pull/5919)
 +* [`declare_interior_mutable_const`] and [`borrow_interior_mutable_const`]: improve detection of interior mutable types
 +  [#6046](https://github.com/rust-lang/rust-clippy/pull/6046)
 +
 +### Suggestion Fixes/Improvements
 +
 +* [`let_and_return`]: add a cast to the suggestion when the return expression has adjustments
 +  [#5946](https://github.com/rust-lang/rust-clippy/pull/5946)
 +* [`useless_conversion`]: show the type in the error message
 +  [#6035](https://github.com/rust-lang/rust-clippy/pull/6035)
 +* [`unnecessary_mut_passed`]: discriminate between functions and methods in the error message
 +  [#5892](https://github.com/rust-lang/rust-clippy/pull/5892)
 +* [`float_cmp`] and [`float_cmp_const`]: change wording to make margin of error less ambiguous
 +  [#6043](https://github.com/rust-lang/rust-clippy/pull/6043)
 +* [`default_trait_access`]: do not use unnecessary type parameters in the suggestion
 +  [#5993](https://github.com/rust-lang/rust-clippy/pull/5993)
 +* [`collapsible_if`]: don't use expanded code in the suggestion
 +  [#5992](https://github.com/rust-lang/rust-clippy/pull/5992)
 +* Do not suggest empty format strings in [`print_with_newline`] and [`write_with_newline`]
 +  [#6042](https://github.com/rust-lang/rust-clippy/pull/6042)
 +* [`unit_arg`]: improve the readability of the suggestion
 +  [#5931](https://github.com/rust-lang/rust-clippy/pull/5931)
 +* [`stable_sort_primitive`]: print the type that is being sorted in the lint message
 +  [#5935](https://github.com/rust-lang/rust-clippy/pull/5935)
 +* Show line count and max lines in [`too_many_lines`] lint message
 +  [#6009](https://github.com/rust-lang/rust-clippy/pull/6009)
 +* Keep parentheses in the suggestion of [`useless_conversion`] where applicable
 +  [#5900](https://github.com/rust-lang/rust-clippy/pull/5900)
 +* [`option_map_unit_fn`] and [`result_map_unit_fn`]: print the unit type `()` explicitly
 +  [#6024](https://github.com/rust-lang/rust-clippy/pull/6024)
 +* [`redundant_allocation`]: suggest replacing `Rc<Box<T>>` with `Rc<T>`
 +  [#5899](https://github.com/rust-lang/rust-clippy/pull/5899)
 +* Make lint messages adhere to rustc dev guide conventions
 +  [#5893](https://github.com/rust-lang/rust-clippy/pull/5893)
 +
 +### ICE Fixes
 +
 +* Fix ICE in [`repeat_once`]
 +  [#5948](https://github.com/rust-lang/rust-clippy/pull/5948)
 +
 +### Documentation Improvements
 +
 +* [`mutable_key_type`]: explain potential for false positives when the interior mutable type is not accessed in the `Hash` implementation
 +  [#6019](https://github.com/rust-lang/rust-clippy/pull/6019)
 +* [`unnecessary_mut_passed`]: fix typo
 +  [#5913](https://github.com/rust-lang/rust-clippy/pull/5913)
 +* Add example of false positive to [`ptr_arg`] docs.
 +  [#5885](https://github.com/rust-lang/rust-clippy/pull/5885)
 +* [`box_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection), [`vec_box`] and [`borrowed_box`]: add link to the documentation of `Box`
 +  [#6023](https://github.com/rust-lang/rust-clippy/pull/6023)
 +
 +## Rust 1.47
 +
 +Released 2020-10-08
 +
 +[c2c07fa...09bd400](https://github.com/rust-lang/rust-clippy/compare/c2c07fa...09bd400)
 +
 +### New lints
 +
 +* [`derive_ord_xor_partial_ord`] [#5848](https://github.com/rust-lang/rust-clippy/pull/5848)
 +* [`trait_duplication_in_bounds`] [#5852](https://github.com/rust-lang/rust-clippy/pull/5852)
 +* [`map_identity`] [#5694](https://github.com/rust-lang/rust-clippy/pull/5694)
 +* [`unit_return_expecting_ord`] [#5737](https://github.com/rust-lang/rust-clippy/pull/5737)
 +* [`pattern_type_mismatch`] [#4841](https://github.com/rust-lang/rust-clippy/pull/4841)
 +* [`repeat_once`] [#5773](https://github.com/rust-lang/rust-clippy/pull/5773)
 +* [`same_item_push`] [#5825](https://github.com/rust-lang/rust-clippy/pull/5825)
 +* [`needless_arbitrary_self_type`] [#5869](https://github.com/rust-lang/rust-clippy/pull/5869)
 +* [`match_like_matches_macro`] [#5769](https://github.com/rust-lang/rust-clippy/pull/5769)
 +* [`stable_sort_primitive`] [#5809](https://github.com/rust-lang/rust-clippy/pull/5809)
 +* [`blanket_clippy_restriction_lints`] [#5750](https://github.com/rust-lang/rust-clippy/pull/5750)
 +* [`option_if_let_else`] [#5301](https://github.com/rust-lang/rust-clippy/pull/5301)
 +
 +### Moves and Deprecations
 +
 +* Deprecate [`regex_macro`] lint
 +  [#5760](https://github.com/rust-lang/rust-clippy/pull/5760)
 +* Move [`range_minus_one`] to `pedantic`
 +  [#5752](https://github.com/rust-lang/rust-clippy/pull/5752)
 +
 +### Enhancements
 +
 +* Improve [`needless_collect`] by catching `collect` calls followed by `iter` or `into_iter` calls
 +  [#5837](https://github.com/rust-lang/rust-clippy/pull/5837)
 +* [`panic`], [`todo`], [`unimplemented`] and [`unreachable`] now detect calls with formatting
 +  [#5811](https://github.com/rust-lang/rust-clippy/pull/5811)
 +* Detect more cases of [`suboptimal_flops`] and [`imprecise_flops`]
 +  [#5443](https://github.com/rust-lang/rust-clippy/pull/5443)
 +* Handle asymmetrical implementations of `PartialEq` in [`cmp_owned`]
 +  [#5701](https://github.com/rust-lang/rust-clippy/pull/5701)
 +* Make it possible to allow [`unsafe_derive_deserialize`]
 +  [#5870](https://github.com/rust-lang/rust-clippy/pull/5870)
 +* Catch `ord.min(a).max(b)` where a < b in [`min_max`]
 +  [#5871](https://github.com/rust-lang/rust-clippy/pull/5871)
 +* Make [`clone_on_copy`] suggestion machine applicable
 +  [#5745](https://github.com/rust-lang/rust-clippy/pull/5745)
 +* Enable [`len_zero`] on ranges now that `is_empty` is stable on them
 +  [#5961](https://github.com/rust-lang/rust-clippy/pull/5961)
 +
 +### False Positive Fixes
 +
 +* Avoid triggering [`or_fun_call`] with const fns that take no arguments
 +  [#5889](https://github.com/rust-lang/rust-clippy/pull/5889)
 +* Fix [`redundant_closure_call`] false positive for closures that have multiple calls
 +  [#5800](https://github.com/rust-lang/rust-clippy/pull/5800)
 +* Don't lint cases involving `ManuallyDrop` in [`redundant_clone`]
 +  [#5824](https://github.com/rust-lang/rust-clippy/pull/5824)
 +* Treat a single expression the same as a single statement in the 2nd arm of a match in [`single_match_else`]
 +  [#5771](https://github.com/rust-lang/rust-clippy/pull/5771)
 +* Don't trigger [`unnested_or_patterns`] if the feature `or_patterns` is not enabled
 +  [#5758](https://github.com/rust-lang/rust-clippy/pull/5758)
 +* Avoid linting if key borrows in [`unnecessary_sort_by`]
 +  [#5756](https://github.com/rust-lang/rust-clippy/pull/5756)
 +* Consider `Try` impl for `Poll` when generating suggestions in [`try_err`]
 +  [#5857](https://github.com/rust-lang/rust-clippy/pull/5857)
 +* Take input lifetimes into account in `manual_async_fn`
 +  [#5859](https://github.com/rust-lang/rust-clippy/pull/5859)
 +* Fix multiple false positives in [`type_repetition_in_bounds`] and add a configuration option
 +  [#5761](https://github.com/rust-lang/rust-clippy/pull/5761)
 +* Limit the [`suspicious_arithmetic_impl`] lint to one binary operation
 +  [#5820](https://github.com/rust-lang/rust-clippy/pull/5820)
 +
 +### Suggestion Fixes/Improvements
 +
 +* Improve readability of [`shadow_unrelated`] suggestion by truncating the RHS snippet
 +  [#5788](https://github.com/rust-lang/rust-clippy/pull/5788)
 +* Suggest `filter_map` instead of `flat_map` when mapping to `Option` in [`map_flatten`]
 +  [#5846](https://github.com/rust-lang/rust-clippy/pull/5846)
 +* Ensure suggestion is shown correctly for long method call chains in [`iter_nth_zero`]
 +  [#5793](https://github.com/rust-lang/rust-clippy/pull/5793)
 +* Drop borrow operator in suggestions of [`redundant_pattern_matching`]
 +  [#5815](https://github.com/rust-lang/rust-clippy/pull/5815)
 +* Add suggestion for [`iter_skip_next`]
 +  [#5843](https://github.com/rust-lang/rust-clippy/pull/5843)
 +* Improve [`collapsible_if`] fix suggestion
 +  [#5732](https://github.com/rust-lang/rust-clippy/pull/5732)
 +
 +### ICE Fixes
 +
 +* Fix ICE caused by [`needless_collect`]
 +  [#5877](https://github.com/rust-lang/rust-clippy/pull/5877)
 +* Fix ICE caused by [`unnested_or_patterns`]
 +  [#5784](https://github.com/rust-lang/rust-clippy/pull/5784)
 +
 +### Documentation Improvements
 +
 +* Fix grammar of [`await_holding_lock`] documentation
 +  [#5748](https://github.com/rust-lang/rust-clippy/pull/5748)
 +
 +### Others
 +
 +* Make lints adhere to the rustc dev guide
 +  [#5888](https://github.com/rust-lang/rust-clippy/pull/5888)
 +
 +## Rust 1.46
 +
 +Released 2020-08-27
 +
 +[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...c2c07fa)
 +
 +### New lints
 +
 +* [`unnested_or_patterns`] [#5378](https://github.com/rust-lang/rust-clippy/pull/5378)
 +* [`iter_next_slice`] [#5597](https://github.com/rust-lang/rust-clippy/pull/5597)
 +* [`unnecessary_sort_by`] [#5623](https://github.com/rust-lang/rust-clippy/pull/5623)
 +* [`vec_resize_to_zero`] [#5637](https://github.com/rust-lang/rust-clippy/pull/5637)
 +
 +### Moves and Deprecations
 +
 +* Move [`cast_ptr_alignment`] to pedantic [#5667](https://github.com/rust-lang/rust-clippy/pull/5667)
 +
 +### Enhancements
 +
 +* Improve [`mem_replace_with_uninit`] lint [#5695](https://github.com/rust-lang/rust-clippy/pull/5695)
 +
 +### False Positive Fixes
 +
 +* [`len_zero`]: Avoid linting ranges when the `range_is_empty` feature is not enabled
 +  [#5656](https://github.com/rust-lang/rust-clippy/pull/5656)
 +* [`let_and_return`]: Don't lint if a temporary borrow is involved
 +  [#5680](https://github.com/rust-lang/rust-clippy/pull/5680)
 +* [`reversed_empty_ranges`]: Avoid linting `N..N` in for loop arguments in
 +  [#5692](https://github.com/rust-lang/rust-clippy/pull/5692)
 +* [`if_same_then_else`]: Don't assume multiplication is always commutative
 +  [#5702](https://github.com/rust-lang/rust-clippy/pull/5702)
 +* [`disallowed_names`]: Remove `bar` from the default configuration
 +  [#5712](https://github.com/rust-lang/rust-clippy/pull/5712)
 +* [`redundant_pattern_matching`]: Avoid suggesting non-`const fn` calls in const contexts
 +  [#5724](https://github.com/rust-lang/rust-clippy/pull/5724)
 +
 +### Suggestion Fixes/Improvements
 +
 +* Fix suggestion of [`unit_arg`] lint, so that it suggest semantic equivalent code
 +  [#4455](https://github.com/rust-lang/rust-clippy/pull/4455)
 +* Add auto applicable suggestion to [`macro_use_imports`]
 +  [#5279](https://github.com/rust-lang/rust-clippy/pull/5279)
 +
 +### ICE Fixes
 +
 +* Fix ICE in the `consts` module of Clippy [#5709](https://github.com/rust-lang/rust-clippy/pull/5709)
 +
 +### Documentation Improvements
 +
 +* Improve code examples across multiple lints [#5664](https://github.com/rust-lang/rust-clippy/pull/5664)
 +
 +### Others
 +
 +* Introduce a `--rustc` flag to `clippy-driver`, which turns `clippy-driver`
 +  into `rustc` and passes all the given arguments to `rustc`. This is especially
 +  useful for tools that need the `rustc` version Clippy was compiled with,
 +  instead of the Clippy version. E.g. `clippy-driver --rustc --version` will
 +  print the output of `rustc --version`.
 +  [#5178](https://github.com/rust-lang/rust-clippy/pull/5178)
 +* New issue templates now make it easier to complain if Clippy is too annoying
 +  or not annoying enough! [#5735](https://github.com/rust-lang/rust-clippy/pull/5735)
 +
 +## Rust 1.45
 +
 +Released 2020-07-16
 +
 +[891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1)
 +
 +### New lints
 +
 +* [`match_wildcard_for_single_variants`] [#5582](https://github.com/rust-lang/rust-clippy/pull/5582)
 +* [`unsafe_derive_deserialize`] [#5493](https://github.com/rust-lang/rust-clippy/pull/5493)
 +* [`if_let_mutex`] [#5332](https://github.com/rust-lang/rust-clippy/pull/5332)
 +* [`mismatched_target_os`] [#5506](https://github.com/rust-lang/rust-clippy/pull/5506)
 +* [`await_holding_lock`] [#5439](https://github.com/rust-lang/rust-clippy/pull/5439)
 +* [`match_on_vec_items`] [#5522](https://github.com/rust-lang/rust-clippy/pull/5522)
 +* [`manual_async_fn`] [#5576](https://github.com/rust-lang/rust-clippy/pull/5576)
 +* [`reversed_empty_ranges`] [#5583](https://github.com/rust-lang/rust-clippy/pull/5583)
 +* [`manual_non_exhaustive`] [#5550](https://github.com/rust-lang/rust-clippy/pull/5550)
 +
 +### Moves and Deprecations
 +
 +* Downgrade [`match_bool`] to pedantic [#5408](https://github.com/rust-lang/rust-clippy/pull/5408)
 +* Downgrade [`match_wild_err_arm`] to pedantic and update help messages. [#5622](https://github.com/rust-lang/rust-clippy/pull/5622)
 +* Downgrade [`useless_let_if_seq`] to nursery. [#5599](https://github.com/rust-lang/rust-clippy/pull/5599)
 +* Generalize `option_and_then_some` and rename to [`bind_instead_of_map`]. [#5529](https://github.com/rust-lang/rust-clippy/pull/5529)
 +* Rename `identity_conversion` to [`useless_conversion`]. [#5568](https://github.com/rust-lang/rust-clippy/pull/5568)
 +* Merge `block_in_if_condition_expr` and `block_in_if_condition_stmt` into [`blocks_in_if_conditions`].
 +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563)
 +* Merge `option_map_unwrap_or`, `option_map_unwrap_or_else` and `result_map_unwrap_or_else` into [`map_unwrap_or`].
 +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563)
 +* Merge `option_unwrap_used` and `result_unwrap_used` into [`unwrap_used`].
 +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563)
 +* Merge `option_expect_used` and `result_expect_used` into [`expect_used`].
 +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563)
 +* Merge `for_loop_over_option` and `for_loop_over_result` into [`for_loops_over_fallibles`].
 +[#5563](https://github.com/rust-lang/rust-clippy/pull/5563)
 +
 +### Enhancements
 +
 +* Avoid running cargo lints when not enabled to improve performance. [#5505](https://github.com/rust-lang/rust-clippy/pull/5505)
 +* Extend [`useless_conversion`] with `TryFrom` and `TryInto`. [#5631](https://github.com/rust-lang/rust-clippy/pull/5631)
 +* Lint also in type parameters and where clauses in [`unused_unit`]. [#5592](https://github.com/rust-lang/rust-clippy/pull/5592)
 +* Do not suggest deriving `Default` in [`new_without_default`]. [#5616](https://github.com/rust-lang/rust-clippy/pull/5616)
 +
 +### False Positive Fixes
 +
 +* [`while_let_on_iterator`] [#5525](https://github.com/rust-lang/rust-clippy/pull/5525)
 +* [`empty_line_after_outer_attr`] [#5609](https://github.com/rust-lang/rust-clippy/pull/5609)
 +* [`unnecessary_unwrap`] [#5558](https://github.com/rust-lang/rust-clippy/pull/5558)
 +* [`comparison_chain`] [#5596](https://github.com/rust-lang/rust-clippy/pull/5596)
 +* Don't trigger [`used_underscore_binding`] in await desugaring. [#5535](https://github.com/rust-lang/rust-clippy/pull/5535)
 +* Don't trigger [`borrowed_box`] on mutable references. [#5491](https://github.com/rust-lang/rust-clippy/pull/5491)
 +* Allow `1 << 0` in [`identity_op`]. [#5602](https://github.com/rust-lang/rust-clippy/pull/5602)
 +* Allow `use super::*;` glob imports in [`wildcard_imports`]. [#5564](https://github.com/rust-lang/rust-clippy/pull/5564)
 +* Whitelist more words in [`doc_markdown`]. [#5611](https://github.com/rust-lang/rust-clippy/pull/5611)
 +* Skip dev and build deps in [`multiple_crate_versions`]. [#5636](https://github.com/rust-lang/rust-clippy/pull/5636)
 +* Honor `allow` attribute on arguments in [`ptr_arg`]. [#5647](https://github.com/rust-lang/rust-clippy/pull/5647)
 +* Honor lint level attributes for [`redundant_field_names`], [`just_underscores_and_digits`], [`many_single_char_names`]
 +and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/5651)
 +* Ignore calls to `len` in [`or_fun_call`]. [#4429](https://github.com/rust-lang/rust-clippy/pull/4429)
 +
 +### Suggestion Improvements
 +
 +* Simplify suggestions in [`manual_memcpy`]. [#5536](https://github.com/rust-lang/rust-clippy/pull/5536)
 +* Fix suggestion in [`redundant_pattern_matching`] for macros. [#5511](https://github.com/rust-lang/rust-clippy/pull/5511)
 +* Avoid suggesting `copied()` for mutable references in [`map_clone`]. [#5530](https://github.com/rust-lang/rust-clippy/pull/5530)
 +* Improve help message for [`clone_double_ref`]. [#5547](https://github.com/rust-lang/rust-clippy/pull/5547)
 +
 +### ICE Fixes
 +
 +* Fix ICE caused in unwrap module. [#5590](https://github.com/rust-lang/rust-clippy/pull/5590)
 +* Fix ICE on rustc test issue-69020-assoc-const-arith-overflow.rs [#5499](https://github.com/rust-lang/rust-clippy/pull/5499)
 +
 +### Documentation
 +
 +* Clarify the documentation of [`unnecessary_mut_passed`]. [#5639](https://github.com/rust-lang/rust-clippy/pull/5639)
 +* Extend example for [`unneeded_field_pattern`]. [#5541](https://github.com/rust-lang/rust-clippy/pull/5541)
 +
 +## Rust 1.44
 +
 +Released 2020-06-04
 +
 +[204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8)
 +
 +### New lints
 +
 +* [`explicit_deref_methods`] [#5226](https://github.com/rust-lang/rust-clippy/pull/5226)
 +* [`implicit_saturating_sub`] [#5427](https://github.com/rust-lang/rust-clippy/pull/5427)
 +* [`macro_use_imports`] [#5230](https://github.com/rust-lang/rust-clippy/pull/5230)
 +* [`verbose_file_reads`] [#5272](https://github.com/rust-lang/rust-clippy/pull/5272)
 +* [`future_not_send`] [#5423](https://github.com/rust-lang/rust-clippy/pull/5423)
 +* [`redundant_pub_crate`] [#5319](https://github.com/rust-lang/rust-clippy/pull/5319)
 +* [`large_const_arrays`] [#5248](https://github.com/rust-lang/rust-clippy/pull/5248)
 +* [`result_map_or_into_option`] [#5415](https://github.com/rust-lang/rust-clippy/pull/5415)
 +* [`redundant_allocation`] [#5349](https://github.com/rust-lang/rust-clippy/pull/5349)
 +* [`fn_address_comparisons`] [#5294](https://github.com/rust-lang/rust-clippy/pull/5294)
 +* [`vtable_address_comparisons`] [#5294](https://github.com/rust-lang/rust-clippy/pull/5294)
 +
 +
 +### Moves and Deprecations
 +
 +* Deprecate [`replace_consts`] lint [#5380](https://github.com/rust-lang/rust-clippy/pull/5380)
 +* Move [`cognitive_complexity`] to nursery [#5428](https://github.com/rust-lang/rust-clippy/pull/5428)
 +* Move [`useless_transmute`] to nursery [#5364](https://github.com/rust-lang/rust-clippy/pull/5364)
 +* Downgrade [`inefficient_to_string`] to pedantic [#5412](https://github.com/rust-lang/rust-clippy/pull/5412)
 +* Downgrade [`option_option`] to pedantic [#5401](https://github.com/rust-lang/rust-clippy/pull/5401)
 +* Downgrade [`unreadable_literal`] to pedantic [#5419](https://github.com/rust-lang/rust-clippy/pull/5419)
 +* Downgrade [`let_unit_value`] to pedantic [#5409](https://github.com/rust-lang/rust-clippy/pull/5409)
 +* Downgrade [`trivially_copy_pass_by_ref`] to pedantic [#5410](https://github.com/rust-lang/rust-clippy/pull/5410)
 +* Downgrade [`implicit_hasher`] to pedantic [#5411](https://github.com/rust-lang/rust-clippy/pull/5411)
 +
 +### Enhancements
 +
 +* On _nightly_ you can now use `cargo clippy --fix -Z unstable-options` to
 +  auto-fix lints that support this [#5363](https://github.com/rust-lang/rust-clippy/pull/5363)
 +* Make [`redundant_clone`] also trigger on cases where the cloned value is not
 +  consumed. [#5304](https://github.com/rust-lang/rust-clippy/pull/5304)
 +* Expand [`integer_arithmetic`] to also disallow bit-shifting [#5430](https://github.com/rust-lang/rust-clippy/pull/5430)
 +* [`option_as_ref_deref`] now detects more deref cases [#5425](https://github.com/rust-lang/rust-clippy/pull/5425)
 +* [`large_enum_variant`] now report the sizes of the largest and second-largest variants [#5466](https://github.com/rust-lang/rust-clippy/pull/5466)
 +* [`bool_comparison`] now also checks for inequality comparisons that can be
 +  written more concisely [#5365](https://github.com/rust-lang/rust-clippy/pull/5365)
 +* Expand [`clone_on_copy`] to work in method call arguments as well [#5441](https://github.com/rust-lang/rust-clippy/pull/5441)
 +* [`redundant_pattern_matching`] now also handles `while let` [#5483](https://github.com/rust-lang/rust-clippy/pull/5483)
 +* [`integer_arithmetic`] now also lints references of integers [#5329](https://github.com/rust-lang/rust-clippy/pull/5329)
 +* Expand [`float_cmp_const`] to also work on arrays [#5345](https://github.com/rust-lang/rust-clippy/pull/5345)
 +* Trigger [`map_flatten`] when map is called on an `Option` [#5473](https://github.com/rust-lang/rust-clippy/pull/5473)
 +
 +### False Positive Fixes
 +
 +* [`many_single_char_names`] [#5468](https://github.com/rust-lang/rust-clippy/pull/5468)
 +* [`should_implement_trait`] [#5437](https://github.com/rust-lang/rust-clippy/pull/5437)
 +* [`unused_self`] [#5387](https://github.com/rust-lang/rust-clippy/pull/5387)
 +* [`redundant_clone`] [#5453](https://github.com/rust-lang/rust-clippy/pull/5453)
 +* [`precedence`] [#5445](https://github.com/rust-lang/rust-clippy/pull/5445)
 +* [`suspicious_op_assign_impl`] [#5424](https://github.com/rust-lang/rust-clippy/pull/5424)
 +* [`needless_lifetimes`] [#5293](https://github.com/rust-lang/rust-clippy/pull/5293)
 +* [`redundant_pattern`] [#5287](https://github.com/rust-lang/rust-clippy/pull/5287)
 +* [`inconsistent_digit_grouping`] [#5451](https://github.com/rust-lang/rust-clippy/pull/5451)
 +
 +
 +### Suggestion Improvements
 +
 +* Improved [`question_mark`] lint suggestion so that it doesn't add redundant `as_ref()` [#5481](https://github.com/rust-lang/rust-clippy/pull/5481)
 +* Improve the suggested placeholder in [`option_map_unit_fn`] [#5292](https://github.com/rust-lang/rust-clippy/pull/5292)
 +* Improve suggestion for [`match_single_binding`] when triggered inside a closure [#5350](https://github.com/rust-lang/rust-clippy/pull/5350)
 +
 +### ICE Fixes
 +
 +* Handle the unstable `trivial_bounds` feature [#5296](https://github.com/rust-lang/rust-clippy/pull/5296)
 +* `shadow_*` lints [#5297](https://github.com/rust-lang/rust-clippy/pull/5297)
 +
 +### Documentation
 +
 +* Fix documentation generation for configurable lints [#5353](https://github.com/rust-lang/rust-clippy/pull/5353)
 +* Update documentation for [`new_ret_no_self`] [#5448](https://github.com/rust-lang/rust-clippy/pull/5448)
 +* The documentation for [`option_option`] now suggest using a tri-state enum [#5403](https://github.com/rust-lang/rust-clippy/pull/5403)
 +* Fix bit mask example in [`verbose_bit_mask`] documentation [#5454](https://github.com/rust-lang/rust-clippy/pull/5454)
 +* [`wildcard_imports`] documentation now mentions that `use ...::prelude::*` is
 +  not linted [#5312](https://github.com/rust-lang/rust-clippy/pull/5312)
 +
 +## Rust 1.43
 +
 +Released 2020-04-23
 +
 +[4ee1206...204bb9b](https://github.com/rust-lang/rust-clippy/compare/4ee1206...204bb9b)
 +
 +### New lints
 +
 +* [`imprecise_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897)
 +* [`suboptimal_flops`] [#4897](https://github.com/rust-lang/rust-clippy/pull/4897)
 +* [`wildcard_imports`] [#5029](https://github.com/rust-lang/rust-clippy/pull/5029)
 +* [`single_component_path_imports`] [#5058](https://github.com/rust-lang/rust-clippy/pull/5058)
 +* [`match_single_binding`] [#5061](https://github.com/rust-lang/rust-clippy/pull/5061)
 +* [`let_underscore_lock`] [#5101](https://github.com/rust-lang/rust-clippy/pull/5101)
 +* [`struct_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125)
 +* [`fn_params_excessive_bools`] [#5125](https://github.com/rust-lang/rust-clippy/pull/5125)
 +* [`option_env_unwrap`] [#5148](https://github.com/rust-lang/rust-clippy/pull/5148)
 +* [`lossy_float_literal`] [#5202](https://github.com/rust-lang/rust-clippy/pull/5202)
 +* [`rest_pat_in_fully_bound_structs`] [#5258](https://github.com/rust-lang/rust-clippy/pull/5258)
 +
 +### Moves and Deprecations
 +
 +* Move [`unneeded_field_pattern`] to pedantic group [#5200](https://github.com/rust-lang/rust-clippy/pull/5200)
 +
 +### Enhancements
 +
 +* Make [`missing_errors_doc`] lint also trigger on `async` functions
 +  [#5181](https://github.com/rust-lang/rust-clippy/pull/5181)
 +* Add more constants to [`approx_constant`] [#5193](https://github.com/rust-lang/rust-clippy/pull/5193)
 +* Extend [`question_mark`] lint [#5266](https://github.com/rust-lang/rust-clippy/pull/5266)
 +
 +### False Positive Fixes
 +
 +* [`use_debug`] [#5047](https://github.com/rust-lang/rust-clippy/pull/5047)
 +* [`unnecessary_unwrap`] [#5132](https://github.com/rust-lang/rust-clippy/pull/5132)
 +* [`zero_prefixed_literal`] [#5170](https://github.com/rust-lang/rust-clippy/pull/5170)
 +* [`missing_const_for_fn`] [#5216](https://github.com/rust-lang/rust-clippy/pull/5216)
 +
 +### Suggestion Improvements
 +
 +* Improve suggestion when blocks of code are suggested [#5134](https://github.com/rust-lang/rust-clippy/pull/5134)
 +
 +### ICE Fixes
 +
 +* `misc_early` lints [#5129](https://github.com/rust-lang/rust-clippy/pull/5129)
 +* [`missing_errors_doc`] [#5213](https://github.com/rust-lang/rust-clippy/pull/5213)
 +* Fix ICE when evaluating `usize`s [#5256](https://github.com/rust-lang/rust-clippy/pull/5256)
 +
 +### Documentation
 +
 +* Improve documentation of [`iter_nth_zero`]
 +* Add documentation pages for stable releases [#5171](https://github.com/rust-lang/rust-clippy/pull/5171)
 +
 +### Others
 +
 +* Clippy now completely runs on GitHub Actions [#5190](https://github.com/rust-lang/rust-clippy/pull/5190)
 +
 +
 +## Rust 1.42
 +
 +Released 2020-03-12
 +
 +[69f99e7...4ee1206](https://github.com/rust-lang/rust-clippy/compare/69f99e7...4ee1206)
 +
 +### New lints
 +
 +* [`filetype_is_file`] [#4543](https://github.com/rust-lang/rust-clippy/pull/4543)
 +* [`let_underscore_must_use`] [#4823](https://github.com/rust-lang/rust-clippy/pull/4823)
 +* [`modulo_arithmetic`] [#4867](https://github.com/rust-lang/rust-clippy/pull/4867)
 +* [`mem_replace_with_default`] [#4881](https://github.com/rust-lang/rust-clippy/pull/4881)
 +* [`mutable_key_type`] [#4885](https://github.com/rust-lang/rust-clippy/pull/4885)
 +* [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945)
 +* [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960)
 +* [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966)
 +* `invalid_atomic_ordering` [#4999](https://github.com/rust-lang/rust-clippy/pull/4999)
 +* [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067)
 +
 +### Moves and Deprecations
 +
 +* Move [`transmute_float_to_int`] from nursery to complexity group
 +  [#5015](https://github.com/rust-lang/rust-clippy/pull/5015)
 +* Move [`range_plus_one`] to pedantic group [#5057](https://github.com/rust-lang/rust-clippy/pull/5057)
 +* Move [`debug_assert_with_mut_call`] to nursery group [#5106](https://github.com/rust-lang/rust-clippy/pull/5106)
 +* Deprecate `unused_label` [#4930](https://github.com/rust-lang/rust-clippy/pull/4930)
 +
 +### Enhancements
 +
 +* Lint vectored IO in [`unused_io_amount`] [#5027](https://github.com/rust-lang/rust-clippy/pull/5027)
 +* Make [`vec_box`] configurable by adding a size threshold [#5081](https://github.com/rust-lang/rust-clippy/pull/5081)
 +* Also lint constants in [`cmp_nan`] [#4910](https://github.com/rust-lang/rust-clippy/pull/4910)
 +* Fix false negative in [`expect_fun_call`] [#4915](https://github.com/rust-lang/rust-clippy/pull/4915)
 +* Fix false negative in [`redundant_clone`] [#5017](https://github.com/rust-lang/rust-clippy/pull/5017)
 +
 +### False Positive Fixes
 +
 +* [`map_clone`] [#4937](https://github.com/rust-lang/rust-clippy/pull/4937)
 +* [`replace_consts`] [#4977](https://github.com/rust-lang/rust-clippy/pull/4977)
 +* [`let_and_return`] [#5008](https://github.com/rust-lang/rust-clippy/pull/5008)
 +* [`eq_op`] [#5079](https://github.com/rust-lang/rust-clippy/pull/5079)
 +* [`possible_missing_comma`] [#5083](https://github.com/rust-lang/rust-clippy/pull/5083)
 +* [`debug_assert_with_mut_call`] [#5106](https://github.com/rust-lang/rust-clippy/pull/5106)
 +* Don't trigger [`let_underscore_must_use`] in external macros
 +  [#5082](https://github.com/rust-lang/rust-clippy/pull/5082)
 +* Don't trigger [`empty_loop`] in `no_std` crates [#5086](https://github.com/rust-lang/rust-clippy/pull/5086)
 +
 +### Suggestion Improvements
 +
 +* `option_map_unwrap_or` [#4634](https://github.com/rust-lang/rust-clippy/pull/4634)
 +* [`wildcard_enum_match_arm`] [#4934](https://github.com/rust-lang/rust-clippy/pull/4934)
 +* [`cognitive_complexity`] [#4935](https://github.com/rust-lang/rust-clippy/pull/4935)
 +* [`decimal_literal_representation`] [#4956](https://github.com/rust-lang/rust-clippy/pull/4956)
 +* `unknown_clippy_lints` [#4963](https://github.com/rust-lang/rust-clippy/pull/4963)
 +* [`explicit_into_iter_loop`] [#4978](https://github.com/rust-lang/rust-clippy/pull/4978)
 +* [`useless_attribute`] [#5022](https://github.com/rust-lang/rust-clippy/pull/5022)
 +* `if_let_some_result` [#5032](https://github.com/rust-lang/rust-clippy/pull/5032)
 +
 +### ICE fixes
 +
 +* [`unsound_collection_transmute`] [#4975](https://github.com/rust-lang/rust-clippy/pull/4975)
 +
 +### Documentation
 +
 +* Improve documentation of [`empty_enum`], [`replace_consts`], [`redundant_clone`], and [`iterator_step_by_zero`]
 +
 +
 +## Rust 1.41
 +
 +Released 2020-01-30
 +
 +[c8e3cfb...69f99e7](https://github.com/rust-lang/rust-clippy/compare/c8e3cfb...69f99e7)
 +
 +* New Lints:
 +  * [`exit`] [#4697](https://github.com/rust-lang/rust-clippy/pull/4697)
 +  * [`to_digit_is_some`] [#4801](https://github.com/rust-lang/rust-clippy/pull/4801)
 +  * [`tabs_in_doc_comments`] [#4806](https://github.com/rust-lang/rust-clippy/pull/4806)
 +  * [`large_stack_arrays`] [#4807](https://github.com/rust-lang/rust-clippy/pull/4807)
 +  * [`same_functions_in_if_condition`] [#4814](https://github.com/rust-lang/rust-clippy/pull/4814)
 +  * [`zst_offset`] [#4816](https://github.com/rust-lang/rust-clippy/pull/4816)
 +  * [`as_conversions`] [#4821](https://github.com/rust-lang/rust-clippy/pull/4821)
 +  * [`missing_errors_doc`] [#4884](https://github.com/rust-lang/rust-clippy/pull/4884)
 +  * [`transmute_float_to_int`] [#4889](https://github.com/rust-lang/rust-clippy/pull/4889)
 +* Remove plugin interface, see
 +  [Inside Rust Blog](https://blog.rust-lang.org/inside-rust/2019/11/04/Clippy-removes-plugin-interface.html) for
 +  details [#4714](https://github.com/rust-lang/rust-clippy/pull/4714)
 +* Move [`use_self`] to nursery group [#4863](https://github.com/rust-lang/rust-clippy/pull/4863)
 +* Deprecate `into_iter_on_array` [#4788](https://github.com/rust-lang/rust-clippy/pull/4788)
 +* Expand [`string_lit_as_bytes`] to also trigger when literal has escapes
 +  [#4808](https://github.com/rust-lang/rust-clippy/pull/4808)
 +* Fix false positive in `comparison_chain` [#4842](https://github.com/rust-lang/rust-clippy/pull/4842)
 +* Fix false positive in `while_immutable_condition` [#4730](https://github.com/rust-lang/rust-clippy/pull/4730)
 +* Fix false positive in `explicit_counter_loop` [#4803](https://github.com/rust-lang/rust-clippy/pull/4803)
 +* Fix false positive in `must_use_candidate` [#4794](https://github.com/rust-lang/rust-clippy/pull/4794)
 +* Fix false positive in `print_with_newline` and `write_with_newline`
 +  [#4769](https://github.com/rust-lang/rust-clippy/pull/4769)
 +* Fix false positive in `derive_hash_xor_eq` [#4766](https://github.com/rust-lang/rust-clippy/pull/4766)
 +* Fix false positive in `missing_inline_in_public_items` [#4870](https://github.com/rust-lang/rust-clippy/pull/4870)
 +* Fix false positive in `string_add` [#4880](https://github.com/rust-lang/rust-clippy/pull/4880)
 +* Fix false positive in `float_arithmetic` [#4851](https://github.com/rust-lang/rust-clippy/pull/4851)
 +* Fix false positive in `cast_sign_loss` [#4883](https://github.com/rust-lang/rust-clippy/pull/4883)
 +* Fix false positive in `manual_swap` [#4877](https://github.com/rust-lang/rust-clippy/pull/4877)
 +* Fix ICEs occurring while checking some block expressions [#4772](https://github.com/rust-lang/rust-clippy/pull/4772)
 +* Fix ICE in `use_self` [#4776](https://github.com/rust-lang/rust-clippy/pull/4776)
 +* Fix ICEs related to `const_generics` [#4780](https://github.com/rust-lang/rust-clippy/pull/4780)
 +* Display help when running `clippy-driver` without arguments, instead of ICEing
 +  [#4810](https://github.com/rust-lang/rust-clippy/pull/4810)
 +* Clippy has its own ICE message now [#4588](https://github.com/rust-lang/rust-clippy/pull/4588)
 +* Show deprecated lints in the documentation again [#4757](https://github.com/rust-lang/rust-clippy/pull/4757)
 +* Improve Documentation by adding positive examples to some lints
 +  [#4832](https://github.com/rust-lang/rust-clippy/pull/4832)
 +
 +## Rust 1.40
 +
 +Released 2019-12-19
 +
 +[4e7e71b...c8e3cfb](https://github.com/rust-lang/rust-clippy/compare/4e7e71b...c8e3cfb)
 +
 +* New Lints:
 +  * [`unneeded_wildcard_pattern`] [#4537](https://github.com/rust-lang/rust-clippy/pull/4537)
 +  * [`needless_doctest_main`] [#4603](https://github.com/rust-lang/rust-clippy/pull/4603)
 +  * [`suspicious_unary_op_formatting`] [#4615](https://github.com/rust-lang/rust-clippy/pull/4615)
 +  * [`debug_assert_with_mut_call`] [#4680](https://github.com/rust-lang/rust-clippy/pull/4680)
 +  * [`unused_self`] [#4619](https://github.com/rust-lang/rust-clippy/pull/4619)
 +  * [`inefficient_to_string`] [#4683](https://github.com/rust-lang/rust-clippy/pull/4683)
 +  * [`must_use_unit`] [#4560](https://github.com/rust-lang/rust-clippy/pull/4560)
 +  * [`must_use_candidate`] [#4560](https://github.com/rust-lang/rust-clippy/pull/4560)
 +  * [`double_must_use`] [#4560](https://github.com/rust-lang/rust-clippy/pull/4560)
 +  * [`comparison_chain`] [#4569](https://github.com/rust-lang/rust-clippy/pull/4569)
 +  * [`unsound_collection_transmute`] [#4592](https://github.com/rust-lang/rust-clippy/pull/4592)
 +  * [`panic`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657)
 +  * [`unreachable`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657)
 +  * [`todo`] [#4657](https://github.com/rust-lang/rust-clippy/pull/4657)
 +  * `option_expect_used` [#4657](https://github.com/rust-lang/rust-clippy/pull/4657)
 +  * `result_expect_used` [#4657](https://github.com/rust-lang/rust-clippy/pull/4657)
 +* Move `redundant_clone` to perf group [#4509](https://github.com/rust-lang/rust-clippy/pull/4509)
 +* Move `manual_mul_add` to nursery group [#4736](https://github.com/rust-lang/rust-clippy/pull/4736)
 +* Expand `unit_cmp` to also work with `assert_eq!`, `debug_assert_eq!`, `assert_ne!` and `debug_assert_ne!` [#4613](https://github.com/rust-lang/rust-clippy/pull/4613)
 +* Expand `integer_arithmetic` to also detect mutating arithmetic like `+=` [#4585](https://github.com/rust-lang/rust-clippy/pull/4585)
 +* Fix false positive in `nonminimal_bool` [#4568](https://github.com/rust-lang/rust-clippy/pull/4568)
 +* Fix false positive in `missing_safety_doc` [#4611](https://github.com/rust-lang/rust-clippy/pull/4611)
 +* Fix false positive in `cast_sign_loss` [#4614](https://github.com/rust-lang/rust-clippy/pull/4614)
 +* Fix false positive in `redundant_clone` [#4509](https://github.com/rust-lang/rust-clippy/pull/4509)
 +* Fix false positive in `try_err` [#4721](https://github.com/rust-lang/rust-clippy/pull/4721)
 +* Fix false positive in `toplevel_ref_arg` [#4570](https://github.com/rust-lang/rust-clippy/pull/4570)
 +* Fix false positive in `multiple_inherent_impl` [#4593](https://github.com/rust-lang/rust-clippy/pull/4593)
 +* Improve more suggestions and tests in preparation for the unstable `cargo fix --clippy` [#4575](https://github.com/rust-lang/rust-clippy/pull/4575)
 +* Improve suggestion for `zero_ptr` [#4599](https://github.com/rust-lang/rust-clippy/pull/4599)
 +* Improve suggestion for `explicit_counter_loop` [#4691](https://github.com/rust-lang/rust-clippy/pull/4691)
 +* Improve suggestion for `mul_add` [#4602](https://github.com/rust-lang/rust-clippy/pull/4602)
 +* Improve suggestion for `assertions_on_constants` [#4635](https://github.com/rust-lang/rust-clippy/pull/4635)
 +* Fix ICE in `use_self` [#4671](https://github.com/rust-lang/rust-clippy/pull/4671)
 +* Fix ICE when encountering const casts [#4590](https://github.com/rust-lang/rust-clippy/pull/4590)
 +
 +## Rust 1.39
 +
 +Released 2019-11-07
 +
 +[3aea860...4e7e71b](https://github.com/rust-lang/rust-clippy/compare/3aea860...4e7e71b)
 +
 +* New Lints:
 +  * [`uninit_assumed_init`] [#4479](https://github.com/rust-lang/rust-clippy/pull/4479)
 +  * [`flat_map_identity`] [#4231](https://github.com/rust-lang/rust-clippy/pull/4231)
 +  * [`missing_safety_doc`] [#4535](https://github.com/rust-lang/rust-clippy/pull/4535)
 +  * [`mem_replace_with_uninit`] [#4511](https://github.com/rust-lang/rust-clippy/pull/4511)
 +  * [`suspicious_map`] [#4394](https://github.com/rust-lang/rust-clippy/pull/4394)
 +  * `option_and_then_some` [#4386](https://github.com/rust-lang/rust-clippy/pull/4386)
 +  * [`manual_saturating_arithmetic`] [#4498](https://github.com/rust-lang/rust-clippy/pull/4498)
 +* Deprecate `unused_collect` lint. This is fully covered by rustc's `#[must_use]` on `collect` [#4348](https://github.com/rust-lang/rust-clippy/pull/4348)
 +* Move `type_repetition_in_bounds` to pedantic group [#4403](https://github.com/rust-lang/rust-clippy/pull/4403)
 +* Move `cast_lossless` to pedantic group [#4539](https://github.com/rust-lang/rust-clippy/pull/4539)
 +* `temporary_cstring_as_ptr` now catches more cases [#4425](https://github.com/rust-lang/rust-clippy/pull/4425)
 +* `use_self` now works in constructors, too [#4525](https://github.com/rust-lang/rust-clippy/pull/4525)
 +* `cargo_common_metadata` now checks for license files [#4518](https://github.com/rust-lang/rust-clippy/pull/4518)
 +* `cognitive_complexity` now includes the measured complexity in the warning message [#4469](https://github.com/rust-lang/rust-clippy/pull/4469)
 +* Fix false positives in `block_in_if_*` lints [#4458](https://github.com/rust-lang/rust-clippy/pull/4458)
 +* Fix false positive in `cast_lossless` [#4473](https://github.com/rust-lang/rust-clippy/pull/4473)
 +* Fix false positive in `clone_on_copy` [#4411](https://github.com/rust-lang/rust-clippy/pull/4411)
 +* Fix false positive in `deref_addrof` [#4487](https://github.com/rust-lang/rust-clippy/pull/4487)
 +* Fix false positive in `too_many_lines` [#4490](https://github.com/rust-lang/rust-clippy/pull/4490)
 +* Fix false positive in `new_ret_no_self` [#4365](https://github.com/rust-lang/rust-clippy/pull/4365)
 +* Fix false positive in `manual_swap` [#4478](https://github.com/rust-lang/rust-clippy/pull/4478)
 +* Fix false positive in `missing_const_for_fn` [#4450](https://github.com/rust-lang/rust-clippy/pull/4450)
 +* Fix false positive in `extra_unused_lifetimes` [#4477](https://github.com/rust-lang/rust-clippy/pull/4477)
 +* Fix false positive in `inherent_to_string` [#4460](https://github.com/rust-lang/rust-clippy/pull/4460)
 +* Fix false positive in `map_entry` [#4495](https://github.com/rust-lang/rust-clippy/pull/4495)
 +* Fix false positive in `unused_unit` [#4445](https://github.com/rust-lang/rust-clippy/pull/4445)
 +* Fix false positive in `redundant_pattern` [#4489](https://github.com/rust-lang/rust-clippy/pull/4489)
 +* Fix false positive in `wrong_self_convention` [#4369](https://github.com/rust-lang/rust-clippy/pull/4369)
 +* Improve various suggestions and tests in preparation for the unstable `cargo fix --clippy` [#4558](https://github.com/rust-lang/rust-clippy/pull/4558)
 +* Improve suggestions for `redundant_pattern_matching` [#4352](https://github.com/rust-lang/rust-clippy/pull/4352)
 +* Improve suggestions for `explicit_write` [#4544](https://github.com/rust-lang/rust-clippy/pull/4544)
 +* Improve suggestion for `or_fun_call` [#4522](https://github.com/rust-lang/rust-clippy/pull/4522)
 +* Improve suggestion for `match_as_ref` [#4446](https://github.com/rust-lang/rust-clippy/pull/4446)
 +* Improve suggestion for `unnecessary_fold_span` [#4382](https://github.com/rust-lang/rust-clippy/pull/4382)
 +* Add suggestions for `unseparated_literal_suffix` [#4401](https://github.com/rust-lang/rust-clippy/pull/4401)
 +* Add suggestions for `char_lit_as_u8` [#4418](https://github.com/rust-lang/rust-clippy/pull/4418)
 +
 +## Rust 1.38
 +
 +Released 2019-09-26
 +
 +[e3cb40e...3aea860](https://github.com/rust-lang/rust-clippy/compare/e3cb40e...3aea860)
 +
 +* New Lints:
 +  * [`main_recursion`] [#4203](https://github.com/rust-lang/rust-clippy/pull/4203)
 +  * [`inherent_to_string`] [#4259](https://github.com/rust-lang/rust-clippy/pull/4259)
 +  * [`inherent_to_string_shadow_display`] [#4259](https://github.com/rust-lang/rust-clippy/pull/4259)
 +  * [`type_repetition_in_bounds`] [#3766](https://github.com/rust-lang/rust-clippy/pull/3766)
 +  * [`try_err`] [#4222](https://github.com/rust-lang/rust-clippy/pull/4222)
 +* Move `{unnecessary,panicking}_unwrap` out of nursery [#4307](https://github.com/rust-lang/rust-clippy/pull/4307)
 +* Extend the `use_self` lint to suggest uses of `Self::Variant` [#4308](https://github.com/rust-lang/rust-clippy/pull/4308)
 +* Improve suggestion for needless return [#4262](https://github.com/rust-lang/rust-clippy/pull/4262)
 +* Add auto-fixable suggestion for `let_unit` [#4337](https://github.com/rust-lang/rust-clippy/pull/4337)
 +* Fix false positive in `pub_enum_variant_names` and `enum_variant_names` [#4345](https://github.com/rust-lang/rust-clippy/pull/4345)
 +* Fix false positive in `cast_ptr_alignment` [#4257](https://github.com/rust-lang/rust-clippy/pull/4257)
 +* Fix false positive in `string_lit_as_bytes` [#4233](https://github.com/rust-lang/rust-clippy/pull/4233)
 +* Fix false positive in `needless_lifetimes` [#4266](https://github.com/rust-lang/rust-clippy/pull/4266)
 +* Fix false positive in `float_cmp` [#4275](https://github.com/rust-lang/rust-clippy/pull/4275)
 +* Fix false positives in `needless_return` [#4274](https://github.com/rust-lang/rust-clippy/pull/4274)
 +* Fix false negative in `match_same_arms` [#4246](https://github.com/rust-lang/rust-clippy/pull/4246)
 +* Fix incorrect suggestion for `needless_bool` [#4335](https://github.com/rust-lang/rust-clippy/pull/4335)
 +* Improve suggestion for `cast_ptr_alignment` [#4257](https://github.com/rust-lang/rust-clippy/pull/4257)
 +* Improve suggestion for `single_char_literal` [#4361](https://github.com/rust-lang/rust-clippy/pull/4361)
 +* Improve suggestion for `len_zero` [#4314](https://github.com/rust-lang/rust-clippy/pull/4314)
 +* Fix ICE in `implicit_hasher` [#4268](https://github.com/rust-lang/rust-clippy/pull/4268)
 +* Fix allow bug in `trivially_copy_pass_by_ref` [#4250](https://github.com/rust-lang/rust-clippy/pull/4250)
 +
 +## Rust 1.37
 +
 +Released 2019-08-15
 +
 +[082cfa7...e3cb40e](https://github.com/rust-lang/rust-clippy/compare/082cfa7...e3cb40e)
 +
 +* New Lints:
 +  * [`checked_conversions`] [#4088](https://github.com/rust-lang/rust-clippy/pull/4088)
 +  * [`get_last_with_len`] [#3832](https://github.com/rust-lang/rust-clippy/pull/3832)
 +  * [`integer_division`] [#4195](https://github.com/rust-lang/rust-clippy/pull/4195)
 +* Renamed Lint: `const_static_lifetime` is now called [`redundant_static_lifetimes`].
 +  The lint now covers statics in addition to consts [#4162](https://github.com/rust-lang/rust-clippy/pull/4162)
 +* [`match_same_arms`] now warns for all identical arms, instead of only the first one [#4102](https://github.com/rust-lang/rust-clippy/pull/4102)
 +* [`needless_return`] now works with void functions [#4220](https://github.com/rust-lang/rust-clippy/pull/4220)
 +* Fix false positive in [`redundant_closure`] [#4190](https://github.com/rust-lang/rust-clippy/pull/4190)
 +* Fix false positive in [`useless_attribute`] [#4107](https://github.com/rust-lang/rust-clippy/pull/4107)
 +* Fix incorrect suggestion for [`float_cmp`] [#4214](https://github.com/rust-lang/rust-clippy/pull/4214)
 +* Add suggestions for [`print_with_newline`] and [`write_with_newline`] [#4136](https://github.com/rust-lang/rust-clippy/pull/4136)
 +* Improve suggestions for `option_map_unwrap_or_else` and `result_map_unwrap_or_else` [#4164](https://github.com/rust-lang/rust-clippy/pull/4164)
 +* Improve suggestions for [`non_ascii_literal`] [#4119](https://github.com/rust-lang/rust-clippy/pull/4119)
 +* Improve diagnostics for [`let_and_return`] [#4137](https://github.com/rust-lang/rust-clippy/pull/4137)
 +* Improve diagnostics for [`trivially_copy_pass_by_ref`] [#4071](https://github.com/rust-lang/rust-clippy/pull/4071)
 +* Add macro check for [`unreadable_literal`] [#4099](https://github.com/rust-lang/rust-clippy/pull/4099)
 +
 +## Rust 1.36
 +
 +Released 2019-07-04
 +
 +[eb9f9b1...082cfa7](https://github.com/rust-lang/rust-clippy/compare/eb9f9b1...082cfa7)
 +
 +* New lints: [`find_map`], [`filter_map_next`] [#4039](https://github.com/rust-lang/rust-clippy/pull/4039)
 +* New lint: [`path_buf_push_overwrite`] [#3954](https://github.com/rust-lang/rust-clippy/pull/3954)
 +* Move `path_buf_push_overwrite` to the nursery [#4013](https://github.com/rust-lang/rust-clippy/pull/4013)
 +* Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101)
 +* Allow allowing of [`toplevel_ref_arg`] lint [#4007](https://github.com/rust-lang/rust-clippy/pull/4007)
 +* Fix false negative in [`or_fun_call`] pertaining to nested constructors [#4084](https://github.com/rust-lang/rust-clippy/pull/4084)
 +* Fix false positive in [`or_fun_call`] pertaining to enum variant constructors [#4018](https://github.com/rust-lang/rust-clippy/pull/4018)
 +* Fix false positive in [`useless_let_if_seq`] pertaining to interior mutability [#4035](https://github.com/rust-lang/rust-clippy/pull/4035)
 +* Fix false positive in [`redundant_closure`] pertaining to non-function types [#4008](https://github.com/rust-lang/rust-clippy/pull/4008)
 +* Fix false positive in [`let_and_return`] pertaining to attributes on `let`s [#4024](https://github.com/rust-lang/rust-clippy/pull/4024)
 +* Fix false positive in [`module_name_repetitions`] lint pertaining to attributes [#4006](https://github.com/rust-lang/rust-clippy/pull/4006)
 +* Fix false positive on [`assertions_on_constants`] pertaining to `debug_assert!` [#3989](https://github.com/rust-lang/rust-clippy/pull/3989)
 +* Improve suggestion in [`map_clone`] to suggest `.copied()` where applicable  [#3970](https://github.com/rust-lang/rust-clippy/pull/3970) [#4043](https://github.com/rust-lang/rust-clippy/pull/4043)
 +* Improve suggestion for [`search_is_some`] [#4049](https://github.com/rust-lang/rust-clippy/pull/4049)
 +* Improve suggestion applicability for [`naive_bytecount`] [#3984](https://github.com/rust-lang/rust-clippy/pull/3984)
 +* Improve suggestion applicability for [`while_let_loop`] [#3975](https://github.com/rust-lang/rust-clippy/pull/3975)
 +* Improve diagnostics for [`too_many_arguments`] [#4053](https://github.com/rust-lang/rust-clippy/pull/4053)
 +* Improve diagnostics for [`cast_lossless`] [#4021](https://github.com/rust-lang/rust-clippy/pull/4021)
 +* Deal with macro checks in desugarings better [#4082](https://github.com/rust-lang/rust-clippy/pull/4082)
 +* Add macro check for [`unnecessary_cast`]  [#4026](https://github.com/rust-lang/rust-clippy/pull/4026)
 +* Remove [`approx_constant`]'s documentation's "Known problems" section. [#4027](https://github.com/rust-lang/rust-clippy/pull/4027)
 +* Fix ICE in [`suspicious_else_formatting`] [#3960](https://github.com/rust-lang/rust-clippy/pull/3960)
 +* Fix ICE in [`decimal_literal_representation`] [#3931](https://github.com/rust-lang/rust-clippy/pull/3931)
 +
 +
 +## Rust 1.35
 +
 +Released 2019-05-20
 +
 +[1fac380..37f5c1e](https://github.com/rust-lang/rust-clippy/compare/1fac380...37f5c1e)
 +
 +* New lint: `drop_bounds` to detect `T: Drop` bounds
 +* Split [`redundant_closure`] into [`redundant_closure`] and [`redundant_closure_for_method_calls`] [#4110](https://github.com/rust-lang/rust-clippy/pull/4101)
 +* Rename `cyclomatic_complexity` to [`cognitive_complexity`], start work on making lint more practical for Rust code
 +* Move [`get_unwrap`] to the restriction category
 +* Improve suggestions for [`iter_cloned_collect`]
 +* Improve suggestions for [`cast_lossless`] to suggest suffixed literals
 +* Fix false positives in [`print_with_newline`] and [`write_with_newline`] pertaining to raw strings
 +* Fix false positive in [`needless_range_loop`] pertaining to structs without a `.iter()`
 +* Fix false positive in [`bool_comparison`] pertaining to non-bool types
 +* Fix false positive in [`redundant_closure`] pertaining to differences in borrows
 +* Fix false positive in `option_map_unwrap_or` on non-copy types
 +* Fix false positives in [`missing_const_for_fn`] pertaining to macros and trait method impls
 +* Fix false positive in [`needless_pass_by_value`] pertaining to procedural macros
 +* Fix false positive in [`needless_continue`] pertaining to loop labels
 +* Fix false positive for [`boxed_local`] pertaining to arguments moved into closures
 +* Fix false positive for [`use_self`] in nested functions
 +* Fix suggestion for [`expect_fun_call`] (https://github.com/rust-lang/rust-clippy/pull/3846)
 +* Fix suggestion for [`explicit_counter_loop`] to deal with parenthesizing range variables
 +* Fix suggestion for [`single_char_pattern`] to correctly escape single quotes
 +* Avoid triggering [`redundant_closure`] in macros
 +* ICE fixes: [#3805](https://github.com/rust-lang/rust-clippy/pull/3805), [#3772](https://github.com/rust-lang/rust-clippy/pull/3772), [#3741](https://github.com/rust-lang/rust-clippy/pull/3741)
 +
 +## Rust 1.34
 +
 +Released 2019-04-10
 +
 +[1b89724...1fac380](https://github.com/rust-lang/rust-clippy/compare/1b89724...1fac380)
 +
 +* New lint: [`assertions_on_constants`] to detect for example `assert!(true)`
 +* New lint: [`dbg_macro`] to detect uses of the `dbg!` macro
 +* New lint: [`missing_const_for_fn`] that can suggest functions to be made `const`
 +* New lint: [`too_many_lines`] to detect functions with excessive LOC. It can be
 +  configured using the `too-many-lines-threshold` configuration.
 +* New lint: [`wildcard_enum_match_arm`] to check for wildcard enum matches using `_`
 +* Expand `redundant_closure` to also work for methods (not only functions)
 +* Fix ICEs in `vec_box`, `needless_pass_by_value` and `implicit_hasher`
 +* Fix false positive in `cast_sign_loss`
 +* Fix false positive in `integer_arithmetic`
 +* Fix false positive in `unit_arg`
 +* Fix false positives in `implicit_return`
 +* Add suggestion to `explicit_write`
 +* Improve suggestions for `question_mark` lint
 +* Fix incorrect suggestion for `cast_lossless`
 +* Fix incorrect suggestion for `expect_fun_call`
 +* Fix incorrect suggestion for `needless_bool`
 +* Fix incorrect suggestion for `needless_range_loop`
 +* Fix incorrect suggestion for `use_self`
 +* Fix incorrect suggestion for `while_let_on_iterator`
 +* Clippy is now slightly easier to invoke in non-cargo contexts. See
 +  [#3665][pull3665] for more details.
 +* We now have [improved documentation][adding_lints] on how to add new lints
 +
 +## Rust 1.33
 +
 +Released 2019-02-26
 +
 +[b2601be...1b89724](https://github.com/rust-lang/rust-clippy/compare/b2601be...1b89724)
 +
 +* New lints: [`implicit_return`], [`vec_box`], [`cast_ref_to_mut`]
 +* The `rust-clippy` repository is now part of the `rust-lang` org.
 +* Rename `stutter` to `module_name_repetitions`
 +* Merge `new_without_default_derive` into `new_without_default` lint
 +* Move `large_digit_groups` from `style` group to `pedantic`
 +* Expand `bool_comparison` to check for `<`, `<=`, `>`, `>=`, and `!=`
 +  comparisons against booleans
 +* Expand `no_effect` to detect writes to constants such as `A_CONST.field = 2`
 +* Expand `redundant_clone` to work on struct fields
 +* Expand `suspicious_else_formatting` to detect `if .. {..} {..}`
 +* Expand `use_self` to work on tuple structs and also in local macros
 +* Fix ICE in `result_map_unit_fn` and `option_map_unit_fn`
 +* Fix false positives in `implicit_return`
 +* Fix false positives in `use_self`
 +* Fix false negative in `clone_on_copy`
 +* Fix false positive in `doc_markdown`
 +* Fix false positive in `empty_loop`
 +* Fix false positive in `if_same_then_else`
 +* Fix false positive in `infinite_iter`
 +* Fix false positive in `question_mark`
 +* Fix false positive in `useless_asref`
 +* Fix false positive in `wildcard_dependencies`
 +* Fix false positive in `write_with_newline`
 +* Add suggestion to `explicit_write`
 +* Improve suggestions for `question_mark` lint
 +* Fix incorrect suggestion for `get_unwrap`
 +
 +## Rust 1.32
 +
 +Released 2019-01-17
 +
 +[2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be)
 +
 +* New lints: [`slow_vector_initialization`], `mem_discriminant_non_enum`,
 +  [`redundant_clone`], [`wildcard_dependencies`],
 +  [`into_iter_on_ref`], `into_iter_on_array`, [`deprecated_cfg_attr`],
 +  [`cargo_common_metadata`]
 +* Add support for `u128` and `i128` to integer related lints
 +* Add float support to `mistyped_literal_suffixes`
 +* Fix false positives in `use_self`
 +* Fix false positives in `missing_comma`
 +* Fix false positives in `new_ret_no_self`
 +* Fix false positives in `possible_missing_comma`
 +* Fix false positive in `integer_arithmetic` in constant items
 +* Fix false positive in `needless_borrow`
 +* Fix false positive in `out_of_bounds_indexing`
 +* Fix false positive in `new_without_default_derive`
 +* Fix false positive in `string_lit_as_bytes`
 +* Fix false negative in `out_of_bounds_indexing`
 +* Fix false negative in `use_self`. It will now also check existential types
 +* Fix incorrect suggestion for `redundant_closure_call`
 +* Fix various suggestions that contained expanded macros
 +* Fix `bool_comparison` triggering 3 times on on on the same code
 +* Expand `trivially_copy_pass_by_ref` to work on trait methods
 +* Improve suggestion for `needless_range_loop`
 +* Move `needless_pass_by_value` from `pedantic` group to `style`
 +
 +## Rust 1.31
 +
 +Released 2018-12-06
 +
 +[125907ad..2e26fdc2](https://github.com/rust-lang/rust-clippy/compare/125907ad..2e26fdc2)
 +
 +* Clippy has been relicensed under a dual MIT / Apache license.
 +  See [#3093](https://github.com/rust-lang/rust-clippy/issues/3093) for more
 +  information.
 +* With Rust 1.31, Clippy is no longer available via crates.io. The recommended
 +  installation method is via `rustup component add clippy`.
 +* New lints: [`redundant_pattern_matching`], [`unnecessary_filter_map`],
 +  [`unused_unit`], [`map_flatten`], [`mem_replace_option_with_none`]
 +* Fix ICE in `if_let_redundant_pattern_matching`
 +* Fix ICE in `needless_pass_by_value` when encountering a generic function
 +  argument with a lifetime parameter
 +* Fix ICE in `needless_range_loop`
 +* Fix ICE in `single_char_pattern` when encountering a constant value
 +* Fix false positive in `assign_op_pattern`
 +* Fix false positive in `boxed_local` on trait implementations
 +* Fix false positive in `cmp_owned`
 +* Fix false positive in `collapsible_if` when conditionals have comments
 +* Fix false positive in `double_parens`
 +* Fix false positive in `excessive_precision`
 +* Fix false positive in `explicit_counter_loop`
 +* Fix false positive in `fn_to_numeric_cast_with_truncation`
 +* Fix false positive in `map_clone`
 +* Fix false positive in `new_ret_no_self`
 +* Fix false positive in `new_without_default` when `new` is unsafe
 +* Fix false positive in `type_complexity` when using extern types
 +* Fix false positive in `useless_format`
 +* Fix false positive in `wrong_self_convention`
 +* Fix incorrect suggestion for `excessive_precision`
 +* Fix incorrect suggestion for `expect_fun_call`
 +* Fix incorrect suggestion for `get_unwrap`
 +* Fix incorrect suggestion for `useless_format`
 +* `fn_to_numeric_cast_with_truncation` lint can be disabled again
 +* Improve suggestions for `manual_memcpy`
 +* Improve help message for `needless_lifetimes`
 +
 +## Rust 1.30
 +
 +Released 2018-10-25
 +
 +[14207503...125907ad](https://github.com/rust-lang/rust-clippy/compare/14207503...125907ad)
 +
 +* Deprecate `assign_ops` lint
 +* New lints: [`mistyped_literal_suffixes`], [`ptr_offset_with_cast`],
 +  [`needless_collect`], [`copy_iterator`]
 +* `cargo clippy -V` now includes the Clippy commit hash of the Rust
 +  Clippy component
 +* Fix ICE in `implicit_hasher`
 +* Fix ICE when encountering `println!("{}" a);`
 +* Fix ICE when encountering a macro call in match statements
 +* Fix false positive in `default_trait_access`
 +* Fix false positive in `trivially_copy_pass_by_ref`
 +* Fix false positive in `similar_names`
 +* Fix false positive in `redundant_field_name`
 +* Fix false positive in `expect_fun_call`
 +* Fix false negative in `identity_conversion`
 +* Fix false negative in `explicit_counter_loop`
 +* Fix `range_plus_one` suggestion and false negative
 +* `print_with_newline` / `write_with_newline`: don't warn about string with several `\n`s in them
 +* Fix `useless_attribute` to also whitelist `unused_extern_crates`
 +* Fix incorrect suggestion for `single_char_pattern`
 +* Improve suggestion for `identity_conversion` lint
 +* Move `explicit_iter_loop` and `explicit_into_iter_loop` from `style` group to `pedantic`
 +* Move `range_plus_one` and `range_minus_one` from `nursery` group to `complexity`
 +* Move `shadow_unrelated` from `restriction` group to `pedantic`
 +* Move `indexing_slicing` from `pedantic` group to `restriction`
 +
 +## Rust 1.29
 +
 +Released 2018-09-13
 +
 +[v0.0.212...14207503](https://github.com/rust-lang/rust-clippy/compare/v0.0.212...14207503)
 +
 +* :tada: :tada: **Rust 1.29 is the first stable Rust that includes a bundled Clippy** :tada:
 +  :tada:
 +  You can now run `rustup component add clippy-preview` and then `cargo
 +  clippy` to run Clippy. This should put an end to the continuous nightly
 +  upgrades for Clippy users.
 +* Clippy now follows the Rust versioning scheme instead of its own
 +* Fix ICE when encountering a `while let (..) = x.iter()` construct
 +* Fix false positives in `use_self`
 +* Fix false positive in `trivially_copy_pass_by_ref`
 +* Fix false positive in `useless_attribute` lint
 +* Fix false positive in `print_literal`
 +* Fix `use_self` regressions
 +* Improve lint message for `neg_cmp_op_on_partial_ord`
 +* Improve suggestion highlight for `single_char_pattern`
 +* Improve suggestions for various print/write macro lints
 +* Improve website header
 +
 +## 0.0.212 (2018-07-10)
 +* Rustup to *rustc 1.29.0-nightly (e06c87544 2018-07-06)*
 +
 +## 0.0.211
 +* Rustup to *rustc 1.28.0-nightly (e3bf634e0 2018-06-28)*
 +
 +## 0.0.210
 +* Rustup to *rustc 1.28.0-nightly (01cc982e9 2018-06-24)*
 +
 +## 0.0.209
 +* Rustup to *rustc 1.28.0-nightly (523097979 2018-06-18)*
 +
 +## 0.0.208
 +* Rustup to *rustc 1.28.0-nightly (86a8f1a63 2018-06-17)*
 +
 +## 0.0.207
 +* Rustup to *rustc 1.28.0-nightly (2a0062974 2018-06-09)*
 +
 +## 0.0.206
 +* Rustup to *rustc 1.28.0-nightly (5bf68db6e 2018-05-28)*
 +
 +## 0.0.205
 +* Rustup to *rustc 1.28.0-nightly (990d8aa74 2018-05-25)*
 +* Rename `unused_lifetimes` to `extra_unused_lifetimes` because of naming conflict with new rustc lint
 +
 +## 0.0.204
 +* Rustup to *rustc 1.28.0-nightly (71e87be38 2018-05-22)*
 +
 +## 0.0.203
 +* Rustup to *rustc 1.28.0-nightly (a3085756e 2018-05-19)*
 +* Clippy attributes are now of the form `clippy::cyclomatic_complexity` instead of `clippy(cyclomatic_complexity)`
 +
 +## 0.0.202
 +* Rustup to *rustc 1.28.0-nightly (952f344cd 2018-05-18)*
 +
 +## 0.0.201
 +* Rustup to *rustc 1.27.0-nightly (2f2a11dfc 2018-05-16)*
 +
 +## 0.0.200
 +* Rustup to *rustc 1.27.0-nightly (9fae15374 2018-05-13)*
 +
 +## 0.0.199
 +* Rustup to *rustc 1.27.0-nightly (ff2ac35db 2018-05-12)*
 +
 +## 0.0.198
 +* Rustup to *rustc 1.27.0-nightly (acd3871ba 2018-05-10)*
 +
 +## 0.0.197
 +* Rustup to *rustc 1.27.0-nightly (428ea5f6b 2018-05-06)*
 +
 +## 0.0.196
 +* Rustup to *rustc 1.27.0-nightly (e82261dfb 2018-05-03)*
 +
 +## 0.0.195
 +* Rustup to *rustc 1.27.0-nightly (ac3c2288f 2018-04-18)*
 +
 +## 0.0.194
 +* Rustup to *rustc 1.27.0-nightly (bd40cbbe1 2018-04-14)*
 +* New lints: [`cast_ptr_alignment`], [`transmute_ptr_to_ptr`], [`write_literal`], [`write_with_newline`], [`writeln_empty_string`]
 +
 +## 0.0.193
 +* Rustup to *rustc 1.27.0-nightly (eeea94c11 2018-04-06)*
 +
 +## 0.0.192
 +* Rustup to *rustc 1.27.0-nightly (fb44b4c0e 2018-04-04)*
 +* New lint: [`print_literal`]
 +
 +## 0.0.191
 +* Rustup to *rustc 1.26.0-nightly (ae544ee1c 2018-03-29)*
 +* Lint audit; categorize lints as style, correctness, complexity, pedantic, nursery, restriction.
 +
 +## 0.0.190
 +* Fix a bunch of intermittent cargo bugs
 +
 +## 0.0.189
 +* Rustup to *rustc 1.26.0-nightly (5508b2714 2018-03-18)*
 +
 +## 0.0.188
 +* Rustup to *rustc 1.26.0-nightly (392645394 2018-03-15)*
 +* New lint: [`while_immutable_condition`]
 +
 +## 0.0.187
 +* Rustup to *rustc 1.26.0-nightly (322d7f7b9 2018-02-25)*
 +* New lints: [`redundant_field_names`], [`suspicious_arithmetic_impl`], [`suspicious_op_assign_impl`]
 +
 +## 0.0.186
 +* Rustup to *rustc 1.25.0-nightly (0c6091fbd 2018-02-04)*
 +* Various false positive fixes
 +
 +## 0.0.185
 +* Rustup to *rustc 1.25.0-nightly (56733bc9f 2018-02-01)*
 +* New lint: [`question_mark`]
 +
 +## 0.0.184
 +* Rustup to *rustc 1.25.0-nightly (90eb44a58 2018-01-29)*
 +* New lints: [`double_comparisons`], [`empty_line_after_outer_attr`]
 +
 +## 0.0.183
 +* Rustup to *rustc 1.25.0-nightly (21882aad7 2018-01-28)*
 +* New lint: [`misaligned_transmute`]
 +
 +## 0.0.182
 +* Rustup to *rustc 1.25.0-nightly (a0dcecff9 2018-01-24)*
 +* New lint: [`decimal_literal_representation`]
 +
 +## 0.0.181
 +* Rustup to *rustc 1.25.0-nightly (97520ccb1 2018-01-21)*
 +* New lints: [`else_if_without_else`], [`option_option`], [`unit_arg`], [`unnecessary_fold`]
 +* Removed `unit_expr`
 +* Various false positive fixes for [`needless_pass_by_value`]
 +
 +## 0.0.180
 +* Rustup to *rustc 1.25.0-nightly (3f92e8d89 2018-01-14)*
 +
 +## 0.0.179
 +* Rustup to *rustc 1.25.0-nightly (61452e506 2018-01-09)*
 +
 +## 0.0.178
 +* Rustup to *rustc 1.25.0-nightly (ee220daca 2018-01-07)*
 +
 +## 0.0.177
 +* Rustup to *rustc 1.24.0-nightly (250b49205 2017-12-21)*
 +* New lint: [`match_as_ref`]
 +
 +## 0.0.176
 +* Rustup to *rustc 1.24.0-nightly (0077d128d 2017-12-14)*
 +
 +## 0.0.175
 +* Rustup to *rustc 1.24.0-nightly (bb42071f6 2017-12-01)*
 +
 +## 0.0.174
 +* Rustup to *rustc 1.23.0-nightly (63739ab7b 2017-11-21)*
 +
 +## 0.0.173
 +* Rustup to *rustc 1.23.0-nightly (33374fa9d 2017-11-20)*
 +
 +## 0.0.172
 +* Rustup to *rustc 1.23.0-nightly (d0f8e2913 2017-11-16)*
 +
 +## 0.0.171
 +* Rustup to *rustc 1.23.0-nightly (ff0f5de3b 2017-11-14)*
 +
 +## 0.0.170
 +* Rustup to *rustc 1.23.0-nightly (d6b06c63a 2017-11-09)*
 +
 +## 0.0.169
 +* Rustup to *rustc 1.23.0-nightly (3b82e4c74 2017-11-05)*
 +* New lints: [`just_underscores_and_digits`], `result_map_unwrap_or_else`, [`transmute_bytes_to_str`]
 +
 +## 0.0.168
 +* Rustup to *rustc 1.23.0-nightly (f0fe716db 2017-10-30)*
 +
 +## 0.0.167
 +* Rustup to *rustc 1.23.0-nightly (90ef3372e 2017-10-29)*
 +* New lints: `const_static_lifetime`, [`erasing_op`], [`fallible_impl_from`], [`println_empty_string`], [`useless_asref`]
 +
 +## 0.0.166
 +* Rustup to *rustc 1.22.0-nightly (b7960878b 2017-10-18)*
 +* New lints: [`explicit_write`], `identity_conversion`, [`implicit_hasher`], `invalid_ref`, [`option_map_or_none`],
 +  [`range_minus_one`], [`range_plus_one`], [`transmute_int_to_bool`], [`transmute_int_to_char`],
 +  [`transmute_int_to_float`]
 +
 +## 0.0.165
 +* Rust upgrade to rustc 1.22.0-nightly (0e6f4cf51 2017-09-27)
 +* New lint: [`mut_range_bound`]
 +
 +## 0.0.164
 +* Update to *rustc 1.22.0-nightly (6c476ce46 2017-09-25)*
 +* New lint: [`int_plus_one`]
 +
 +## 0.0.163
 +* Update to *rustc 1.22.0-nightly (14039a42a 2017-09-22)*
 +
 +## 0.0.162
 +* Update to *rustc 1.22.0-nightly (0701b37d9 2017-09-18)*
 +* New lint: [`chars_last_cmp`]
 +* Improved suggestions for [`needless_borrow`], [`ptr_arg`],
 +
 +## 0.0.161
 +* Update to *rustc 1.22.0-nightly (539f2083d 2017-09-13)*
 +
 +## 0.0.160
 +* Update to *rustc 1.22.0-nightly (dd08c3070 2017-09-12)*
 +
 +## 0.0.159
 +* Update to *rustc 1.22.0-nightly (eba374fb2 2017-09-11)*
 +* New lint: [`clone_on_ref_ptr`]
 +
 +## 0.0.158
 +* New lint: [`manual_memcpy`]
 +* [`cast_lossless`] no longer has redundant parentheses in its suggestions
 +* Update to *rustc 1.22.0-nightly (dead08cb3 2017-09-08)*
 +
 +## 0.0.157 - 2017-09-04
 +* Update to *rustc 1.22.0-nightly (981ce7d8d 2017-09-03)*
 +* New lint: `unit_expr`
 +
 +## 0.0.156 - 2017-09-03
 +* Update to *rustc 1.22.0-nightly (744dd6c1d 2017-09-02)*
 +
 +## 0.0.155
 +* Update to *rustc 1.21.0-nightly (c11f689d2 2017-08-29)*
 +* New lint: [`infinite_iter`], [`maybe_infinite_iter`], [`cast_lossless`]
 +
 +## 0.0.154
 +* Update to *rustc 1.21.0-nightly (2c0558f63 2017-08-24)*
 +* Fix [`use_self`] triggering inside derives
 +* Add support for linting an entire workspace with `cargo clippy --all`
 +* New lint: [`naive_bytecount`]
 +
 +## 0.0.153
 +* Update to *rustc 1.21.0-nightly (8c303ed87 2017-08-20)*
 +* New lint: [`use_self`]
 +
 +## 0.0.152
 +* Update to *rustc 1.21.0-nightly (df511d554 2017-08-14)*
 +
 +## 0.0.151
 +* Update to *rustc 1.21.0-nightly (13d94d5fa 2017-08-10)*
 +
 +## 0.0.150
 +* Update to *rustc 1.21.0-nightly (215e0b10e 2017-08-08)*
 +
 +## 0.0.148
 +* Update to *rustc 1.21.0-nightly (37c7d0ebb 2017-07-31)*
 +* New lints: [`unreadable_literal`], [`inconsistent_digit_grouping`], [`large_digit_groups`]
 +
 +## 0.0.147
 +* Update to *rustc 1.21.0-nightly (aac223f4f 2017-07-30)*
 +
 +## 0.0.146
 +* Update to *rustc 1.21.0-nightly (52a330969 2017-07-27)*
 +* Fixes false positives in `inline_always`
 +* Fixes false negatives in `panic_params`
 +
 +## 0.0.145
 +* Update to *rustc 1.20.0-nightly (afe145d22 2017-07-23)*
 +
 +## 0.0.144
 +* Update to *rustc 1.20.0-nightly (086eaa78e 2017-07-15)*
 +
 +## 0.0.143
 +* Update to *rustc 1.20.0-nightly (d84693b93 2017-07-09)*
 +* Fix `cargo clippy` crashing on `dylib` projects
 +* Fix false positives around `nested_while_let` and `never_loop`
 +
 +## 0.0.142
 +* Update to *rustc 1.20.0-nightly (067971139 2017-07-02)*
 +
 +## 0.0.141
 +* Rewrite of the `doc_markdown` lint.
 +* Deprecated [`range_step_by_zero`]
 +* New lint: [`iterator_step_by_zero`]
 +* New lint: [`needless_borrowed_reference`]
 +* Update to *rustc 1.20.0-nightly (69c65d296 2017-06-28)*
 +
 +## 0.0.140 - 2017-06-16
 +* Update to *rustc 1.19.0-nightly (258ae6dd9 2017-06-15)*
 +
 +## 0.0.139 — 2017-06-10
 +* Update to *rustc 1.19.0-nightly (4bf5c99af 2017-06-10)*
 +* Fix bugs with for loop desugaring
 +* Check for [`AsRef`]/[`AsMut`] arguments in [`wrong_self_convention`]
 +
 +## 0.0.138 — 2017-06-05
 +* Update to *rustc 1.19.0-nightly (0418fa9d3 2017-06-04)*
 +
 +## 0.0.137 — 2017-06-05
 +* Update to *rustc 1.19.0-nightly (6684d176c 2017-06-03)*
 +
 +## 0.0.136 — 2017—05—26
 +* Update to *rustc 1.19.0-nightly (557967766 2017-05-26)*
 +
 +## 0.0.135 — 2017—05—24
 +* Update to *rustc 1.19.0-nightly (5b13bff52 2017-05-23)*
 +
 +## 0.0.134 — 2017—05—19
 +* Update to *rustc 1.19.0-nightly (0ed1ec9f9 2017-05-18)*
 +
 +## 0.0.133 — 2017—05—14
 +* Update to *rustc 1.19.0-nightly (826d8f385 2017-05-13)*
 +
 +## 0.0.132 — 2017—05—05
 +* Fix various bugs and some ices
 +
 +## 0.0.131 — 2017—05—04
 +* Update to *rustc 1.19.0-nightly (2d4ed8e0c 2017-05-03)*
 +
 +## 0.0.130 — 2017—05—03
 +* Update to *rustc 1.19.0-nightly (6a5fc9eec 2017-05-02)*
 +
 +## 0.0.129 — 2017-05-01
 +* Update to *rustc 1.19.0-nightly (06fb4d256 2017-04-30)*
 +
 +## 0.0.128 — 2017-04-28
 +* Update to *rustc 1.18.0-nightly (94e884b63 2017-04-27)*
 +
 +## 0.0.127 — 2017-04-27
 +* Update to *rustc 1.18.0-nightly (036983201 2017-04-26)*
 +* New lint: [`needless_continue`]
 +
 +## 0.0.126 — 2017-04-24
 +* Update to *rustc 1.18.0-nightly (2bd4b5c6d 2017-04-23)*
 +
 +## 0.0.125 — 2017-04-19
 +* Update to *rustc 1.18.0-nightly (9f2abadca 2017-04-18)*
 +
 +## 0.0.124 — 2017-04-16
 +* Update to *rustc 1.18.0-nightly (d5cf1cb64 2017-04-15)*
 +
 +## 0.0.123 — 2017-04-07
 +* Fix various false positives
 +
 +## 0.0.122 — 2017-04-07
 +* Rustup to *rustc 1.18.0-nightly (91ae22a01 2017-04-05)*
 +* New lint: [`op_ref`]
 +
 +## 0.0.121 — 2017-03-21
 +* Rustup to *rustc 1.17.0-nightly (134c4a0f0 2017-03-20)*
 +
 +## 0.0.120 — 2017-03-17
 +* Rustup to *rustc 1.17.0-nightly (0aeb9c129 2017-03-15)*
 +
 +## 0.0.119 — 2017-03-13
 +* Rustup to *rustc 1.17.0-nightly (824c9ebbd 2017-03-12)*
 +
 +## 0.0.118 — 2017-03-05
 +* Rustup to *rustc 1.17.0-nightly (b1e31766d 2017-03-03)*
 +
 +## 0.0.117 — 2017-03-01
 +* Rustup to *rustc 1.17.0-nightly (be760566c 2017-02-28)*
 +
 +## 0.0.116 — 2017-02-28
 +* Fix `cargo clippy` on 64 bit windows systems
 +
 +## 0.0.115 — 2017-02-27
 +* Rustup to *rustc 1.17.0-nightly (60a0edc6c 2017-02-26)*
 +* New lints: [`zero_ptr`], [`never_loop`], [`mut_from_ref`]
 +
 +## 0.0.114 — 2017-02-08
 +* Rustup to *rustc 1.17.0-nightly (c49d10207 2017-02-07)*
 +* Tests are now ui tests (testing the exact output of rustc)
 +
 +## 0.0.113 — 2017-02-04
 +* Rustup to *rustc 1.16.0-nightly (eedaa94e3 2017-02-02)*
 +* New lint: [`large_enum_variant`]
 +* `explicit_into_iter_loop` provides suggestions
 +
 +## 0.0.112 — 2017-01-27
 +* Rustup to *rustc 1.16.0-nightly (df8debf6d 2017-01-25)*
 +
 +## 0.0.111 — 2017-01-21
 +* Rustup to *rustc 1.16.0-nightly (a52da95ce 2017-01-20)*
 +
 +## 0.0.110 — 2017-01-20
 +* Add badges and categories to `Cargo.toml`
 +
 +## 0.0.109 — 2017-01-19
 +* Update to *rustc 1.16.0-nightly (c07a6ae77 2017-01-17)*
 +
 +## 0.0.108 — 2017-01-12
 +* Update to *rustc 1.16.0-nightly (2782e8f8f 2017-01-12)*
 +
 +## 0.0.107 — 2017-01-11
 +* Update regex dependency
 +* Fix FP when matching `&&mut` by `&ref`
 +* Reintroduce `for (_, x) in &mut hash_map` -> `for x in hash_map.values_mut()`
 +* New lints: [`unused_io_amount`], [`forget_ref`], [`short_circuit_statement`]
 +
 +## 0.0.106 — 2017-01-04
 +* Fix FP introduced by rustup in [`wrong_self_convention`]
 +
 +## 0.0.105 — 2017-01-04
 +* Update to *rustc 1.16.0-nightly (468227129 2017-01-03)*
 +* New lints: [`deref_addrof`], [`double_parens`], [`pub_enum_variant_names`]
 +* Fix suggestion in [`new_without_default`]
 +* FP fix in [`absurd_extreme_comparisons`]
 +
 +## 0.0.104 — 2016-12-15
 +* Update to *rustc 1.15.0-nightly (8f02c429a 2016-12-15)*
 +
 +## 0.0.103 — 2016-11-25
 +* Update to *rustc 1.15.0-nightly (d5814b03e 2016-11-23)*
 +
 +## 0.0.102 — 2016-11-24
 +* Update to *rustc 1.15.0-nightly (3bf2be9ce 2016-11-22)*
 +
 +## 0.0.101 — 2016-11-23
 +* Update to *rustc 1.15.0-nightly (7b3eeea22 2016-11-21)*
 +* New lint: [`string_extend_chars`]
 +
 +## 0.0.100 — 2016-11-20
 +* Update to *rustc 1.15.0-nightly (ac635aa95 2016-11-18)*
 +
 +## 0.0.99 — 2016-11-18
 +* Update to rustc 1.15.0-nightly (0ed951993 2016-11-14)
 +* New lint: [`get_unwrap`]
 +
 +## 0.0.98 — 2016-11-08
 +* Fixes an issue due to a change in how cargo handles `--sysroot`, which broke `cargo clippy`
 +
 +## 0.0.97 — 2016-11-03
 +* For convenience, `cargo clippy` defines a `cargo-clippy` feature. This was
 +  previously added for a short time under the name `clippy` but removed for
 +  compatibility.
 +* `cargo clippy --help` is more helping (and less helpful :smile:)
 +* Rustup to *rustc 1.14.0-nightly (5665bdf3e 2016-11-02)*
 +* New lints: [`if_let_redundant_pattern_matching`], [`partialeq_ne_impl`]
 +
 +## 0.0.96 — 2016-10-22
 +* Rustup to *rustc 1.14.0-nightly (f09420685 2016-10-20)*
 +* New lint: [`iter_skip_next`]
 +
 +## 0.0.95 — 2016-10-06
 +* Rustup to *rustc 1.14.0-nightly (3210fd5c2 2016-10-05)*
 +
 +## 0.0.94 — 2016-10-04
 +* Fixes bustage on Windows due to forbidden directory name
 +
 +## 0.0.93 — 2016-10-03
 +* Rustup to *rustc 1.14.0-nightly (144af3e97 2016-10-02)*
 +* `option_map_unwrap_or` and `option_map_unwrap_or_else` are now
 +  allowed by default.
 +* New lint: [`explicit_into_iter_loop`]
 +
 +## 0.0.92 — 2016-09-30
 +* Rustup to *rustc 1.14.0-nightly (289f3a4ca 2016-09-29)*
 +
 +## 0.0.91 — 2016-09-28
 +* Rustup to *rustc 1.13.0-nightly (d0623cf7b 2016-09-26)*
 +
 +## 0.0.90 — 2016-09-09
 +* Rustup to *rustc 1.13.0-nightly (f1f40f850 2016-09-09)*
 +
 +## 0.0.89 — 2016-09-06
 +* Rustup to *rustc 1.13.0-nightly (cbe4de78e 2016-09-05)*
 +
 +## 0.0.88 — 2016-09-04
 +* Rustup to *rustc 1.13.0-nightly (70598e04f 2016-09-03)*
 +* The following lints are not new but were only usable through the `clippy`
 +  lint groups: [`filter_next`], `for_loop_over_option`,
 +  `for_loop_over_result` and [`match_overlapping_arm`]. You should now be
 +  able to `#[allow/deny]` them individually and they are available directly
 +  through `cargo clippy`.
 +
 +## 0.0.87 — 2016-08-31
 +* Rustup to *rustc 1.13.0-nightly (eac41469d 2016-08-30)*
 +* New lints: [`builtin_type_shadow`]
 +* Fix FP in [`zero_prefixed_literal`] and `0b`/`0o`
 +
 +## 0.0.86 — 2016-08-28
 +* Rustup to *rustc 1.13.0-nightly (a23064af5 2016-08-27)*
 +* New lints: [`missing_docs_in_private_items`], [`zero_prefixed_literal`]
 +
 +## 0.0.85 — 2016-08-19
 +* Fix ICE with [`useless_attribute`]
 +* [`useless_attribute`] ignores `unused_imports` on `use` statements
 +
 +## 0.0.84 — 2016-08-18
 +* Rustup to *rustc 1.13.0-nightly (aef6971ca 2016-08-17)*
 +
 +## 0.0.83 — 2016-08-17
 +* Rustup to *rustc 1.12.0-nightly (1bf5fa326 2016-08-16)*
 +* New lints: [`print_with_newline`], [`useless_attribute`]
 +
 +## 0.0.82 — 2016-08-17
 +* Rustup to *rustc 1.12.0-nightly (197be89f3 2016-08-15)*
 +* New lint: [`module_inception`]
 +
 +## 0.0.81 — 2016-08-14
 +* Rustup to *rustc 1.12.0-nightly (1deb02ea6 2016-08-12)*
 +* New lints: [`eval_order_dependence`], [`mixed_case_hex_literals`], [`unseparated_literal_suffix`]
 +* False positive fix in [`too_many_arguments`]
 +* Addition of functionality to [`needless_borrow`]
 +* Suggestions for [`clone_on_copy`]
 +* Bug fix in [`wrong_self_convention`]
 +* Doc improvements
 +
 +## 0.0.80 — 2016-07-31
 +* Rustup to *rustc 1.12.0-nightly (1225e122f 2016-07-30)*
 +* New lints: [`misrefactored_assign_op`], [`serde_api_misuse`]
 +
 +## 0.0.79 — 2016-07-10
 +* Rustup to *rustc 1.12.0-nightly (f93aaf84c 2016-07-09)*
 +* Major suggestions refactoring
 +
 +## 0.0.78 — 2016-07-02
 +* Rustup to *rustc 1.11.0-nightly (01411937f 2016-07-01)*
 +* New lints: [`wrong_transmute`], [`double_neg`], [`filter_map`]
 +* For compatibility, `cargo clippy` does not defines the `clippy` feature
 +  introduced in 0.0.76 anymore
 +* [`collapsible_if`] now considers `if let`
 +
 +## 0.0.77 — 2016-06-21
 +* Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)*
 +* New lints: `stutter` and [`iter_nth`]
 +
 +## 0.0.76 — 2016-06-10
 +* Rustup to *rustc 1.11.0-nightly (7d2f75a95 2016-06-09)*
 +* `cargo clippy` now automatically defines the `clippy` feature
 +* New lint: [`not_unsafe_ptr_arg_deref`]
 +
 +## 0.0.75 — 2016-06-08
 +* Rustup to *rustc 1.11.0-nightly (763f9234b 2016-06-06)*
 +
 +## 0.0.74 — 2016-06-07
 +* Fix bug with `cargo-clippy` JSON parsing
 +* Add the `CLIPPY_DISABLE_DOCS_LINKS` environment variable to deactivate the
 +  “for further information visit *lint-link*” message.
 +
 +## 0.0.73 — 2016-06-05
 +* Fix false positives in [`useless_let_if_seq`]
 +
 +## 0.0.72 — 2016-06-04
 +* Fix false positives in [`useless_let_if_seq`]
 +
 +## 0.0.71 — 2016-05-31
 +* Rustup to *rustc 1.11.0-nightly (a967611d8 2016-05-30)*
 +* New lint: [`useless_let_if_seq`]
 +
 +## 0.0.70 — 2016-05-28
 +* Rustup to *rustc 1.10.0-nightly (7bddce693 2016-05-27)*
 +* [`invalid_regex`] and [`trivial_regex`] can now warn on `RegexSet::new`,
 +  `RegexBuilder::new` and byte regexes
 +
 +## 0.0.69 — 2016-05-20
 +* Rustup to *rustc 1.10.0-nightly (476fe6eef 2016-05-21)*
 +* [`used_underscore_binding`] has been made `Allow` temporarily
 +
 +## 0.0.68 — 2016-05-17
 +* Rustup to *rustc 1.10.0-nightly (cd6a40017 2016-05-16)*
 +* New lint: [`unnecessary_operation`]
 +
 +## 0.0.67 — 2016-05-12
 +* Rustup to *rustc 1.10.0-nightly (22ac88f1a 2016-05-11)*
 +
 +## 0.0.66 — 2016-05-11
 +* New `cargo clippy` subcommand
 +* New lints: [`assign_op_pattern`], [`assign_ops`], [`needless_borrow`]
 +
 +## 0.0.65 — 2016-05-08
 +* Rustup to *rustc 1.10.0-nightly (62e2b2fb7 2016-05-06)*
 +* New lints: [`float_arithmetic`], [`integer_arithmetic`]
 +
 +## 0.0.64 — 2016-04-26
 +* Rustup to *rustc 1.10.0-nightly (645dd013a 2016-04-24)*
 +* New lints: `temporary_cstring_as_ptr`, [`unsafe_removed_from_name`], and [`mem_forget`]
 +
 +## 0.0.63 — 2016-04-08
 +* Rustup to *rustc 1.9.0-nightly (7979dd608 2016-04-07)*
 +
 +## 0.0.62 — 2016-04-07
 +* Rustup to *rustc 1.9.0-nightly (bf5da36f1 2016-04-06)*
 +
 +## 0.0.61 — 2016-04-03
 +* Rustup to *rustc 1.9.0-nightly (5ab11d72c 2016-04-02)*
 +* New lint: [`invalid_upcast_comparisons`]
 +
 +## 0.0.60 — 2016-04-01
 +* Rustup to *rustc 1.9.0-nightly (e1195c24b 2016-03-31)*
 +
 +## 0.0.59 — 2016-03-31
 +* Rustup to *rustc 1.9.0-nightly (30a3849f2 2016-03-30)*
 +* New lints: [`logic_bug`], [`nonminimal_bool`]
 +* Fixed: [`match_same_arms`] now ignores arms with guards
 +* Improved: [`useless_vec`] now warns on `for … in vec![…]`
 +
 +## 0.0.58 — 2016-03-27
 +* Rustup to *rustc 1.9.0-nightly (d5a91e695 2016-03-26)*
 +* New lint: [`doc_markdown`]
 +
 +## 0.0.57 — 2016-03-27
 +* Update to *rustc 1.9.0-nightly (a1e29daf1 2016-03-25)*
 +* Deprecated lints: [`str_to_string`], [`string_to_string`], [`unstable_as_slice`], [`unstable_as_mut_slice`]
 +* New lint: [`crosspointer_transmute`]
 +
 +## 0.0.56 — 2016-03-23
 +* Update to *rustc 1.9.0-nightly (0dcc413e4 2016-03-22)*
 +* New lints: [`many_single_char_names`] and [`similar_names`]
 +
 +## 0.0.55 — 2016-03-21
 +* Update to *rustc 1.9.0-nightly (02310fd31 2016-03-19)*
 +
 +## 0.0.54 — 2016-03-16
 +* Update to *rustc 1.9.0-nightly (c66d2380a 2016-03-15)*
 +
 +## 0.0.53 — 2016-03-15
 +* Add a [configuration file]
 +
 +## ~~0.0.52~~
 +
 +## 0.0.51 — 2016-03-13
 +* Add `str` to types considered by [`len_zero`]
 +* New lints: [`indexing_slicing`]
 +
 +## 0.0.50 — 2016-03-11
 +* Update to *rustc 1.9.0-nightly (c9629d61c 2016-03-10)*
 +
 +## 0.0.49 — 2016-03-09
 +* Update to *rustc 1.9.0-nightly (eabfc160f 2016-03-08)*
 +* New lints: [`overflow_check_conditional`], `unused_label`, [`new_without_default`]
 +
 +## 0.0.48 — 2016-03-07
 +* Fixed: ICE in [`needless_range_loop`] with globals
 +
 +## 0.0.47 — 2016-03-07
 +* Update to *rustc 1.9.0-nightly (998a6720b 2016-03-07)*
 +* New lint: [`redundant_closure_call`]
 +
 +[`AsMut`]: https://doc.rust-lang.org/std/convert/trait.AsMut.html
 +[`AsRef`]: https://doc.rust-lang.org/std/convert/trait.AsRef.html
 +[configuration file]: ./rust-clippy#configuration
 +[pull3665]: https://github.com/rust-lang/rust-clippy/pull/3665
 +[adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md
 +[`README.md`]: https://github.com/rust-lang/rust-clippy/blob/master/README.md
 +
 +<!-- lint disable no-unused-definitions -->
 +<!-- begin autogenerated links to lint list -->
 +[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons
 +[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
 +[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
 +[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
 +[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
 +[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
 +[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
 +[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
 +[`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
 +[`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut
 +[`as_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore
 +[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants
 +[`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_result_states
 +[`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern
 +[`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops
 +[`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async
 +[`await_holding_invalid_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type
 +[`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock
 +[`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref
 +[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
 +[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map
 +[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name
 +[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints
 +[`block_in_if_condition_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_expr
 +[`block_in_if_condition_stmt`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt
 +[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions
 +[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison
 +[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
 +[`bool_to_int_with_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_to_int_with_if
 +[`borrow_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr
 +[`borrow_deref_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_deref_ref
 +[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
 +[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
 +[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection
 +[`box_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_default
 +[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
 +[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
 +[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
 +[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
 +[`bytes_count_to_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_count_to_len
 +[`bytes_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_nth
 +[`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata
 +[`case_sensitive_file_extension_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#case_sensitive_file_extension_comparisons
 +[`cast_abs_to_unsigned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned
 +[`cast_enum_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_constructor
 +[`cast_enum_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_truncation
 +[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless
 +[`cast_nan_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_nan_to_int
 +[`cast_possible_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation
 +[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap
 +[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
 +[`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ptr_alignment
 +[`cast_ref_to_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ref_to_mut
 +[`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_sign_loss
 +[`cast_slice_different_sizes`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_different_sizes
 +[`cast_slice_from_raw_parts`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_from_raw_parts
 +[`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_lit_as_u8
 +[`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp
 +[`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp
 +[`checked_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions
 +[`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref
 +[`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy
 +[`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_ref_ptr
 +[`cloned_instead_of_copied`]: https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied
 +[`cmp_nan`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_nan
 +[`cmp_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_null
 +[`cmp_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_owned
 +[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
 +[`collapsible_else_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_else_if
 +[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
 +[`collapsible_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
 +[`collapsible_str_replace`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace
 +[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
 +[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
 +[`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_static_lifetime
 +[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
 +[`crate_in_macro_def`]: https://rust-lang.github.io/rust-clippy/master/index.html#crate_in_macro_def
 +[`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir
 +[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
 +[`cyclomatic_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cyclomatic_complexity
 +[`dbg_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro
 +[`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call
 +[`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation
 +[`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const
 +[`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_instead_of_iter_empty
 +[`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback
 +[`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access
 +[`default_union_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_union_representation
 +[`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr
 +[`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver
 +[`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
 +[`deref_by_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_by_slicing
 +[`derivable_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls
 +[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
 +[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
 +[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
++[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq
 +[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
 +[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
 +[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods
 +[`disallowed_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names
 +[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents
 +[`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_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
 +[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
 +[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
 +[`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use
 +[`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg
 +[`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens
 +[`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds
 +[`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy
 +[`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop
 +[`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref
 +[`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod
 +[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument
 +[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
 +[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
 +[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
 +[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
 +[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
 +[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
 +[`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets
 +[`enum_clike_unportable_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant
 +[`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use
 +[`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names
 +[`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op
 +[`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/master/index.html#equatable_if_let
 +[`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op
 +[`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect
 +[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence
 +[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision
 +[`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums
 +[`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs
 +[`exit`]: https://rust-lang.github.io/rust-clippy/master/index.html#exit
 +[`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call
 +[`expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_used
 +[`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy
 +[`explicit_auto_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref
 +[`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop
 +[`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_deref_methods
 +[`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop
 +[`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop
 +[`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write
 +[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice
 +[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
 +[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
 +[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
 +[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
 +[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
 +[`filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map
 +[`filter_map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_identity
 +[`filter_map_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next
 +[`filter_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_next
 +[`find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#find_map
 +[`flat_map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_identity
 +[`flat_map_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option
 +[`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic
 +[`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp
 +[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const
 +[`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_equality_without_abs
 +[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons
 +[`fn_null_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_null_check
 +[`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools
 +[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
 +[`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_any
 +[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation
 +[`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map
 +[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option
 +[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result
 +[`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles
 +[`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy
 +[`forget_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_non_drop
 +[`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref
 +[`format_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_in_format_args
 +[`format_push_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_push_string
 +[`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect
 +[`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into
 +[`from_raw_with_void_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_raw_with_void_ptr
 +[`from_str_radix_10`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_str_radix_10
 +[`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send
 +[`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first
 +[`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len
 +[`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap
 +[`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion
 +[`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op
 +[`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex
 +[`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching
 +[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result
 +[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else
 +[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
 +[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
 +[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
 +[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
 +[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
 +[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
 +[`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_add
 +[`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
 +[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
 +[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
 +[`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor
 +[`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice
 +[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
 +[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
 +[`inefficient_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inefficient_to_string
 +[`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_destructuring_match
 +[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter
 +[`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string
 +[`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string_shadow_display
 +[`init_numbered_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#init_numbered_fields
 +[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always
 +[`inline_asm_x86_att_syntax`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_asm_x86_att_syntax
 +[`inline_asm_x86_intel_syntax`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_asm_x86_intel_syntax
 +[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
 +[`inspect_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#inspect_for_each
 +[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
 +[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic
 +[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
 +[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
 +[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
 +[`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering
 +[`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage
 +[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref
 +[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
 +[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
 +[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
 +[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
 +[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
 +[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
 +[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
 +[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count
 +[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map
 +[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
 +[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice
 +[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator
 +[`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth
 +[`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero
 +[`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections
 +[`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_single_items
 +[`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_overeager_cloned
 +[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
 +[`iter_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_with_drain
 +[`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero
 +[`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits
 +[`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays
 +[`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_digit_groups
 +[`large_enum_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
 +[`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file
 +[`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
 +[`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value
 +[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty
 +[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
 +[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return
 +[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop
 +[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
 +[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
 +[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
 +[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
 +[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
 +[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
 +[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
 +[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
 +[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
 +[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
 +[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
 +[`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits
 +[`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp
 +[`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter
 +[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
 +[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
 +[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
 +[`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten
 +[`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed
 +[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
 +[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
 +[`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
 +[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
 +[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 +[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 +[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
 +[`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
 +[`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain
 +[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
 +[`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once
 +[`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat
 +[`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new
 +[`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip
 +[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
 +[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
 +[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
 +[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
 +[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit
 +[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
 +[`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_err_ignore
 +[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
 +[`map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_identity
 +[`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or
 +[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref
 +[`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool
 +[`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro
 +[`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items
 +[`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm
 +[`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats
 +[`match_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_result_ok
 +[`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms
 +[`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding
 +[`match_str_case_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_str_case_mismatch
 +[`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm
 +[`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants
 +[`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter
 +[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum
 +[`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget
 +[`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none
 +[`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default
 +[`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit
 +[`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max
 +[`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute
 +[`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os
 +[`mismatching_type_param_order`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatching_type_param_order
 +[`misnamed_getters`]: https://rust-lang.github.io/rust-clippy/master/index.html#misnamed_getters
 +[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op
 +[`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn
 +[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
 +[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames
 +[`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc
 +[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
 +[`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
 +[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
 +[`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
 +[`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
 +[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
 +[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
 +[`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression
 +[`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files
 +[`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception
 +[`module_name_repetitions`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions
 +[`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic
 +[`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one
 +[`multi_assignments`]: https://rust-lang.github.io/rust-clippy/master/index.html#multi_assignments
 +[`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions
 +[`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl
 +[`must_use_candidate`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
 +[`must_use_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_unit
 +[`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_from_ref
 +[`mut_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mut
 +[`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mutex_lock
 +[`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_range_bound
 +[`mutable_key_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
 +[`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic
 +[`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer
 +[`naive_bytecount`]: https://rust-lang.github.io/rust-clippy/master/index.html#naive_bytecount
 +[`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type
 +[`needless_bitwise_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bitwise_bool
 +[`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool
 +[`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow
 +[`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference
 +[`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect
 +[`needless_continue`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue
 +[`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main
 +[`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each
 +[`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init
 +[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
 +[`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match
 +[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
 +[`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take
 +[`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals
 +[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
 +[`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
 +[`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop
 +[`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
 +[`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn
 +[`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update
 +[`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord
 +[`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply
 +[`negative_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#negative_feature_names
 +[`never_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#never_loop
 +[`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self
 +[`new_without_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default
 +[`new_without_default_derive`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default_derive
 +[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect
 +[`no_effect_replace`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_replace
 +[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
 +[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
 +[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 +[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
 +[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
 +[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
 +[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
 +[`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref
 +[`obfuscated_if_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#obfuscated_if_else
 +[`octal_escapes`]: https://rust-lang.github.io/rust-clippy/master/index.html#octal_escapes
 +[`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect
 +[`only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#only_used_in_recursion
 +[`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
 +[`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some
 +[`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref
 +[`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap
 +[`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used
 +[`option_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_filter_map
 +[`option_if_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else
 +[`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none
 +[`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn
 +[`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or
 +[`option_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else
 +[`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option
 +[`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_used
 +[`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call
 +[`or_then_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_then_unwrap
 +[`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing
 +[`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional
 +[`overly_complex_bool_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#overly_complex_bool_expr
 +[`panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic
 +[`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_in_result_fn
 +[`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params
 +[`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap
 +[`partial_pub_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#partial_pub_fields
 +[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl
 +[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
 +[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
 +[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
 +[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
 +[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
 +[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
 +[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
 +[`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_in_format_impl
 +[`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal
 +[`print_stderr`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr
 +[`print_stdout`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout
 +[`print_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_with_newline
 +[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string
 +[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
 +[`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr
 +[`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
 +[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
 +[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
 +[`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use
 +[`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
 +[`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one
 +[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
 +[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
 +[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len
 +[`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer
 +[`rc_clone_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_clone_in_vec_init
 +[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex
 +[`read_zero_byte_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#read_zero_byte_vec
 +[`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl
 +[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
 +[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
 +[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
 +[`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
 +[`redundant_closure_for_method_calls`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
 +[`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else
 +[`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names
 +[`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
 +[`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern
 +[`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching
 +[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
 +[`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
 +[`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
 +[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 +[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 +[`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
 +[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
 +[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
 +[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
 +[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs
 +[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used
 +[`result_large_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
 +[`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option
 +[`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn
 +[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else
 +[`result_unit_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unit_err
 +[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
 +[`return_self_not_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use
 +[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges
 +[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition
 +[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
 +[`same_name_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_name_method
 +[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
 +[`seek_from_current`]: https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current
 +[`seek_to_start_instead_of_rewind`]: https://rust-lang.github.io/rust-clippy/master/index.html#seek_to_start_instead_of_rewind
 +[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
 +[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
 +[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
 +[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
 +[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block
 +[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block
 +[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
 +[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
 +[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
 +[`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same
 +[`shadow_unrelated`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_unrelated
 +[`short_circuit_statement`]: https://rust-lang.github.io/rust-clippy/master/index.html#short_circuit_statement
 +[`should_assert_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_assert_eq
 +[`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
 +[`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee
 +[`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
 +[`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str
 +[`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names
 +[`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
 +[`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str
 +[`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports
 +[`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop
 +[`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
 +[`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
 +[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
 +[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
 +[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
 +[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
 +[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
 +[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
 +[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core
 +[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
 +[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
 +[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign
 +[`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars
 +[`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes
 +[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
 +[`string_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_slice
 +[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
 +[`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings
 +[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
 +[`stutter`]: https://rust-lang.github.io/rust-clippy/master/index.html#stutter
 +[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
 +[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
 +[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting
 +[`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting
 +[`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
 +[`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
 +[`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings
 +[`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn
 +[`suspicious_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_to_owned
 +[`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
 +[`suspicious_xor_used_as_pow`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_xor_used_as_pow
 +[`swap_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#swap_ptr_to_ref
 +[`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
 +[`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
 +[`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr
 +[`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some
 +[`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display
 +[`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args
 +[`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
 +[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
 +[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
 +[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
 +[`trailing_empty_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#trailing_empty_array
 +[`trait_duplication_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#trait_duplication_in_bounds
 +[`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str
 +[`transmute_float_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_float_to_int
 +[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool
 +[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char
 +[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float
 +[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn
 +[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes
 +[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr
 +[`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref
 +[`transmute_undefined_repr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_undefined_repr
 +[`transmutes_expressible_as_ptr_casts`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmutes_expressible_as_ptr_casts
 +[`transmuting_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmuting_null
 +[`trim_split_whitespace`]: https://rust-lang.github.io/rust-clippy/master/index.html#trim_split_whitespace
 +[`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex
 +[`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref
 +[`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err
 +[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity
 +[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds
 +[`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction
 +[`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks
 +[`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops
 +[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc
 +[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented
 +[`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init
 +[`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec
 +[`uninlined_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
 +[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
 +[`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
 +[`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
 +[`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
 +[`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints
 +[`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
 +[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
 +[`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map
 +[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
 +[`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join
 +[`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations
 +[`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed
 +[`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation
 +[`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings
 +[`unnecessary_safety_comment`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_comment
 +[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
 +[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
 +[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
 +[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
 +[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
 +[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
 +[`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern
 +[`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern
 +[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns
 +[`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable
 +[`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal
 +[`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize
 +[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name
 +[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization
 +[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix
 +[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
 +[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
 +[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
 +[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
 +[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
 +[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs
 +[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
 +[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
 +[`unused_peekable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_peekable
 +[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
 +[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
 +[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
 +[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
 +[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
 +[`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default
 +[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
 +[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
 +[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
 +[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
 +[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding
 +[`useless_asref`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref
 +[`useless_attribute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute
 +[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
 +[`useless_format`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_format
 +[`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq
 +[`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute
 +[`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec
 +[`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box
 +[`vec_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_init_then_push
 +[`vec_resize_to_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_resize_to_zero
 +[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask
 +[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads
 +[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
 +[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition
 +[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop
 +[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator
 +[`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies
 +[`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm
 +[`wildcard_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports
 +[`wildcard_in_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_in_or_patterns
 +[`write_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_literal
 +[`write_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#write_with_newline
 +[`writeln_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#writeln_empty_string
 +[`wrong_pub_self_convention`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_pub_self_convention
 +[`wrong_self_convention`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention
 +[`wrong_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#wrong_transmute
 +[`zero_divided_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_divided_by_zero
 +[`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal
 +[`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr
 +[`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values
 +[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
 +[`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
 +<!-- end autogenerated links to lint list -->
index b2a28d0be622f1874e15f922d487016710ddd248,0000000000000000000000000000000000000000..cce888b17d4d3fe6f914b52cceb2f930fb44b777
mode 100644,000000..100644
--- /dev/null
@@@ -1,24 -1,0 +1,24 @@@
- If you're using `rustup` to install and manage you're Rust toolchains, Clippy is
 +# Installation
 +
++If you're using `rustup` to install and manage your Rust toolchains, Clippy is
 +usually **already installed**. In that case you can skip this chapter and go to
 +the [Usage] chapter.
 +
 +> Note: If you used the `minimal` profile when installing a Rust toolchain,
 +> Clippy is not automatically installed.
 +
 +## Using Rustup
 +
 +If Clippy was not installed for a toolchain, it can be installed with
 +
 +```
 +$ rustup component add clippy [--toolchain=<name>]
 +```
 +
 +## From Source
 +
 +Take a look at the [Basics] chapter in the Clippy developer guide to find step
 +by step instructions on how to build and install Clippy from source.
 +
 +[Basics]: development/basics.md#install-from-source
 +[Usage]: usage.md
index 80bb83af43b19106469fbee7523e575bf7e9543d,0000000000000000000000000000000000000000..e70488165b99bb2dec1fc07cb0e3d6d8ce800ff7
mode 100644,000000..100644
--- /dev/null
@@@ -1,57 -1,0 +1,60 @@@
 +#![feature(let_chains)]
 +#![feature(once_cell)]
 +#![feature(rustc_private)]
 +#![cfg_attr(feature = "deny-warnings", deny(warnings))]
 +// warn on lints, that are included in `rust-lang/rust`s bootstrap
 +#![warn(rust_2018_idioms, unused_lifetimes)]
 +
++// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
++#[allow(unused_extern_crates)]
++extern crate rustc_driver;
 +extern crate rustc_lexer;
 +
 +use std::path::PathBuf;
 +
 +pub mod bless;
 +pub mod dogfood;
 +pub mod fmt;
 +pub mod lint;
 +pub mod new_lint;
 +pub mod serve;
 +pub mod setup;
 +pub mod update_lints;
 +
 +#[cfg(not(windows))]
 +static CARGO_CLIPPY_EXE: &str = "cargo-clippy";
 +#[cfg(windows)]
 +static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe";
 +
 +/// Returns the path to the `cargo-clippy` binary
 +#[must_use]
 +pub fn cargo_clippy_path() -> PathBuf {
 +    let mut path = std::env::current_exe().expect("failed to get current executable name");
 +    path.set_file_name(CARGO_CLIPPY_EXE);
 +    path
 +}
 +
 +/// Returns the path to the Clippy project directory
 +///
 +/// # Panics
 +///
 +/// Panics if the current directory could not be retrieved, there was an error reading any of the
 +/// Cargo.toml files or ancestor directory is the clippy root directory
 +#[must_use]
 +pub fn clippy_project_root() -> PathBuf {
 +    let current_dir = std::env::current_dir().unwrap();
 +    for path in current_dir.ancestors() {
 +        let result = std::fs::read_to_string(path.join("Cargo.toml"));
 +        if let Err(err) = &result {
 +            if err.kind() == std::io::ErrorKind::NotFound {
 +                continue;
 +            }
 +        }
 +
 +        let content = result.unwrap();
 +        if content.contains("[package]\nname = \"clippy\"") {
 +            return path.to_path_buf();
 +        }
 +    }
 +    panic!("error: Can't determine root of project. Please run inside a Clippy working dir.");
 +}
index 91900542af8330e52d72655efb34be044bbfbbf5,0000000000000000000000000000000000000000..9d98a6bab71073efed82eefdc75a6fa33d091e9b
mode 100644,000000..100644
--- /dev/null
@@@ -1,129 -1,0 +1,129 @@@
- use rustc_middle::lint::in_external_macro;
 +use clippy_utils::{
 +    diagnostics::span_lint_and_sugg, get_parent_node, is_default_equivalent, macros::macro_backtrace, match_path,
 +    path_def_id, paths, ty::expr_sig,
 +};
 +use rustc_errors::Applicability;
 +use rustc_hir::{
 +    intravisit::{walk_ty, Visitor},
 +    Block, Expr, ExprKind, Local, Node, QPath, TyKind,
 +};
 +use rustc_lint::{LateContext, LateLintPass, LintContext};
-                     format!("Box::<{arg_ty}>::default()")
++use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::sym;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// checks for `Box::new(T::default())`, which is better written as
 +    /// `Box::<T>::default()`.
 +    ///
 +    /// ### Why is this bad?
 +    /// First, it's more complex, involving two calls instead of one.
 +    /// Second, `Box::default()` can be faster
 +    /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let x: Box<String> = Box::new(Default::default());
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    /// let x: Box<String> = Box::default();
 +    /// ```
 +    #[clippy::version = "1.66.0"]
 +    pub BOX_DEFAULT,
 +    perf,
 +    "Using Box::new(T::default()) instead of Box::default()"
 +}
 +
 +declare_lint_pass!(BoxDefault => [BOX_DEFAULT]);
 +
 +impl LateLintPass<'_> for BoxDefault {
 +    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
 +        if let ExprKind::Call(box_new, [arg]) = expr.kind
 +            && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_new.kind
 +            && let ExprKind::Call(arg_path, ..) = arg.kind
 +            && !in_external_macro(cx.sess(), expr.span)
 +            && (expr.span.eq_ctxt(arg.span) || is_vec_expn(cx, arg))
 +            && seg.ident.name == sym::new
 +            && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
 +            && is_default_equivalent(cx, arg)
 +        {
 +            let arg_ty = cx.typeck_results().expr_ty(arg);
 +            span_lint_and_sugg(
 +                cx,
 +                BOX_DEFAULT,
 +                expr.span,
 +                "`Box::new(_)` of default value",
 +                "try",
 +                if is_plain_default(arg_path) || given_type(cx, expr) {
 +                    "Box::default()".into()
 +                } else {
++                    with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
 +                },
 +                Applicability::MachineApplicable
 +            );
 +        }
 +    }
 +}
 +
 +fn is_plain_default(arg_path: &Expr<'_>) -> bool {
 +    // we need to match the actual path so we don't match e.g. "u8::default"
 +    if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind {
 +        // avoid generic parameters
 +        match_path(path, &paths::DEFAULT_TRAIT_METHOD) && path.segments.iter().all(|seg| seg.args.is_none())
 +    } else {
 +        false
 +    }
 +}
 +
 +fn is_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +    macro_backtrace(expr.span)
 +        .next()
 +        .map_or(false, |call| cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id))
 +}
 +
 +#[derive(Default)]
 +struct InferVisitor(bool);
 +
 +impl<'tcx> Visitor<'tcx> for InferVisitor {
 +    fn visit_ty(&mut self, t: &rustc_hir::Ty<'_>) {
 +        self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
 +        if !self.0 {
 +            walk_ty(self, t);
 +        }
 +    }
 +}
 +
 +fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +    match get_parent_node(cx.tcx, expr.hir_id) {
 +        Some(Node::Local(Local { ty: Some(ty), .. })) => {
 +            let mut v = InferVisitor::default();
 +            v.visit_ty(ty);
 +            !v.0
 +        },
 +        Some(
 +            Node::Expr(Expr {
 +                kind: ExprKind::Call(path, args),
 +                ..
 +            }) | Node::Block(Block {
 +                expr:
 +                    Some(Expr {
 +                        kind: ExprKind::Call(path, args),
 +                        ..
 +                    }),
 +                ..
 +            }),
 +        ) => {
 +            if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) &&
 +                let Some(sig) = expr_sig(cx, path) &&
 +                let Some(input) = sig.input(index)
 +            {
 +                input.no_bound_vars().is_some()
 +            } else {
 +                false
 +            }
 +        },
 +        _ => false,
 +    }
 +}
index 0e3d9317590f3c80782c517e5c64fc66019dc40d,0000000000000000000000000000000000000000..f10c35cde52a1e9b0eed124ae7b1609efbc3d625
mode 100644,000000..100644
--- /dev/null
@@@ -1,584 -1,0 +1,588 @@@
-                 let mut walker = ContainsName { name, result: false };
 +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
 +use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, snippet_opt};
 +use clippy_utils::ty::needs_ordered_drop;
 +use clippy_utils::visitors::for_each_expr;
 +use clippy_utils::{
 +    capture_local_usage, eq_expr_value, get_enclosing_block, hash_expr, hash_stmt, if_sequence, is_else_clause,
 +    is_lint_allowed, path_to_local, search_same, ContainsName, HirEqInterExpr, SpanlessEq,
 +};
 +use core::iter;
 +use core::ops::ControlFlow;
 +use rustc_errors::Applicability;
 +use rustc_hir::intravisit;
 +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::hygiene::walk_chain;
 +use rustc_span::source_map::SourceMap;
 +use rustc_span::{BytePos, Span, Symbol};
 +use std::borrow::Cow;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for consecutive `if`s with the same condition.
 +    ///
 +    /// ### Why is this bad?
 +    /// This is probably a copy & paste error.
 +    ///
 +    /// ### Example
 +    /// ```ignore
 +    /// if a == b {
 +    ///     …
 +    /// } else if a == b {
 +    ///     …
 +    /// }
 +    /// ```
 +    ///
 +    /// Note that this lint ignores all conditions with a function call as it could
 +    /// have side effects:
 +    ///
 +    /// ```ignore
 +    /// if foo() {
 +    ///     …
 +    /// } else if foo() { // not linted
 +    ///     …
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub IFS_SAME_COND,
 +    correctness,
 +    "consecutive `if`s with the same condition"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for consecutive `if`s with the same function call.
 +    ///
 +    /// ### Why is this bad?
 +    /// This is probably a copy & paste error.
 +    /// Despite the fact that function can have side effects and `if` works as
 +    /// intended, such an approach is implicit and can be considered a "code smell".
 +    ///
 +    /// ### Example
 +    /// ```ignore
 +    /// if foo() == bar {
 +    ///     …
 +    /// } else if foo() == bar {
 +    ///     …
 +    /// }
 +    /// ```
 +    ///
 +    /// This probably should be:
 +    /// ```ignore
 +    /// if foo() == bar {
 +    ///     …
 +    /// } else if foo() == baz {
 +    ///     …
 +    /// }
 +    /// ```
 +    ///
 +    /// or if the original code was not a typo and called function mutates a state,
 +    /// consider move the mutation out of the `if` condition to avoid similarity to
 +    /// a copy & paste error:
 +    ///
 +    /// ```ignore
 +    /// let first = foo();
 +    /// if first == bar {
 +    ///     …
 +    /// } else {
 +    ///     let second = foo();
 +    ///     if second == bar {
 +    ///     …
 +    ///     }
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.41.0"]
 +    pub SAME_FUNCTIONS_IN_IF_CONDITION,
 +    pedantic,
 +    "consecutive `if`s with the same function call"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for `if/else` with the same body as the *then* part
 +    /// and the *else* part.
 +    ///
 +    /// ### Why is this bad?
 +    /// This is probably a copy & paste error.
 +    ///
 +    /// ### Example
 +    /// ```ignore
 +    /// let foo = if … {
 +    ///     42
 +    /// } else {
 +    ///     42
 +    /// };
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub IF_SAME_THEN_ELSE,
 +    correctness,
 +    "`if` with the same `then` and `else` blocks"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks if the `if` and `else` block contain shared code that can be
 +    /// moved out of the blocks.
 +    ///
 +    /// ### Why is this bad?
 +    /// Duplicate code is less maintainable.
 +    ///
 +    /// ### Known problems
 +    /// * The lint doesn't check if the moved expressions modify values that are being used in
 +    ///   the if condition. The suggestion can in that case modify the behavior of the program.
 +    ///   See [rust-clippy#7452](https://github.com/rust-lang/rust-clippy/issues/7452)
 +    ///
 +    /// ### Example
 +    /// ```ignore
 +    /// let foo = if … {
 +    ///     println!("Hello World");
 +    ///     13
 +    /// } else {
 +    ///     println!("Hello World");
 +    ///     42
 +    /// };
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```ignore
 +    /// println!("Hello World");
 +    /// let foo = if … {
 +    ///     13
 +    /// } else {
 +    ///     42
 +    /// };
 +    /// ```
 +    #[clippy::version = "1.53.0"]
 +    pub BRANCHES_SHARING_CODE,
 +    nursery,
 +    "`if` statement with shared code in all blocks"
 +}
 +
 +declare_lint_pass!(CopyAndPaste => [
 +    IFS_SAME_COND,
 +    SAME_FUNCTIONS_IN_IF_CONDITION,
 +    IF_SAME_THEN_ELSE,
 +    BRANCHES_SHARING_CODE
 +]);
 +
 +impl<'tcx> LateLintPass<'tcx> for CopyAndPaste {
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 +        if !expr.span.from_expansion() && matches!(expr.kind, ExprKind::If(..)) && !is_else_clause(cx.tcx, expr) {
 +            let (conds, blocks) = if_sequence(expr);
 +            lint_same_cond(cx, &conds);
 +            lint_same_fns_in_if_cond(cx, &conds);
 +            let all_same =
 +                !is_lint_allowed(cx, IF_SAME_THEN_ELSE, expr.hir_id) && lint_if_same_then_else(cx, &conds, &blocks);
 +            if !all_same && conds.len() != blocks.len() {
 +                lint_branches_sharing_code(cx, &conds, &blocks, expr);
 +            }
 +        }
 +    }
 +}
 +
 +/// Checks if the given expression is a let chain.
 +fn contains_let(e: &Expr<'_>) -> bool {
 +    match e.kind {
 +        ExprKind::Let(..) => true,
 +        ExprKind::Binary(op, lhs, rhs) if op.node == BinOpKind::And => {
 +            matches!(lhs.kind, ExprKind::Let(..)) || contains_let(rhs)
 +        },
 +        _ => false,
 +    }
 +}
 +
 +fn lint_if_same_then_else(cx: &LateContext<'_>, conds: &[&Expr<'_>], blocks: &[&Block<'_>]) -> bool {
 +    let mut eq = SpanlessEq::new(cx);
 +    blocks
 +        .array_windows::<2>()
 +        .enumerate()
 +        .fold(true, |all_eq, (i, &[lhs, rhs])| {
 +            if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).map_or(true, |e| !contains_let(e)) {
 +                span_lint_and_note(
 +                    cx,
 +                    IF_SAME_THEN_ELSE,
 +                    lhs.span,
 +                    "this `if` has identical blocks",
 +                    Some(rhs.span),
 +                    "same as this",
 +                );
 +                all_eq
 +            } else {
 +                false
 +            }
 +        })
 +}
 +
 +fn lint_branches_sharing_code<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    conds: &[&'tcx Expr<'_>],
 +    blocks: &[&'tcx Block<'_>],
 +    expr: &'tcx Expr<'_>,
 +) {
 +    // We only lint ifs with multiple blocks
 +    let &[first_block, ref blocks @ ..] = blocks else {
 +        return;
 +    };
 +    let &[.., last_block] = blocks else {
 +        return;
 +    };
 +
 +    let res = scan_block_for_eq(cx, conds, first_block, blocks);
 +    let sm = cx.tcx.sess.source_map();
 +    let start_suggestion = res.start_span(first_block, sm).map(|span| {
 +        let first_line_span = first_line_of_span(cx, expr.span);
 +        let replace_span = first_line_span.with_hi(span.hi());
 +        let cond_span = first_line_span.until(first_block.span);
 +        let cond_snippet = reindent_multiline(snippet(cx, cond_span, "_"), false, None);
 +        let cond_indent = indent_of(cx, cond_span);
 +        let moved_snippet = reindent_multiline(snippet(cx, span, "_"), true, None);
 +        let suggestion = moved_snippet.to_string() + "\n" + &cond_snippet + "{";
 +        let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, cond_indent);
 +        (replace_span, suggestion.to_string())
 +    });
 +    let end_suggestion = res.end_span(last_block, sm).map(|span| {
 +        let moved_snipped = reindent_multiline(snippet(cx, span, "_"), true, None);
 +        let indent = indent_of(cx, expr.span.shrink_to_hi());
 +        let suggestion = "}\n".to_string() + &moved_snipped;
 +        let suggestion = reindent_multiline(Cow::Borrowed(&suggestion), true, indent);
 +
 +        let span = span.with_hi(last_block.span.hi());
 +        // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
 +        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent());
 +        let span = if snippet_opt(cx, test_span).map_or(false, |snip| snip == "    ") {
 +            span.with_lo(test_span.lo())
 +        } else {
 +            span
 +        };
 +        (span, suggestion.to_string())
 +    });
 +
 +    let (span, msg, end_span) = match (&start_suggestion, &end_suggestion) {
 +        (&Some((span, _)), &Some((end_span, _))) => (
 +            span,
 +            "all if blocks contain the same code at both the start and the end",
 +            Some(end_span),
 +        ),
 +        (&Some((span, _)), None) => (span, "all if blocks contain the same code at the start", None),
 +        (None, &Some((span, _))) => (span, "all if blocks contain the same code at the end", None),
 +        (None, None) => return,
 +    };
 +    span_lint_and_then(cx, BRANCHES_SHARING_CODE, span, msg, |diag| {
 +        if let Some(span) = end_span {
 +            diag.span_note(span, "this code is shared at the end");
 +        }
 +        if let Some((span, sugg)) = start_suggestion {
 +            diag.span_suggestion(
 +                span,
 +                "consider moving these statements before the if",
 +                sugg,
 +                Applicability::Unspecified,
 +            );
 +        }
 +        if let Some((span, sugg)) = end_suggestion {
 +            diag.span_suggestion(
 +                span,
 +                "consider moving these statements after the if",
 +                sugg,
 +                Applicability::Unspecified,
 +            );
 +            if !cx.typeck_results().expr_ty(expr).is_unit() {
 +                diag.note("the end suggestion probably needs some adjustments to use the expression result correctly");
 +            }
 +        }
 +        if check_for_warn_of_moved_symbol(cx, &res.moved_locals, expr) {
 +            diag.warn("some moved values might need to be renamed to avoid wrong references");
 +        }
 +    });
 +}
 +
 +struct BlockEq {
 +    /// The end of the range of equal stmts at the start.
 +    start_end_eq: usize,
 +    /// The start of the range of equal stmts at the end.
 +    end_begin_eq: Option<usize>,
 +    /// The name and id of every local which can be moved at the beginning and the end.
 +    moved_locals: Vec<(HirId, Symbol)>,
 +}
 +impl BlockEq {
 +    fn start_span(&self, b: &Block<'_>, sm: &SourceMap) -> Option<Span> {
 +        match &b.stmts[..self.start_end_eq] {
 +            [first, .., last] => Some(sm.stmt_span(first.span, b.span).to(sm.stmt_span(last.span, b.span))),
 +            [s] => Some(sm.stmt_span(s.span, b.span)),
 +            [] => None,
 +        }
 +    }
 +
 +    fn end_span(&self, b: &Block<'_>, sm: &SourceMap) -> Option<Span> {
 +        match (&b.stmts[b.stmts.len() - self.end_begin_eq?..], b.expr) {
 +            ([first, .., last], None) => Some(sm.stmt_span(first.span, b.span).to(sm.stmt_span(last.span, b.span))),
 +            ([first, ..], Some(last)) => Some(sm.stmt_span(first.span, b.span).to(sm.stmt_span(last.span, b.span))),
 +            ([s], None) => Some(sm.stmt_span(s.span, b.span)),
 +            ([], Some(e)) => Some(walk_chain(e.span, b.span.ctxt())),
 +            ([], None) => None,
 +        }
 +    }
 +}
 +
 +/// If the statement is a local, checks if the bound names match the expected list of names.
 +fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool {
 +    if let StmtKind::Local(l) = s.kind {
 +        let mut i = 0usize;
 +        let mut res = true;
 +        l.pat.each_binding_or_first(&mut |_, _, _, name| {
 +            if names.get(i).map_or(false, |&(_, n)| n == name.name) {
 +                i += 1;
 +            } else {
 +                res = false;
 +            }
 +        });
 +        res && i == names.len()
 +    } else {
 +        false
 +    }
 +}
 +
 +/// Checks if the statement modifies or moves any of the given locals.
 +fn modifies_any_local<'tcx>(cx: &LateContext<'tcx>, s: &'tcx Stmt<'_>, locals: &HirIdSet) -> bool {
 +    for_each_expr(s, |e| {
 +        if let Some(id) = path_to_local(e)
 +            && locals.contains(&id)
 +            && !capture_local_usage(cx, e).is_imm_ref()
 +        {
 +            ControlFlow::Break(())
 +        } else {
 +            ControlFlow::Continue(())
 +        }
 +    })
 +    .is_some()
 +}
 +
 +/// Checks if the given statement should be considered equal to the statement in the same position
 +/// for each block.
 +fn eq_stmts(
 +    stmt: &Stmt<'_>,
 +    blocks: &[&Block<'_>],
 +    get_stmt: impl for<'a> Fn(&'a Block<'a>) -> Option<&'a Stmt<'a>>,
 +    eq: &mut HirEqInterExpr<'_, '_, '_>,
 +    moved_bindings: &mut Vec<(HirId, Symbol)>,
 +) -> bool {
 +    (if let StmtKind::Local(l) = stmt.kind {
 +        let old_count = moved_bindings.len();
 +        l.pat.each_binding_or_first(&mut |_, id, _, name| {
 +            moved_bindings.push((id, name.name));
 +        });
 +        let new_bindings = &moved_bindings[old_count..];
 +        blocks
 +            .iter()
 +            .all(|b| get_stmt(b).map_or(false, |s| eq_binding_names(s, new_bindings)))
 +    } else {
 +        true
 +    }) && blocks
 +        .iter()
 +        .all(|b| get_stmt(b).map_or(false, |s| eq.eq_stmt(s, stmt)))
 +}
 +
 +#[expect(clippy::too_many_lines)]
 +fn scan_block_for_eq<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    conds: &[&'tcx Expr<'_>],
 +    block: &'tcx Block<'_>,
 +    blocks: &[&'tcx Block<'_>],
 +) -> BlockEq {
 +    let mut eq = SpanlessEq::new(cx);
 +    let mut eq = eq.inter_expr();
 +    let mut moved_locals = Vec::new();
 +
 +    let mut cond_locals = HirIdSet::default();
 +    for &cond in conds {
 +        let _: Option<!> = for_each_expr(cond, |e| {
 +            if let Some(id) = path_to_local(e) {
 +                cond_locals.insert(id);
 +            }
 +            ControlFlow::Continue(())
 +        });
 +    }
 +
 +    let mut local_needs_ordered_drop = false;
 +    let start_end_eq = block
 +        .stmts
 +        .iter()
 +        .enumerate()
 +        .find(|&(i, stmt)| {
 +            if let StmtKind::Local(l) = stmt.kind
 +                && needs_ordered_drop(cx, cx.typeck_results().node_type(l.hir_id))
 +            {
 +                local_needs_ordered_drop = true;
 +                return true;
 +            }
 +            modifies_any_local(cx, stmt, &cond_locals)
 +                || !eq_stmts(stmt, blocks, |b| b.stmts.get(i), &mut eq, &mut moved_locals)
 +        })
 +        .map_or(block.stmts.len(), |(i, _)| i);
 +
 +    if local_needs_ordered_drop {
 +        return BlockEq {
 +            start_end_eq,
 +            end_begin_eq: None,
 +            moved_locals,
 +        };
 +    }
 +
 +    // Walk backwards through the final expression/statements so long as their hashes are equal. Note
 +    // `SpanlessHash` treats all local references as equal allowing locals declared earlier in the block
 +    // to match those in other blocks. e.g. If each block ends with the following the hash value will be
 +    // the same even though each `x` binding will have a different `HirId`:
 +    //     let x = foo();
 +    //     x + 50
 +    let expr_hash_eq = if let Some(e) = block.expr {
 +        let hash = hash_expr(cx, e);
 +        blocks
 +            .iter()
 +            .all(|b| b.expr.map_or(false, |e| hash_expr(cx, e) == hash))
 +    } else {
 +        blocks.iter().all(|b| b.expr.is_none())
 +    };
 +    if !expr_hash_eq {
 +        return BlockEq {
 +            start_end_eq,
 +            end_begin_eq: None,
 +            moved_locals,
 +        };
 +    }
 +    let end_search_start = block.stmts[start_end_eq..]
 +        .iter()
 +        .rev()
 +        .enumerate()
 +        .find(|&(offset, stmt)| {
 +            let hash = hash_stmt(cx, stmt);
 +            blocks.iter().any(|b| {
 +                b.stmts
 +                    // the bounds check will catch the underflow
 +                    .get(b.stmts.len().wrapping_sub(offset + 1))
 +                    .map_or(true, |s| hash != hash_stmt(cx, s))
 +            })
 +        })
 +        .map_or(block.stmts.len() - start_end_eq, |(i, _)| i);
 +
 +    let moved_locals_at_start = moved_locals.len();
 +    let mut i = end_search_start;
 +    let end_begin_eq = block.stmts[block.stmts.len() - end_search_start..]
 +        .iter()
 +        .zip(iter::repeat_with(move || {
 +            let x = i;
 +            i -= 1;
 +            x
 +        }))
 +        .fold(end_search_start, |init, (stmt, offset)| {
 +            if eq_stmts(
 +                stmt,
 +                blocks,
 +                |b| b.stmts.get(b.stmts.len() - offset),
 +                &mut eq,
 +                &mut moved_locals,
 +            ) {
 +                init
 +            } else {
 +                // Clear out all locals seen at the end so far. None of them can be moved.
 +                let stmts = &blocks[0].stmts;
 +                for stmt in &stmts[stmts.len() - init..=stmts.len() - offset] {
 +                    if let StmtKind::Local(l) = stmt.kind {
 +                        l.pat.each_binding_or_first(&mut |_, id, _, _| {
 +                            eq.locals.remove(&id);
 +                        });
 +                    }
 +                }
 +                moved_locals.truncate(moved_locals_at_start);
 +                offset - 1
 +            }
 +        });
 +    if let Some(e) = block.expr {
 +        for block in blocks {
 +            if block.expr.map_or(false, |expr| !eq.eq_expr(expr, e)) {
 +                moved_locals.truncate(moved_locals_at_start);
 +                return BlockEq {
 +                    start_end_eq,
 +                    end_begin_eq: None,
 +                    moved_locals,
 +                };
 +            }
 +        }
 +    }
 +
 +    BlockEq {
 +        start_end_eq,
 +        end_begin_eq: Some(end_begin_eq),
 +        moved_locals,
 +    }
 +}
 +
 +fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbol)], if_expr: &Expr<'_>) -> bool {
 +    get_enclosing_block(cx, if_expr.hir_id).map_or(false, |block| {
 +        let ignore_span = block.span.shrink_to_lo().to(if_expr.span);
 +
 +        symbols
 +            .iter()
 +            .filter(|&&(_, name)| !name.as_str().starts_with('_'))
 +            .any(|&(_, name)| {
++                let mut walker = ContainsName {
++                    name,
++                    result: false,
++                    cx,
++                };
 +
 +                // Scan block
 +                block
 +                    .stmts
 +                    .iter()
 +                    .filter(|stmt| !ignore_span.overlaps(stmt.span))
 +                    .for_each(|stmt| intravisit::walk_stmt(&mut walker, stmt));
 +
 +                if let Some(expr) = block.expr {
 +                    intravisit::walk_expr(&mut walker, expr);
 +                }
 +
 +                walker.result
 +            })
 +    })
 +}
 +
 +/// Implementation of `IFS_SAME_COND`.
 +fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) {
 +    for (i, j) in search_same(conds, |e| hash_expr(cx, e), |lhs, rhs| eq_expr_value(cx, lhs, rhs)) {
 +        span_lint_and_note(
 +            cx,
 +            IFS_SAME_COND,
 +            j.span,
 +            "this `if` has the same condition as a previous `if`",
 +            Some(i.span),
 +            "same as this",
 +        );
 +    }
 +}
 +
 +/// Implementation of `SAME_FUNCTIONS_IN_IF_CONDITION`.
 +fn lint_same_fns_in_if_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>]) {
 +    let eq: &dyn Fn(&&Expr<'_>, &&Expr<'_>) -> bool = &|&lhs, &rhs| -> bool {
 +        // Do not lint if any expr originates from a macro
 +        if lhs.span.from_expansion() || rhs.span.from_expansion() {
 +            return false;
 +        }
 +        // Do not spawn warning if `IFS_SAME_COND` already produced it.
 +        if eq_expr_value(cx, lhs, rhs) {
 +            return false;
 +        }
 +        SpanlessEq::new(cx).eq_expr(lhs, rhs)
 +    };
 +
 +    for (i, j) in search_same(conds, |e| hash_expr(cx, e), eq) {
 +        span_lint_and_note(
 +            cx,
 +            SAME_FUNCTIONS_IN_IF_CONDITION,
 +            j.span,
 +            "this `if` has the same function call as a previous `if`",
 +            Some(i.span),
 +            "same as this",
 +        );
 +    }
 +}
index fe9f4f9ae3cb9f08ebeef9e3d586fb45650dc3ab,0000000000000000000000000000000000000000..799e71e847a9fcf60fc176d86e413f5aa7de57a1
mode 100644,000000..100644
--- /dev/null
@@@ -1,101 -1,0 +1,101 @@@
-     /// Checks for usage of dbg!() macro.
 +use clippy_utils::diagnostics::span_lint_and_sugg;
 +use clippy_utils::macros::root_macro_call_first_node;
 +use clippy_utils::source::snippet_with_applicability;
 +use clippy_utils::{is_in_cfg_test, is_in_test_function};
 +use rustc_errors::Applicability;
 +use rustc_hir::{Expr, ExprKind};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::sym;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
-     /// `dbg!` macro is intended as a debugging tool. It
-     /// should not be in version control.
++    /// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro.
 +    ///
 +    /// ### Why is this bad?
-                 "`dbg!` macro is intended as a debugging tool",
-                 "ensure to avoid having uses of it in version control",
++    /// The `dbg!` macro is intended as a debugging tool. It should not be present in released
++    /// software or committed to a version control system.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// dbg!(true)
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust,ignore
 +    /// true
 +    /// ```
 +    #[clippy::version = "1.34.0"]
 +    pub DBG_MACRO,
 +    restriction,
 +    "`dbg!` macro is intended as a debugging tool"
 +}
 +
 +#[derive(Copy, Clone)]
 +pub struct DbgMacro {
 +    allow_dbg_in_tests: bool,
 +}
 +
 +impl_lint_pass!(DbgMacro => [DBG_MACRO]);
 +
 +impl DbgMacro {
 +    pub fn new(allow_dbg_in_tests: bool) -> Self {
 +        DbgMacro { allow_dbg_in_tests }
 +    }
 +}
 +
 +impl LateLintPass<'_> for DbgMacro {
 +    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
 +        let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
 +        if cx.tcx.is_diagnostic_item(sym::dbg_macro, macro_call.def_id) {
 +            // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
 +            if self.allow_dbg_in_tests
 +                && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id))
 +            {
 +                return;
 +            }
 +            let mut applicability = Applicability::MachineApplicable;
 +            let suggestion = match expr.peel_drop_temps().kind {
 +                // dbg!()
 +                ExprKind::Block(_, _) => String::new(),
 +                // dbg!(1)
 +                ExprKind::Match(val, ..) => {
 +                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string()
 +                },
 +                // dbg!(2, 3)
 +                ExprKind::Tup(
 +                    [
 +                        Expr {
 +                            kind: ExprKind::Match(first, ..),
 +                            ..
 +                        },
 +                        ..,
 +                        Expr {
 +                            kind: ExprKind::Match(last, ..),
 +                            ..
 +                        },
 +                    ],
 +                ) => {
 +                    let snippet = snippet_with_applicability(
 +                        cx,
 +                        first.span.source_callsite().to(last.span.source_callsite()),
 +                        "..",
 +                        &mut applicability,
 +                    );
 +                    format!("({snippet})")
 +                },
 +                _ => return,
 +            };
 +
 +            span_lint_and_sugg(
 +                cx,
 +                DBG_MACRO,
 +                macro_call.span,
++                "the `dbg!` macro is intended as a debugging tool",
++                "remove the invocation before committing it to a version control system",
 +                suggestion,
 +                applicability,
 +            );
 +        }
 +    }
 +}
index 2982460c9cfa49b6d2a4850eae3edd85a3daaa4f,0000000000000000000000000000000000000000..91ca73633f062d7e0f1c3e10ac31b3ef085ec297
mode 100644,000000..100644
--- /dev/null
@@@ -1,636 -1,0 +1,636 @@@
-     crate::derive::DERIVE_HASH_XOR_EQ_INFO,
 +// This file was generated by `cargo dev update_lints`.
 +// Use that command to update this file and do not edit by hand.
 +// Manual edits will be overwritten.
 +
 +pub(crate) static LINTS: &[&crate::LintInfo] = &[
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::if_chain_style::IF_CHAIN_STYLE_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::invalid_paths::INVALID_PATHS_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
 +    #[cfg(feature = "internal")]
 +    crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
 +    crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
 +    crate::approx_const::APPROX_CONSTANT_INFO,
 +    crate::as_conversions::AS_CONVERSIONS_INFO,
 +    crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
 +    crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO,
 +    crate::assertions_on_constants::ASSERTIONS_ON_CONSTANTS_INFO,
 +    crate::assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES_INFO,
 +    crate::async_yields_async::ASYNC_YIELDS_ASYNC_INFO,
 +    crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO,
 +    crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
 +    crate::attrs::DEPRECATED_CFG_ATTR_INFO,
 +    crate::attrs::DEPRECATED_SEMVER_INFO,
 +    crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
 +    crate::attrs::INLINE_ALWAYS_INFO,
 +    crate::attrs::MISMATCHED_TARGET_OS_INFO,
 +    crate::attrs::USELESS_ATTRIBUTE_INFO,
 +    crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
 +    crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
 +    crate::await_holding_invalid::AWAIT_HOLDING_REFCELL_REF_INFO,
 +    crate::blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS_INFO,
 +    crate::bool_assert_comparison::BOOL_ASSERT_COMPARISON_INFO,
 +    crate::bool_to_int_with_if::BOOL_TO_INT_WITH_IF_INFO,
 +    crate::booleans::NONMINIMAL_BOOL_INFO,
 +    crate::booleans::OVERLY_COMPLEX_BOOL_EXPR_INFO,
 +    crate::borrow_deref_ref::BORROW_DEREF_REF_INFO,
 +    crate::box_default::BOX_DEFAULT_INFO,
 +    crate::cargo::CARGO_COMMON_METADATA_INFO,
 +    crate::cargo::MULTIPLE_CRATE_VERSIONS_INFO,
 +    crate::cargo::NEGATIVE_FEATURE_NAMES_INFO,
 +    crate::cargo::REDUNDANT_FEATURE_NAMES_INFO,
 +    crate::cargo::WILDCARD_DEPENDENCIES_INFO,
 +    crate::casts::AS_PTR_CAST_MUT_INFO,
 +    crate::casts::AS_UNDERSCORE_INFO,
 +    crate::casts::BORROW_AS_PTR_INFO,
 +    crate::casts::CAST_ABS_TO_UNSIGNED_INFO,
 +    crate::casts::CAST_ENUM_CONSTRUCTOR_INFO,
 +    crate::casts::CAST_ENUM_TRUNCATION_INFO,
 +    crate::casts::CAST_LOSSLESS_INFO,
 +    crate::casts::CAST_NAN_TO_INT_INFO,
 +    crate::casts::CAST_POSSIBLE_TRUNCATION_INFO,
 +    crate::casts::CAST_POSSIBLE_WRAP_INFO,
 +    crate::casts::CAST_PRECISION_LOSS_INFO,
 +    crate::casts::CAST_PTR_ALIGNMENT_INFO,
 +    crate::casts::CAST_REF_TO_MUT_INFO,
 +    crate::casts::CAST_SIGN_LOSS_INFO,
 +    crate::casts::CAST_SLICE_DIFFERENT_SIZES_INFO,
 +    crate::casts::CAST_SLICE_FROM_RAW_PARTS_INFO,
 +    crate::casts::CHAR_LIT_AS_U8_INFO,
 +    crate::casts::FN_TO_NUMERIC_CAST_INFO,
 +    crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO,
 +    crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
 +    crate::casts::PTR_AS_PTR_INFO,
 +    crate::casts::UNNECESSARY_CAST_INFO,
 +    crate::checked_conversions::CHECKED_CONVERSIONS_INFO,
 +    crate::cognitive_complexity::COGNITIVE_COMPLEXITY_INFO,
 +    crate::collapsible_if::COLLAPSIBLE_ELSE_IF_INFO,
 +    crate::collapsible_if::COLLAPSIBLE_IF_INFO,
 +    crate::comparison_chain::COMPARISON_CHAIN_INFO,
 +    crate::copies::BRANCHES_SHARING_CODE_INFO,
 +    crate::copies::IFS_SAME_COND_INFO,
 +    crate::copies::IF_SAME_THEN_ELSE_INFO,
 +    crate::copies::SAME_FUNCTIONS_IN_IF_CONDITION_INFO,
 +    crate::copy_iterator::COPY_ITERATOR_INFO,
 +    crate::crate_in_macro_def::CRATE_IN_MACRO_DEF_INFO,
 +    crate::create_dir::CREATE_DIR_INFO,
 +    crate::dbg_macro::DBG_MACRO_INFO,
 +    crate::default::DEFAULT_TRAIT_ACCESS_INFO,
 +    crate::default::FIELD_REASSIGN_WITH_DEFAULT_INFO,
 +    crate::default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY_INFO,
 +    crate::default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK_INFO,
 +    crate::default_union_representation::DEFAULT_UNION_REPRESENTATION_INFO,
 +    crate::dereference::EXPLICIT_AUTO_DEREF_INFO,
 +    crate::dereference::EXPLICIT_DEREF_METHODS_INFO,
 +    crate::dereference::NEEDLESS_BORROW_INFO,
 +    crate::dereference::REF_BINDING_TO_REFERENCE_INFO,
 +    crate::derivable_impls::DERIVABLE_IMPLS_INFO,
++    crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO,
 +    crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO,
 +    crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO,
 +    crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO,
 +    crate::derive::UNSAFE_DERIVE_DESERIALIZE_INFO,
 +    crate::disallowed_macros::DISALLOWED_MACROS_INFO,
 +    crate::disallowed_methods::DISALLOWED_METHODS_INFO,
 +    crate::disallowed_names::DISALLOWED_NAMES_INFO,
 +    crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO,
 +    crate::disallowed_types::DISALLOWED_TYPES_INFO,
 +    crate::doc::DOC_LINK_WITH_QUOTES_INFO,
 +    crate::doc::DOC_MARKDOWN_INFO,
 +    crate::doc::MISSING_ERRORS_DOC_INFO,
 +    crate::doc::MISSING_PANICS_DOC_INFO,
 +    crate::doc::MISSING_SAFETY_DOC_INFO,
 +    crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
 +    crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
 +    crate::double_parens::DOUBLE_PARENS_INFO,
 +    crate::drop_forget_ref::DROP_COPY_INFO,
 +    crate::drop_forget_ref::DROP_NON_DROP_INFO,
 +    crate::drop_forget_ref::DROP_REF_INFO,
 +    crate::drop_forget_ref::FORGET_COPY_INFO,
 +    crate::drop_forget_ref::FORGET_NON_DROP_INFO,
 +    crate::drop_forget_ref::FORGET_REF_INFO,
 +    crate::drop_forget_ref::UNDROPPED_MANUALLY_DROPS_INFO,
 +    crate::duplicate_mod::DUPLICATE_MOD_INFO,
 +    crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
 +    crate::empty_drop::EMPTY_DROP_INFO,
 +    crate::empty_enum::EMPTY_ENUM_INFO,
 +    crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
 +    crate::entry::MAP_ENTRY_INFO,
 +    crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO,
 +    crate::enum_variants::ENUM_VARIANT_NAMES_INFO,
 +    crate::enum_variants::MODULE_INCEPTION_INFO,
 +    crate::enum_variants::MODULE_NAME_REPETITIONS_INFO,
 +    crate::equatable_if_let::EQUATABLE_IF_LET_INFO,
 +    crate::escape::BOXED_LOCAL_INFO,
 +    crate::eta_reduction::REDUNDANT_CLOSURE_INFO,
 +    crate::eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS_INFO,
 +    crate::excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS_INFO,
 +    crate::excessive_bools::STRUCT_EXCESSIVE_BOOLS_INFO,
 +    crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO,
 +    crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
 +    crate::exit::EXIT_INFO,
 +    crate::explicit_write::EXPLICIT_WRITE_INFO,
 +    crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO,
 +    crate::float_literal::EXCESSIVE_PRECISION_INFO,
 +    crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
 +    crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
 +    crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
 +    crate::fn_null_check::FN_NULL_CHECK_INFO,
 +    crate::format::USELESS_FORMAT_INFO,
 +    crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
 +    crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
 +    crate::format_args::UNINLINED_FORMAT_ARGS_INFO,
 +    crate::format_args::UNUSED_FORMAT_SPECS_INFO,
 +    crate::format_impl::PRINT_IN_FORMAT_IMPL_INFO,
 +    crate::format_impl::RECURSIVE_FORMAT_IMPL_INFO,
 +    crate::format_push_string::FORMAT_PUSH_STRING_INFO,
 +    crate::formatting::POSSIBLE_MISSING_COMMA_INFO,
 +    crate::formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING_INFO,
 +    crate::formatting::SUSPICIOUS_ELSE_FORMATTING_INFO,
 +    crate::formatting::SUSPICIOUS_UNARY_OP_FORMATTING_INFO,
 +    crate::from_over_into::FROM_OVER_INTO_INFO,
 +    crate::from_raw_with_void_ptr::FROM_RAW_WITH_VOID_PTR_INFO,
 +    crate::from_str_radix_10::FROM_STR_RADIX_10_INFO,
 +    crate::functions::DOUBLE_MUST_USE_INFO,
 +    crate::functions::MISNAMED_GETTERS_INFO,
 +    crate::functions::MUST_USE_CANDIDATE_INFO,
 +    crate::functions::MUST_USE_UNIT_INFO,
 +    crate::functions::NOT_UNSAFE_PTR_ARG_DEREF_INFO,
 +    crate::functions::RESULT_LARGE_ERR_INFO,
 +    crate::functions::RESULT_UNIT_ERR_INFO,
 +    crate::functions::TOO_MANY_ARGUMENTS_INFO,
 +    crate::functions::TOO_MANY_LINES_INFO,
 +    crate::future_not_send::FUTURE_NOT_SEND_INFO,
 +    crate::if_let_mutex::IF_LET_MUTEX_INFO,
 +    crate::if_not_else::IF_NOT_ELSE_INFO,
 +    crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
 +    crate::implicit_hasher::IMPLICIT_HASHER_INFO,
 +    crate::implicit_return::IMPLICIT_RETURN_INFO,
 +    crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
 +    crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
 +    crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
 +    crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO,
 +    crate::indexing_slicing::INDEXING_SLICING_INFO,
 +    crate::indexing_slicing::OUT_OF_BOUNDS_INDEXING_INFO,
 +    crate::infinite_iter::INFINITE_ITER_INFO,
 +    crate::infinite_iter::MAYBE_INFINITE_ITER_INFO,
 +    crate::inherent_impl::MULTIPLE_INHERENT_IMPL_INFO,
 +    crate::inherent_to_string::INHERENT_TO_STRING_INFO,
 +    crate::inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY_INFO,
 +    crate::init_numbered_fields::INIT_NUMBERED_FIELDS_INFO,
 +    crate::inline_fn_without_body::INLINE_FN_WITHOUT_BODY_INFO,
 +    crate::instant_subtraction::MANUAL_INSTANT_ELAPSED_INFO,
 +    crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
 +    crate::int_plus_one::INT_PLUS_ONE_INFO,
 +    crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
 +    crate::invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED_INFO,
 +    crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO,
 +    crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
 +    crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO,
 +    crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO,
 +    crate::large_include_file::LARGE_INCLUDE_FILE_INFO,
 +    crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO,
 +    crate::len_zero::COMPARISON_TO_EMPTY_INFO,
 +    crate::len_zero::LEN_WITHOUT_IS_EMPTY_INFO,
 +    crate::len_zero::LEN_ZERO_INFO,
 +    crate::let_if_seq::USELESS_LET_IF_SEQ_INFO,
 +    crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
 +    crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
 +    crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
 +    crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
 +    crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
 +    crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO,
 +    crate::literal_representation::INCONSISTENT_DIGIT_GROUPING_INFO,
 +    crate::literal_representation::LARGE_DIGIT_GROUPS_INFO,
 +    crate::literal_representation::MISTYPED_LITERAL_SUFFIXES_INFO,
 +    crate::literal_representation::UNREADABLE_LITERAL_INFO,
 +    crate::literal_representation::UNUSUAL_BYTE_GROUPINGS_INFO,
 +    crate::loops::EMPTY_LOOP_INFO,
 +    crate::loops::EXPLICIT_COUNTER_LOOP_INFO,
 +    crate::loops::EXPLICIT_INTO_ITER_LOOP_INFO,
 +    crate::loops::EXPLICIT_ITER_LOOP_INFO,
 +    crate::loops::FOR_KV_MAP_INFO,
 +    crate::loops::ITER_NEXT_LOOP_INFO,
 +    crate::loops::MANUAL_FIND_INFO,
 +    crate::loops::MANUAL_FLATTEN_INFO,
 +    crate::loops::MANUAL_MEMCPY_INFO,
 +    crate::loops::MISSING_SPIN_LOOP_INFO,
 +    crate::loops::MUT_RANGE_BOUND_INFO,
 +    crate::loops::NEEDLESS_RANGE_LOOP_INFO,
 +    crate::loops::NEVER_LOOP_INFO,
 +    crate::loops::SAME_ITEM_PUSH_INFO,
 +    crate::loops::SINGLE_ELEMENT_LOOP_INFO,
 +    crate::loops::WHILE_IMMUTABLE_CONDITION_INFO,
 +    crate::loops::WHILE_LET_LOOP_INFO,
 +    crate::loops::WHILE_LET_ON_ITERATOR_INFO,
 +    crate::macro_use::MACRO_USE_IMPORTS_INFO,
 +    crate::main_recursion::MAIN_RECURSION_INFO,
 +    crate::manual_assert::MANUAL_ASSERT_INFO,
 +    crate::manual_async_fn::MANUAL_ASYNC_FN_INFO,
 +    crate::manual_bits::MANUAL_BITS_INFO,
 +    crate::manual_clamp::MANUAL_CLAMP_INFO,
 +    crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO,
 +    crate::manual_let_else::MANUAL_LET_ELSE_INFO,
 +    crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
 +    crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO,
 +    crate::manual_retain::MANUAL_RETAIN_INFO,
 +    crate::manual_string_new::MANUAL_STRING_NEW_INFO,
 +    crate::manual_strip::MANUAL_STRIP_INFO,
 +    crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO,
 +    crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO,
 +    crate::match_result_ok::MATCH_RESULT_OK_INFO,
 +    crate::matches::COLLAPSIBLE_MATCH_INFO,
 +    crate::matches::INFALLIBLE_DESTRUCTURING_MATCH_INFO,
 +    crate::matches::MANUAL_FILTER_INFO,
 +    crate::matches::MANUAL_MAP_INFO,
 +    crate::matches::MANUAL_UNWRAP_OR_INFO,
 +    crate::matches::MATCH_AS_REF_INFO,
 +    crate::matches::MATCH_BOOL_INFO,
 +    crate::matches::MATCH_LIKE_MATCHES_MACRO_INFO,
 +    crate::matches::MATCH_ON_VEC_ITEMS_INFO,
 +    crate::matches::MATCH_OVERLAPPING_ARM_INFO,
 +    crate::matches::MATCH_REF_PATS_INFO,
 +    crate::matches::MATCH_SAME_ARMS_INFO,
 +    crate::matches::MATCH_SINGLE_BINDING_INFO,
 +    crate::matches::MATCH_STR_CASE_MISMATCH_INFO,
 +    crate::matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS_INFO,
 +    crate::matches::MATCH_WILD_ERR_ARM_INFO,
 +    crate::matches::NEEDLESS_MATCH_INFO,
 +    crate::matches::REDUNDANT_PATTERN_MATCHING_INFO,
 +    crate::matches::REST_PAT_IN_FULLY_BOUND_STRUCTS_INFO,
 +    crate::matches::SIGNIFICANT_DROP_IN_SCRUTINEE_INFO,
 +    crate::matches::SINGLE_MATCH_INFO,
 +    crate::matches::SINGLE_MATCH_ELSE_INFO,
 +    crate::matches::TRY_ERR_INFO,
 +    crate::matches::WILDCARD_ENUM_MATCH_ARM_INFO,
 +    crate::matches::WILDCARD_IN_OR_PATTERNS_INFO,
 +    crate::mem_forget::MEM_FORGET_INFO,
 +    crate::mem_replace::MEM_REPLACE_OPTION_WITH_NONE_INFO,
 +    crate::mem_replace::MEM_REPLACE_WITH_DEFAULT_INFO,
 +    crate::mem_replace::MEM_REPLACE_WITH_UNINIT_INFO,
 +    crate::methods::BIND_INSTEAD_OF_MAP_INFO,
 +    crate::methods::BYTES_COUNT_TO_LEN_INFO,
 +    crate::methods::BYTES_NTH_INFO,
 +    crate::methods::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS_INFO,
 +    crate::methods::CHARS_LAST_CMP_INFO,
 +    crate::methods::CHARS_NEXT_CMP_INFO,
 +    crate::methods::CLONED_INSTEAD_OF_COPIED_INFO,
 +    crate::methods::CLONE_DOUBLE_REF_INFO,
 +    crate::methods::CLONE_ON_COPY_INFO,
 +    crate::methods::CLONE_ON_REF_PTR_INFO,
 +    crate::methods::COLLAPSIBLE_STR_REPLACE_INFO,
 +    crate::methods::ERR_EXPECT_INFO,
 +    crate::methods::EXPECT_FUN_CALL_INFO,
 +    crate::methods::EXPECT_USED_INFO,
 +    crate::methods::EXTEND_WITH_DRAIN_INFO,
 +    crate::methods::FILETYPE_IS_FILE_INFO,
 +    crate::methods::FILTER_MAP_IDENTITY_INFO,
 +    crate::methods::FILTER_MAP_NEXT_INFO,
 +    crate::methods::FILTER_NEXT_INFO,
 +    crate::methods::FLAT_MAP_IDENTITY_INFO,
 +    crate::methods::FLAT_MAP_OPTION_INFO,
 +    crate::methods::FROM_ITER_INSTEAD_OF_COLLECT_INFO,
 +    crate::methods::GET_FIRST_INFO,
 +    crate::methods::GET_LAST_WITH_LEN_INFO,
 +    crate::methods::GET_UNWRAP_INFO,
 +    crate::methods::IMPLICIT_CLONE_INFO,
 +    crate::methods::INEFFICIENT_TO_STRING_INFO,
 +    crate::methods::INSPECT_FOR_EACH_INFO,
 +    crate::methods::INTO_ITER_ON_REF_INFO,
 +    crate::methods::IS_DIGIT_ASCII_RADIX_INFO,
 +    crate::methods::ITERATOR_STEP_BY_ZERO_INFO,
 +    crate::methods::ITER_CLONED_COLLECT_INFO,
 +    crate::methods::ITER_COUNT_INFO,
 +    crate::methods::ITER_KV_MAP_INFO,
 +    crate::methods::ITER_NEXT_SLICE_INFO,
 +    crate::methods::ITER_NTH_INFO,
 +    crate::methods::ITER_NTH_ZERO_INFO,
 +    crate::methods::ITER_ON_EMPTY_COLLECTIONS_INFO,
 +    crate::methods::ITER_ON_SINGLE_ITEMS_INFO,
 +    crate::methods::ITER_OVEREAGER_CLONED_INFO,
 +    crate::methods::ITER_SKIP_NEXT_INFO,
 +    crate::methods::ITER_WITH_DRAIN_INFO,
 +    crate::methods::MANUAL_FILTER_MAP_INFO,
 +    crate::methods::MANUAL_FIND_MAP_INFO,
 +    crate::methods::MANUAL_OK_OR_INFO,
 +    crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
 +    crate::methods::MANUAL_SPLIT_ONCE_INFO,
 +    crate::methods::MANUAL_STR_REPEAT_INFO,
 +    crate::methods::MAP_CLONE_INFO,
 +    crate::methods::MAP_COLLECT_RESULT_UNIT_INFO,
 +    crate::methods::MAP_ERR_IGNORE_INFO,
 +    crate::methods::MAP_FLATTEN_INFO,
 +    crate::methods::MAP_IDENTITY_INFO,
 +    crate::methods::MAP_UNWRAP_OR_INFO,
 +    crate::methods::MUT_MUTEX_LOCK_INFO,
 +    crate::methods::NAIVE_BYTECOUNT_INFO,
 +    crate::methods::NEEDLESS_COLLECT_INFO,
 +    crate::methods::NEEDLESS_OPTION_AS_DEREF_INFO,
 +    crate::methods::NEEDLESS_OPTION_TAKE_INFO,
 +    crate::methods::NEEDLESS_SPLITN_INFO,
 +    crate::methods::NEW_RET_NO_SELF_INFO,
 +    crate::methods::NONSENSICAL_OPEN_OPTIONS_INFO,
 +    crate::methods::NO_EFFECT_REPLACE_INFO,
 +    crate::methods::OBFUSCATED_IF_ELSE_INFO,
 +    crate::methods::OK_EXPECT_INFO,
 +    crate::methods::OPTION_AS_REF_DEREF_INFO,
 +    crate::methods::OPTION_FILTER_MAP_INFO,
 +    crate::methods::OPTION_MAP_OR_NONE_INFO,
 +    crate::methods::OR_FUN_CALL_INFO,
 +    crate::methods::OR_THEN_UNWRAP_INFO,
 +    crate::methods::PATH_BUF_PUSH_OVERWRITE_INFO,
 +    crate::methods::RANGE_ZIP_WITH_LEN_INFO,
 +    crate::methods::REPEAT_ONCE_INFO,
 +    crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO,
 +    crate::methods::SEARCH_IS_SOME_INFO,
 +    crate::methods::SEEK_FROM_CURRENT_INFO,
 +    crate::methods::SEEK_TO_START_INSTEAD_OF_REWIND_INFO,
 +    crate::methods::SHOULD_IMPLEMENT_TRAIT_INFO,
 +    crate::methods::SINGLE_CHAR_ADD_STR_INFO,
 +    crate::methods::SINGLE_CHAR_PATTERN_INFO,
 +    crate::methods::SKIP_WHILE_NEXT_INFO,
 +    crate::methods::STABLE_SORT_PRIMITIVE_INFO,
 +    crate::methods::STRING_EXTEND_CHARS_INFO,
 +    crate::methods::SUSPICIOUS_MAP_INFO,
 +    crate::methods::SUSPICIOUS_SPLITN_INFO,
 +    crate::methods::SUSPICIOUS_TO_OWNED_INFO,
 +    crate::methods::UNINIT_ASSUMED_INIT_INFO,
 +    crate::methods::UNIT_HASH_INFO,
 +    crate::methods::UNNECESSARY_FILTER_MAP_INFO,
 +    crate::methods::UNNECESSARY_FIND_MAP_INFO,
 +    crate::methods::UNNECESSARY_FOLD_INFO,
 +    crate::methods::UNNECESSARY_JOIN_INFO,
 +    crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO,
 +    crate::methods::UNNECESSARY_SORT_BY_INFO,
 +    crate::methods::UNNECESSARY_TO_OWNED_INFO,
 +    crate::methods::UNWRAP_OR_ELSE_DEFAULT_INFO,
 +    crate::methods::UNWRAP_USED_INFO,
 +    crate::methods::USELESS_ASREF_INFO,
 +    crate::methods::VEC_RESIZE_TO_ZERO_INFO,
 +    crate::methods::VERBOSE_FILE_READS_INFO,
 +    crate::methods::WRONG_SELF_CONVENTION_INFO,
 +    crate::methods::ZST_OFFSET_INFO,
 +    crate::minmax::MIN_MAX_INFO,
 +    crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
 +    crate::misc::TOPLEVEL_REF_ARG_INFO,
 +    crate::misc::USED_UNDERSCORE_BINDING_INFO,
 +    crate::misc::ZERO_PTR_INFO,
 +    crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
 +    crate::misc_early::DOUBLE_NEG_INFO,
 +    crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
 +    crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO,
 +    crate::misc_early::REDUNDANT_PATTERN_INFO,
 +    crate::misc_early::SEPARATED_LITERAL_SUFFIX_INFO,
 +    crate::misc_early::UNNEEDED_FIELD_PATTERN_INFO,
 +    crate::misc_early::UNNEEDED_WILDCARD_PATTERN_INFO,
 +    crate::misc_early::UNSEPARATED_LITERAL_SUFFIX_INFO,
 +    crate::misc_early::ZERO_PREFIXED_LITERAL_INFO,
 +    crate::mismatching_type_param_order::MISMATCHING_TYPE_PARAM_ORDER_INFO,
 +    crate::missing_const_for_fn::MISSING_CONST_FOR_FN_INFO,
 +    crate::missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS_INFO,
 +    crate::missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES_INFO,
 +    crate::missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS_INFO,
 +    crate::missing_trait_methods::MISSING_TRAIT_METHODS_INFO,
 +    crate::mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION_INFO,
 +    crate::mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION_INFO,
 +    crate::module_style::MOD_MODULE_FILES_INFO,
 +    crate::module_style::SELF_NAMED_MODULE_FILES_INFO,
 +    crate::multi_assignments::MULTI_ASSIGNMENTS_INFO,
 +    crate::mut_key::MUTABLE_KEY_TYPE_INFO,
 +    crate::mut_mut::MUT_MUT_INFO,
 +    crate::mut_reference::UNNECESSARY_MUT_PASSED_INFO,
 +    crate::mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL_INFO,
 +    crate::mutex_atomic::MUTEX_ATOMIC_INFO,
 +    crate::mutex_atomic::MUTEX_INTEGER_INFO,
 +    crate::needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE_INFO,
 +    crate::needless_bool::BOOL_COMPARISON_INFO,
 +    crate::needless_bool::NEEDLESS_BOOL_INFO,
 +    crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO,
 +    crate::needless_continue::NEEDLESS_CONTINUE_INFO,
 +    crate::needless_for_each::NEEDLESS_FOR_EACH_INFO,
 +    crate::needless_late_init::NEEDLESS_LATE_INIT_INFO,
 +    crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO,
 +    crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO,
 +    crate::needless_question_mark::NEEDLESS_QUESTION_MARK_INFO,
 +    crate::needless_update::NEEDLESS_UPDATE_INFO,
 +    crate::neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD_INFO,
 +    crate::neg_multiply::NEG_MULTIPLY_INFO,
 +    crate::new_without_default::NEW_WITHOUT_DEFAULT_INFO,
 +    crate::no_effect::NO_EFFECT_INFO,
 +    crate::no_effect::NO_EFFECT_UNDERSCORE_BINDING_INFO,
 +    crate::no_effect::UNNECESSARY_OPERATION_INFO,
 +    crate::non_copy_const::BORROW_INTERIOR_MUTABLE_CONST_INFO,
 +    crate::non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST_INFO,
 +    crate::non_expressive_names::JUST_UNDERSCORES_AND_DIGITS_INFO,
 +    crate::non_expressive_names::MANY_SINGLE_CHAR_NAMES_INFO,
 +    crate::non_expressive_names::SIMILAR_NAMES_INFO,
 +    crate::non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS_INFO,
 +    crate::non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY_INFO,
 +    crate::nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES_INFO,
 +    crate::octal_escapes::OCTAL_ESCAPES_INFO,
 +    crate::only_used_in_recursion::ONLY_USED_IN_RECURSION_INFO,
 +    crate::operators::ABSURD_EXTREME_COMPARISONS_INFO,
 +    crate::operators::ARITHMETIC_SIDE_EFFECTS_INFO,
 +    crate::operators::ASSIGN_OP_PATTERN_INFO,
 +    crate::operators::BAD_BIT_MASK_INFO,
 +    crate::operators::CMP_NAN_INFO,
 +    crate::operators::CMP_OWNED_INFO,
 +    crate::operators::DOUBLE_COMPARISONS_INFO,
 +    crate::operators::DURATION_SUBSEC_INFO,
 +    crate::operators::EQ_OP_INFO,
 +    crate::operators::ERASING_OP_INFO,
 +    crate::operators::FLOAT_ARITHMETIC_INFO,
 +    crate::operators::FLOAT_CMP_INFO,
 +    crate::operators::FLOAT_CMP_CONST_INFO,
 +    crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
 +    crate::operators::IDENTITY_OP_INFO,
 +    crate::operators::INEFFECTIVE_BIT_MASK_INFO,
 +    crate::operators::INTEGER_ARITHMETIC_INFO,
 +    crate::operators::INTEGER_DIVISION_INFO,
 +    crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
 +    crate::operators::MODULO_ARITHMETIC_INFO,
 +    crate::operators::MODULO_ONE_INFO,
 +    crate::operators::NEEDLESS_BITWISE_BOOL_INFO,
 +    crate::operators::OP_REF_INFO,
 +    crate::operators::PTR_EQ_INFO,
 +    crate::operators::SELF_ASSIGNMENT_INFO,
 +    crate::operators::VERBOSE_BIT_MASK_INFO,
 +    crate::option_env_unwrap::OPTION_ENV_UNWRAP_INFO,
 +    crate::option_if_let_else::OPTION_IF_LET_ELSE_INFO,
 +    crate::overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL_INFO,
 +    crate::panic_in_result_fn::PANIC_IN_RESULT_FN_INFO,
 +    crate::panic_unimplemented::PANIC_INFO,
 +    crate::panic_unimplemented::TODO_INFO,
 +    crate::panic_unimplemented::UNIMPLEMENTED_INFO,
 +    crate::panic_unimplemented::UNREACHABLE_INFO,
 +    crate::partial_pub_fields::PARTIAL_PUB_FIELDS_INFO,
 +    crate::partialeq_ne_impl::PARTIALEQ_NE_IMPL_INFO,
 +    crate::partialeq_to_none::PARTIALEQ_TO_NONE_INFO,
 +    crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO,
 +    crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO,
 +    crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
 +    crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
 +    crate::precedence::PRECEDENCE_INFO,
 +    crate::ptr::CMP_NULL_INFO,
 +    crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
 +    crate::ptr::MUT_FROM_REF_INFO,
 +    crate::ptr::PTR_ARG_INFO,
 +    crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO,
 +    crate::pub_use::PUB_USE_INFO,
 +    crate::question_mark::QUESTION_MARK_INFO,
 +    crate::ranges::MANUAL_RANGE_CONTAINS_INFO,
 +    crate::ranges::RANGE_MINUS_ONE_INFO,
 +    crate::ranges::RANGE_PLUS_ONE_INFO,
 +    crate::ranges::REVERSED_EMPTY_RANGES_INFO,
 +    crate::rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT_INFO,
 +    crate::read_zero_byte_vec::READ_ZERO_BYTE_VEC_INFO,
 +    crate::redundant_clone::REDUNDANT_CLONE_INFO,
 +    crate::redundant_closure_call::REDUNDANT_CLOSURE_CALL_INFO,
 +    crate::redundant_else::REDUNDANT_ELSE_INFO,
 +    crate::redundant_field_names::REDUNDANT_FIELD_NAMES_INFO,
 +    crate::redundant_pub_crate::REDUNDANT_PUB_CRATE_INFO,
 +    crate::redundant_slicing::DEREF_BY_SLICING_INFO,
 +    crate::redundant_slicing::REDUNDANT_SLICING_INFO,
 +    crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
 +    crate::ref_option_ref::REF_OPTION_REF_INFO,
 +    crate::reference::DEREF_ADDROF_INFO,
 +    crate::regex::INVALID_REGEX_INFO,
 +    crate::regex::TRIVIAL_REGEX_INFO,
 +    crate::return_self_not_must_use::RETURN_SELF_NOT_MUST_USE_INFO,
 +    crate::returns::LET_AND_RETURN_INFO,
 +    crate::returns::NEEDLESS_RETURN_INFO,
 +    crate::same_name_method::SAME_NAME_METHOD_INFO,
 +    crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
 +    crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,
 +    crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO,
 +    crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO,
 +    crate::serde_api::SERDE_API_MISUSE_INFO,
 +    crate::shadow::SHADOW_REUSE_INFO,
 +    crate::shadow::SHADOW_SAME_INFO,
 +    crate::shadow::SHADOW_UNRELATED_INFO,
 +    crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
 +    crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
 +    crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
 +    crate::size_of_ref::SIZE_OF_REF_INFO,
 +    crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
 +    crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO,
 +    crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO,
 +    crate::std_instead_of_core::STD_INSTEAD_OF_CORE_INFO,
 +    crate::strings::STRING_ADD_INFO,
 +    crate::strings::STRING_ADD_ASSIGN_INFO,
 +    crate::strings::STRING_FROM_UTF8_AS_BYTES_INFO,
 +    crate::strings::STRING_LIT_AS_BYTES_INFO,
 +    crate::strings::STRING_SLICE_INFO,
 +    crate::strings::STRING_TO_STRING_INFO,
 +    crate::strings::STR_TO_STRING_INFO,
 +    crate::strings::TRIM_SPLIT_WHITESPACE_INFO,
 +    crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO,
 +    crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO,
 +    crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO,
 +    crate::suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL_INFO,
 +    crate::suspicious_xor_used_as_pow::SUSPICIOUS_XOR_USED_AS_POW_INFO,
 +    crate::swap::ALMOST_SWAPPED_INFO,
 +    crate::swap::MANUAL_SWAP_INFO,
 +    crate::swap_ptr_to_ref::SWAP_PTR_TO_REF_INFO,
 +    crate::tabs_in_doc_comments::TABS_IN_DOC_COMMENTS_INFO,
 +    crate::temporary_assignment::TEMPORARY_ASSIGNMENT_INFO,
 +    crate::to_digit_is_some::TO_DIGIT_IS_SOME_INFO,
 +    crate::trailing_empty_array::TRAILING_EMPTY_ARRAY_INFO,
 +    crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO,
 +    crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO,
 +    crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
 +    crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
 +    crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
 +    crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO,
 +    crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
 +    crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO,
 +    crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO,
 +    crate::transmute::TRANSMUTE_NULL_TO_FN_INFO,
 +    crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO,
 +    crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO,
 +    crate::transmute::TRANSMUTE_PTR_TO_REF_INFO,
 +    crate::transmute::TRANSMUTE_UNDEFINED_REPR_INFO,
 +    crate::transmute::TRANSMUTING_NULL_INFO,
 +    crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO,
 +    crate::transmute::USELESS_TRANSMUTE_INFO,
 +    crate::transmute::WRONG_TRANSMUTE_INFO,
 +    crate::types::BORROWED_BOX_INFO,
 +    crate::types::BOX_COLLECTION_INFO,
 +    crate::types::LINKEDLIST_INFO,
 +    crate::types::OPTION_OPTION_INFO,
 +    crate::types::RC_BUFFER_INFO,
 +    crate::types::RC_MUTEX_INFO,
 +    crate::types::REDUNDANT_ALLOCATION_INFO,
 +    crate::types::TYPE_COMPLEXITY_INFO,
 +    crate::types::VEC_BOX_INFO,
 +    crate::undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS_INFO,
 +    crate::undocumented_unsafe_blocks::UNNECESSARY_SAFETY_COMMENT_INFO,
 +    crate::unicode::INVISIBLE_CHARACTERS_INFO,
 +    crate::unicode::NON_ASCII_LITERAL_INFO,
 +    crate::unicode::UNICODE_NOT_NFC_INFO,
 +    crate::uninit_vec::UNINIT_VEC_INFO,
 +    crate::unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD_INFO,
 +    crate::unit_types::LET_UNIT_VALUE_INFO,
 +    crate::unit_types::UNIT_ARG_INFO,
 +    crate::unit_types::UNIT_CMP_INFO,
 +    crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
 +    crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
 +    crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
 +    crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
 +    crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
 +    crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
 +    crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
 +    crate::unused_async::UNUSED_ASYNC_INFO,
 +    crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO,
 +    crate::unused_peekable::UNUSED_PEEKABLE_INFO,
 +    crate::unused_rounding::UNUSED_ROUNDING_INFO,
 +    crate::unused_self::UNUSED_SELF_INFO,
 +    crate::unused_unit::UNUSED_UNIT_INFO,
 +    crate::unwrap::PANICKING_UNWRAP_INFO,
 +    crate::unwrap::UNNECESSARY_UNWRAP_INFO,
 +    crate::unwrap_in_result::UNWRAP_IN_RESULT_INFO,
 +    crate::upper_case_acronyms::UPPER_CASE_ACRONYMS_INFO,
 +    crate::use_self::USE_SELF_INFO,
 +    crate::useless_conversion::USELESS_CONVERSION_INFO,
 +    crate::vec::USELESS_VEC_INFO,
 +    crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO,
 +    crate::wildcard_imports::ENUM_GLOB_USE_INFO,
 +    crate::wildcard_imports::WILDCARD_IMPORTS_INFO,
 +    crate::write::PRINTLN_EMPTY_STRING_INFO,
 +    crate::write::PRINT_LITERAL_INFO,
 +    crate::write::PRINT_STDERR_INFO,
 +    crate::write::PRINT_STDOUT_INFO,
 +    crate::write::PRINT_WITH_NEWLINE_INFO,
 +    crate::write::USE_DEBUG_INFO,
 +    crate::write::WRITELN_EMPTY_STRING_INFO,
 +    crate::write::WRITE_LITERAL_INFO,
 +    crate::write::WRITE_WITH_NEWLINE_INFO,
 +    crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO,
 +    crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO,
 +];
index 7f937de1dd3120f594436fc8facb97be30e72316,0000000000000000000000000000000000000000..a04693f4637ab9697d0e14171eed47f7867cd81f
mode 100644,000000..100644
--- /dev/null
@@@ -1,307 -1,0 +1,306 @@@
-                 // TODO: Work out a way to put "whatever the imported way of referencing
-                 // this type in this file" rather than a fully-qualified type.
-                 let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did()));
 +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
 +use clippy_utils::source::snippet_with_macro_callsite;
 +use clippy_utils::ty::{has_drop, is_copy};
 +use clippy_utils::{
 +    any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro, match_def_path, paths,
 +};
 +use if_chain::if_chain;
 +use rustc_data_structures::fx::FxHashSet;
 +use rustc_errors::Applicability;
 +use rustc_hir::def::Res;
 +use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::ty;
++use rustc_middle::ty::print::with_forced_trimmed_paths;
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::symbol::{Ident, Symbol};
 +use rustc_span::Span;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for literal calls to `Default::default()`.
 +    ///
 +    /// ### Why is this bad?
 +    /// It's easier for the reader if the name of the type is used, rather than the
 +    /// generic `Default`.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let s: String = Default::default();
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// let s = String::default();
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub DEFAULT_TRAIT_ACCESS,
 +    pedantic,
 +    "checks for literal calls to `Default::default()`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for immediate reassignment of fields initialized
 +    /// with Default::default().
 +    ///
 +    /// ### Why is this bad?
 +    ///It's more idiomatic to use the [functional update syntax](https://doc.rust-lang.org/reference/expressions/struct-expr.html#functional-update-syntax).
 +    ///
 +    /// ### Known problems
 +    /// Assignments to patterns that are of tuple type are not linted.
 +    ///
 +    /// ### Example
 +    /// ```
 +    /// # #[derive(Default)]
 +    /// # struct A { i: i32 }
 +    /// let mut a: A = Default::default();
 +    /// a.i = 42;
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```
 +    /// # #[derive(Default)]
 +    /// # struct A { i: i32 }
 +    /// let a = A {
 +    ///     i: 42,
 +    ///     .. Default::default()
 +    /// };
 +    /// ```
 +    #[clippy::version = "1.49.0"]
 +    pub FIELD_REASSIGN_WITH_DEFAULT,
 +    style,
 +    "binding initialized with Default should have its fields set in the initializer"
 +}
 +
 +#[derive(Default)]
 +pub struct Default {
 +    // Spans linted by `field_reassign_with_default`.
 +    reassigned_linted: FxHashSet<Span>,
 +}
 +
 +impl_lint_pass!(Default => [DEFAULT_TRAIT_ACCESS, FIELD_REASSIGN_WITH_DEFAULT]);
 +
 +impl<'tcx> LateLintPass<'tcx> for Default {
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 +        if_chain! {
 +            if !expr.span.from_expansion();
 +            // Avoid cases already linted by `field_reassign_with_default`
 +            if !self.reassigned_linted.contains(&expr.span);
 +            if let ExprKind::Call(path, ..) = expr.kind;
 +            if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
 +            if let ExprKind::Path(ref qpath) = path.kind;
 +            if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
 +            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
 +            if !is_update_syntax_base(cx, expr);
 +            // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
 +            if let QPath::Resolved(None, _path) = qpath;
 +            let expr_ty = cx.typeck_results().expr_ty(expr);
 +            if let ty::Adt(def, ..) = expr_ty.kind();
 +            if !is_from_proc_macro(cx, expr);
 +            then {
-                     if contains_name(binding_name, assign_rhs) {
++                let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
 +                span_lint_and_sugg(
 +                    cx,
 +                    DEFAULT_TRAIT_ACCESS,
 +                    expr.span,
 +                    &format!("calling `{replacement}` is more clear than this expression"),
 +                    "try",
 +                    replacement,
 +                    Applicability::Unspecified, // First resolve the TODO above
 +                );
 +            }
 +        }
 +    }
 +
 +    #[expect(clippy::too_many_lines)]
 +    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
 +        // start from the `let mut _ = _::default();` and look at all the following
 +        // statements, see if they re-assign the fields of the binding
 +        let stmts_head = match block.stmts {
 +            // Skip the last statement since there cannot possibly be any following statements that re-assign fields.
 +            [head @ .., _] if !head.is_empty() => head,
 +            _ => return,
 +        };
 +        for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
 +            // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
 +            // `default` method of the `Default` trait, and store statement index in current block being
 +            // checked and the name of the bound variable
 +            let (local, variant, binding_name, binding_type, span) = if_chain! {
 +                // only take `let ...` statements
 +                if let StmtKind::Local(local) = stmt.kind;
 +                if let Some(expr) = local.init;
 +                if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
 +                if !expr.span.from_expansion();
 +                // only take bindings to identifiers
 +                if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
 +                // only when assigning `... = Default::default()`
 +                if is_expr_default(expr, cx);
 +                let binding_type = cx.typeck_results().node_type(binding_id);
 +                if let Some(adt) = binding_type.ty_adt_def();
 +                if adt.is_struct();
 +                let variant = adt.non_enum_variant();
 +                if adt.did().is_local() || !variant.is_field_list_non_exhaustive();
 +                let module_did = cx.tcx.parent_module(stmt.hir_id);
 +                if variant
 +                    .fields
 +                    .iter()
 +                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx));
 +                let all_fields_are_copy = variant
 +                    .fields
 +                    .iter()
 +                    .all(|field| {
 +                        is_copy(cx, cx.tcx.type_of(field.did))
 +                    });
 +                if !has_drop(cx, binding_type) || all_fields_are_copy;
 +                then {
 +                    (local, variant, ident.name, binding_type, expr.span)
 +                } else {
 +                    continue;
 +                }
 +            };
 +
 +            // find all "later statement"'s where the fields of the binding set as
 +            // Default::default() get reassigned, unless the reassignment refers to the original binding
 +            let mut first_assign = None;
 +            let mut assigned_fields = Vec::new();
 +            let mut cancel_lint = false;
 +            for consecutive_statement in &block.stmts[stmt_idx + 1..] {
 +                // find out if and which field was set by this `consecutive_statement`
 +                if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
 +                    // interrupt and cancel lint if assign_rhs references the original binding
++                    if contains_name(binding_name, assign_rhs, cx) {
 +                        cancel_lint = true;
 +                        break;
 +                    }
 +
 +                    // if the field was previously assigned, replace the assignment, otherwise insert the assignment
 +                    if let Some(prev) = assigned_fields
 +                        .iter_mut()
 +                        .find(|(field_name, _)| field_name == &field_ident.name)
 +                    {
 +                        *prev = (field_ident.name, assign_rhs);
 +                    } else {
 +                        assigned_fields.push((field_ident.name, assign_rhs));
 +                    }
 +
 +                    // also set first instance of error for help message
 +                    if first_assign.is_none() {
 +                        first_assign = Some(consecutive_statement);
 +                    }
 +                }
 +                // interrupt if no field was assigned, since we only want to look at consecutive statements
 +                else {
 +                    break;
 +                }
 +            }
 +
 +            // if there are incorrectly assigned fields, do a span_lint_and_note to suggest
 +            // construction using `Ty { fields, ..Default::default() }`
 +            if !assigned_fields.is_empty() && !cancel_lint {
 +                // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
 +                let ext_with_default = !variant
 +                    .fields
 +                    .iter()
 +                    .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.name));
 +
 +                let field_list = assigned_fields
 +                    .into_iter()
 +                    .map(|(field, rhs)| {
 +                        // extract and store the assigned value for help message
 +                        let value_snippet = snippet_with_macro_callsite(cx, rhs.span, "..");
 +                        format!("{field}: {value_snippet}")
 +                    })
 +                    .collect::<Vec<String>>()
 +                    .join(", ");
 +
 +                // give correct suggestion if generics are involved (see #6944)
 +                let binding_type = if_chain! {
 +                    if let ty::Adt(adt_def, substs) = binding_type.kind();
 +                    if !substs.is_empty();
 +                    then {
 +                        let adt_def_ty_name = cx.tcx.item_name(adt_def.did());
 +                        let generic_args = substs.iter().collect::<Vec<_>>();
 +                        let tys_str = generic_args
 +                            .iter()
 +                            .map(ToString::to_string)
 +                            .collect::<Vec<_>>()
 +                            .join(", ");
 +                        format!("{adt_def_ty_name}::<{}>", &tys_str)
 +                    } else {
 +                        binding_type.to_string()
 +                    }
 +                };
 +
 +                let sugg = if ext_with_default {
 +                    if field_list.is_empty() {
 +                        format!("{binding_type}::default()")
 +                    } else {
 +                        format!("{binding_type} {{ {field_list}, ..Default::default() }}")
 +                    }
 +                } else {
 +                    format!("{binding_type} {{ {field_list} }}")
 +                };
 +
 +                // span lint once per statement that binds default
 +                span_lint_and_note(
 +                    cx,
 +                    FIELD_REASSIGN_WITH_DEFAULT,
 +                    first_assign.unwrap().span,
 +                    "field assignment outside of initializer for an instance created with Default::default()",
 +                    Some(local.span),
 +                    &format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
 +                );
 +                self.reassigned_linted.insert(span);
 +            }
 +        }
 +    }
 +}
 +
 +/// Checks if the given expression is the `default` method belonging to the `Default` trait.
 +fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool {
 +    if_chain! {
 +        if let ExprKind::Call(fn_expr, _) = &expr.kind;
 +        if let ExprKind::Path(qpath) = &fn_expr.kind;
 +        if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
 +        then {
 +            // right hand side of assignment is `Default::default`
 +            match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD)
 +        } else {
 +            false
 +        }
 +    }
 +}
 +
 +/// Returns the reassigned field and the assigning expression (right-hand side of assign).
 +fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
 +    if_chain! {
 +        // only take assignments
 +        if let StmtKind::Semi(later_expr) = this.kind;
 +        if let ExprKind::Assign(assign_lhs, assign_rhs, _) = later_expr.kind;
 +        // only take assignments to fields where the left-hand side field is a field of
 +        // the same binding as the previous statement
 +        if let ExprKind::Field(binding, field_ident) = assign_lhs.kind;
 +        if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind;
 +        if let Some(second_binding_name) = path.segments.last();
 +        if second_binding_name.ident.name == binding_name;
 +        then {
 +            Some((field_ident, assign_rhs))
 +        } else {
 +            None
 +        }
 +    }
 +}
 +
 +/// Returns whether `expr` is the update syntax base: `Foo { a: 1, .. base }`
 +fn is_update_syntax_base<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
 +    if_chain! {
 +        if let Some(parent) = get_parent_expr(cx, expr);
 +        if let ExprKind::Struct(_, _, Some(base)) = parent.kind;
 +        then {
 +            base.hir_id == expr.hir_id
 +        } else {
 +            false
 +        }
 +    }
 +}
index f327c9a71b3c1f420e98fe502841ac60f1f58df4,0000000000000000000000000000000000000000..05f2b92c037093affa39e21fe5ac1dc058528cb6
mode 100644,000000..100644
--- /dev/null
@@@ -1,1643 -1,0 +1,1643 @@@
-         // If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The
-         // reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible
-         // borrower of itself. See the comment in that method for an explanation as to why.
-         possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location)
 +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 +use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
 +use clippy_utils::msrvs::{self, Msrv};
 +use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 +use clippy_utils::sugg::has_enclosing_paren;
 +use clippy_utils::ty::{expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res};
 +use clippy_utils::{
 +    fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
 +};
 +
 +use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
 +use rustc_data_structures::fx::FxIndexMap;
 +use rustc_data_structures::graph::iterate::{CycleDetector, TriColorDepthFirstSearch};
 +use rustc_errors::Applicability;
 +use rustc_hir::intravisit::{walk_ty, Visitor};
 +use rustc_hir::{
 +    self as hir,
 +    def_id::{DefId, LocalDefId},
 +    BindingAnnotation, Body, BodyId, BorrowKind, Closure, Expr, ExprKind, FnRetTy, GenericArg, HirId, ImplItem,
 +    ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem,
 +    TraitItemKind, TyKind, UnOp,
 +};
 +use rustc_index::bit_set::BitSet;
 +use rustc_infer::infer::TyCtxtInferExt;
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::mir::{Rvalue, StatementKind};
 +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 +use rustc_middle::ty::{
 +    self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
 +    ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
 +};
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::{symbol::sym, Span, Symbol};
 +use rustc_trait_selection::infer::InferCtxtExt as _;
 +use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
 +use std::collections::VecDeque;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for explicit `deref()` or `deref_mut()` method calls.
 +    ///
 +    /// ### Why is this bad?
 +    /// Dereferencing by `&*x` or `&mut *x` is clearer and more concise,
 +    /// when not part of a method chain.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// use std::ops::Deref;
 +    /// let a: &mut String = &mut String::from("foo");
 +    /// let b: &str = a.deref();
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// let a: &mut String = &mut String::from("foo");
 +    /// let b = &*a;
 +    /// ```
 +    ///
 +    /// This lint excludes:
 +    /// ```rust,ignore
 +    /// let _ = d.unwrap().deref();
 +    /// ```
 +    #[clippy::version = "1.44.0"]
 +    pub EXPLICIT_DEREF_METHODS,
 +    pedantic,
 +    "Explicit use of deref or deref_mut method while not in a method chain."
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for address of operations (`&`) that are going to
 +    /// be dereferenced immediately by the compiler.
 +    ///
 +    /// ### Why is this bad?
 +    /// Suggests that the receiver of the expression borrows
 +    /// the expression.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// fn fun(_a: &i32) {}
 +    ///
 +    /// let x: &i32 = &&&&&&5;
 +    /// fun(&x);
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// # fn fun(_a: &i32) {}
 +    /// let x: &i32 = &5;
 +    /// fun(x);
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub NEEDLESS_BORROW,
 +    style,
 +    "taking a reference that is going to be automatically dereferenced"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for `ref` bindings which create a reference to a reference.
 +    ///
 +    /// ### Why is this bad?
 +    /// The address-of operator at the use site is clearer about the need for a reference.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let x = Some("");
 +    /// if let Some(ref x) = x {
 +    ///     // use `x` here
 +    /// }
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// let x = Some("");
 +    /// if let Some(x) = x {
 +    ///     // use `&x` here
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.54.0"]
 +    pub REF_BINDING_TO_REFERENCE,
 +    pedantic,
 +    "`ref` binding to a reference"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for dereferencing expressions which would be covered by auto-deref.
 +    ///
 +    /// ### Why is this bad?
 +    /// This unnecessarily complicates the code.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let x = String::new();
 +    /// let y: &str = &*x;
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    /// let x = String::new();
 +    /// let y: &str = &x;
 +    /// ```
 +    #[clippy::version = "1.64.0"]
 +    pub EXPLICIT_AUTO_DEREF,
 +    complexity,
 +    "dereferencing when the compiler would automatically dereference"
 +}
 +
 +impl_lint_pass!(Dereferencing<'_> => [
 +    EXPLICIT_DEREF_METHODS,
 +    NEEDLESS_BORROW,
 +    REF_BINDING_TO_REFERENCE,
 +    EXPLICIT_AUTO_DEREF,
 +]);
 +
 +#[derive(Default)]
 +pub struct Dereferencing<'tcx> {
 +    state: Option<(State, StateData)>,
 +
 +    // While parsing a `deref` method call in ufcs form, the path to the function is itself an
 +    // expression. This is to store the id of that expression so it can be skipped when
 +    // `check_expr` is called for it.
 +    skip_expr: Option<HirId>,
 +
 +    /// The body the first local was found in. Used to emit lints when the traversal of the body has
 +    /// been finished. Note we can't lint at the end of every body as they can be nested within each
 +    /// other.
 +    current_body: Option<BodyId>,
 +
 +    /// The list of locals currently being checked by the lint.
 +    /// If the value is `None`, then the binding has been seen as a ref pattern, but is not linted.
 +    /// This is needed for or patterns where one of the branches can be linted, but another can not
 +    /// be.
 +    ///
 +    /// e.g. `m!(x) | Foo::Bar(ref x)`
 +    ref_locals: FxIndexMap<HirId, Option<RefPat>>,
 +
 +    /// Stack of (body owner, `PossibleBorrowerMap`) pairs. Used by
 +    /// `needless_borrow_impl_arg_position` to determine when a borrowed expression can instead
 +    /// be moved.
 +    possible_borrowers: Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
 +
 +    // `IntoIterator` for arrays requires Rust 1.53.
 +    msrv: Msrv,
 +}
 +
 +impl<'tcx> Dereferencing<'tcx> {
 +    #[must_use]
 +    pub fn new(msrv: Msrv) -> Self {
 +        Self {
 +            msrv,
 +            ..Dereferencing::default()
 +        }
 +    }
 +}
 +
 +#[derive(Debug)]
 +struct StateData {
 +    /// Span of the top level expression
 +    span: Span,
 +    hir_id: HirId,
 +    position: Position,
 +}
 +
 +#[derive(Debug)]
 +struct DerefedBorrow {
 +    count: usize,
 +    msg: &'static str,
 +    snip_expr: Option<HirId>,
 +}
 +
 +#[derive(Debug)]
 +enum State {
 +    // Any number of deref method calls.
 +    DerefMethod {
 +        // The number of calls in a sequence which changed the referenced type
 +        ty_changed_count: usize,
 +        is_final_ufcs: bool,
 +        /// The required mutability
 +        target_mut: Mutability,
 +    },
 +    DerefedBorrow(DerefedBorrow),
 +    ExplicitDeref {
 +        mutability: Option<Mutability>,
 +    },
 +    ExplicitDerefField {
 +        name: Symbol,
 +    },
 +    Reborrow {
 +        mutability: Mutability,
 +    },
 +    Borrow {
 +        mutability: Mutability,
 +    },
 +}
 +
 +// A reference operation considered by this lint pass
 +enum RefOp {
 +    Method(Mutability),
 +    Deref,
 +    AddrOf(Mutability),
 +}
 +
 +struct RefPat {
 +    /// Whether every usage of the binding is dereferenced.
 +    always_deref: bool,
 +    /// The spans of all the ref bindings for this local.
 +    spans: Vec<Span>,
 +    /// The applicability of this suggestion.
 +    app: Applicability,
 +    /// All the replacements which need to be made.
 +    replacements: Vec<(Span, String)>,
 +    /// The [`HirId`] that the lint should be emitted at.
 +    hir_id: HirId,
 +}
 +
 +impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
 +    #[expect(clippy::too_many_lines)]
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 +        // Skip path expressions from deref calls. e.g. `Deref::deref(e)`
 +        if Some(expr.hir_id) == self.skip_expr.take() {
 +            return;
 +        }
 +
 +        if let Some(local) = path_to_local(expr) {
 +            self.check_local_usage(cx, expr, local);
 +        }
 +
 +        // Stop processing sub expressions when a macro call is seen
 +        if expr.span.from_expansion() {
 +            if let Some((state, data)) = self.state.take() {
 +                report(cx, expr, state, data);
 +            }
 +            return;
 +        }
 +
 +        let typeck = cx.typeck_results();
 +        let Some((kind, sub_expr)) = try_parse_ref_op(cx.tcx, typeck, expr) else {
 +            // The whole chain of reference operations has been seen
 +            if let Some((state, data)) = self.state.take() {
 +                report(cx, expr, state, data);
 +            }
 +            return;
 +        };
 +
 +        match (self.state.take(), kind) {
 +            (None, kind) => {
 +                let expr_ty = typeck.expr_ty(expr);
 +                let (position, adjustments) = walk_parents(cx, &mut self.possible_borrowers, expr, &self.msrv);
 +                match kind {
 +                    RefOp::Deref => {
 +                        let sub_ty = typeck.expr_ty(sub_expr);
 +                        if let Position::FieldAccess {
 +                            name,
 +                            of_union: false,
 +                        } = position
 +                            && !ty_contains_field(sub_ty, name)
 +                        {
 +                            self.state = Some((
 +                                State::ExplicitDerefField { name },
 +                                StateData { span: expr.span, hir_id: expr.hir_id, position },
 +                            ));
 +                        } else if position.is_deref_stable() && sub_ty.is_ref() {
 +                            self.state = Some((
 +                                State::ExplicitDeref { mutability: None },
 +                                StateData { span: expr.span, hir_id: expr.hir_id, position },
 +                            ));
 +                        }
 +                    },
 +                    RefOp::Method(target_mut)
 +                        if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
 +                            && position.lint_explicit_deref() =>
 +                    {
 +                        let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)));
 +                        self.state = Some((
 +                            State::DerefMethod {
 +                                ty_changed_count,
 +                                is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
 +                                target_mut,
 +                            },
 +                            StateData {
 +                                span: expr.span,
 +                                hir_id: expr.hir_id,
 +                                position,
 +                            },
 +                        ));
 +                    },
 +                    RefOp::AddrOf(mutability) => {
 +                        // Find the number of times the borrow is auto-derefed.
 +                        let mut iter = adjustments.iter();
 +                        let mut deref_count = 0usize;
 +                        let next_adjust = loop {
 +                            match iter.next() {
 +                                Some(adjust) => {
 +                                    if !matches!(adjust.kind, Adjust::Deref(_)) {
 +                                        break Some(adjust);
 +                                    } else if !adjust.target.is_ref() {
 +                                        deref_count += 1;
 +                                        break iter.next();
 +                                    }
 +                                    deref_count += 1;
 +                                },
 +                                None => break None,
 +                            };
 +                        };
 +
 +                        // Determine the required number of references before any can be removed. In all cases the
 +                        // reference made by the current expression will be removed. After that there are four cases to
 +                        // handle.
 +                        //
 +                        // 1. Auto-borrow will trigger in the current position, so no further references are required.
 +                        // 2. Auto-deref ends at a reference, or the underlying type, so one extra needs to be left to
 +                        //    handle the automatically inserted re-borrow.
 +                        // 3. Auto-deref hits a user-defined `Deref` impl, so at least one reference needs to exist to
 +                        //    start auto-deref.
 +                        // 4. If the chain of non-user-defined derefs ends with a mutable re-borrow, and re-borrow
 +                        //    adjustments will not be inserted automatically, then leave one further reference to avoid
 +                        //    moving a mutable borrow.
 +                        //    e.g.
 +                        //        fn foo<T>(x: &mut Option<&mut T>, y: &mut T) {
 +                        //            let x = match x {
 +                        //                // Removing the borrow will cause `x` to be moved
 +                        //                Some(x) => &mut *x,
 +                        //                None => y
 +                        //            };
 +                        //        }
 +                        let deref_msg =
 +                            "this expression creates a reference which is immediately dereferenced by the compiler";
 +                        let borrow_msg = "this expression borrows a value the compiler would automatically borrow";
 +                        let impl_msg = "the borrowed expression implements the required traits";
 +
 +                        let (required_refs, msg, snip_expr) = if position.can_auto_borrow() {
 +                            (1, if deref_count == 1 { borrow_msg } else { deref_msg }, None)
 +                        } else if let Position::ImplArg(hir_id) = position {
 +                            (0, impl_msg, Some(hir_id))
 +                        } else if let Some(&Adjust::Borrow(AutoBorrow::Ref(_, mutability))) =
 +                            next_adjust.map(|a| &a.kind)
 +                        {
 +                            if matches!(mutability, AutoBorrowMutability::Mut { .. }) && !position.is_reborrow_stable()
 +                            {
 +                                (3, deref_msg, None)
 +                            } else {
 +                                (2, deref_msg, None)
 +                            }
 +                        } else {
 +                            (2, deref_msg, None)
 +                        };
 +
 +                        if deref_count >= required_refs {
 +                            self.state = Some((
 +                                State::DerefedBorrow(DerefedBorrow {
 +                                    // One of the required refs is for the current borrow expression, the remaining ones
 +                                    // can't be removed without breaking the code. See earlier comment.
 +                                    count: deref_count - required_refs,
 +                                    msg,
 +                                    snip_expr,
 +                                }),
 +                                StateData {
 +                                    span: expr.span,
 +                                    hir_id: expr.hir_id,
 +                                    position,
 +                                },
 +                            ));
 +                        } else if position.is_deref_stable()
 +                            // Auto-deref doesn't combine with other adjustments
 +                            && next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
 +                            && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
 +                        {
 +                            self.state = Some((
 +                                State::Borrow { mutability },
 +                                StateData {
 +                                    span: expr.span,
 +                                    hir_id: expr.hir_id,
 +                                    position,
 +                                },
 +                            ));
 +                        }
 +                    },
 +                    RefOp::Method(..) => (),
 +                }
 +            },
 +            (
 +                Some((
 +                    State::DerefMethod {
 +                        target_mut,
 +                        ty_changed_count,
 +                        ..
 +                    },
 +                    data,
 +                )),
 +                RefOp::Method(_),
 +            ) => {
 +                self.state = Some((
 +                    State::DerefMethod {
 +                        ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) {
 +                            ty_changed_count
 +                        } else {
 +                            ty_changed_count + 1
 +                        },
 +                        is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
 +                        target_mut,
 +                    },
 +                    data,
 +                ));
 +            },
 +            (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf(_)) if state.count != 0 => {
 +                self.state = Some((
 +                    State::DerefedBorrow(DerefedBorrow {
 +                        count: state.count - 1,
 +                        ..state
 +                    }),
 +                    data,
 +                ));
 +            },
 +            (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf(mutability)) => {
 +                let position = data.position;
 +                report(cx, expr, State::DerefedBorrow(state), data);
 +                if position.is_deref_stable() {
 +                    self.state = Some((
 +                        State::Borrow { mutability },
 +                        StateData {
 +                            span: expr.span,
 +                            hir_id: expr.hir_id,
 +                            position,
 +                        },
 +                    ));
 +                }
 +            },
 +            (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
 +                let position = data.position;
 +                report(cx, expr, State::DerefedBorrow(state), data);
 +                if let Position::FieldAccess{name, ..} = position
 +                    && !ty_contains_field(typeck.expr_ty(sub_expr), name)
 +                {
 +                    self.state = Some((
 +                        State::ExplicitDerefField { name },
 +                        StateData { span: expr.span, hir_id: expr.hir_id, position },
 +                    ));
 +                } else if position.is_deref_stable() {
 +                    self.state = Some((
 +                        State::ExplicitDeref { mutability: None },
 +                        StateData { span: expr.span, hir_id: expr.hir_id, position },
 +                    ));
 +                }
 +            },
 +
 +            (Some((State::Borrow { mutability }, data)), RefOp::Deref) => {
 +                if typeck.expr_ty(sub_expr).is_ref() {
 +                    self.state = Some((State::Reborrow { mutability }, data));
 +                } else {
 +                    self.state = Some((
 +                        State::ExplicitDeref {
 +                            mutability: Some(mutability),
 +                        },
 +                        data,
 +                    ));
 +                }
 +            },
 +            (Some((State::Reborrow { mutability }, data)), RefOp::Deref) => {
 +                self.state = Some((
 +                    State::ExplicitDeref {
 +                        mutability: Some(mutability),
 +                    },
 +                    data,
 +                ));
 +            },
 +            (state @ Some((State::ExplicitDeref { .. }, _)), RefOp::Deref) => {
 +                self.state = state;
 +            },
 +            (Some((State::ExplicitDerefField { name }, data)), RefOp::Deref)
 +                if !ty_contains_field(typeck.expr_ty(sub_expr), name) =>
 +            {
 +                self.state = Some((State::ExplicitDerefField { name }, data));
 +            },
 +
 +            (Some((state, data)), _) => report(cx, expr, state, data),
 +        }
 +    }
 +
 +    fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
 +        if let PatKind::Binding(BindingAnnotation::REF, id, name, _) = pat.kind {
 +            if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
 +                // This binding id has been seen before. Add this pattern to the list of changes.
 +                if let Some(prev_pat) = opt_prev_pat {
 +                    if pat.span.from_expansion() {
 +                        // Doesn't match the context of the previous pattern. Can't lint here.
 +                        *opt_prev_pat = None;
 +                    } else {
 +                        prev_pat.spans.push(pat.span);
 +                        prev_pat.replacements.push((
 +                            pat.span,
 +                            snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut prev_pat.app)
 +                                .0
 +                                .into(),
 +                        ));
 +                    }
 +                }
 +                return;
 +            }
 +
 +            if_chain! {
 +                if !pat.span.from_expansion();
 +                if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
 +                // only lint immutable refs, because borrowed `&mut T` cannot be moved out
 +                if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
 +                then {
 +                    let mut app = Applicability::MachineApplicable;
 +                    let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
 +                    self.current_body = self.current_body.or(cx.enclosing_body);
 +                    self.ref_locals.insert(
 +                        id,
 +                        Some(RefPat {
 +                            always_deref: true,
 +                            spans: vec![pat.span],
 +                            app,
 +                            replacements: vec![(pat.span, snip.into())],
 +                            hir_id: pat.hir_id,
 +                        }),
 +                    );
 +                }
 +            }
 +        }
 +    }
 +
 +    fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
 +        if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| {
 +            local_def_id == cx.tcx.hir().body_owner_def_id(body.id())
 +        }) {
 +            self.possible_borrowers.pop();
 +        }
 +
 +        if Some(body.id()) == self.current_body {
 +            for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) {
 +                let replacements = pat.replacements;
 +                let app = pat.app;
 +                let lint = if pat.always_deref {
 +                    NEEDLESS_BORROW
 +                } else {
 +                    REF_BINDING_TO_REFERENCE
 +                };
 +                span_lint_hir_and_then(
 +                    cx,
 +                    lint,
 +                    pat.hir_id,
 +                    pat.spans,
 +                    "this pattern creates a reference to a reference",
 +                    |diag| {
 +                        diag.multipart_suggestion("try this", replacements, app);
 +                    },
 +                );
 +            }
 +            self.current_body = None;
 +        }
 +    }
 +
 +    extract_msrv_attr!(LateContext);
 +}
 +
 +fn try_parse_ref_op<'tcx>(
 +    tcx: TyCtxt<'tcx>,
 +    typeck: &'tcx TypeckResults<'_>,
 +    expr: &'tcx Expr<'_>,
 +) -> Option<(RefOp, &'tcx Expr<'tcx>)> {
 +    let (def_id, arg) = match expr.kind {
 +        ExprKind::MethodCall(_, arg, [], _) => (typeck.type_dependent_def_id(expr.hir_id)?, arg),
 +        ExprKind::Call(
 +            Expr {
 +                kind: ExprKind::Path(path),
 +                hir_id,
 +                ..
 +            },
 +            [arg],
 +        ) => (typeck.qpath_res(path, *hir_id).opt_def_id()?, arg),
 +        ExprKind::Unary(UnOp::Deref, sub_expr) if !typeck.expr_ty(sub_expr).is_unsafe_ptr() => {
 +            return Some((RefOp::Deref, sub_expr));
 +        },
 +        ExprKind::AddrOf(BorrowKind::Ref, mutability, sub_expr) => return Some((RefOp::AddrOf(mutability), sub_expr)),
 +        _ => return None,
 +    };
 +    if tcx.is_diagnostic_item(sym::deref_method, def_id) {
 +        Some((RefOp::Method(Mutability::Not), arg))
 +    } else if tcx.trait_of_item(def_id)? == tcx.lang_items().deref_mut_trait()? {
 +        Some((RefOp::Method(Mutability::Mut), arg))
 +    } else {
 +        None
 +    }
 +}
 +
 +// Checks whether the type for a deref call actually changed the type, not just the mutability of
 +// the reference.
 +fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
 +    match (result_ty.kind(), arg_ty.kind()) {
 +        (ty::Ref(_, result_ty, _), ty::Ref(_, arg_ty, _)) => result_ty == arg_ty,
 +
 +        // The result type for a deref method is always a reference
 +        // Not matching the previous pattern means the argument type is not a reference
 +        // This means that the type did change
 +        _ => false,
 +    }
 +}
 +
 +/// The position of an expression relative to it's parent.
 +#[derive(Clone, Copy, Debug)]
 +enum Position {
 +    MethodReceiver,
 +    /// The method is defined on a reference type. e.g. `impl Foo for &T`
 +    MethodReceiverRefImpl,
 +    Callee,
 +    ImplArg(HirId),
 +    FieldAccess {
 +        name: Symbol,
 +        of_union: bool,
 +    }, // union fields cannot be auto borrowed
 +    Postfix,
 +    Deref,
 +    /// Any other location which will trigger auto-deref to a specific time.
 +    /// Contains the precedence of the parent expression and whether the target type is sized.
 +    DerefStable(i8, bool),
 +    /// Any other location which will trigger auto-reborrowing.
 +    /// Contains the precedence of the parent expression.
 +    ReborrowStable(i8),
 +    /// Contains the precedence of the parent expression.
 +    Other(i8),
 +}
 +impl Position {
 +    fn is_deref_stable(self) -> bool {
 +        matches!(self, Self::DerefStable(..))
 +    }
 +
 +    fn is_reborrow_stable(self) -> bool {
 +        matches!(self, Self::DerefStable(..) | Self::ReborrowStable(_))
 +    }
 +
 +    fn can_auto_borrow(self) -> bool {
 +        matches!(
 +            self,
 +            Self::MethodReceiver | Self::FieldAccess { of_union: false, .. } | Self::Callee
 +        )
 +    }
 +
 +    fn lint_explicit_deref(self) -> bool {
 +        matches!(self, Self::Other(_) | Self::DerefStable(..) | Self::ReborrowStable(_))
 +    }
 +
 +    fn precedence(self) -> i8 {
 +        match self {
 +            Self::MethodReceiver
 +            | Self::MethodReceiverRefImpl
 +            | Self::Callee
 +            | Self::FieldAccess { .. }
 +            | Self::Postfix => PREC_POSTFIX,
 +            Self::ImplArg(_) | Self::Deref => PREC_PREFIX,
 +            Self::DerefStable(p, _) | Self::ReborrowStable(p) | Self::Other(p) => p,
 +        }
 +    }
 +}
 +
 +/// Walks up the parent expressions attempting to determine both how stable the auto-deref result
 +/// is, and which adjustments will be applied to it. Note this will not consider auto-borrow
 +/// locations as those follow different rules.
 +#[expect(clippy::too_many_lines)]
 +fn walk_parents<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
 +    e: &'tcx Expr<'_>,
 +    msrv: &Msrv,
 +) -> (Position, &'tcx [Adjustment<'tcx>]) {
 +    let mut adjustments = [].as_slice();
 +    let mut precedence = 0i8;
 +    let ctxt = e.span.ctxt();
 +    let position = walk_to_expr_usage(cx, e, &mut |parent, child_id| {
 +        // LocalTableInContext returns the wrong lifetime, so go use `expr_adjustments` instead.
 +        if adjustments.is_empty() && let Node::Expr(e) = cx.tcx.hir().get(child_id) {
 +            adjustments = cx.typeck_results().expr_adjustments(e);
 +        }
 +        match parent {
 +            Node::Local(Local { ty: Some(ty), span, .. }) if span.ctxt() == ctxt => {
 +                Some(binding_ty_auto_deref_stability(cx, ty, precedence, List::empty()))
 +            },
 +            Node::Item(&Item {
 +                kind: ItemKind::Static(..) | ItemKind::Const(..),
 +                owner_id,
 +                span,
 +                ..
 +            })
 +            | Node::TraitItem(&TraitItem {
 +                kind: TraitItemKind::Const(..),
 +                owner_id,
 +                span,
 +                ..
 +            })
 +            | Node::ImplItem(&ImplItem {
 +                kind: ImplItemKind::Const(..),
 +                owner_id,
 +                span,
 +                ..
 +            }) if span.ctxt() == ctxt => {
 +                let ty = cx.tcx.type_of(owner_id.def_id);
 +                Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
 +            },
 +
 +            Node::Item(&Item {
 +                kind: ItemKind::Fn(..),
 +                owner_id,
 +                span,
 +                ..
 +            })
 +            | Node::TraitItem(&TraitItem {
 +                kind: TraitItemKind::Fn(..),
 +                owner_id,
 +                span,
 +                ..
 +            })
 +            | Node::ImplItem(&ImplItem {
 +                kind: ImplItemKind::Fn(..),
 +                owner_id,
 +                span,
 +                ..
 +            }) if span.ctxt() == ctxt => {
 +                let output = cx
 +                    .tcx
 +                    .erase_late_bound_regions(cx.tcx.fn_sig(owner_id.to_def_id()).output());
 +                Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx))
 +            },
 +
 +            Node::ExprField(field) if field.span.ctxt() == ctxt => match get_parent_expr_for_hir(cx, field.hir_id) {
 +                Some(Expr {
 +                    hir_id,
 +                    kind: ExprKind::Struct(path, ..),
 +                    ..
 +                }) => variant_of_res(cx, cx.qpath_res(path, *hir_id))
 +                    .and_then(|variant| variant.fields.iter().find(|f| f.name == field.ident.name))
 +                    .map(|field_def| {
 +                        ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did), precedence).position_for_arg()
 +                    }),
 +                _ => None,
 +            },
 +
 +            Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
 +                ExprKind::Ret(_) => {
 +                    let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
 +                    Some(
 +                        if let Node::Expr(
 +                            closure_expr @ Expr {
 +                                kind: ExprKind::Closure(closure),
 +                                ..
 +                            },
 +                        ) = cx.tcx.hir().get(owner_id)
 +                        {
 +                            closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
 +                        } else {
 +                            let output = cx
 +                                .tcx
 +                                .erase_late_bound_regions(cx.tcx.fn_sig(cx.tcx.hir().local_def_id(owner_id)).output());
 +                            ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)
 +                        },
 +                    )
 +                },
 +                ExprKind::Closure(closure) => Some(closure_result_position(
 +                    cx,
 +                    closure,
 +                    cx.typeck_results().expr_ty(parent),
 +                    precedence,
 +                )),
 +                ExprKind::Call(func, _) if func.hir_id == child_id => {
 +                    (child_id == e.hir_id).then_some(Position::Callee)
 +                },
 +                ExprKind::Call(func, args) => args
 +                    .iter()
 +                    .position(|arg| arg.hir_id == child_id)
 +                    .zip(expr_sig(cx, func))
 +                    .and_then(|(i, sig)| {
 +                        sig.input_with_hir(i).map(|(hir_ty, ty)| {
 +                            match hir_ty {
 +                                // Type inference for closures can depend on how they're called. Only go by the explicit
 +                                // types here.
 +                                Some(hir_ty) => {
 +                                    binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars())
 +                                },
 +                                None => {
 +                                    // `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
 +                                    // `!call_is_qualified(func)` for https://github.com/rust-lang/rust-clippy/issues/9782
 +                                    if e.hir_id == child_id
 +                                        && !call_is_qualified(func)
 +                                        && let ty::Param(param_ty) = ty.skip_binder().kind()
 +                                    {
 +                                        needless_borrow_impl_arg_position(
 +                                            cx,
 +                                            possible_borrowers,
 +                                            parent,
 +                                            i,
 +                                            *param_ty,
 +                                            e,
 +                                            precedence,
 +                                            msrv,
 +                                        )
 +                                    } else {
 +                                        ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
 +                                            .position_for_arg()
 +                                    }
 +                                },
 +                            }
 +                        })
 +                    }),
 +                ExprKind::MethodCall(method, receiver, args, _) => {
 +                    let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
 +                    if receiver.hir_id == child_id {
 +                        // Check for calls to trait methods where the trait is implemented on a reference.
 +                        // Two cases need to be handled:
 +                        // * `self` methods on `&T` will never have auto-borrow
 +                        // * `&self` methods on `&T` can have auto-borrow, but `&self` methods on `T` will take
 +                        //   priority.
 +                        if e.hir_id != child_id {
 +                            return Some(Position::ReborrowStable(precedence))
 +                        } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
 +                            && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
 +                            && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
 +                            && let subs = cx
 +                                .typeck_results()
 +                                .node_substs_opt(parent.hir_id).map(|subs| &subs[1..]).unwrap_or_default()
 +                            && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
 +                                // Trait methods taking `&self`
 +                                sub_ty
 +                            } else {
 +                                // Trait methods taking `self`
 +                                arg_ty
 +                            } && impl_ty.is_ref()
 +                            && let infcx = cx.tcx.infer_ctxt().build()
 +                            && infcx
 +                                .type_implements_trait(
 +                                    trait_id,
 +                                    [impl_ty.into()].into_iter().chain(subs.iter().copied()),
 +                                    cx.param_env,
 +                                )
 +                                .must_apply_modulo_regions()
 +                        {
 +                            return Some(Position::MethodReceiverRefImpl)
 +                        }
 +                        return Some(Position::MethodReceiver);
 +                    }
 +                    args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
 +                        let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
 +                        // `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
 +                        // `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
 +                        if e.hir_id == child_id && method.args.is_none() && let ty::Param(param_ty) = ty.kind() {
 +                            needless_borrow_impl_arg_position(
 +                                cx,
 +                                possible_borrowers,
 +                                parent,
 +                                i + 1,
 +                                *param_ty,
 +                                e,
 +                                precedence,
 +                                msrv,
 +                            )
 +                        } else {
 +                            ty_auto_deref_stability(
 +                                cx,
 +                                cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
 +                                precedence,
 +                            )
 +                            .position_for_arg()
 +                        }
 +                    })
 +                },
 +                ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess {
 +                    name: name.name,
 +                    of_union: is_union(cx.typeck_results(), child),
 +                }),
 +                ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
 +                ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
 +                | ExprKind::Index(child, _)
 +                    if child.hir_id == e.hir_id =>
 +                {
 +                    Some(Position::Postfix)
 +                },
 +                _ if child_id == e.hir_id => {
 +                    precedence = parent.precedence().order();
 +                    None
 +                },
 +                _ => None,
 +            },
 +            _ => None,
 +        }
 +    })
 +    .unwrap_or(Position::Other(precedence));
 +    (position, adjustments)
 +}
 +
 +fn is_union<'tcx>(typeck: &'tcx TypeckResults<'_>, path_expr: &'tcx Expr<'_>) -> bool {
 +    typeck
 +        .expr_ty_adjusted(path_expr)
 +        .ty_adt_def()
 +        .map_or(false, rustc_middle::ty::AdtDef::is_union)
 +}
 +
 +fn closure_result_position<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    closure: &'tcx Closure<'_>,
 +    ty: Ty<'tcx>,
 +    precedence: i8,
 +) -> Position {
 +    match closure.fn_decl.output {
 +        FnRetTy::Return(hir_ty) => {
 +            if let Some(sig) = ty_sig(cx, ty)
 +                && let Some(output) = sig.output()
 +            {
 +                binding_ty_auto_deref_stability(cx, hir_ty, precedence, output.bound_vars())
 +            } else {
 +                Position::Other(precedence)
 +            }
 +        },
 +        FnRetTy::DefaultReturn(_) => Position::Other(precedence),
 +    }
 +}
 +
 +// Checks the stability of auto-deref when assigned to a binding with the given explicit type.
 +//
 +// e.g.
 +// let x = Box::new(Box::new(0u32));
 +// let y1: &Box<_> = x.deref();
 +// let y2: &Box<_> = &x;
 +//
 +// Here `y1` and `y2` would resolve to different types, so the type `&Box<_>` is not stable when
 +// switching to auto-dereferencing.
 +fn binding_ty_auto_deref_stability<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    ty: &'tcx hir::Ty<'_>,
 +    precedence: i8,
 +    binder_args: &'tcx List<BoundVariableKind>,
 +) -> Position {
 +    let TyKind::Ref(_, ty) = &ty.kind else {
 +        return Position::Other(precedence);
 +    };
 +    let mut ty = ty;
 +
 +    loop {
 +        break match ty.ty.kind {
 +            TyKind::Ref(_, ref ref_ty) => {
 +                ty = ref_ty;
 +                continue;
 +            },
 +            TyKind::Path(
 +                QPath::TypeRelative(_, path)
 +                | QPath::Resolved(
 +                    _,
 +                    Path {
 +                        segments: [.., path], ..
 +                    },
 +                ),
 +            ) => {
 +                if let Some(args) = path.args
 +                    && args.args.iter().any(|arg| match arg {
 +                        GenericArg::Infer(_) => true,
 +                        GenericArg::Type(ty) => ty_contains_infer(ty),
 +                        _ => false,
 +                    })
 +                {
 +                    Position::ReborrowStable(precedence)
 +                } else {
 +                    Position::DerefStable(
 +                        precedence,
 +                        cx.tcx
 +                            .erase_late_bound_regions(Binder::bind_with_vars(
 +                                cx.typeck_results().node_type(ty.ty.hir_id),
 +                                binder_args,
 +                            ))
 +                            .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
 +                    )
 +                }
 +            },
 +            TyKind::Slice(_) => Position::DerefStable(precedence, false),
 +            TyKind::Array(..) | TyKind::Ptr(_) | TyKind::BareFn(_) => Position::DerefStable(precedence, true),
 +            TyKind::Never
 +            | TyKind::Tup(_)
 +            | TyKind::Path(_) => Position::DerefStable(
 +                precedence,
 +                cx.tcx
 +                    .erase_late_bound_regions(Binder::bind_with_vars(
 +                        cx.typeck_results().node_type(ty.ty.hir_id),
 +                        binder_args,
 +                    ))
 +                    .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
 +            ),
 +            TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
 +                Position::ReborrowStable(precedence)
 +            },
 +        };
 +    }
 +}
 +
 +// Checks whether a type is inferred at some point.
 +// e.g. `_`, `Box<_>`, `[_]`
 +fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
 +    struct V(bool);
 +    impl Visitor<'_> for V {
 +        fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
 +            if self.0
 +                || matches!(
 +                    ty.kind,
 +                    TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err
 +                )
 +            {
 +                self.0 = true;
 +            } else {
 +                walk_ty(self, ty);
 +            }
 +        }
 +
 +        fn visit_generic_arg(&mut self, arg: &GenericArg<'_>) {
 +            if self.0 || matches!(arg, GenericArg::Infer(_)) {
 +                self.0 = true;
 +            } else if let GenericArg::Type(ty) = arg {
 +                self.visit_ty(ty);
 +            }
 +        }
 +    }
 +    let mut v = V(false);
 +    v.visit_ty(ty);
 +    v.0
 +}
 +
 +fn call_is_qualified(expr: &Expr<'_>) -> bool {
 +    if let ExprKind::Path(path) = &expr.kind {
 +        match path {
 +            QPath::Resolved(_, path) => path.segments.last().map_or(false, |segment| segment.args.is_some()),
 +            QPath::TypeRelative(_, segment) => segment.args.is_some(),
 +            QPath::LangItem(..) => false,
 +        }
 +    } else {
 +        false
 +    }
 +}
 +
 +// Checks whether:
 +// * child is an expression of the form `&e` in an argument position requiring an `impl Trait`
 +// * `e`'s type implements `Trait` and is copyable
 +// If the conditions are met, returns `Some(Position::ImplArg(..))`; otherwise, returns `None`.
 +//   The "is copyable" condition is to avoid the case where removing the `&` means `e` would have to
 +// be moved, but it cannot be.
 +#[expect(clippy::too_many_arguments, clippy::too_many_lines)]
 +fn needless_borrow_impl_arg_position<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
 +    parent: &Expr<'tcx>,
 +    arg_index: usize,
 +    param_ty: ParamTy,
 +    mut expr: &Expr<'tcx>,
 +    precedence: i8,
 +    msrv: &Msrv,
 +) -> Position {
 +    let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait();
 +    let sized_trait_def_id = cx.tcx.lang_items().sized_trait();
 +
 +    let Some(callee_def_id) = fn_def_id(cx, parent) else { return Position::Other(precedence) };
 +    let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
 +    let substs_with_expr_ty = cx
 +        .typeck_results()
 +        .node_substs(if let ExprKind::Call(callee, _) = parent.kind {
 +            callee.hir_id
 +        } else {
 +            parent.hir_id
 +        });
 +
 +    let predicates = cx.tcx.param_env(callee_def_id).caller_bounds();
 +    let projection_predicates = predicates
 +        .iter()
 +        .filter_map(|predicate| {
 +            if let PredicateKind::Clause(Clause::Projection(projection_predicate)) = predicate.kind().skip_binder() {
 +                Some(projection_predicate)
 +            } else {
 +                None
 +            }
 +        })
 +        .collect::<Vec<_>>();
 +
 +    let mut trait_with_ref_mut_self_method = false;
 +
 +    // If no traits were found, or only the `Destruct`, `Sized`, or `Any` traits were found, return.
 +    if predicates
 +        .iter()
 +        .filter_map(|predicate| {
 +            if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder()
 +                && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx)
 +            {
 +                Some(trait_predicate.trait_ref.def_id)
 +            } else {
 +                None
 +            }
 +        })
 +        .inspect(|trait_def_id| {
 +            trait_with_ref_mut_self_method |= has_ref_mut_self_method(cx, *trait_def_id);
 +        })
 +        .all(|trait_def_id| {
 +            Some(trait_def_id) == destruct_trait_def_id
 +                || Some(trait_def_id) == sized_trait_def_id
 +                || cx.tcx.is_diagnostic_item(sym::Any, trait_def_id)
 +        })
 +    {
 +        return Position::Other(precedence);
 +    }
 +
 +    // See:
 +    // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1289294201
 +    // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1292225232
 +    if projection_predicates
 +        .iter()
 +        .any(|projection_predicate| is_mixed_projection_predicate(cx, callee_def_id, projection_predicate))
 +    {
 +        return Position::Other(precedence);
 +    }
 +
 +    // `substs_with_referent_ty` can be constructed outside of `check_referent` because the same
 +    // elements are modified each time `check_referent` is called.
 +    let mut substs_with_referent_ty = substs_with_expr_ty.to_vec();
 +
 +    let mut check_reference_and_referent = |reference, referent| {
 +        let referent_ty = cx.typeck_results().expr_ty(referent);
 +
 +        if !is_copy(cx, referent_ty)
 +            && (referent_ty.has_significant_drop(cx.tcx, cx.param_env)
 +                || !referent_used_exactly_once(cx, possible_borrowers, reference))
 +        {
 +            return false;
 +        }
 +
 +        // https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321
 +        if trait_with_ref_mut_self_method && !matches!(referent_ty.kind(), ty::Ref(_, _, Mutability::Mut)) {
 +            return false;
 +        }
 +
 +        if !replace_types(
 +            cx,
 +            param_ty,
 +            referent_ty,
 +            fn_sig,
 +            arg_index,
 +            &projection_predicates,
 +            &mut substs_with_referent_ty,
 +        ) {
 +            return false;
 +        }
 +
 +        predicates.iter().all(|predicate| {
 +            if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder()
 +                && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id)
 +                && let ty::Param(param_ty) = trait_predicate.self_ty().kind()
 +                && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack()
 +                && ty.is_array()
 +                && !msrv.meets(msrvs::ARRAY_INTO_ITERATOR)
 +            {
 +                return false;
 +            }
 +
 +            let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty);
 +            let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
 +            let infcx = cx.tcx.infer_ctxt().build();
 +            infcx.predicate_must_hold_modulo_regions(&obligation)
 +        })
 +    };
 +
 +    let mut needless_borrow = false;
 +    while let ExprKind::AddrOf(_, _, referent) = expr.kind {
 +        if !check_reference_and_referent(expr, referent) {
 +            break;
 +        }
 +        expr = referent;
 +        needless_borrow = true;
 +    }
 +
 +    if needless_borrow {
 +        Position::ImplArg(expr.hir_id)
 +    } else {
 +        Position::Other(precedence)
 +    }
 +}
 +
 +fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
 +    cx.tcx
 +        .associated_items(trait_def_id)
 +        .in_definition_order()
 +        .any(|assoc_item| {
 +            if assoc_item.fn_has_self_parameter {
 +                let self_ty = cx.tcx.fn_sig(assoc_item.def_id).skip_binder().inputs()[0];
 +                matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Mut))
 +            } else {
 +                false
 +            }
 +        })
 +}
 +
 +fn is_mixed_projection_predicate<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    callee_def_id: DefId,
 +    projection_predicate: &ProjectionPredicate<'tcx>,
 +) -> bool {
 +    let generics = cx.tcx.generics_of(callee_def_id);
 +    // The predicate requires the projected type to equal a type parameter from the parent context.
 +    if let Some(term_ty) = projection_predicate.term.ty()
 +        && let ty::Param(term_param_ty) = term_ty.kind()
 +        && (term_param_ty.index as usize) < generics.parent_count
 +    {
 +        // The inner-most self type is a type parameter from the current function.
 +        let mut projection_ty = projection_predicate.projection_ty;
 +        loop {
 +            match projection_ty.self_ty().kind() {
 +                ty::Alias(ty::Projection, inner_projection_ty) => {
 +                    projection_ty = *inner_projection_ty;
 +                }
 +                ty::Param(param_ty) => {
 +                    return (param_ty.index as usize) >= generics.parent_count;
 +                }
 +                _ => {
 +                    return false;
 +                }
 +            }
 +        }
 +    } else {
 +        false
 +    }
 +}
 +
 +fn referent_used_exactly_once<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
 +    reference: &Expr<'tcx>,
 +) -> bool {
 +    let mir = enclosing_mir(cx.tcx, reference.hir_id);
 +    if let Some(local) = expr_local(cx.tcx, reference)
 +        && let [location] = *local_assignments(mir, local).as_slice()
 +        && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index)
 +        && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
 +        && !place.has_deref()
 +        // Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710)
 +        && TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none()
 +    {
 +        let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id);
 +        if possible_borrowers
 +            .last()
 +            .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id)
 +        {
 +            possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
 +        }
 +        let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
++        // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
++        // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
++        // itself. See the comment in that method for an explanation as to why.
++        possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
 +            && used_exactly_once(mir, place.local).unwrap_or(false)
 +    } else {
 +        false
 +    }
 +}
 +
 +// Iteratively replaces `param_ty` with `new_ty` in `substs`, and similarly for each resulting
 +// projected type that is a type parameter. Returns `false` if replacing the types would have an
 +// effect on the function signature beyond substituting `new_ty` for `param_ty`.
 +// See: https://github.com/rust-lang/rust-clippy/pull/9136#discussion_r927212757
 +fn replace_types<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    param_ty: ParamTy,
 +    new_ty: Ty<'tcx>,
 +    fn_sig: FnSig<'tcx>,
 +    arg_index: usize,
 +    projection_predicates: &[ProjectionPredicate<'tcx>],
 +    substs: &mut [ty::GenericArg<'tcx>],
 +) -> bool {
 +    let mut replaced = BitSet::new_empty(substs.len());
 +
 +    let mut deque = VecDeque::with_capacity(substs.len());
 +    deque.push_back((param_ty, new_ty));
 +
 +    while let Some((param_ty, new_ty)) = deque.pop_front() {
 +        // If `replaced.is_empty()`, then `param_ty` and `new_ty` are those initially passed in.
 +        if !fn_sig
 +            .inputs_and_output
 +            .iter()
 +            .enumerate()
 +            .all(|(i, ty)| (replaced.is_empty() && i == arg_index) || !ty.contains(param_ty.to_ty(cx.tcx)))
 +        {
 +            return false;
 +        }
 +
 +        substs[param_ty.index as usize] = ty::GenericArg::from(new_ty);
 +
 +        // The `replaced.insert(...)` check provides some protection against infinite loops.
 +        if replaced.insert(param_ty.index) {
 +            for projection_predicate in projection_predicates {
 +                if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx)
 +                    && let Some(term_ty) = projection_predicate.term.ty()
 +                    && let ty::Param(term_param_ty) = term_ty.kind()
 +                {
 +                    let item_def_id = projection_predicate.projection_ty.def_id;
 +                    let assoc_item = cx.tcx.associated_item(item_def_id);
 +                    let projection = cx.tcx
 +                        .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
 +
 +                    if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
 +                        && substs[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty)
 +                    {
 +                        deque.push_back((*term_param_ty, projected_ty));
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +    true
 +}
 +
 +struct TyPosition<'tcx> {
 +    position: Position,
 +    ty: Option<Ty<'tcx>>,
 +}
 +impl From<Position> for TyPosition<'_> {
 +    fn from(position: Position) -> Self {
 +        Self { position, ty: None }
 +    }
 +}
 +impl<'tcx> TyPosition<'tcx> {
 +    fn new_deref_stable_for_result(precedence: i8, ty: Ty<'tcx>) -> Self {
 +        Self {
 +            position: Position::ReborrowStable(precedence),
 +            ty: Some(ty),
 +        }
 +    }
 +    fn position_for_result(self, cx: &LateContext<'tcx>) -> Position {
 +        match (self.position, self.ty) {
 +            (Position::ReborrowStable(precedence), Some(ty)) => {
 +                Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env))
 +            },
 +            (position, _) => position,
 +        }
 +    }
 +    fn position_for_arg(self) -> Position {
 +        self.position
 +    }
 +}
 +
 +// Checks whether a type is stable when switching to auto dereferencing,
 +fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedence: i8) -> TyPosition<'tcx> {
 +    let ty::Ref(_, mut ty, _) = *ty.kind() else {
 +        return Position::Other(precedence).into();
 +    };
 +
 +    loop {
 +        break match *ty.kind() {
 +            ty::Ref(_, ref_ty, _) => {
 +                ty = ref_ty;
 +                continue;
 +            },
 +            ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
 +            ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
 +                TyPosition::new_deref_stable_for_result(precedence, ty)
 +            },
 +            ty::Infer(_)
 +            | ty::Error(_)
 +            | ty::Bound(..)
 +            | ty::Alias(ty::Opaque, ..)
 +            | ty::Placeholder(_)
 +            | ty::Dynamic(..) => Position::ReborrowStable(precedence).into(),
 +            ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
 +                Position::ReborrowStable(precedence).into()
 +            },
 +            ty::Adt(_, substs) if substs.has_non_region_param() => {
 +                TyPosition::new_deref_stable_for_result(precedence, ty)
 +            },
 +            ty::Bool
 +            | ty::Char
 +            | ty::Int(_)
 +            | ty::Uint(_)
 +            | ty::Array(..)
 +            | ty::Float(_)
 +            | ty::RawPtr(..)
 +            | ty::FnPtr(_) => Position::DerefStable(precedence, true).into(),
 +            ty::Str | ty::Slice(..) => Position::DerefStable(precedence, false).into(),
 +            ty::Adt(..)
 +            | ty::Foreign(_)
 +            | ty::FnDef(..)
 +            | ty::Generator(..)
 +            | ty::GeneratorWitness(..)
 +            | ty::Closure(..)
 +            | ty::Never
 +            | ty::Tuple(_)
 +            | ty::Alias(ty::Projection, _) => {
 +                Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
 +            },
 +        };
 +    }
 +}
 +
 +fn ty_contains_field(ty: Ty<'_>, name: Symbol) -> bool {
 +    if let ty::Adt(adt, _) = *ty.kind() {
 +        adt.is_struct() && adt.all_fields().any(|f| f.name == name)
 +    } else {
 +        false
 +    }
 +}
 +
 +#[expect(clippy::needless_pass_by_value, clippy::too_many_lines)]
 +fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: StateData) {
 +    match state {
 +        State::DerefMethod {
 +            ty_changed_count,
 +            is_final_ufcs,
 +            target_mut,
 +        } => {
 +            let mut app = Applicability::MachineApplicable;
 +            let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
 +            let ty = cx.typeck_results().expr_ty(expr);
 +            let (_, ref_count) = peel_mid_ty_refs(ty);
 +            let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
 +                // a deref call changing &T -> &U requires two deref operators the first time
 +                // this occurs. One to remove the reference, a second to call the deref impl.
 +                "*".repeat(ty_changed_count + 1)
 +            } else {
 +                "*".repeat(ty_changed_count)
 +            };
 +            let addr_of_str = if ty_changed_count < ref_count {
 +                // Check if a reborrow from &mut T -> &T is required.
 +                if target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) {
 +                    "&*"
 +                } else {
 +                    ""
 +                }
 +            } else if target_mut == Mutability::Mut {
 +                "&mut "
 +            } else {
 +                "&"
 +            };
 +
 +            let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
 +                format!("({expr_str})")
 +            } else {
 +                expr_str.into_owned()
 +            };
 +
 +            span_lint_and_sugg(
 +                cx,
 +                EXPLICIT_DEREF_METHODS,
 +                data.span,
 +                match target_mut {
 +                    Mutability::Not => "explicit `deref` method call",
 +                    Mutability::Mut => "explicit `deref_mut` method call",
 +                },
 +                "try this",
 +                format!("{addr_of_str}{deref_str}{expr_str}"),
 +                app,
 +            );
 +        },
 +        State::DerefedBorrow(state) => {
 +            let mut app = Applicability::MachineApplicable;
 +            let snip_expr = state.snip_expr.map_or(expr, |hir_id| cx.tcx.hir().expect_expr(hir_id));
 +            let (snip, snip_is_macro) = snippet_with_context(cx, snip_expr.span, data.span.ctxt(), "..", &mut app);
 +            span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| {
 +                let calls_field = matches!(expr.kind, ExprKind::Field(..)) && matches!(data.position, Position::Callee);
 +                let sugg = if !snip_is_macro
 +                    && !has_enclosing_paren(&snip)
 +                    && (expr.precedence().order() < data.position.precedence() || calls_field)
 +                {
 +                    format!("({snip})")
 +                } else {
 +                    snip.into()
 +                };
 +                diag.span_suggestion(data.span, "change this to", sugg, app);
 +            });
 +        },
 +        State::ExplicitDeref { mutability } => {
 +            if matches!(
 +                expr.kind,
 +                ExprKind::Block(..)
 +                    | ExprKind::ConstBlock(_)
 +                    | ExprKind::If(..)
 +                    | ExprKind::Loop(..)
 +                    | ExprKind::Match(..)
 +            ) && matches!(data.position, Position::DerefStable(_, true))
 +            {
 +                // Rustc bug: auto deref doesn't work on block expression when targeting sized types.
 +                return;
 +            }
 +
 +            let (prefix, precedence) = if let Some(mutability) = mutability
 +                && !cx.typeck_results().expr_ty(expr).is_ref()
 +            {
 +                let prefix = match mutability {
 +                    Mutability::Not => "&",
 +                    Mutability::Mut => "&mut ",
 +                };
 +                (prefix, 0)
 +            } else {
 +                ("", data.position.precedence())
 +            };
 +            span_lint_hir_and_then(
 +                cx,
 +                EXPLICIT_AUTO_DEREF,
 +                data.hir_id,
 +                data.span,
 +                "deref which would be done by auto-deref",
 +                |diag| {
 +                    let mut app = Applicability::MachineApplicable;
 +                    let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
 +                    let sugg =
 +                        if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) {
 +                            format!("{prefix}({snip})")
 +                        } else {
 +                            format!("{prefix}{snip}")
 +                        };
 +                    diag.span_suggestion(data.span, "try this", sugg, app);
 +                },
 +            );
 +        },
 +        State::ExplicitDerefField { .. } => {
 +            if matches!(
 +                expr.kind,
 +                ExprKind::Block(..)
 +                    | ExprKind::ConstBlock(_)
 +                    | ExprKind::If(..)
 +                    | ExprKind::Loop(..)
 +                    | ExprKind::Match(..)
 +            ) && matches!(data.position, Position::DerefStable(_, true))
 +            {
 +                // Rustc bug: auto deref doesn't work on block expression when targeting sized types.
 +                return;
 +            }
 +
 +            span_lint_hir_and_then(
 +                cx,
 +                EXPLICIT_AUTO_DEREF,
 +                data.hir_id,
 +                data.span,
 +                "deref which would be done by auto-deref",
 +                |diag| {
 +                    let mut app = Applicability::MachineApplicable;
 +                    let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0;
 +                    diag.span_suggestion(data.span, "try this", snip.into_owned(), app);
 +                },
 +            );
 +        },
 +        State::Borrow { .. } | State::Reborrow { .. } => (),
 +    }
 +}
 +
 +impl<'tcx> Dereferencing<'tcx> {
 +    fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &Expr<'tcx>, local: HirId) {
 +        if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
 +            if let Some(pat) = outer_pat {
 +                // Check for auto-deref
 +                if !matches!(
 +                    cx.typeck_results().expr_adjustments(e),
 +                    [
 +                        Adjustment {
 +                            kind: Adjust::Deref(_),
 +                            ..
 +                        },
 +                        Adjustment {
 +                            kind: Adjust::Deref(_),
 +                            ..
 +                        },
 +                        ..
 +                    ]
 +                ) {
 +                    match get_parent_expr(cx, e) {
 +                        // Field accesses are the same no matter the number of references.
 +                        Some(Expr {
 +                            kind: ExprKind::Field(..),
 +                            ..
 +                        }) => (),
 +                        Some(&Expr {
 +                            span,
 +                            kind: ExprKind::Unary(UnOp::Deref, _),
 +                            ..
 +                        }) if !span.from_expansion() => {
 +                            // Remove explicit deref.
 +                            let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
 +                            pat.replacements.push((span, snip.into()));
 +                        },
 +                        Some(parent) if !parent.span.from_expansion() => {
 +                            // Double reference might be needed at this point.
 +                            if parent.precedence().order() == PREC_POSTFIX {
 +                                // Parentheses would be needed here, don't lint.
 +                                *outer_pat = None;
 +                            } else {
 +                                pat.always_deref = false;
 +                                let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
 +                                pat.replacements.push((e.span, format!("&{snip}")));
 +                            }
 +                        },
 +                        _ if !e.span.from_expansion() => {
 +                            // Double reference might be needed at this point.
 +                            pat.always_deref = false;
 +                            let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
 +                            pat.replacements.push((e.span, format!("&{snip}")));
 +                        },
 +                        // Edge case for macros. The span of the identifier will usually match the context of the
 +                        // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
 +                        // macros
 +                        _ => *outer_pat = None,
 +                    }
 +                }
 +            }
 +        }
 +    }
 +}
index ae8f6b794499fc47439d2a093fc45944dc47452a,0000000000000000000000000000000000000000..bc18e2e5ed5fdcd25e1d824dc79547e0efa8a738
mode 100644,000000..100644
--- /dev/null
@@@ -1,131 -1,0 +1,204 @@@
-     def::{DefKind, Res},
-     Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
 +use clippy_utils::diagnostics::span_lint_and_then;
++use clippy_utils::msrvs::{self, Msrv};
++use clippy_utils::source::indent_of;
 +use clippy_utils::{is_default_equivalent, peel_blocks};
 +use rustc_errors::Applicability;
 +use rustc_hir::{
- use rustc_session::{declare_lint_pass, declare_tool_lint};
++    def::{CtorKind, CtorOf, DefKind, Res},
++    Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
 +};
 +use rustc_lint::{LateContext, LateLintPass};
- declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
++use rustc_middle::ty::{AdtDef, DefIdTree};
++use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::sym;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Detects manual `std::default::Default` implementations that are identical to a derived implementation.
 +    ///
 +    /// ### Why is this bad?
 +    /// It is less concise.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// struct Foo {
 +    ///     bar: bool
 +    /// }
 +    ///
 +    /// impl Default for Foo {
 +    ///     fn default() -> Self {
 +    ///         Self {
 +    ///             bar: false
 +    ///         }
 +    ///     }
 +    /// }
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// #[derive(Default)]
 +    /// struct Foo {
 +    ///     bar: bool
 +    /// }
 +    /// ```
 +    ///
 +    /// ### Known problems
 +    /// Derive macros [sometimes use incorrect bounds](https://github.com/rust-lang/rust/issues/26925)
 +    /// in generic types and the user defined `impl` may be more generalized or
 +    /// specialized than what derive will produce. This lint can't detect the manual `impl`
 +    /// has exactly equal bounds, and therefore this lint is disabled for types with
 +    /// generic parameters.
 +    #[clippy::version = "1.57.0"]
 +    pub DERIVABLE_IMPLS,
 +    complexity,
 +    "manual implementation of the `Default` trait which is equal to a derive"
 +}
 +
-             if adt_def.is_struct();
-             then {
-                 if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
-                     if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
-                         for arg in a.args {
-                             if !matches!(arg, GenericArg::Lifetime(_)) {
-                                 return;
-                             }
-                         }
-                     }
-                 }
-                 let should_emit = match peel_blocks(func_expr).kind {
-                     ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
-                     ExprKind::Call(callee, args)
-                         if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
-                     ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
-                     _ => false,
-                 };
++pub struct DerivableImpls {
++    msrv: Msrv,
++}
++
++impl DerivableImpls {
++    #[must_use]
++    pub fn new(msrv: Msrv) -> Self {
++        DerivableImpls { msrv }
++    }
++}
++
++impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
 +
 +fn is_path_self(e: &Expr<'_>) -> bool {
 +    if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind {
 +        matches!(p.res, Res::SelfCtor(..) | Res::Def(DefKind::Ctor(..), _))
 +    } else {
 +        false
 +    }
 +}
 +
++fn check_struct<'tcx>(
++    cx: &LateContext<'tcx>,
++    item: &'tcx Item<'_>,
++    self_ty: &Ty<'_>,
++    func_expr: &Expr<'_>,
++    adt_def: AdtDef<'_>,
++) {
++    if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
++        if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
++            for arg in a.args {
++                if !matches!(arg, GenericArg::Lifetime(_)) {
++                    return;
++                }
++            }
++        }
++    }
++    let should_emit = match peel_blocks(func_expr).kind {
++        ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
++        ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
++        ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
++        _ => false,
++    };
++
++    if should_emit {
++        let struct_span = cx.tcx.def_span(adt_def.did());
++        span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
++            diag.span_suggestion_hidden(
++                item.span,
++                "remove the manual implementation...",
++                String::new(),
++                Applicability::MachineApplicable,
++            );
++            diag.span_suggestion(
++                struct_span.shrink_to_lo(),
++                "...and instead derive it",
++                "#[derive(Default)]\n".to_string(),
++                Applicability::MachineApplicable,
++            );
++        });
++    }
++}
++
++fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) {
++    if_chain! {
++        if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind;
++        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res;
++        if let variant_id = cx.tcx.parent(id);
++        if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id);
++        if variant_def.fields.is_empty();
++        if !variant_def.is_field_list_non_exhaustive();
++
++        then {
++            let enum_span = cx.tcx.def_span(adt_def.did());
++            let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
++            let variant_span = cx.tcx.def_span(variant_def.def_id);
++            let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
++            span_lint_and_then(
++                cx,
++                DERIVABLE_IMPLS,
++                item.span,
++                "this `impl` can be derived",
++                |diag| {
++                    diag.span_suggestion_hidden(
++                        item.span,
++                        "remove the manual implementation...",
++                        String::new(),
++                        Applicability::MachineApplicable
++                    );
++                    diag.span_suggestion(
++                        enum_span.shrink_to_lo(),
++                        "...and instead derive it...",
++                        format!(
++                            "#[derive(Default)]\n{indent}",
++                            indent = " ".repeat(indent_enum),
++                        ),
++                        Applicability::MachineApplicable
++                    );
++                    diag.span_suggestion(
++                        variant_span.shrink_to_lo(),
++                        "...and mark the default variant",
++                        format!(
++                            "#[default]\n{indent}",
++                            indent = " ".repeat(indent_variant),
++                        ),
++                        Applicability::MachineApplicable
++                    );
++                }
++            );
++        }
++    }
++}
++
 +impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
 +    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
 +        if_chain! {
 +            if let ItemKind::Impl(Impl {
 +                of_trait: Some(ref trait_ref),
 +                items: [child],
 +                self_ty,
 +                ..
 +            }) = item.kind;
 +            if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
 +            if !item.span.from_expansion();
 +            if let Some(def_id) = trait_ref.trait_def_id();
 +            if cx.tcx.is_diagnostic_item(sym::Default, def_id);
 +            if let impl_item_hir = child.id.hir_id();
 +            if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
 +            if let ImplItemKind::Fn(_, b) = &impl_item.kind;
 +            if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
 +            if let Some(adt_def) = cx.tcx.type_of(item.owner_id).ty_adt_def();
 +            if let attrs = cx.tcx.hir().attrs(item.hir_id());
 +            if !attrs.iter().any(|attr| attr.doc_str().is_some());
 +            if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
 +            if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
-                 if should_emit {
-                     let struct_span = cx.tcx.def_span(adt_def.did());
-                     span_lint_and_then(
-                         cx,
-                         DERIVABLE_IMPLS,
-                         item.span,
-                         "this `impl` can be derived",
-                         |diag| {
-                             diag.span_suggestion_hidden(
-                                 item.span,
-                                 "remove the manual implementation...",
-                                 String::new(),
-                                 Applicability::MachineApplicable
-                             );
-                             diag.span_suggestion(
-                                 struct_span.shrink_to_lo(),
-                                 "...and instead derive it",
-                                 "#[derive(Default)]\n".to_string(),
-                                 Applicability::MachineApplicable
-                             );
-                         }
-                     );
 +
++            then {
++                if adt_def.is_struct() {
++                    check_struct(cx, item, self_ty, func_expr, adt_def);
++                } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
++                    check_enum(cx, item, func_expr, adt_def);
 +                }
 +            }
 +        }
 +    }
++
++    extract_msrv_attr!(LateContext);
 +}
index cf3483d4c00b17134724bbc51eafcf6abb904aaa,0000000000000000000000000000000000000000..f4b15e0916dbf47bca1aa427e5d46f35d9bfa45a
mode 100644,000000..100644
--- /dev/null
@@@ -1,525 -1,0 +1,528 @@@
-     self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
-     Ty, TyCtxt,
 +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
 +use clippy_utils::paths;
 +use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
 +use clippy_utils::{is_lint_allowed, match_def_path};
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir::def_id::DefId;
 +use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
 +use rustc_hir::{
 +    self as hir, BlockCheckMode, BodyId, Constness, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, UnsafeSource,
 +    Unsafety,
 +};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::hir::nested_filter;
 +use rustc_middle::traits::Reveal;
 +use rustc_middle::ty::{
-     pub DERIVE_HASH_XOR_EQ,
++    self, Binder, BoundConstness, Clause, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind,
++    TraitPredicate, Ty, TyCtxt,
 +};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::source_map::Span;
 +use rustc_span::sym;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for deriving `Hash` but implementing `PartialEq`
 +    /// explicitly or vice versa.
 +    ///
 +    /// ### Why is this bad?
 +    /// The implementation of these traits must agree (for
 +    /// example for use with `HashMap`) so it’s probably a bad idea to use a
 +    /// default-generated `Hash` implementation with an explicitly defined
 +    /// `PartialEq`. In particular, the following must hold for any type:
 +    ///
 +    /// ```text
 +    /// k1 == k2 ⇒ hash(k1) == hash(k2)
 +    /// ```
 +    ///
 +    /// ### Example
 +    /// ```ignore
 +    /// #[derive(Hash)]
 +    /// struct Foo;
 +    ///
 +    /// impl PartialEq for Foo {
 +    ///     ...
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
-     DERIVE_HASH_XOR_EQ,
++    pub DERIVED_HASH_WITH_MANUAL_EQ,
 +    correctness,
 +    "deriving `Hash` but implementing `PartialEq` explicitly"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for deriving `Ord` but implementing `PartialOrd`
 +    /// explicitly or vice versa.
 +    ///
 +    /// ### Why is this bad?
 +    /// The implementation of these traits must agree (for
 +    /// example for use with `sort`) so it’s probably a bad idea to use a
 +    /// default-generated `Ord` implementation with an explicitly defined
 +    /// `PartialOrd`. In particular, the following must hold for any type
 +    /// implementing `Ord`:
 +    ///
 +    /// ```text
 +    /// k1.cmp(&k2) == k1.partial_cmp(&k2).unwrap()
 +    /// ```
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// #[derive(Ord, PartialEq, Eq)]
 +    /// struct Foo;
 +    ///
 +    /// impl PartialOrd for Foo {
 +    ///     ...
 +    /// }
 +    /// ```
 +    /// Use instead:
 +    /// ```rust,ignore
 +    /// #[derive(PartialEq, Eq)]
 +    /// struct Foo;
 +    ///
 +    /// impl PartialOrd for Foo {
 +    ///     fn partial_cmp(&self, other: &Foo) -> Option<Ordering> {
 +    ///        Some(self.cmp(other))
 +    ///     }
 +    /// }
 +    ///
 +    /// impl Ord for Foo {
 +    ///     ...
 +    /// }
 +    /// ```
 +    /// or, if you don't need a custom ordering:
 +    /// ```rust,ignore
 +    /// #[derive(Ord, PartialOrd, PartialEq, Eq)]
 +    /// struct Foo;
 +    /// ```
 +    #[clippy::version = "1.47.0"]
 +    pub DERIVE_ORD_XOR_PARTIAL_ORD,
 +    correctness,
 +    "deriving `Ord` but implementing `PartialOrd` explicitly"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for explicit `Clone` implementations for `Copy`
 +    /// types.
 +    ///
 +    /// ### Why is this bad?
 +    /// To avoid surprising behavior, these traits should
 +    /// agree and the behavior of `Copy` cannot be overridden. In almost all
 +    /// situations a `Copy` type should have a `Clone` implementation that does
 +    /// nothing more than copy the object, which is what `#[derive(Copy, Clone)]`
 +    /// gets you.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// #[derive(Copy)]
 +    /// struct Foo;
 +    ///
 +    /// impl Clone for Foo {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub EXPL_IMPL_CLONE_ON_COPY,
 +    pedantic,
 +    "implementing `Clone` explicitly on `Copy` types"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for deriving `serde::Deserialize` on a type that
 +    /// has methods using `unsafe`.
 +    ///
 +    /// ### Why is this bad?
 +    /// Deriving `serde::Deserialize` will create a constructor
 +    /// that may violate invariants hold by another constructor.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// use serde::Deserialize;
 +    ///
 +    /// #[derive(Deserialize)]
 +    /// pub struct Foo {
 +    ///     // ..
 +    /// }
 +    ///
 +    /// impl Foo {
 +    ///     pub fn new() -> Self {
 +    ///         // setup here ..
 +    ///     }
 +    ///
 +    ///     pub unsafe fn parts() -> (&str, &str) {
 +    ///         // assumes invariants hold
 +    ///     }
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.45.0"]
 +    pub UNSAFE_DERIVE_DESERIALIZE,
 +    pedantic,
 +    "deriving `serde::Deserialize` on a type that has methods using `unsafe`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for types that derive `PartialEq` and could implement `Eq`.
 +    ///
 +    /// ### Why is this bad?
 +    /// If a type `T` derives `PartialEq` and all of its members implement `Eq`,
 +    /// then `T` can always implement `Eq`. Implementing `Eq` allows `T` to be used
 +    /// in APIs that require `Eq` types. It also allows structs containing `T` to derive
 +    /// `Eq` themselves.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// #[derive(PartialEq)]
 +    /// struct Foo {
 +    ///     i_am_eq: i32,
 +    ///     i_am_eq_too: Vec<String>,
 +    /// }
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    /// #[derive(PartialEq, Eq)]
 +    /// struct Foo {
 +    ///     i_am_eq: i32,
 +    ///     i_am_eq_too: Vec<String>,
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.63.0"]
 +    pub DERIVE_PARTIAL_EQ_WITHOUT_EQ,
 +    nursery,
 +    "deriving `PartialEq` on a type that can implement `Eq`, without implementing `Eq`"
 +}
 +
 +declare_lint_pass!(Derive => [
 +    EXPL_IMPL_CLONE_ON_COPY,
- /// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
++    DERIVED_HASH_WITH_MANUAL_EQ,
 +    DERIVE_ORD_XOR_PARTIAL_ORD,
 +    UNSAFE_DERIVE_DESERIALIZE,
 +    DERIVE_PARTIAL_EQ_WITHOUT_EQ
 +]);
 +
 +impl<'tcx> LateLintPass<'tcx> for Derive {
 +    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
 +        if let ItemKind::Impl(Impl {
 +            of_trait: Some(ref trait_ref),
 +            ..
 +        }) = item.kind
 +        {
 +            let ty = cx.tcx.type_of(item.owner_id);
 +            let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
 +
 +            check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
 +            check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
 +
 +            if is_automatically_derived {
 +                check_unsafe_derive_deserialize(cx, item, trait_ref, ty);
 +                check_partial_eq_without_eq(cx, item.span, trait_ref, ty);
 +            } else {
 +                check_copy_clone(cx, item, trait_ref, ty);
 +            }
 +        }
 +    }
 +}
 +
-                 if peq_is_automatically_derived == hash_is_automatically_derived {
++/// Implementation of the `DERIVED_HASH_WITH_MANUAL_EQ` lint.
 +fn check_hash_peq<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    span: Span,
 +    trait_ref: &hir::TraitRef<'_>,
 +    ty: Ty<'tcx>,
 +    hash_is_automatically_derived: bool,
 +) {
 +    if_chain! {
 +        if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait();
 +        if let Some(def_id) = trait_ref.trait_def_id();
 +        if cx.tcx.is_diagnostic_item(sym::Hash, def_id);
 +        then {
 +            // Look for the PartialEq implementations for `ty`
 +            cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
 +                let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
 +
-                     let mess = if peq_is_automatically_derived {
-                         "you are implementing `Hash` explicitly but have derived `PartialEq`"
-                     } else {
-                         "you are deriving `Hash` but have implemented `PartialEq` explicitly"
-                     };
++                if !hash_is_automatically_derived || peq_is_automatically_derived {
 +                    return;
 +                }
 +
 +                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
 +
 +                // Only care about `impl PartialEq<Foo> for Foo`
 +                // For `impl PartialEq<B> for A, input_types is [A, B]
 +                if trait_ref.substs.type_at(1) == ty {
-                         DERIVE_HASH_XOR_EQ,
 +                    span_lint_and_then(
 +                        cx,
-                         mess,
++                        DERIVED_HASH_WITH_MANUAL_EQ,
 +                        span,
++                        "you are deriving `Hash` but have implemented `PartialEq` explicitly",
 +                        |diag| {
 +                            if let Some(local_def_id) = impl_id.as_local() {
 +                                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
 +                                diag.span_note(
 +                                    cx.tcx.hir().span(hir_id),
 +                                    "`PartialEq` implemented here"
 +                                );
 +                            }
 +                        }
 +                    );
 +                }
 +            });
 +        }
 +    }
 +}
 +
 +/// Implementation of the `DERIVE_ORD_XOR_PARTIAL_ORD` lint.
 +fn check_ord_partial_ord<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    span: Span,
 +    trait_ref: &hir::TraitRef<'_>,
 +    ty: Ty<'tcx>,
 +    ord_is_automatically_derived: bool,
 +) {
 +    if_chain! {
 +        if let Some(ord_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Ord);
 +        if let Some(partial_ord_trait_def_id) = cx.tcx.lang_items().partial_ord_trait();
 +        if let Some(def_id) = &trait_ref.trait_def_id();
 +        if *def_id == ord_trait_def_id;
 +        then {
 +            // Look for the PartialOrd implementations for `ty`
 +            cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| {
 +                let partial_ord_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
 +
 +                if partial_ord_is_automatically_derived == ord_is_automatically_derived {
 +                    return;
 +                }
 +
 +                let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation");
 +
 +                // Only care about `impl PartialOrd<Foo> for Foo`
 +                // For `impl PartialOrd<B> for A, input_types is [A, B]
 +                if trait_ref.substs.type_at(1) == ty {
 +                    let mess = if partial_ord_is_automatically_derived {
 +                        "you are implementing `Ord` explicitly but have derived `PartialOrd`"
 +                    } else {
 +                        "you are deriving `Ord` but have implemented `PartialOrd` explicitly"
 +                    };
 +
 +                    span_lint_and_then(
 +                        cx,
 +                        DERIVE_ORD_XOR_PARTIAL_ORD,
 +                        span,
 +                        mess,
 +                        |diag| {
 +                            if let Some(local_def_id) = impl_id.as_local() {
 +                                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
 +                                diag.span_note(
 +                                    cx.tcx.hir().span(hir_id),
 +                                    "`PartialOrd` implemented here"
 +                                );
 +                            }
 +                        }
 +                    );
 +                }
 +            });
 +        }
 +    }
 +}
 +
 +/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
 +fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) {
 +    let clone_id = match cx.tcx.lang_items().clone_trait() {
 +        Some(id) if trait_ref.trait_def_id() == Some(id) => id,
 +        _ => return,
 +    };
 +    let Some(copy_id) = cx.tcx.lang_items().copy_trait() else { return };
 +    let (ty_adt, ty_subs) = match *ty.kind() {
 +        // Unions can't derive clone.
 +        ty::Adt(adt, subs) if !adt.is_union() => (adt, subs),
 +        _ => return,
 +    };
 +    // If the current self type doesn't implement Copy (due to generic constraints), search to see if
 +    // there's a Copy impl for any instance of the adt.
 +    if !is_copy(cx, ty) {
 +        if ty_subs.non_erasable_generics().next().is_some() {
 +            let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
 +                impls
 +                    .iter()
 +                    .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
 +            });
 +            if !has_copy_impl {
 +                return;
 +            }
 +        } else {
 +            return;
 +        }
 +    }
 +    // Derive constrains all generic types to requiring Clone. Check if any type is not constrained for
 +    // this impl.
 +    if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) {
 +        return;
 +    }
++    // `#[repr(packed)]` structs with type/const parameters can't derive `Clone`.
++    // https://github.com/rust-lang/rust-clippy/issues/10188
++    if ty_adt.repr().packed()
++        && ty_subs
++            .iter()
++            .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
++    {
++        return;
++    }
 +
 +    span_lint_and_note(
 +        cx,
 +        EXPL_IMPL_CLONE_ON_COPY,
 +        item.span,
 +        "you are implementing `Clone` explicitly on a `Copy` type",
 +        Some(item.span),
 +        "consider deriving `Clone` or removing `Copy`",
 +    );
 +}
 +
 +/// Implementation of the `UNSAFE_DERIVE_DESERIALIZE` lint.
 +fn check_unsafe_derive_deserialize<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    item: &Item<'_>,
 +    trait_ref: &hir::TraitRef<'_>,
 +    ty: Ty<'tcx>,
 +) {
 +    fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
 +        let mut visitor = UnsafeVisitor { cx, has_unsafe: false };
 +        walk_item(&mut visitor, item);
 +        visitor.has_unsafe
 +    }
 +
 +    if_chain! {
 +        if let Some(trait_def_id) = trait_ref.trait_def_id();
 +        if match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE);
 +        if let ty::Adt(def, _) = ty.kind();
 +        if let Some(local_def_id) = def.did().as_local();
 +        let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
 +        if !is_lint_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
 +        if cx.tcx.inherent_impls(def.did())
 +            .iter()
 +            .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
 +            .any(|imp| has_unsafe(cx, imp));
 +        then {
 +            span_lint_and_help(
 +                cx,
 +                UNSAFE_DERIVE_DESERIALIZE,
 +                item.span,
 +                "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`",
 +                None,
 +                "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html"
 +            );
 +        }
 +    }
 +}
 +
 +struct UnsafeVisitor<'a, 'tcx> {
 +    cx: &'a LateContext<'tcx>,
 +    has_unsafe: bool,
 +}
 +
 +impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
 +    type NestedFilter = nested_filter::All;
 +
 +    fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: HirId) {
 +        if self.has_unsafe {
 +            return;
 +        }
 +
 +        if_chain! {
 +            if let Some(header) = kind.header();
 +            if header.unsafety == Unsafety::Unsafe;
 +            then {
 +                self.has_unsafe = true;
 +            }
 +        }
 +
 +        walk_fn(self, kind, decl, body_id, id);
 +    }
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if self.has_unsafe {
 +            return;
 +        }
 +
 +        if let ExprKind::Block(block, _) = expr.kind {
 +            if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) {
 +                self.has_unsafe = true;
 +            }
 +        }
 +
 +        walk_expr(self, expr);
 +    }
 +
 +    fn nested_visit_map(&mut self) -> Self::Map {
 +        self.cx.tcx.hir()
 +    }
 +}
 +
 +/// Implementation of the `DERIVE_PARTIAL_EQ_WITHOUT_EQ` lint.
 +fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) {
 +    if_chain! {
 +        if let ty::Adt(adt, substs) = ty.kind();
 +        if cx.tcx.visibility(adt.did()).is_public();
 +        if let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq);
 +        if let Some(def_id) = trait_ref.trait_def_id();
 +        if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id);
 +        let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id);
 +        if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, []);
 +        // If all of our fields implement `Eq`, we can implement `Eq` too
 +        if adt
 +            .all_fields()
 +            .map(|f| f.ty(cx.tcx, substs))
 +            .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, []));
 +        then {
 +            span_lint_and_sugg(
 +                cx,
 +                DERIVE_PARTIAL_EQ_WITHOUT_EQ,
 +                span.ctxt().outer_expn_data().call_site,
 +                "you are deriving `PartialEq` and can implement `Eq`",
 +                "consider deriving `Eq` as well",
 +                "PartialEq, Eq".to_string(),
 +                Applicability::MachineApplicable,
 +            )
 +        }
 +    }
 +}
 +
 +/// Creates the `ParamEnv` used for the give type's derived `Eq` impl.
 +fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv<'_> {
 +    // Initial map from generic index to param def.
 +    // Vec<(param_def, needs_eq)>
 +    let mut params = tcx
 +        .generics_of(did)
 +        .params
 +        .iter()
 +        .map(|p| (p, matches!(p.kind, GenericParamDefKind::Type { .. })))
 +        .collect::<Vec<_>>();
 +
 +    let ty_predicates = tcx.predicates_of(did).predicates;
 +    for (p, _) in ty_predicates {
 +        if let PredicateKind::Clause(Clause::Trait(p)) = p.kind().skip_binder()
 +            && p.trait_ref.def_id == eq_trait_id
 +            && let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
 +            && p.constness == BoundConstness::NotConst
 +        {
 +            // Flag types which already have an `Eq` bound.
 +            params[self_ty.index as usize].1 = false;
 +        }
 +    }
 +
 +    ParamEnv::new(
 +        tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
 +            params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
 +                tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
 +                    trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
 +                    constness: BoundConstness::NotConst,
 +                    polarity: ImplPolarity::Positive,
 +                }))))
 +            }),
 +        )),
 +        Reveal::UserFacing,
 +        Constness::NotConst,
 +    )
 +}
index 4721a7b370567c5ebb3a23275de952275d3a2912,0000000000000000000000000000000000000000..11e1bcdf12d1ec79f309902c6bd64bb9b614e50d
mode 100644,000000..100644
--- /dev/null
@@@ -1,263 -1,0 +1,263 @@@
-                 sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY),
 +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
 +use clippy_utils::get_parent_node;
 +use clippy_utils::is_must_use_func_call;
 +use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item};
 +use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::sym;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for calls to `std::mem::drop` with a reference
 +    /// instead of an owned value.
 +    ///
 +    /// ### Why is this bad?
 +    /// Calling `drop` on a reference will only drop the
 +    /// reference itself, which is a no-op. It will not call the `drop` method (from
 +    /// the `Drop` trait implementation) on the underlying referenced value, which
 +    /// is likely what was intended.
 +    ///
 +    /// ### Example
 +    /// ```ignore
 +    /// let mut lock_guard = mutex.lock();
 +    /// std::mem::drop(&lock_guard) // Should have been drop(lock_guard), mutex
 +    /// // still locked
 +    /// operation_that_requires_mutex_to_be_unlocked();
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub DROP_REF,
 +    correctness,
 +    "calls to `std::mem::drop` with a reference instead of an owned value"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for calls to `std::mem::forget` with a reference
 +    /// instead of an owned value.
 +    ///
 +    /// ### Why is this bad?
 +    /// Calling `forget` on a reference will only forget the
 +    /// reference itself, which is a no-op. It will not forget the underlying
 +    /// referenced
 +    /// value, which is likely what was intended.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let x = Box::new(1);
 +    /// std::mem::forget(&x) // Should have been forget(x), x will still be dropped
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub FORGET_REF,
 +    correctness,
 +    "calls to `std::mem::forget` with a reference instead of an owned value"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for calls to `std::mem::drop` with a value
 +    /// that derives the Copy trait
 +    ///
 +    /// ### Why is this bad?
 +    /// Calling `std::mem::drop` [does nothing for types that
 +    /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
 +    /// value will be copied and moved into the function on invocation.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let x: i32 = 42; // i32 implements Copy
 +    /// std::mem::drop(x) // A copy of x is passed to the function, leaving the
 +    ///                   // original unaffected
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub DROP_COPY,
 +    correctness,
 +    "calls to `std::mem::drop` with a value that implements Copy"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for calls to `std::mem::forget` with a value that
 +    /// derives the Copy trait
 +    ///
 +    /// ### Why is this bad?
 +    /// Calling `std::mem::forget` [does nothing for types that
 +    /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html) since the
 +    /// value will be copied and moved into the function on invocation.
 +    ///
 +    /// An alternative, but also valid, explanation is that Copy types do not
 +    /// implement
 +    /// the Drop trait, which means they have no destructors. Without a destructor,
 +    /// there
 +    /// is nothing for `std::mem::forget` to ignore.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// let x: i32 = 42; // i32 implements Copy
 +    /// std::mem::forget(x) // A copy of x is passed to the function, leaving the
 +    ///                     // original unaffected
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub FORGET_COPY,
 +    correctness,
 +    "calls to `std::mem::forget` with a value that implements Copy"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for calls to `std::mem::drop` with a value that does not implement `Drop`.
 +    ///
 +    /// ### Why is this bad?
 +    /// Calling `std::mem::drop` is no different than dropping such a type. A different value may
 +    /// have been intended.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// struct Foo;
 +    /// let x = Foo;
 +    /// std::mem::drop(x);
 +    /// ```
 +    #[clippy::version = "1.62.0"]
 +    pub DROP_NON_DROP,
 +    suspicious,
 +    "call to `std::mem::drop` with a value which does not implement `Drop`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for calls to `std::mem::forget` with a value that does not implement `Drop`.
 +    ///
 +    /// ### Why is this bad?
 +    /// Calling `std::mem::forget` is no different than dropping such a type. A different value may
 +    /// have been intended.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// struct Foo;
 +    /// let x = Foo;
 +    /// std::mem::forget(x);
 +    /// ```
 +    #[clippy::version = "1.62.0"]
 +    pub FORGET_NON_DROP,
 +    suspicious,
 +    "call to `std::mem::forget` with a value which does not implement `Drop`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`.
 +    ///
 +    /// ### Why is this bad?
 +    /// The safe `drop` function does not drop the inner value of a `ManuallyDrop`.
 +    ///
 +    /// ### Known problems
 +    /// Does not catch cases if the user binds `std::mem::drop`
 +    /// to a different name and calls it that way.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// struct S;
 +    /// drop(std::mem::ManuallyDrop::new(S));
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    /// struct S;
 +    /// unsafe {
 +    ///     std::mem::ManuallyDrop::drop(&mut std::mem::ManuallyDrop::new(S));
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.49.0"]
 +    pub UNDROPPED_MANUALLY_DROPS,
 +    correctness,
 +    "use of safe `std::mem::drop` function to drop a std::mem::ManuallyDrop, which will not drop the inner value"
 +}
 +
 +const DROP_REF_SUMMARY: &str = "calls to `std::mem::drop` with a reference instead of an owned value. \
 +                                Dropping a reference does nothing";
 +const FORGET_REF_SUMMARY: &str = "calls to `std::mem::forget` with a reference instead of an owned value. \
 +                                  Forgetting a reference does nothing";
 +const DROP_COPY_SUMMARY: &str = "calls to `std::mem::drop` with a value that implements `Copy`. \
 +                                 Dropping a copy leaves the original intact";
 +const FORGET_COPY_SUMMARY: &str = "calls to `std::mem::forget` with a value that implements `Copy`. \
 +                                   Forgetting a copy leaves the original intact";
 +const DROP_NON_DROP_SUMMARY: &str = "call to `std::mem::drop` with a value that does not implement `Drop`. \
 +                                 Dropping such a type only extends its contained lifetimes";
 +const FORGET_NON_DROP_SUMMARY: &str = "call to `std::mem::forget` with a value that does not implement `Drop`. \
 +                                   Forgetting such a type is the same as dropping it";
 +
 +declare_lint_pass!(DropForgetRef => [
 +    DROP_REF,
 +    FORGET_REF,
 +    DROP_COPY,
 +    FORGET_COPY,
 +    DROP_NON_DROP,
 +    FORGET_NON_DROP,
 +    UNDROPPED_MANUALLY_DROPS
 +]);
 +
 +impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 +        if let ExprKind::Call(path, [arg]) = expr.kind
 +            && let ExprKind::Path(ref qpath) = path.kind
 +            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
 +            && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
 +        {
 +            let arg_ty = cx.typeck_results().expr_ty(arg);
 +            let is_copy = is_copy(cx, arg_ty);
 +            let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
 +            let (lint, msg) = match fn_name {
++                sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
 +                sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
 +                sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
 +                sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
 +                sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => {
 +                    span_lint_and_help(
 +                        cx,
 +                        UNDROPPED_MANUALLY_DROPS,
 +                        expr.span,
 +                        "the inner value of this ManuallyDrop will not be dropped",
 +                        None,
 +                        "to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop",
 +                    );
 +                    return;
 +                }
 +                sym::mem_drop
 +                    if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
 +                        || is_must_use_func_call(cx, arg)
 +                        || is_must_use_ty(cx, arg_ty)
 +                        || drop_is_single_call_in_arm
 +                        ) =>
 +                {
 +                    (DROP_NON_DROP, DROP_NON_DROP_SUMMARY)
 +                },
 +                sym::mem_forget if !arg_ty.needs_drop(cx.tcx, cx.param_env) => {
 +                    (FORGET_NON_DROP, FORGET_NON_DROP_SUMMARY)
 +                },
 +                _ => return,
 +            };
 +            span_lint_and_note(
 +                cx,
 +                lint,
 +                expr.span,
 +                msg,
 +                Some(arg.span),
 +                &format!("argument has type `{arg_ty}`"),
 +            );
 +        }
 +    }
 +}
 +
 +// dropping returned value of a function like in the following snippet is considered idiomatic, see
 +// #9482 for examples match <var> {
 +//     <pat> => drop(fn_with_side_effect_and_returning_some_value()),
 +//     ..
 +// }
 +fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool {
 +    if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
 +        let parent_node = get_parent_node(cx.tcx, drop_expr.hir_id);
 +        if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
 +            return body.hir_id == drop_expr.hir_id;
 +        }
 +    }
 +    false
 +}
index 08bf80a422900f533d61225670031aacc77cc37e,0000000000000000000000000000000000000000..c3a020433de85bea0c68c3b9de7fd53fdb6608d1
mode 100644,000000..100644
--- /dev/null
@@@ -1,99 -1,0 +1,99 @@@
-                         Applicability::MachineApplicable);
 +use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt};
 +use rustc_ast::ast::{Item, ItemKind, VariantData};
 +use rustc_errors::Applicability;
 +use rustc_lexer::TokenKind;
 +use rustc_lint::{EarlyContext, EarlyLintPass};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::Span;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Finds structs without fields (a so-called "empty struct") that are declared with brackets.
 +    ///
 +    /// ### Why is this bad?
 +    /// Empty brackets after a struct declaration can be omitted.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// struct Cookie {}
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    /// struct Cookie;
 +    /// ```
 +    #[clippy::version = "1.62.0"]
 +    pub EMPTY_STRUCTS_WITH_BRACKETS,
 +    restriction,
 +    "finds struct declarations with empty brackets"
 +}
 +declare_lint_pass!(EmptyStructsWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS]);
 +
 +impl EarlyLintPass for EmptyStructsWithBrackets {
 +    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
 +        let span_after_ident = item.span.with_lo(item.ident.span.hi());
 +
 +        if let ItemKind::Struct(var_data, _) = &item.kind
 +            && has_brackets(var_data)
 +            && has_no_fields(cx, var_data, span_after_ident) {
 +            span_lint_and_then(
 +                cx,
 +                EMPTY_STRUCTS_WITH_BRACKETS,
 +                span_after_ident,
 +                "found empty brackets on struct declaration",
 +                |diagnostic| {
 +                    diagnostic.span_suggestion_hidden(
 +                        span_after_ident,
 +                        "remove the brackets",
 +                        ";",
++                        Applicability::Unspecified);
 +                    },
 +            );
 +        }
 +    }
 +}
 +
 +fn has_no_ident_token(braces_span_str: &str) -> bool {
 +    !rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident)
 +}
 +
 +fn has_brackets(var_data: &VariantData) -> bool {
 +    !matches!(var_data, VariantData::Unit(_))
 +}
 +
 +fn has_no_fields(cx: &EarlyContext<'_>, var_data: &VariantData, braces_span: Span) -> bool {
 +    if !var_data.fields().is_empty() {
 +        return false;
 +    }
 +
 +    // there might still be field declarations hidden from the AST
 +    // (conditionally compiled code using #[cfg(..)])
 +
 +    let Some(braces_span_str) = snippet_opt(cx, braces_span) else {
 +        return false;
 +    };
 +
 +    has_no_ident_token(braces_span_str.as_ref())
 +}
 +
 +#[cfg(test)]
 +mod unit_test {
 +    use super::*;
 +
 +    #[test]
 +    fn test_has_no_ident_token() {
 +        let input = "{ field: u8 }";
 +        assert!(!has_no_ident_token(input));
 +
 +        let input = "(u8, String);";
 +        assert!(!has_no_ident_token(input));
 +
 +        let input = " {
 +                // test = 5
 +        }
 +        ";
 +        assert!(has_no_ident_token(input));
 +
 +        let input = " ();";
 +        assert!(has_no_ident_token(input));
 +    }
 +}
index dcd8ca81ae87210dd1e033adec09e657274ded6a,0000000000000000000000000000000000000000..d8e2ae02c5a65cf1467d0cfee62e5edbf87c14dc
mode 100644,000000..100644
--- /dev/null
@@@ -1,972 -1,0 +1,972 @@@
-     store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls));
 +#![feature(array_windows)]
 +#![feature(binary_heap_into_iter_sorted)]
 +#![feature(box_patterns)]
 +#![feature(control_flow_enum)]
 +#![feature(drain_filter)]
 +#![feature(iter_intersperse)]
 +#![feature(let_chains)]
 +#![feature(lint_reasons)]
 +#![feature(never_type)]
 +#![feature(once_cell)]
 +#![feature(rustc_private)]
 +#![feature(stmt_expr_attributes)]
 +#![recursion_limit = "512"]
 +#![cfg_attr(feature = "deny-warnings", deny(warnings))]
 +#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)]
 +#![warn(trivial_casts, trivial_numeric_casts)]
 +// warn on lints, that are included in `rust-lang/rust`s bootstrap
 +#![warn(rust_2018_idioms, unused_lifetimes)]
 +// warn on rustc internal lints
 +#![warn(rustc::internal)]
 +// Disable this rustc lint for now, as it was also done in rustc
 +#![allow(rustc::potential_query_instability)]
 +
 +// FIXME: switch to something more ergonomic here, once available.
 +// (Currently there is no way to opt into sysroot crates without `extern crate`.)
 +extern crate rustc_arena;
 +extern crate rustc_ast;
 +extern crate rustc_ast_pretty;
 +extern crate rustc_data_structures;
 +extern crate rustc_driver;
 +extern crate rustc_errors;
 +extern crate rustc_hir;
 +extern crate rustc_hir_analysis;
 +extern crate rustc_hir_pretty;
 +extern crate rustc_hir_typeck;
 +extern crate rustc_index;
 +extern crate rustc_infer;
 +extern crate rustc_lexer;
 +extern crate rustc_lint;
 +extern crate rustc_middle;
 +extern crate rustc_parse;
 +extern crate rustc_session;
 +extern crate rustc_span;
 +extern crate rustc_target;
 +extern crate rustc_trait_selection;
 +
 +#[macro_use]
 +extern crate clippy_utils;
 +#[macro_use]
 +extern crate declare_clippy_lint;
 +
 +use std::io;
 +use std::path::PathBuf;
 +
 +use clippy_utils::msrvs::Msrv;
 +use rustc_data_structures::fx::FxHashSet;
 +use rustc_lint::{Lint, LintId};
 +use rustc_session::Session;
 +
 +#[cfg(feature = "internal")]
 +pub mod deprecated_lints;
 +#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
 +mod utils;
 +
 +mod declared_lints;
 +mod renamed_lints;
 +
 +// begin lints modules, do not remove this comment, it’s used in `update_lints`
 +mod almost_complete_range;
 +mod approx_const;
 +mod as_conversions;
 +mod asm_syntax;
 +mod assertions_on_constants;
 +mod assertions_on_result_states;
 +mod async_yields_async;
 +mod attrs;
 +mod await_holding_invalid;
 +mod blocks_in_if_conditions;
 +mod bool_assert_comparison;
 +mod bool_to_int_with_if;
 +mod booleans;
 +mod borrow_deref_ref;
 +mod box_default;
 +mod cargo;
 +mod casts;
 +mod checked_conversions;
 +mod cognitive_complexity;
 +mod collapsible_if;
 +mod comparison_chain;
 +mod copies;
 +mod copy_iterator;
 +mod crate_in_macro_def;
 +mod create_dir;
 +mod dbg_macro;
 +mod default;
 +mod default_instead_of_iter_empty;
 +mod default_numeric_fallback;
 +mod default_union_representation;
 +mod dereference;
 +mod derivable_impls;
 +mod derive;
 +mod disallowed_macros;
 +mod disallowed_methods;
 +mod disallowed_names;
 +mod disallowed_script_idents;
 +mod disallowed_types;
 +mod doc;
 +mod double_parens;
 +mod drop_forget_ref;
 +mod duplicate_mod;
 +mod else_if_without_else;
 +mod empty_drop;
 +mod empty_enum;
 +mod empty_structs_with_brackets;
 +mod entry;
 +mod enum_clike;
 +mod enum_variants;
 +mod equatable_if_let;
 +mod escape;
 +mod eta_reduction;
 +mod excessive_bools;
 +mod exhaustive_items;
 +mod exit;
 +mod explicit_write;
 +mod fallible_impl_from;
 +mod float_literal;
 +mod floating_point_arithmetic;
 +mod fn_null_check;
 +mod format;
 +mod format_args;
 +mod format_impl;
 +mod format_push_string;
 +mod formatting;
 +mod from_over_into;
 +mod from_raw_with_void_ptr;
 +mod from_str_radix_10;
 +mod functions;
 +mod future_not_send;
 +mod if_let_mutex;
 +mod if_not_else;
 +mod if_then_some_else_none;
 +mod implicit_hasher;
 +mod implicit_return;
 +mod implicit_saturating_add;
 +mod implicit_saturating_sub;
 +mod inconsistent_struct_constructor;
 +mod index_refutable_slice;
 +mod indexing_slicing;
 +mod infinite_iter;
 +mod inherent_impl;
 +mod inherent_to_string;
 +mod init_numbered_fields;
 +mod inline_fn_without_body;
 +mod instant_subtraction;
 +mod int_plus_one;
 +mod invalid_upcast_comparisons;
 +mod invalid_utf8_in_unchecked;
 +mod items_after_statements;
 +mod iter_not_returning_iterator;
 +mod large_const_arrays;
 +mod large_enum_variant;
 +mod large_include_file;
 +mod large_stack_arrays;
 +mod len_zero;
 +mod let_if_seq;
 +mod let_underscore;
 +mod lifetimes;
 +mod literal_representation;
 +mod loops;
 +mod macro_use;
 +mod main_recursion;
 +mod manual_assert;
 +mod manual_async_fn;
 +mod manual_bits;
 +mod manual_clamp;
 +mod manual_is_ascii_check;
 +mod manual_let_else;
 +mod manual_non_exhaustive;
 +mod manual_rem_euclid;
 +mod manual_retain;
 +mod manual_string_new;
 +mod manual_strip;
 +mod map_unit_fn;
 +mod match_result_ok;
 +mod matches;
 +mod mem_forget;
 +mod mem_replace;
 +mod methods;
 +mod minmax;
 +mod misc;
 +mod misc_early;
 +mod mismatching_type_param_order;
 +mod missing_const_for_fn;
 +mod missing_doc;
 +mod missing_enforced_import_rename;
 +mod missing_inline;
 +mod missing_trait_methods;
 +mod mixed_read_write_in_expression;
 +mod module_style;
 +mod multi_assignments;
 +mod mut_key;
 +mod mut_mut;
 +mod mut_reference;
 +mod mutable_debug_assertion;
 +mod mutex_atomic;
 +mod needless_arbitrary_self_type;
 +mod needless_bool;
 +mod needless_borrowed_ref;
 +mod needless_continue;
 +mod needless_for_each;
 +mod needless_late_init;
 +mod needless_parens_on_range_literals;
 +mod needless_pass_by_value;
 +mod needless_question_mark;
 +mod needless_update;
 +mod neg_cmp_op_on_partial_ord;
 +mod neg_multiply;
 +mod new_without_default;
 +mod no_effect;
 +mod non_copy_const;
 +mod non_expressive_names;
 +mod non_octal_unix_permissions;
 +mod non_send_fields_in_send_ty;
 +mod nonstandard_macro_braces;
 +mod octal_escapes;
 +mod only_used_in_recursion;
 +mod operators;
 +mod option_env_unwrap;
 +mod option_if_let_else;
 +mod overflow_check_conditional;
 +mod panic_in_result_fn;
 +mod panic_unimplemented;
 +mod partial_pub_fields;
 +mod partialeq_ne_impl;
 +mod partialeq_to_none;
 +mod pass_by_ref_or_value;
 +mod pattern_type_mismatch;
 +mod permissions_set_readonly_false;
 +mod precedence;
 +mod ptr;
 +mod ptr_offset_with_cast;
 +mod pub_use;
 +mod question_mark;
 +mod ranges;
 +mod rc_clone_in_vec_init;
 +mod read_zero_byte_vec;
 +mod redundant_clone;
 +mod redundant_closure_call;
 +mod redundant_else;
 +mod redundant_field_names;
 +mod redundant_pub_crate;
 +mod redundant_slicing;
 +mod redundant_static_lifetimes;
 +mod ref_option_ref;
 +mod reference;
 +mod regex;
 +mod return_self_not_must_use;
 +mod returns;
 +mod same_name_method;
 +mod self_named_constructors;
 +mod semicolon_block;
 +mod semicolon_if_nothing_returned;
 +mod serde_api;
 +mod shadow;
 +mod single_char_lifetime_names;
 +mod single_component_path_imports;
 +mod size_of_in_element_count;
 +mod size_of_ref;
 +mod slow_vector_initialization;
 +mod std_instead_of_core;
 +mod strings;
 +mod strlen_on_c_strings;
 +mod suspicious_operation_groupings;
 +mod suspicious_trait_impl;
 +mod suspicious_xor_used_as_pow;
 +mod swap;
 +mod swap_ptr_to_ref;
 +mod tabs_in_doc_comments;
 +mod temporary_assignment;
 +mod to_digit_is_some;
 +mod trailing_empty_array;
 +mod trait_bounds;
 +mod transmute;
 +mod types;
 +mod undocumented_unsafe_blocks;
 +mod unicode;
 +mod uninit_vec;
 +mod unit_return_expecting_ord;
 +mod unit_types;
 +mod unnamed_address;
 +mod unnecessary_owned_empty_strings;
 +mod unnecessary_self_imports;
 +mod unnecessary_wraps;
 +mod unnested_or_patterns;
 +mod unsafe_removed_from_name;
 +mod unused_async;
 +mod unused_io_amount;
 +mod unused_peekable;
 +mod unused_rounding;
 +mod unused_self;
 +mod unused_unit;
 +mod unwrap;
 +mod unwrap_in_result;
 +mod upper_case_acronyms;
 +mod use_self;
 +mod useless_conversion;
 +mod vec;
 +mod vec_init_then_push;
 +mod wildcard_imports;
 +mod write;
 +mod zero_div_zero;
 +mod zero_sized_map_values;
 +// end lints modules, do not remove this comment, it’s used in `update_lints`
 +
 +use crate::utils::conf::{format_error, TryConf};
 +pub use crate::utils::conf::{lookup_conf_file, Conf};
 +
 +/// Register all pre expansion lints
 +///
 +/// Pre-expansion lints run before any macro expansion has happened.
 +///
 +/// Note that due to the architecture of the compiler, currently `cfg_attr` attributes on crate
 +/// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass.
 +///
 +/// Used in `./src/driver.rs`.
 +pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
 +    // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
 +    let msrv = Msrv::read(&conf.msrv, sess);
 +    let msrv = move || msrv.clone();
 +
 +    store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv: msrv() }));
 +}
 +
 +#[doc(hidden)]
 +pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
 +    let file_name = match path {
 +        Ok(Some(path)) => path,
 +        Ok(None) => return Conf::default(),
 +        Err(error) => {
 +            sess.struct_err(format!("error finding Clippy's configuration file: {error}"))
 +                .emit();
 +            return Conf::default();
 +        },
 +    };
 +
 +    let TryConf { conf, errors, warnings } = utils::conf::read(file_name);
 +    // all conf errors are non-fatal, we just use the default conf in case of error
 +    for error in errors {
 +        sess.err(format!(
 +            "error reading Clippy's configuration file `{}`: {}",
 +            file_name.display(),
 +            format_error(error)
 +        ));
 +    }
 +
 +    for warning in warnings {
 +        sess.struct_warn(format!(
 +            "error reading Clippy's configuration file `{}`: {}",
 +            file_name.display(),
 +            format_error(warning)
 +        ))
 +        .emit();
 +    }
 +
 +    conf
 +}
 +
 +#[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>,
 +    #[cfg(feature = "internal")]
 +    internal: 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);
 +        #[cfg(feature = "internal")]
 +        store.register_group(true, "clippy::internal", Some("clippy_internal"), self.internal);
 +    }
 +}
 +
 +#[derive(Copy, Clone)]
 +pub(crate) enum LintCategory {
 +    Cargo,
 +    Complexity,
 +    Correctness,
 +    Nursery,
 +    Pedantic,
 +    Perf,
 +    Restriction,
 +    Style,
 +    Suspicious,
 +    #[cfg(feature = "internal")]
 +    Internal,
 +}
 +#[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,
 +            #[cfg(feature = "internal")]
 +            Internal => &mut groups.internal,
 +        }
 +    }
 +}
 +
 +pub(crate) struct LintInfo {
 +    /// Double reference to maintain pointer equality
 +    lint: &'static &'static Lint,
 +    category: LintCategory,
 +    explanation: &'static str,
 +}
 +
 +pub fn explain(name: &str) {
 +    let target = format!("clippy::{}", name.to_ascii_uppercase());
 +    match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
 +        Some(info) => print!("{}", info.explanation),
 +        None => println!("unknown lint: {name}"),
 +    }
 +}
 +
 +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 plugin registry
 +///
 +/// Used in `./src/driver.rs`.
 +#[expect(clippy::too_many_lines)]
 +pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
 +    register_removed_non_tool_lints(store);
 +    register_categories(store);
 +
 +    include!("lib.deprecated.rs");
 +
 +    #[cfg(feature = "internal")]
 +    {
 +        if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
 +            store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
 +            return;
 +        }
 +    }
 +
 +    // all the internal lints
 +    #[cfg(feature = "internal")]
 +    {
 +        store.register_early_pass(|| Box::new(utils::internal_lints::clippy_lints_internal::ClippyLintsInternal));
 +        store.register_early_pass(|| Box::new(utils::internal_lints::produce_ice::ProduceIce));
 +        store.register_late_pass(|_| Box::new(utils::internal_lints::collapsible_calls::CollapsibleCalls));
 +        store.register_late_pass(|_| {
 +            Box::new(utils::internal_lints::compiler_lint_functions::CompilerLintFunctions::new())
 +        });
 +        store.register_late_pass(|_| Box::new(utils::internal_lints::if_chain_style::IfChainStyle));
 +        store.register_late_pass(|_| Box::new(utils::internal_lints::invalid_paths::InvalidPaths));
 +        store.register_late_pass(|_| {
 +            Box::<utils::internal_lints::interning_defined_symbol::InterningDefinedSymbol>::default()
 +        });
 +        store.register_late_pass(|_| {
 +            Box::<utils::internal_lints::lint_without_lint_pass::LintWithoutLintPass>::default()
 +        });
 +        store.register_late_pass(|_| Box::<utils::internal_lints::unnecessary_def_path::UnnecessaryDefPath>::default());
 +        store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass));
 +        store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl));
 +    }
 +
 +    let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
 +    let arithmetic_side_effects_allowed_binary = conf.arithmetic_side_effects_allowed_binary.clone();
 +    let arithmetic_side_effects_allowed_unary = conf.arithmetic_side_effects_allowed_unary.clone();
 +    store.register_late_pass(move |_| {
 +        Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(
 +            arithmetic_side_effects_allowed
 +                .iter()
 +                .flat_map(|el| [[el.clone(), "*".to_string()], ["*".to_string(), el.clone()]])
 +                .chain(arithmetic_side_effects_allowed_binary.clone())
 +                .collect(),
 +            arithmetic_side_effects_allowed
 +                .iter()
 +                .chain(arithmetic_side_effects_allowed_unary.iter())
 +                .cloned()
 +                .collect(),
 +        ))
 +    });
 +    store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
 +    store.register_late_pass(|_| Box::new(utils::author::Author));
 +    let await_holding_invalid_types = conf.await_holding_invalid_types.clone();
 +    store.register_late_pass(move |_| {
 +        Box::new(await_holding_invalid::AwaitHolding::new(
 +            await_holding_invalid_types.clone(),
 +        ))
 +    });
 +    store.register_late_pass(|_| Box::new(serde_api::SerdeApi));
 +    let vec_box_size_threshold = conf.vec_box_size_threshold;
 +    let type_complexity_threshold = conf.type_complexity_threshold;
 +    let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
 +    store.register_late_pass(move |_| {
 +        Box::new(types::Types::new(
 +            vec_box_size_threshold,
 +            type_complexity_threshold,
 +            avoid_breaking_exported_api,
 +        ))
 +    });
 +    store.register_late_pass(|_| Box::new(booleans::NonminimalBool));
 +    store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant));
 +    store.register_late_pass(|_| Box::new(float_literal::FloatLiteral));
 +    store.register_late_pass(|_| Box::new(ptr::Ptr));
 +    store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
 +    store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
 +    store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
 +    store.register_late_pass(|_| Box::<misc::LintPass>::default());
 +    store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
 +    store.register_late_pass(|_| Box::new(mut_mut::MutMut));
 +    store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
 +    store.register_late_pass(|_| Box::new(len_zero::LenZero));
 +    store.register_late_pass(|_| Box::new(attrs::Attributes));
 +    store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
 +    store.register_late_pass(|_| Box::new(unicode::Unicode));
 +    store.register_late_pass(|_| Box::new(uninit_vec::UninitVec));
 +    store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
 +    store.register_late_pass(|_| Box::new(strings::StringAdd));
 +    store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn));
 +    store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub));
 +    store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback));
 +    store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
 +    store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
 +    store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
 +
 +    let msrv = Msrv::read(&conf.msrv, sess);
 +    let msrv = move || msrv.clone();
 +    let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
 +    let allow_expect_in_tests = conf.allow_expect_in_tests;
 +    let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
 +    let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const;
 +    store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
 +    store.register_late_pass(move |_| {
 +        Box::new(methods::Methods::new(
 +            avoid_breaking_exported_api,
 +            msrv(),
 +            allow_expect_in_tests,
 +            allow_unwrap_in_tests,
 +        ))
 +    });
 +    store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv())));
 +    let matches_for_let_else = conf.matches_for_let_else;
 +    store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv(), matches_for_let_else)));
 +    store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv())));
 +    store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv())));
 +    store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark));
 +    store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv())));
 +    store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv())));
 +    store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount));
 +    store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod));
 +    let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length;
 +    store.register_late_pass(move |_| {
 +        Box::new(index_refutable_slice::IndexRefutableSlice::new(
 +            max_suggested_slice_pattern_length,
 +            msrv(),
 +        ))
 +    });
 +    store.register_late_pass(|_| Box::<shadow::Shadow>::default());
 +    store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
 +    store.register_late_pass(|_| Box::new(loops::Loops));
 +    store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
 +    store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
 +    store.register_late_pass(|_| Box::new(entry::HashMapPass));
 +    store.register_late_pass(|_| Box::new(minmax::MinMaxPass));
 +    store.register_late_pass(|_| Box::new(zero_div_zero::ZeroDiv));
 +    store.register_late_pass(|_| Box::new(mutex_atomic::Mutex));
 +    store.register_late_pass(|_| Box::new(needless_update::NeedlessUpdate));
 +    store.register_late_pass(|_| Box::new(needless_borrowed_ref::NeedlessBorrowedRef));
 +    store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef));
 +    store.register_late_pass(|_| Box::new(no_effect::NoEffect));
 +    store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment));
 +    store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv())));
 +    let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
 +    store.register_late_pass(move |_| {
 +        Box::new(cognitive_complexity::CognitiveComplexity::new(
 +            cognitive_complexity_threshold,
 +        ))
 +    });
 +    let too_large_for_stack = conf.too_large_for_stack;
 +    store.register_late_pass(move |_| Box::new(escape::BoxedLocal { too_large_for_stack }));
 +    store.register_late_pass(move |_| Box::new(vec::UselessVec { too_large_for_stack }));
 +    store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
 +    store.register_late_pass(|_| Box::new(strings::StringLitAsBytes));
 +    store.register_late_pass(|_| Box::new(derive::Derive));
++    store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(msrv())));
 +    store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
 +    store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
 +    store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
 +    store.register_late_pass(|_| Box::new(regex::Regex));
 +    store.register_late_pass(|_| Box::new(copies::CopyAndPaste));
 +    store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator));
 +    store.register_late_pass(|_| Box::new(format::UselessFormat));
 +    store.register_late_pass(|_| Box::new(swap::Swap));
 +    store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional));
 +    store.register_late_pass(|_| Box::<new_without_default::NewWithoutDefault>::default());
 +    let disallowed_names = conf.disallowed_names.iter().cloned().collect::<FxHashSet<_>>();
 +    store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone())));
 +    let too_many_arguments_threshold = conf.too_many_arguments_threshold;
 +    let too_many_lines_threshold = conf.too_many_lines_threshold;
 +    let large_error_threshold = conf.large_error_threshold;
 +    store.register_late_pass(move |_| {
 +        Box::new(functions::Functions::new(
 +            too_many_arguments_threshold,
 +            too_many_lines_threshold,
 +            large_error_threshold,
 +        ))
 +    });
 +    let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
 +    store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
 +    store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply));
 +    store.register_late_pass(|_| Box::new(mem_forget::MemForget));
 +    store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
 +    store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
 +    store.register_late_pass(|_| Box::new(missing_doc::MissingDoc::new()));
 +    store.register_late_pass(|_| Box::new(missing_inline::MissingInline));
 +    store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems));
 +    store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk));
 +    store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl));
 +    store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount));
 +    let enum_variant_size_threshold = conf.enum_variant_size_threshold;
 +    store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold)));
 +    store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite));
 +    store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue));
 +    let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
 +        conf.trivial_copy_size_limit,
 +        conf.pass_by_value_size_limit,
 +        conf.avoid_breaking_exported_api,
 +        &sess.target,
 +    );
 +    store.register_late_pass(move |_| Box::new(pass_by_ref_or_value));
 +    store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef));
 +    store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter));
 +    store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody));
 +    store.register_late_pass(|_| Box::<useless_conversion::UselessConversion>::default());
 +    store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher));
 +    store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom));
 +    store.register_late_pass(|_| Box::new(question_mark::QuestionMark));
 +    store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings));
 +    store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl));
 +    store.register_late_pass(|_| Box::new(map_unit_fn::MapUnit));
 +    store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl));
 +    store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
 +    store.register_late_pass(|_| Box::new(unwrap::Unwrap));
 +    store.register_late_pass(move |_| {
 +        Box::new(indexing_slicing::IndexingSlicing::new(
 +            suppress_restriction_lint_in_const,
 +        ))
 +    });
 +    store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst));
 +    store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
 +    store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
 +    store.register_late_pass(|_| Box::new(slow_vector_initialization::SlowVectorInit));
 +    store.register_late_pass(move |_| Box::new(unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api)));
 +    store.register_late_pass(|_| Box::new(assertions_on_constants::AssertionsOnConstants));
 +    store.register_late_pass(|_| Box::new(assertions_on_result_states::AssertionsOnResultStates));
 +    store.register_late_pass(|_| Box::new(inherent_to_string::InherentToString));
 +    let max_trait_bounds = conf.max_trait_bounds;
 +    store.register_late_pass(move |_| Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
 +    store.register_late_pass(|_| Box::new(comparison_chain::ComparisonChain));
 +    let ignore_interior_mutability = conf.ignore_interior_mutability.clone();
 +    store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone())));
 +    store.register_early_pass(|| Box::new(reference::DerefAddrOf));
 +    store.register_early_pass(|| Box::new(double_parens::DoubleParens));
 +    store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new()));
 +    store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
 +    store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
 +    store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
 +    store.register_early_pass(|| Box::new(formatting::Formatting));
 +    store.register_early_pass(|| Box::new(misc_early::MiscEarlyLints));
 +    store.register_early_pass(|| Box::new(redundant_closure_call::RedundantClosureCall));
 +    store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
 +    store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
 +    store.register_late_pass(|_| Box::new(returns::Return));
 +    store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
 +    store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements));
 +    store.register_early_pass(|| Box::new(precedence::Precedence));
 +    store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
 +    store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue));
 +    store.register_early_pass(|| Box::new(redundant_else::RedundantElse));
 +    store.register_late_pass(|_| Box::new(create_dir::CreateDir));
 +    store.register_early_pass(|| Box::new(needless_arbitrary_self_type::NeedlessArbitrarySelfType));
 +    let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
 +    store.register_early_pass(move || {
 +        Box::new(literal_representation::LiteralDigitGrouping::new(
 +            literal_representation_lint_fraction_readability,
 +        ))
 +    });
 +    let literal_representation_threshold = conf.literal_representation_threshold;
 +    store.register_early_pass(move || {
 +        Box::new(literal_representation::DecimalLiteralRepresentation::new(
 +            literal_representation_threshold,
 +        ))
 +    });
 +    let enum_variant_name_threshold = conf.enum_variant_name_threshold;
 +    store.register_late_pass(move |_| {
 +        Box::new(enum_variants::EnumVariantNames::new(
 +            enum_variant_name_threshold,
 +            avoid_breaking_exported_api,
 +        ))
 +    });
 +    store.register_early_pass(|| Box::new(tabs_in_doc_comments::TabsInDocComments));
 +    let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
 +    store.register_late_pass(move |_| {
 +        Box::new(upper_case_acronyms::UpperCaseAcronyms::new(
 +            avoid_breaking_exported_api,
 +            upper_case_acronyms_aggressive,
 +        ))
 +    });
 +    store.register_late_pass(|_| Box::<default::Default>::default());
 +    store.register_late_pass(move |_| Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api)));
 +    store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
 +    store.register_late_pass(|_| Box::new(exit::Exit));
 +    store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome));
 +    let array_size_threshold = conf.array_size_threshold;
 +    store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
 +    store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
 +    store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
 +    store.register_early_pass(|| Box::new(as_conversions::AsConversions));
 +    store.register_late_pass(|_| Box::new(let_underscore::LetUnderscore));
 +    store.register_early_pass(|| Box::<single_component_path_imports::SingleComponentPathImports>::default());
 +    let max_fn_params_bools = conf.max_fn_params_bools;
 +    let max_struct_bools = conf.max_struct_bools;
 +    store.register_late_pass(move |_| {
 +        Box::new(excessive_bools::ExcessiveBools::new(
 +            max_struct_bools,
 +            max_fn_params_bools,
 +        ))
 +    });
 +    store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
 +    let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
 +    store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)));
 +    store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
 +    store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
 +    store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv())));
 +    store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
 +    store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
 +    store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex));
 +    store.register_late_pass(|_| Box::new(if_not_else::IfNotElse));
 +    store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality));
 +    store.register_late_pass(|_| Box::new(manual_async_fn::ManualAsyncFn));
 +    store.register_late_pass(|_| Box::new(panic_in_result_fn::PanicInResultFn));
 +    let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
 +    store.register_early_pass(move || {
 +        Box::new(non_expressive_names::NonExpressiveNames {
 +            single_char_binding_names_threshold,
 +        })
 +    });
 +    let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::<FxHashSet<_>>();
 +    store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(&macro_matcher)));
 +    store.register_late_pass(|_| Box::<macro_use::MacroUseImports>::default());
 +    store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch));
 +    store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult));
 +    store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned));
 +    store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync));
 +    let disallowed_macros = conf.disallowed_macros.clone();
 +    store.register_late_pass(move |_| Box::new(disallowed_macros::DisallowedMacros::new(disallowed_macros.clone())));
 +    let disallowed_methods = conf.disallowed_methods.clone();
 +    store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
 +    store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
 +    store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax));
 +    store.register_late_pass(|_| Box::new(empty_drop::EmptyDrop));
 +    store.register_late_pass(|_| Box::new(strings::StrToString));
 +    store.register_late_pass(|_| Box::new(strings::StringToString));
 +    store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues));
 +    store.register_late_pass(|_| Box::<vec_init_then_push::VecInitThenPush>::default());
 +    store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing));
 +    store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10));
 +    store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv())));
 +    store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison));
 +    store.register_early_pass(move || Box::new(module_style::ModStyle));
 +    store.register_late_pass(|_| Box::new(unused_async::UnusedAsync));
 +    let disallowed_types = conf.disallowed_types.clone();
 +    store.register_late_pass(move |_| Box::new(disallowed_types::DisallowedTypes::new(disallowed_types.clone())));
 +    let import_renames = conf.enforced_import_renames.clone();
 +    store.register_late_pass(move |_| {
 +        Box::new(missing_enforced_import_rename::ImportRename::new(
 +            import_renames.clone(),
 +        ))
 +    });
 +    let scripts = conf.allowed_scripts.clone();
 +    store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts)));
 +    store.register_late_pass(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings));
 +    store.register_late_pass(move |_| Box::new(self_named_constructors::SelfNamedConstructors));
 +    store.register_late_pass(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator));
 +    store.register_late_pass(move |_| Box::new(manual_assert::ManualAssert));
 +    let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
 +    store.register_late_pass(move |_| {
 +        Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(
 +            enable_raw_pointer_heuristic_for_send,
 +        ))
 +    });
 +    store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
 +    let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args;
 +    store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined)));
 +    store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
 +    store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
 +    store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit));
 +    store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse));
 +    store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields));
 +    store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
 +    store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv())));
 +    store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
 +    store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
 +    let allow_dbg_in_tests = conf.allow_dbg_in_tests;
 +    store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
 +    let allow_print_in_tests = conf.allow_print_in_tests;
 +    store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests)));
 +    let cargo_ignore_publish = conf.cargo_ignore_publish;
 +    store.register_late_pass(move |_| {
 +        Box::new(cargo::Cargo {
 +            ignore_publish: cargo_ignore_publish,
 +        })
 +    });
 +    store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
 +    store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
 +    store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
 +    store.register_early_pass(|| Box::new(pub_use::PubUse));
 +    store.register_late_pass(|_| Box::new(format_push_string::FormatPushString));
 +    let max_include_file_size = conf.max_include_file_size;
 +    store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size)));
 +    store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace));
 +    store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
 +    store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
 +    store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
 +    store.register_early_pass(move || Box::new(almost_complete_range::AlmostCompleteRange::new(msrv())));
 +    store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
 +    store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
 +    store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
 +    store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
 +    store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv())));
 +    store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv())));
 +    let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
 +    store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
 +    store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
 +    store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
 +    store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
 +    store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
 +    store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv())));
 +    store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
 +    store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
 +    store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
 +    store.register_late_pass(|_| Box::new(bool_to_int_with_if::BoolToIntWithIf));
 +    store.register_late_pass(|_| Box::new(box_default::BoxDefault));
 +    store.register_late_pass(|_| Box::new(implicit_saturating_add::ImplicitSaturatingAdd));
 +    store.register_early_pass(|| Box::new(partial_pub_fields::PartialPubFields));
 +    store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods));
 +    store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
 +    store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
 +    store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
 +    store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
 +    store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
 +    store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
 +    store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
 +    // add lints here, do not remove this comment, it's used in `new_lint`
 +}
 +
 +#[rustfmt::skip]
 +fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
 +    store.register_removed(
 +        "should_assert_eq",
 +        "`assert!()` will be more flexible with RFC 2011",
 +    );
 +    store.register_removed(
 +        "extend_from_slice",
 +        "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice",
 +    );
 +    store.register_removed(
 +        "range_step_by_zero",
 +        "`iterator.step_by(0)` panics nowadays",
 +    );
 +    store.register_removed(
 +        "unstable_as_slice",
 +        "`Vec::as_slice` has been stabilized in 1.7",
 +    );
 +    store.register_removed(
 +        "unstable_as_mut_slice",
 +        "`Vec::as_mut_slice` has been stabilized in 1.7",
 +    );
 +    store.register_removed(
 +        "misaligned_transmute",
 +        "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
 +    );
 +    store.register_removed(
 +        "assign_ops",
 +        "using compound assignment operators (e.g., `+=`) is harmless",
 +    );
 +    store.register_removed(
 +        "if_let_redundant_pattern_matching",
 +        "this lint has been changed to redundant_pattern_matching",
 +    );
 +    store.register_removed(
 +        "unsafe_vector_initialization",
 +        "the replacement suggested by this lint had substantially different behavior",
 +    );
 +    store.register_removed(
 +        "reverse_range_loop",
 +        "this lint is now included in reversed_empty_ranges",
 +    );
 +}
 +
 +/// Register renamed lints.
 +///
 +/// Used in `./src/driver.rs`.
 +pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
 +    for (old_name, new_name) in renamed_lints::RENAMED_LINTS {
 +        ls.register_renamed(old_name, new_name);
 +    }
 +}
 +
 +// only exists to let the dogfood integration test works.
 +// Don't run clippy as an executable directly
 +#[allow(dead_code)]
 +fn main() {
 +    panic!("Please use the cargo-clippy executable");
 +}
index 27ba27202bf7e8b6ec2c764d51c133c434d6593a,0000000000000000000000000000000000000000..3bca93d80aa7f7540dfdecd9243f32bda0ed8c06
mode 100644,000000..100644
--- /dev/null
@@@ -1,393 -1,0 +1,393 @@@
-                 } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start) {
 +use super::NEEDLESS_RANGE_LOOP;
 +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 +use clippy_utils::source::snippet;
 +use clippy_utils::ty::has_iter_method;
 +use clippy_utils::visitors::is_local_used;
 +use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
 +use if_chain::if_chain;
 +use rustc_ast::ast;
 +use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 +use rustc_hir::def::{DefKind, Res};
 +use rustc_hir::intravisit::{walk_expr, Visitor};
 +use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
 +use rustc_lint::LateContext;
 +use rustc_middle::middle::region;
 +use rustc_middle::ty::{self, Ty};
 +use rustc_span::symbol::{sym, Symbol};
 +use std::iter::{self, Iterator};
 +use std::mem;
 +
 +/// Checks for looping over a range and then indexing a sequence with it.
 +/// The iteratee must be a range literal.
 +#[expect(clippy::too_many_lines)]
 +pub(super) fn check<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    pat: &'tcx Pat<'_>,
 +    arg: &'tcx Expr<'_>,
 +    body: &'tcx Expr<'_>,
 +    expr: &'tcx Expr<'_>,
 +) {
 +    if let Some(higher::Range {
 +        start: Some(start),
 +        ref end,
 +        limits,
 +    }) = higher::Range::hir(arg)
 +    {
 +        // the var must be a single name
 +        if let PatKind::Binding(_, canonical_id, ident, _) = pat.kind {
 +            let mut visitor = VarVisitor {
 +                cx,
 +                var: canonical_id,
 +                indexed_mut: FxHashSet::default(),
 +                indexed_indirectly: FxHashMap::default(),
 +                indexed_directly: FxHashMap::default(),
 +                referenced: FxHashSet::default(),
 +                nonindex: false,
 +                prefer_mutable: false,
 +            };
 +            walk_expr(&mut visitor, body);
 +
 +            // linting condition: we only indexed one variable, and indexed it directly
 +            if visitor.indexed_indirectly.is_empty() && visitor.indexed_directly.len() == 1 {
 +                let (indexed, (indexed_extent, indexed_ty)) = visitor
 +                    .indexed_directly
 +                    .into_iter()
 +                    .next()
 +                    .expect("already checked that we have exactly 1 element");
 +
 +                // ensure that the indexed variable was declared before the loop, see #601
 +                if let Some(indexed_extent) = indexed_extent {
 +                    let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id);
 +                    let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id);
 +                    let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
 +                    if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) {
 +                        return;
 +                    }
 +                }
 +
 +                // don't lint if the container that is indexed does not have .iter() method
 +                let has_iter = has_iter_method(cx, indexed_ty);
 +                if has_iter.is_none() {
 +                    return;
 +                }
 +
 +                // don't lint if the container that is indexed into is also used without
 +                // indexing
 +                if visitor.referenced.contains(&indexed) {
 +                    return;
 +                }
 +
 +                let starts_at_zero = is_integer_const(cx, start, 0);
 +
 +                let skip = if starts_at_zero {
 +                    String::new()
-                     } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr) {
++                } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
 +                    return;
 +                } else {
 +                    format!(".skip({})", snippet(cx, start.span, ".."))
 +                };
 +
 +                let mut end_is_start_plus_val = false;
 +
 +                let take = if let Some(end) = *end {
 +                    let mut take_expr = end;
 +
 +                    if let ExprKind::Binary(ref op, left, right) = end.kind {
 +                        if op.node == BinOpKind::Add {
 +                            let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left);
 +                            let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right);
 +
 +                            if start_equal_left {
 +                                take_expr = right;
 +                            } else if start_equal_right {
 +                                take_expr = left;
 +                            }
 +
 +                            end_is_start_plus_val = start_equal_left | start_equal_right;
 +                        }
 +                    }
 +
 +                    if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
 +                        String::new()
++                    } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
 +                        return;
 +                    } else {
 +                        match limits {
 +                            ast::RangeLimits::Closed => {
 +                                let take_expr = sugg::Sugg::hir(cx, take_expr, "<count>");
 +                                format!(".take({})", take_expr + sugg::ONE)
 +                            },
 +                            ast::RangeLimits::HalfOpen => {
 +                                format!(".take({})", snippet(cx, take_expr.span, ".."))
 +                            },
 +                        }
 +                    }
 +                } else {
 +                    String::new()
 +                };
 +
 +                let (ref_mut, method) = if visitor.indexed_mut.contains(&indexed) {
 +                    ("mut ", "iter_mut")
 +                } else {
 +                    ("", "iter")
 +                };
 +
 +                let take_is_empty = take.is_empty();
 +                let mut method_1 = take;
 +                let mut method_2 = skip;
 +
 +                if end_is_start_plus_val {
 +                    mem::swap(&mut method_1, &mut method_2);
 +                }
 +
 +                if visitor.nonindex {
 +                    span_lint_and_then(
 +                        cx,
 +                        NEEDLESS_RANGE_LOOP,
 +                        arg.span,
 +                        &format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
 +                        |diag| {
 +                            multispan_sugg(
 +                                diag,
 +                                "consider using an iterator",
 +                                vec![
 +                                    (pat.span, format!("({}, <item>)", ident.name)),
 +                                    (
 +                                        arg.span,
 +                                        format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
 +                                    ),
 +                                ],
 +                            );
 +                        },
 +                    );
 +                } else {
 +                    let repl = if starts_at_zero && take_is_empty {
 +                        format!("&{ref_mut}{indexed}")
 +                    } else {
 +                        format!("{indexed}.{method}(){method_1}{method_2}")
 +                    };
 +
 +                    span_lint_and_then(
 +                        cx,
 +                        NEEDLESS_RANGE_LOOP,
 +                        arg.span,
 +                        &format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
 +                        |diag| {
 +                            multispan_sugg(
 +                                diag,
 +                                "consider using an iterator",
 +                                vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
 +                            );
 +                        },
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +fn is_len_call(expr: &Expr<'_>, var: Symbol) -> bool {
 +    if_chain! {
 +        if let ExprKind::MethodCall(method, recv, [], _) = expr.kind;
 +        if method.ident.name == sym::len;
 +        if let ExprKind::Path(QPath::Resolved(_, path)) = recv.kind;
 +        if path.segments.len() == 1;
 +        if path.segments[0].ident.name == var;
 +        then {
 +            return true;
 +        }
 +    }
 +
 +    false
 +}
 +
 +fn is_end_eq_array_len<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    end: &Expr<'_>,
 +    limits: ast::RangeLimits,
 +    indexed_ty: Ty<'tcx>,
 +) -> bool {
 +    if_chain! {
 +        if let ExprKind::Lit(ref lit) = end.kind;
 +        if let ast::LitKind::Int(end_int, _) = lit.node;
 +        if let ty::Array(_, arr_len_const) = indexed_ty.kind();
 +        if let Some(arr_len) = arr_len_const.try_eval_usize(cx.tcx, cx.param_env);
 +        then {
 +            return match limits {
 +                ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
 +                ast::RangeLimits::HalfOpen => end_int >= arr_len.into(),
 +            };
 +        }
 +    }
 +
 +    false
 +}
 +
 +struct VarVisitor<'a, 'tcx> {
 +    /// context reference
 +    cx: &'a LateContext<'tcx>,
 +    /// var name to look for as index
 +    var: HirId,
 +    /// indexed variables that are used mutably
 +    indexed_mut: FxHashSet<Symbol>,
 +    /// indirectly indexed variables (`v[(i + 4) % N]`), the extend is `None` for global
 +    indexed_indirectly: FxHashMap<Symbol, Option<region::Scope>>,
 +    /// subset of `indexed` of vars that are indexed directly: `v[i]`
 +    /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]`
 +    indexed_directly: FxHashMap<Symbol, (Option<region::Scope>, Ty<'tcx>)>,
 +    /// Any names that are used outside an index operation.
 +    /// Used to detect things like `&mut vec` used together with `vec[i]`
 +    referenced: FxHashSet<Symbol>,
 +    /// has the loop variable been used in expressions other than the index of
 +    /// an index op?
 +    nonindex: bool,
 +    /// Whether we are inside the `$` in `&mut $` or `$ = foo` or `$.bar`, where bar
 +    /// takes `&mut self`
 +    prefer_mutable: bool,
 +}
 +
 +impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
 +    fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) -> bool {
 +        if_chain! {
 +            // the indexed container is referenced by a name
 +            if let ExprKind::Path(ref seqpath) = seqexpr.kind;
 +            if let QPath::Resolved(None, seqvar) = *seqpath;
 +            if seqvar.segments.len() == 1;
 +            if is_local_used(self.cx, idx, self.var);
 +            then {
 +                if self.prefer_mutable {
 +                    self.indexed_mut.insert(seqvar.segments[0].ident.name);
 +                }
 +                let index_used_directly = matches!(idx.kind, ExprKind::Path(_));
 +                let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
 +                match res {
 +                    Res::Local(hir_id) => {
 +                        let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
 +                        let extent = self
 +                            .cx
 +                            .tcx
 +                            .region_scope_tree(parent_def_id)
 +                            .var_scope(hir_id.local_id)
 +                            .unwrap();
 +                        if index_used_directly {
 +                            self.indexed_directly.insert(
 +                                seqvar.segments[0].ident.name,
 +                                (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
 +                            );
 +                        } else {
 +                            self.indexed_indirectly
 +                                .insert(seqvar.segments[0].ident.name, Some(extent));
 +                        }
 +                        return false; // no need to walk further *on the variable*
 +                    },
 +                    Res::Def(DefKind::Static(_) | DefKind::Const, ..) => {
 +                        if index_used_directly {
 +                            self.indexed_directly.insert(
 +                                seqvar.segments[0].ident.name,
 +                                (None, self.cx.typeck_results().node_type(seqexpr.hir_id)),
 +                            );
 +                        } else {
 +                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
 +                        }
 +                        return false; // no need to walk further *on the variable*
 +                    },
 +                    _ => (),
 +                }
 +            }
 +        }
 +        true
 +    }
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if_chain! {
 +            // a range index op
 +            if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
 +            if let Some(trait_id) = self
 +                .cx
 +                .typeck_results()
 +                .type_dependent_def_id(expr.hir_id)
 +                .and_then(|def_id| self.cx.tcx.trait_of_item(def_id));
 +            if (meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id))
 +                || (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id));
 +            if !self.check(args_1, args_0, expr);
 +            then {
 +                return;
 +            }
 +        }
 +
 +        if_chain! {
 +            // an index op
 +            if let ExprKind::Index(seqexpr, idx) = expr.kind;
 +            if !self.check(idx, seqexpr, expr);
 +            then {
 +                return;
 +            }
 +        }
 +
 +        if_chain! {
 +            // directly using a variable
 +            if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind;
 +            if let Res::Local(local_id) = path.res;
 +            then {
 +                if local_id == self.var {
 +                    self.nonindex = true;
 +                } else {
 +                    // not the correct variable, but still a variable
 +                    self.referenced.insert(path.segments[0].ident.name);
 +                }
 +            }
 +        }
 +
 +        let old = self.prefer_mutable;
 +        match expr.kind {
 +            ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
 +                self.prefer_mutable = true;
 +                self.visit_expr(lhs);
 +                self.prefer_mutable = false;
 +                self.visit_expr(rhs);
 +            },
 +            ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => {
 +                if mutbl == Mutability::Mut {
 +                    self.prefer_mutable = true;
 +                }
 +                self.visit_expr(expr);
 +            },
 +            ExprKind::Call(f, args) => {
 +                self.visit_expr(f);
 +                for expr in args {
 +                    let ty = self.cx.typeck_results().expr_ty_adjusted(expr);
 +                    self.prefer_mutable = false;
 +                    if let ty::Ref(_, _, mutbl) = *ty.kind() {
 +                        if mutbl == Mutability::Mut {
 +                            self.prefer_mutable = true;
 +                        }
 +                    }
 +                    self.visit_expr(expr);
 +                }
 +            },
 +            ExprKind::MethodCall(_, receiver, args, _) => {
 +                let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
 +                for (ty, expr) in iter::zip(
 +                    self.cx.tcx.fn_sig(def_id).inputs().skip_binder(),
 +                    std::iter::once(receiver).chain(args.iter()),
 +                ) {
 +                    self.prefer_mutable = false;
 +                    if let ty::Ref(_, _, mutbl) = *ty.kind() {
 +                        if mutbl == Mutability::Mut {
 +                            self.prefer_mutable = true;
 +                        }
 +                    }
 +                    self.visit_expr(expr);
 +                }
 +            },
 +            ExprKind::Closure(&Closure { body, .. }) => {
 +                let body = self.cx.tcx.hir().body(body);
 +                self.visit_expr(body.value);
 +            },
 +            _ => walk_expr(self, expr),
 +        }
 +        self.prefer_mutable = old;
 +    }
 +}
index f4b47808dfaa362b8b7f9ce3d6625d87d07d8a48,0000000000000000000000000000000000000000..744fd61bd135c62c70efb6586f6f4e82e40ac397
mode 100644,000000..100644
--- /dev/null
@@@ -1,98 -1,0 +1,100 @@@
 +use super::SINGLE_ELEMENT_LOOP;
 +use clippy_utils::diagnostics::span_lint_and_sugg;
 +use clippy_utils::source::{indent_of, snippet_with_applicability};
++use clippy_utils::visitors::contains_break_or_continue;
 +use if_chain::if_chain;
 +use rustc_ast::util::parser::PREC_PREFIX;
 +use rustc_ast::Mutability;
 +use rustc_errors::Applicability;
 +use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat};
 +use rustc_lint::LateContext;
 +use rustc_span::edition::Edition;
 +
 +pub(super) fn check<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    pat: &'tcx Pat<'_>,
 +    arg: &'tcx Expr<'_>,
 +    body: &'tcx Expr<'_>,
 +    expr: &'tcx Expr<'_>,
 +) {
 +    let (arg_expression, prefix) = match arg.kind {
 +        ExprKind::AddrOf(
 +            BorrowKind::Ref,
 +            Mutability::Not,
 +            Expr {
 +                kind: ExprKind::Array([arg]),
 +                ..
 +            },
 +        ) => (arg, "&"),
 +        ExprKind::AddrOf(
 +            BorrowKind::Ref,
 +            Mutability::Mut,
 +            Expr {
 +                kind: ExprKind::Array([arg]),
 +                ..
 +            },
 +        ) => (arg, "&mut "),
 +        ExprKind::MethodCall(
 +            method,
 +            Expr {
 +                kind: ExprKind::Array([arg]),
 +                ..
 +            },
 +            [],
 +            _,
 +        ) if method.ident.name == rustc_span::sym::iter => (arg, "&"),
 +        ExprKind::MethodCall(
 +            method,
 +            Expr {
 +                kind: ExprKind::Array([arg]),
 +                ..
 +            },
 +            [],
 +            _,
 +        ) if method.ident.name.as_str() == "iter_mut" => (arg, "&mut "),
 +        ExprKind::MethodCall(
 +            method,
 +            Expr {
 +                kind: ExprKind::Array([arg]),
 +                ..
 +            },
 +            [],
 +            _,
 +        ) if method.ident.name == rustc_span::sym::into_iter => (arg, ""),
 +        // Only check for arrays edition 2021 or later, as this case will trigger a compiler error otherwise.
 +        ExprKind::Array([arg]) if cx.tcx.sess.edition() >= Edition::Edition2021 => (arg, ""),
 +        _ => return,
 +    };
 +    if_chain! {
 +        if let ExprKind::Block(block, _) = body.kind;
 +        if !block.stmts.is_empty();
++        if !contains_break_or_continue(body);
 +        then {
 +            let mut applicability = Applicability::MachineApplicable;
 +            let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
 +            let mut arg_snip = snippet_with_applicability(cx, arg_expression.span, "..", &mut applicability);
 +            let mut block_str = snippet_with_applicability(cx, block.span, "..", &mut applicability).into_owned();
 +            block_str.remove(0);
 +            block_str.pop();
 +            let indent = " ".repeat(indent_of(cx, block.stmts[0].span).unwrap_or(0));
 +
 +            // Reference iterator from `&(mut) []` or `[].iter(_mut)()`.
 +            if !prefix.is_empty() && (
 +                // Precedence of internal expression is less than or equal to precedence of `&expr`.
 +                arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression)
 +            ) {
 +                arg_snip = format!("({arg_snip})").into();
 +            }
 +
 +            span_lint_and_sugg(
 +                cx,
 +                SINGLE_ELEMENT_LOOP,
 +                expr.span,
 +                "for loop over a single element",
 +                "try",
 +                format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"),
 +                applicability,
 +            )
 +        }
 +    }
 +}
index d226c0bba6593f4fccfc89237d866d8d8d1784e2,0000000000000000000000000000000000000000..0b3bf22743fae1b0c446c72112b6be8536a1ef4c
mode 100644,000000..100644
--- /dev/null
@@@ -1,41 -1,0 +1,77 @@@
- use clippy_utils::diagnostics::span_lint_and_help;
++use clippy_utils::diagnostics::span_lint_and_then;
++use clippy_utils::source::snippet_opt;
++use clippy_utils::source::{indent_of, reindent_multiline};
 +use clippy_utils::ty::is_type_lang_item;
 +use if_chain::if_chain;
 +use rustc_ast::ast::LitKind;
++use rustc_errors::Applicability;
 +use rustc_hir::{Expr, ExprKind, LangItem};
 +use rustc_lint::LateContext;
 +use rustc_span::{source_map::Spanned, Span};
 +
 +use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
 +
 +pub(super) fn check<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    expr: &'tcx Expr<'_>,
 +    call_span: Span,
 +    recv: &'tcx Expr<'_>,
 +    arg: &'tcx Expr<'_>,
 +) {
++    if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
++        if matches!(
++            path_segment.ident.name.as_str(),
++            "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
++        ) {
++            return;
++        }
++    }
++
 +    if_chain! {
 +        if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
 +        if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
 +        if cx.tcx.type_of(impl_id).is_str();
 +        if let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = arg.kind;
 +        if (2..=6).contains(&ext_literal.as_str().len());
 +        let ext_str = ext_literal.as_str();
 +        if ext_str.starts_with('.');
 +        if ext_str.chars().skip(1).all(|c| c.is_uppercase() || c.is_ascii_digit())
 +            || ext_str.chars().skip(1).all(|c| c.is_lowercase() || c.is_ascii_digit());
 +        let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
 +        if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
 +        then {
-             span_lint_and_help(
++            span_lint_and_then(
 +                cx,
 +                CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
-                 call_span,
++                recv.span.to(call_span),
 +                "case-sensitive file extension comparison",
-                 None,
-                 "consider using a case-insensitive comparison instead",
++                |diag| {
++                    diag.help("consider using a case-insensitive comparison instead");
++                    if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
++
++                        if !cx.typeck_results().expr_ty(recv).is_ref() {
++                            recv_source = format!("&{recv_source}");
++                        }
++
++                        let suggestion_source = reindent_multiline(
++                            format!(
++                                "std::path::Path::new({})
++                                    .extension()
++                                    .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
++                                recv_source, ext_str.strip_prefix('.').unwrap()).into(),
++                            true,
++                            Some(indent_of(cx, call_span).unwrap_or(0) + 4)
++                        );
++
++                        diag.span_suggestion(
++                            recv.span.to(call_span),
++                            "use std::path::Path",
++                            suggestion_source,
++                            Applicability::MaybeIncorrect,
++                        );
++                    }
++                }
 +            );
 +        }
 +    }
 +}
index 7c7938dd2e8b04f5e76fc1f10c4eb654bbcf2f93,0000000000000000000000000000000000000000..3795c0ec250987c0ba4560263d6ef35231f9345f
mode 100644,000000..100644
--- /dev/null
@@@ -1,138 -1,0 +1,140 @@@
- use rustc_middle::ty::{self, adjustment::Adjust};
 +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 +use clippy_utils::get_parent_node;
 +use clippy_utils::source::snippet_with_context;
 +use clippy_utils::sugg;
 +use clippy_utils::ty::is_copy;
 +use rustc_errors::Applicability;
 +use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
 +use rustc_lint::LateContext;
-                 &format!(
++use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
 +use rustc_span::symbol::{sym, Symbol};
 +
 +use super::CLONE_DOUBLE_REF;
 +use super::CLONE_ON_COPY;
 +
 +/// Checks for the `CLONE_ON_COPY` lint.
 +#[allow(clippy::too_many_lines)]
 +pub(super) fn check(
 +    cx: &LateContext<'_>,
 +    expr: &Expr<'_>,
 +    method_name: Symbol,
 +    receiver: &Expr<'_>,
 +    args: &[Expr<'_>],
 +) {
 +    let arg = if method_name == sym::clone && args.is_empty() {
 +        receiver
 +    } else {
 +        return;
 +    };
 +    if cx
 +        .typeck_results()
 +        .type_dependent_def_id(expr.hir_id)
 +        .and_then(|id| cx.tcx.trait_of_item(id))
 +        .zip(cx.tcx.lang_items().clone_trait())
 +        .map_or(true, |(x, y)| x != y)
 +    {
 +        return;
 +    }
 +    let arg_adjustments = cx.typeck_results().expr_adjustments(arg);
 +    let arg_ty = arg_adjustments
 +        .last()
 +        .map_or_else(|| cx.typeck_results().expr_ty(arg), |a| a.target);
 +
 +    let ty = cx.typeck_results().expr_ty(expr);
 +    if let ty::Ref(_, inner, _) = arg_ty.kind() {
 +        if let ty::Ref(_, innermost, _) = inner.kind() {
 +            span_lint_and_then(
 +                cx,
 +                CLONE_DOUBLE_REF,
 +                expr.span,
-                 ),
++                &with_forced_trimmed_paths!(format!(
 +                    "using `clone` on a double-reference; \
 +                    this will copy the reference of type `{ty}` instead of cloning the inner type"
-                         let explicit = format!("<{refs}{ty}>::clone({snip})");
++                )),
 +                |diag| {
 +                    if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
 +                        let mut ty = innermost;
 +                        let mut n = 0;
 +                        while let ty::Ref(_, inner, _) = ty.kind() {
 +                            ty = inner;
 +                            n += 1;
 +                        }
 +                        let refs = "&".repeat(n + 1);
 +                        let derefs = "*".repeat(n);
-                             format!("{refs}({derefs}{}).clone()", snip.deref()),
++                        let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})"));
 +                        diag.span_suggestion(
 +                            expr.span,
 +                            "try dereferencing it",
-             &format!("using `clone` on type `{ty}` which implements the `Copy` trait"),
++                            with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())),
 +                            Applicability::MaybeIncorrect,
 +                        );
 +                        diag.span_suggestion(
 +                            expr.span,
 +                            "or try being explicit if you are sure, that you want to clone a reference",
 +                            explicit,
 +                            Applicability::MaybeIncorrect,
 +                        );
 +                    }
 +                },
 +            );
 +            return; // don't report clone_on_copy
 +        }
 +    }
 +
 +    if is_copy(cx, ty) {
 +        let parent_is_suffix_expr = match get_parent_node(cx.tcx, expr.hir_id) {
 +            Some(Node::Expr(parent)) => match parent.kind {
 +                // &*x is a nop, &x.clone() is not
 +                ExprKind::AddrOf(..) => return,
 +                // (*x).func() is useless, x.clone().func() can work in case func borrows self
 +                ExprKind::MethodCall(_, self_arg, ..)
 +                    if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
 +                {
 +                    return;
 +                },
 +                // ? is a Call, makes sure not to rec *x?, but rather (*x)?
 +                ExprKind::Call(hir_callee, _) => matches!(
 +                    hir_callee.kind,
 +                    ExprKind::Path(QPath::LangItem(rustc_hir::LangItem::TryTraitBranch, _, _))
 +                ),
 +                ExprKind::MethodCall(_, self_arg, ..) if expr.hir_id == self_arg.hir_id => true,
 +                ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
 +                | ExprKind::Field(..)
 +                | ExprKind::Index(..) => true,
 +                _ => false,
 +            },
 +            // local binding capturing a reference
 +            Some(Node::Local(l)) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
 +                return;
 +            },
 +            _ => false,
 +        };
 +
 +        let mut app = Applicability::MachineApplicable;
 +        let snip = snippet_with_context(cx, arg.span, expr.span.ctxt(), "_", &mut app).0;
 +
 +        let deref_count = arg_adjustments
 +            .iter()
 +            .take_while(|adj| matches!(adj.kind, Adjust::Deref(_)))
 +            .count();
 +        let (help, sugg) = if deref_count == 0 {
 +            ("try removing the `clone` call", snip.into())
 +        } else if parent_is_suffix_expr {
 +            ("try dereferencing it", format!("({}{snip})", "*".repeat(deref_count)))
 +        } else {
 +            ("try dereferencing it", format!("{}{snip}", "*".repeat(deref_count)))
 +        };
 +
 +        span_lint_and_sugg(
 +            cx,
 +            CLONE_ON_COPY,
 +            expr.span,
++            &with_forced_trimmed_paths!(format!(
++                "using `clone` on type `{ty}` which implements the `Copy` trait"
++            )),
 +            help,
 +            sugg,
 +            app,
 +        );
 +    }
 +}
index f888c58a72de93a605f3193e5dbfc5907d86ef24,0000000000000000000000000000000000000000..fc80f2eeae0152825267c2bfe39375bf771325a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,197 -1,0 +1,197 @@@
-                     if ident.name == method_name;
-                     if let hir::ExprKind::Path(path) = &receiver.kind;
-                     if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
-                     then {
-                         return arg_id == *local
-                     }
 +use clippy_utils::diagnostics::span_lint_and_sugg;
 +use clippy_utils::source::{indent_of, reindent_multiline, snippet};
 +use clippy_utils::ty::is_type_diagnostic_item;
 +use clippy_utils::{is_trait_method, path_to_local_id, peel_blocks, SpanlessEq};
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir as hir;
 +use rustc_hir::def::Res;
 +use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
 +use rustc_lint::LateContext;
 +use rustc_middle::ty::adjustment::Adjust;
 +use rustc_span::source_map::Span;
 +use rustc_span::symbol::{sym, Symbol};
 +use std::borrow::Cow;
 +
 +use super::MANUAL_FILTER_MAP;
 +use super::MANUAL_FIND_MAP;
 +use super::OPTION_FILTER_MAP;
 +
 +fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
 +    match &expr.kind {
 +        hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name,
 +        hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
 +            segments.segments.last().unwrap().ident.name == method_name
 +        },
 +        hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
 +            let body = cx.tcx.hir().body(body);
 +            let closure_expr = peel_blocks(body.value);
 +            let arg_id = body.params[0].pat.hir_id;
 +            match closure_expr.kind {
 +                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
 +                    if_chain! {
-             if is_trait_method(cx, map_recv, sym::Iterator);
-             // filter(|x| ...is_some())...
-             if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
-             let filter_body = cx.tcx.hir().body(filter_body_id);
-             if let [filter_param] = filter_body.params;
-             // optional ref pattern: `filter(|&x| ..)`
-             let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
-                 (ref_pat, true)
-             } else {
-                 (filter_param.pat, false)
++                        if ident.name == method_name;
++                        if let hir::ExprKind::Path(path) = &receiver.kind;
++                        if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
++                        then {
++                            return arg_id == *local
++                        }
 +                    }
 +                    false
 +                },
 +                _ => false,
 +            }
 +        },
 +        _ => false,
 +    }
 +}
 +
 +fn is_option_filter_map(cx: &LateContext<'_>, filter_arg: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) -> bool {
 +    is_method(cx, map_arg, sym::unwrap) && is_method(cx, filter_arg, sym!(is_some))
 +}
 +
 +/// is `filter(|x| x.is_some()).map(|x| x.unwrap())`
 +fn is_filter_some_map_unwrap(
 +    cx: &LateContext<'_>,
 +    expr: &hir::Expr<'_>,
 +    filter_recv: &hir::Expr<'_>,
 +    filter_arg: &hir::Expr<'_>,
 +    map_arg: &hir::Expr<'_>,
 +) -> bool {
 +    let iterator = is_trait_method(cx, expr, sym::Iterator);
 +    let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::Option);
 +
 +    (iterator || option) && is_option_filter_map(cx, filter_arg, map_arg)
 +}
 +
 +/// lint use of `filter().map()` or `find().map()` for `Iterators`
 +#[allow(clippy::too_many_arguments)]
 +pub(super) fn check(
 +    cx: &LateContext<'_>,
 +    expr: &hir::Expr<'_>,
 +    filter_recv: &hir::Expr<'_>,
 +    filter_arg: &hir::Expr<'_>,
 +    filter_span: Span,
 +    map_recv: &hir::Expr<'_>,
 +    map_arg: &hir::Expr<'_>,
 +    map_span: Span,
 +    is_find: bool,
 +) {
 +    if is_filter_some_map_unwrap(cx, expr, filter_recv, filter_arg, map_arg) {
 +        span_lint_and_sugg(
 +            cx,
 +            OPTION_FILTER_MAP,
 +            filter_span.with_hi(expr.span.hi()),
 +            "`filter` for `Some` followed by `unwrap`",
 +            "consider using `flatten` instead",
 +            reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, map_span)).into_owned(),
 +            Applicability::MachineApplicable,
 +        );
 +
 +        return;
 +    }
 +
 +    if_chain! {
-             // closure ends with is_some() or is_ok()
-             if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
-             if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
-             if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
-             if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
-                 Some(false)
-             } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
-                 Some(true)
++        if is_trait_method(cx, map_recv, sym::Iterator);
++
++        // filter(|x| ...is_some())...
++        if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
++        let filter_body = cx.tcx.hir().body(filter_body_id);
++        if let [filter_param] = filter_body.params;
++        // optional ref pattern: `filter(|&x| ..)`
++        let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
++            (ref_pat, true)
++        } else {
++            (filter_param.pat, false)
++        };
++        // closure ends with is_some() or is_ok()
++        if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
++        if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
++        if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
++        if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
++            Some(false)
++        } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
++            Some(true)
++        } else {
++            None
++        };
++        if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
++
++        // ...map(|x| ...unwrap())
++        if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
++        let map_body = cx.tcx.hir().body(map_body_id);
++        if let [map_param] = map_body.params;
++        if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
++        // closure ends with expect() or unwrap()
++        if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
++        if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
++
++        // .filter(..).map(|y| f(y).copied().unwrap())
++        //                     ~~~~
++        let map_arg_peeled = match map_arg.kind {
++            ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
++                original_arg
++            },
++            _ => map_arg,
++        };
++
++        // .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
++        let simple_equal = path_to_local_id(filter_arg, filter_param_id)
++            && path_to_local_id(map_arg_peeled, map_param_id);
++
++        let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
++            // in `filter(|x| ..)`, replace `*x` with `x`
++            let a_path = if_chain! {
++                if !is_filter_param_ref;
++                if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
++                then { expr_path } else { a }
 +            };
-                 None
-             };
-             if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
-             // ...map(|x| ...unwrap())
-             if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
-             let map_body = cx.tcx.hir().body(map_body_id);
-             if let [map_param] = map_body.params;
-             if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
-             // closure ends with expect() or unwrap()
-             if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
-             if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
-             // .filter(..).map(|y| f(y).copied().unwrap())
-             //                     ~~~~
-             let map_arg_peeled = match map_arg.kind {
-                 ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
-                     original_arg
-                 },
-                 _ => map_arg,
++            // let the filter closure arg and the map closure arg be equal
++            path_to_local_id(a_path, filter_param_id)
++                && path_to_local_id(b, map_param_id)
++                && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
++        };
++
++        if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
++        then {
++            let span = filter_span.with_hi(expr.span.hi());
++            let (filter_name, lint) = if is_find {
++                ("find", MANUAL_FIND_MAP)
 +            } else {
-             // .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
-             let simple_equal = path_to_local_id(filter_arg, filter_param_id)
-                 && path_to_local_id(map_arg_peeled, map_param_id);
-             let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
-                 // in `filter(|x| ..)`, replace `*x` with `x`
-                 let a_path = if_chain! {
-                     if !is_filter_param_ref;
-                     if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
-                     then { expr_path } else { a }
-                 };
-                 // let the filter closure arg and the map closure arg be equal
-                 path_to_local_id(a_path, filter_param_id)
-                     && path_to_local_id(b, map_param_id)
-                     && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
++                ("filter", MANUAL_FILTER_MAP)
 +            };
++            let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
++            let (to_opt, deref) = if is_result {
++                (".ok()", String::new())
++            } else {
++                let derefs = cx.typeck_results()
++                    .expr_adjustments(map_arg)
++                    .iter()
++                    .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
++                    .count();
 +
-             if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
-             then {
-                 let span = filter_span.with_hi(expr.span.hi());
-                 let (filter_name, lint) = if is_find {
-                     ("find", MANUAL_FIND_MAP)
-                 } else {
-                     ("filter", MANUAL_FILTER_MAP)
-                 };
-                 let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
-                 let (to_opt, deref) = if is_result {
-                     (".ok()", String::new())
-                 } else {
-                     let derefs = cx.typeck_results()
-                         .expr_adjustments(map_arg)
-                         .iter()
-                         .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
-                         .count();
-                     ("", "*".repeat(derefs))
-                 };
-                 let sugg = format!(
-                     "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
-                     snippet(cx, map_arg.span, ".."),
-                 );
-                 span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
-             }
++                ("", "*".repeat(derefs))
 +            };
++            let sugg = format!(
++                "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
++                snippet(cx, map_arg.span, ".."),
++            );
++            span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
++        }
 +    }
 +}
 +
 +fn acceptable_methods(method: &PathSegment<'_>) -> bool {
 +    let methods: [Symbol; 8] = [
 +        sym::clone,
 +        sym::as_ref,
 +        sym!(copied),
 +        sym!(cloned),
 +        sym!(as_deref),
 +        sym!(as_mut),
 +        sym!(as_deref_mut),
 +        sym!(to_owned),
 +    ];
 +
 +    methods.contains(&method.ident.name)
 +}
index 2244ebfb129277036c95e95013d0a39d8f213a60,0000000000000000000000000000000000000000..c87f5daab6f241ebfc51e0b75f3275dd058c4fcf
mode 100644,000000..100644
--- /dev/null
@@@ -1,87 -1,0 +1,97 @@@
- use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
 +#![allow(unused_imports)]
 +
 +use super::ITER_KV_MAP;
 +use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then};
 +use clippy_utils::source::{snippet, snippet_with_applicability};
 +use clippy_utils::sugg;
 +use clippy_utils::ty::is_type_diagnostic_item;
 +use clippy_utils::visitors::is_local_used;
-         let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
-             (key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
-             (PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
++use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
 +use rustc_lint::{LateContext, LintContext};
 +use rustc_middle::ty;
 +use rustc_span::sym;
 +use rustc_span::Span;
 +
 +/// lint use of:
 +/// - `hashmap.iter().map(|(_, v)| v)`
 +/// - `hashmap.into_iter().map(|(_, v)| v)`
 +/// on `HashMaps` and `BTreeMaps` in std
 +
 +pub(super) fn check<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    map_type: &'tcx str,     // iter / into_iter
 +    expr: &'tcx Expr<'tcx>,  // .iter().map(|(_, v_| v))
 +    recv: &'tcx Expr<'tcx>,  // hashmap
 +    m_arg: &'tcx Expr<'tcx>, // |(_, v)| v
 +) {
 +    if_chain! {
 +        if !expr.span.from_expansion();
 +        if let ExprKind::Closure(c) = m_arg.kind;
 +        if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
 +        if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
 +
-                 if local_ident.ident.as_str() == binded_ident.as_str();
++        let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
++            (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
++            (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
 +            _ => return,
 +        };
 +
 +        let ty = cx.typeck_results().expr_ty(recv);
 +        if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap);
 +
 +        then {
 +            let mut applicability = rustc_errors::Applicability::MachineApplicable;
 +            let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability);
 +            let into_prefix = if map_type == "into_iter" {"into_"} else {""};
 +
 +            if_chain! {
 +                if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
 +                if let [local_ident] = path.segments;
-                         format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
++                if local_ident.ident.as_str() == bound_ident.as_str();
 +
 +                then {
 +                    span_lint_and_sugg(
 +                        cx,
 +                        ITER_KV_MAP,
 +                        expr.span,
 +                        &format!("iterating on a map's {replacement_kind}s"),
 +                        "try",
 +                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"),
 +                        applicability,
 +                    );
 +                } else {
++                    let ref_annotation = if annotation.0 == ByRef::Yes {
++                        "ref "
++                    } else {
++                        ""
++                    };
++                    let mut_annotation = if annotation.1 == Mutability::Mut {
++                        "mut "
++                    } else {
++                        ""
++                    };
 +                    span_lint_and_sugg(
 +                        cx,
 +                        ITER_KV_MAP,
 +                        expr.span,
 +                        &format!("iterating on a map's {replacement_kind}s"),
 +                        "try",
++                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
 +                            snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
 +                        applicability,
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +/// Returns `true` if the pattern is a `PatWild`, or is an ident prefixed with `_`
 +/// that is not locally used.
 +fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
 +    match *pat {
 +        PatKind::Wild => true,
 +        PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => !is_local_used(cx, body, id),
 +        _ => false,
 +    }
 +}
index 15c1c618c5137e76069e3b0e3b02008b1e5bb8fa,0000000000000000000000000000000000000000..fe88fa41fd91efd3cdf558f836ed41ba8f210b7f
mode 100644,000000..100644
--- /dev/null
@@@ -1,36 -1,0 +1,38 @@@
- use rustc_middle::ty;
 +use clippy_utils::diagnostics::span_lint_and_sugg;
 +use clippy_utils::is_diag_trait_item;
 +use clippy_utils::source::snippet_with_context;
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir as hir;
 +use rustc_lint::LateContext;
-                 &format!("this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"),
++use rustc_middle::ty::{self, print::with_forced_trimmed_paths};
 +use rustc_span::sym;
 +
 +use super::SUSPICIOUS_TO_OWNED;
 +
 +pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -> bool {
 +    if_chain! {
 +        if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
 +        if is_diag_trait_item(cx, method_def_id, sym::ToOwned);
 +        let input_type = cx.typeck_results().expr_ty(expr);
 +        if let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind();
 +        if cx.tcx.is_diagnostic_item(sym::Cow, adt.did());
 +        then {
 +            let mut app = Applicability::MaybeIncorrect;
 +            let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
 +            span_lint_and_sugg(
 +                cx,
 +                SUSPICIOUS_TO_OWNED,
 +                expr.span,
++                &with_forced_trimmed_paths!(format!(
++                    "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
++                )),
 +                "consider using, depending on intent",
 +                format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
 +                app,
 +            );
 +            return true;
 +        }
 +    }
 +    false
 +}
index 09cb53331763d04f5188d36089dee85f1e360b77,0000000000000000000000000000000000000000..dc866ab6373bbb76fd013d62159e30f2ab3587e3
mode 100644,000000..100644
--- /dev/null
@@@ -1,109 -1,0 +1,113 @@@
- //! This lint is **warn** by default
 +//! Checks for uses of mutex where an atomic value could be used
 +//!
-     nursery,
-     "using a mutex where an atomic value could be used instead"
++//! This lint is **allow** by default
 +
 +use clippy_utils::diagnostics::span_lint;
 +use clippy_utils::ty::is_type_diagnostic_item;
 +use rustc_hir::Expr;
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::ty::{self, Ty};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::sym;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for usages of `Mutex<X>` where an atomic will do.
 +    ///
 +    /// ### Why is this bad?
 +    /// Using a mutex just to make access to a plain bool or
 +    /// reference sequential is shooting flies with cannons.
 +    /// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
 +    /// faster.
 +    ///
++    /// On the other hand, `Mutex`es are, in general, easier to
++    /// verify correctness. An atomic does not behave the same as
++    /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s commentary for more details.
++    ///
 +    /// ### Known problems
 +    /// This lint cannot detect if the mutex is actually used
 +    /// for waiting before a critical section.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # let y = true;
 +    /// # use std::sync::Mutex;
 +    /// let x = Mutex::new(&y);
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// # let y = true;
 +    /// # use std::sync::atomic::AtomicBool;
 +    /// let x = AtomicBool::new(y);
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub MUTEX_ATOMIC,
++    restriction,
++    "using a mutex where an atomic value could be used instead."
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for usages of `Mutex<X>` where `X` is an integral
 +    /// type.
 +    ///
 +    /// ### Why is this bad?
 +    /// Using a mutex just to make access to a plain integer
 +    /// sequential is
 +    /// shooting flies with cannons. `std::sync::atomic::AtomicUsize` is leaner and faster.
 +    ///
 +    /// ### Known problems
 +    /// This lint cannot detect if the mutex is actually used
 +    /// for waiting before a critical section.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # use std::sync::Mutex;
 +    /// let x = Mutex::new(0usize);
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// # use std::sync::atomic::AtomicUsize;
 +    /// let x = AtomicUsize::new(0usize);
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub MUTEX_INTEGER,
 +    nursery,
 +    "using a mutex for an integer type"
 +}
 +
 +declare_lint_pass!(Mutex => [MUTEX_ATOMIC, MUTEX_INTEGER]);
 +
 +impl<'tcx> LateLintPass<'tcx> for Mutex {
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 +        let ty = cx.typeck_results().expr_ty(expr);
 +        if let ty::Adt(_, subst) = ty.kind() {
 +            if is_type_diagnostic_item(cx, ty, sym::Mutex) {
 +                let mutex_param = subst.type_at(0);
 +                if let Some(atomic_name) = get_atomic_name(mutex_param) {
 +                    let msg = format!(
 +                        "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \
 +                         behavior and not the internal type, consider using `Mutex<()>`"
 +                    );
 +                    match *mutex_param.kind() {
 +                        ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
 +                        ty::Int(t) if t != ty::IntTy::Isize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
 +                        _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg),
 +                    };
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +fn get_atomic_name(ty: Ty<'_>) -> Option<&'static str> {
 +    match ty.kind() {
 +        ty::Bool => Some("AtomicBool"),
 +        ty::Uint(_) => Some("AtomicUsize"),
 +        ty::Int(_) => Some("AtomicIsize"),
 +        ty::RawPtr(_) => Some("AtomicPtr"),
 +        _ => None,
 +    }
 +}
index 4fbc8398e373443d5cc80c80eb2214933bfe786d,0000000000000000000000000000000000000000..cff82b875f11a73830cf2ab574593664030ac9f2
mode 100644,000000..100644
--- /dev/null
@@@ -1,234 -1,0 +1,237 @@@
-     peel_hir_expr_refs,
 +use super::ARITHMETIC_SIDE_EFFECTS;
 +use clippy_utils::{
 +    consts::{constant, constant_simple},
 +    diagnostics::span_lint,
-         if let hir::ExprKind::Lit(ref lit) = expr.kind && let ast::LitKind::Int(n, _) = lit.node {
++    peel_hir_expr_refs, peel_hir_expr_unary,
 +};
 +use rustc_ast as ast;
 +use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 +use rustc_hir as hir;
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::ty::Ty;
 +use rustc_session::impl_lint_pass;
 +use rustc_span::source_map::{Span, Spanned};
 +
 +const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
 +    ["f32", "f32"],
 +    ["f64", "f64"],
 +    ["std::num::Saturating", "std::num::Saturating"],
 +    ["std::num::Wrapping", "std::num::Wrapping"],
 +    ["std::string::String", "&str"],
 +];
 +const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
 +
 +#[derive(Debug)]
 +pub struct ArithmeticSideEffects {
 +    allowed_binary: FxHashMap<String, FxHashSet<String>>,
 +    allowed_unary: FxHashSet<String>,
 +    // Used to check whether expressions are constants, such as in enum discriminants and consts
 +    const_span: Option<Span>,
 +    expr_span: Option<Span>,
 +}
 +
 +impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]);
 +
 +impl ArithmeticSideEffects {
 +    #[must_use]
 +    pub fn new(user_allowed_binary: Vec<[String; 2]>, user_allowed_unary: Vec<String>) -> Self {
 +        let mut allowed_binary: FxHashMap<String, FxHashSet<String>> = <_>::default();
 +        for [lhs, rhs] in user_allowed_binary.into_iter().chain(
 +            HARD_CODED_ALLOWED_BINARY
 +                .iter()
 +                .copied()
 +                .map(|[lhs, rhs]| [lhs.to_string(), rhs.to_string()]),
 +        ) {
 +            allowed_binary.entry(lhs).or_default().insert(rhs);
 +        }
 +        let allowed_unary = user_allowed_unary
 +            .into_iter()
 +            .chain(HARD_CODED_ALLOWED_UNARY.iter().copied().map(String::from))
 +            .collect();
 +        Self {
 +            allowed_binary,
 +            allowed_unary,
 +            const_span: None,
 +            expr_span: None,
 +        }
 +    }
 +
 +    /// Checks if the lhs and the rhs types of a binary operation like "addition" or
 +    /// "multiplication" are present in the inner set of allowed types.
 +    fn has_allowed_binary(&self, lhs_ty: Ty<'_>, rhs_ty: Ty<'_>) -> bool {
 +        let lhs_ty_string = lhs_ty.to_string();
 +        let lhs_ty_string_elem = lhs_ty_string.split('<').next().unwrap_or_default();
 +        let rhs_ty_string = rhs_ty.to_string();
 +        let rhs_ty_string_elem = rhs_ty_string.split('<').next().unwrap_or_default();
 +        if let Some(rhs_from_specific) = self.allowed_binary.get(lhs_ty_string_elem)
 +            && {
 +                let rhs_has_allowed_ty = rhs_from_specific.contains(rhs_ty_string_elem);
 +                rhs_has_allowed_ty || rhs_from_specific.contains("*")
 +            }
 +        {
 +           true
 +        } else if let Some(rhs_from_glob) = self.allowed_binary.get("*") {
 +            rhs_from_glob.contains(rhs_ty_string_elem)
 +        } else {
 +            false
 +        }
 +    }
 +
 +    /// Checks if the type of an unary operation like "negation" is present in the inner set of
 +    /// allowed types.
 +    fn has_allowed_unary(&self, ty: Ty<'_>) -> bool {
 +        let ty_string = ty.to_string();
 +        let ty_string_elem = ty_string.split('<').next().unwrap_or_default();
 +        self.allowed_unary.contains(ty_string_elem)
 +    }
 +
 +    // For example, 8i32 or &i64::MAX.
 +    fn is_integral(ty: Ty<'_>) -> bool {
 +        ty.peel_refs().is_integral()
 +    }
 +
 +    // Common entry-point to avoid code duplication.
 +    fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
 +        let msg = "arithmetic operation that can potentially result in unexpected side-effects";
 +        span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
 +        self.expr_span = Some(expr.span);
 +    }
 +
 +    /// If `expr` is not a literal integer like `1`, returns `None`.
++    ///
++    /// Returns the absolute value of the expression, if this is an integer literal.
 +    fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
-                 | hir::BinOpKind::Sub
-                 | hir::BinOpKind::Mul
++        let actual = peel_hir_expr_unary(expr).0;
++        if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
 +            Some(n)
 +        }
 +        else {
 +            None
 +        }
 +    }
 +
 +    /// Manages when the lint should be triggered. Operations in constant environments, hard coded
 +    /// types, custom allowed types and non-constant operations that won't overflow are ignored.
 +    fn manage_bin_ops<'tcx>(
 +        &mut self,
 +        cx: &LateContext<'tcx>,
 +        expr: &hir::Expr<'tcx>,
 +        op: &Spanned<hir::BinOpKind>,
 +        lhs: &hir::Expr<'tcx>,
 +        rhs: &hir::Expr<'tcx>,
 +    ) {
 +        if constant_simple(cx, cx.typeck_results(), expr).is_some() {
 +            return;
 +        }
 +        if !matches!(
 +            op.node,
 +            hir::BinOpKind::Add
 +                | hir::BinOpKind::Div
++                | hir::BinOpKind::Mul
 +                | hir::BinOpKind::Rem
 +                | hir::BinOpKind::Shl
 +                | hir::BinOpKind::Shr
++                | hir::BinOpKind::Sub
 +        ) {
 +            return;
 +        };
 +        let lhs_ty = cx.typeck_results().expr_ty(lhs);
 +        let rhs_ty = cx.typeck_results().expr_ty(rhs);
 +        if self.has_allowed_binary(lhs_ty, rhs_ty) {
 +            return;
 +        }
 +        let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
 +            let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
 +            let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
 +            match (Self::literal_integer(actual_lhs), Self::literal_integer(actual_rhs)) {
 +                (None, None) => false,
 +                (None, Some(n)) | (Some(n), None) => match (&op.node, n) {
 +                    (hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
 +                    (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
 +                    | (hir::BinOpKind::Div | hir::BinOpKind::Rem, _)
 +                    | (hir::BinOpKind::Mul, 0 | 1) => true,
 +                    _ => false,
 +                },
 +                (Some(_), Some(_)) => {
 +                    matches!((lhs_ref_counter, rhs_ref_counter), (0, 0))
 +                },
 +            }
 +        } else {
 +            false
 +        };
 +        if !has_valid_op {
 +            self.issue_lint(cx, expr);
 +        }
 +    }
 +
 +    fn manage_unary_ops<'tcx>(
 +        &mut self,
 +        cx: &LateContext<'tcx>,
 +        expr: &hir::Expr<'tcx>,
 +        un_expr: &hir::Expr<'tcx>,
 +        un_op: hir::UnOp,
 +    ) {
 +        let hir::UnOp::Neg = un_op else { return; };
 +        if constant(cx, cx.typeck_results(), un_expr).is_some() {
 +            return;
 +        }
 +        let ty = cx.typeck_results().expr_ty(expr).peel_refs();
 +        if self.has_allowed_unary(ty) {
 +            return;
 +        }
 +        let actual_un_expr = peel_hir_expr_refs(un_expr).0;
 +        if Self::literal_integer(actual_un_expr).is_some() {
 +            return;
 +        }
 +        self.issue_lint(cx, expr);
 +    }
 +
 +    fn should_skip_expr(&mut self, expr: &hir::Expr<'_>) -> bool {
 +        self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span))
 +    }
 +}
 +
 +impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
 +        if self.should_skip_expr(expr) {
 +            return;
 +        }
 +        match &expr.kind {
 +            hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => {
 +                self.manage_bin_ops(cx, expr, op, lhs, rhs);
 +            },
 +            hir::ExprKind::Unary(un_op, un_expr) => {
 +                self.manage_unary_ops(cx, expr, un_expr, *un_op);
 +            },
 +            _ => {},
 +        }
 +    }
 +
 +    fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
 +        let body_owner = cx.tcx.hir().body_owner(body.id());
 +        let body_owner_def_id = cx.tcx.hir().local_def_id(body_owner);
 +        let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
 +        if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind {
 +            let body_span = cx.tcx.hir().span_with_body(body_owner);
 +            if let Some(span) = self.const_span && span.contains(body_span) {
 +                return;
 +            }
 +            self.const_span = Some(body_span);
 +        }
 +    }
 +
 +    fn check_body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
 +        let body_owner = cx.tcx.hir().body_owner(body.id());
 +        let body_span = cx.tcx.hir().span(body_owner);
 +        if let Some(span) = self.const_span && span.contains(body_span) {
 +            return;
 +        }
 +        self.const_span = None;
 +    }
 +
 +    fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
 +        if Some(expr.span) == self.expr_span {
 +            self.expr_span = None;
 +        }
 +    }
 +}
index 0a1b9d173cf9409ee453de6f7085ac14b9f8ab89,0000000000000000000000000000000000000000..fc655fe2d0bb3469bfb813de501e75bcc457288b
mode 100644,000000..100644
--- /dev/null
@@@ -1,532 -1,0 +1,532 @@@
-     /// are constant and `x` is greater or equal to `y`.
 +use clippy_utils::consts::{constant, Constant};
 +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 +use clippy_utils::higher;
 +use clippy_utils::msrvs::{self, Msrv};
 +use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
 +use clippy_utils::sugg::Sugg;
 +use clippy_utils::{get_parent_expr, in_constant, is_integer_const, path_to_local};
 +use if_chain::if_chain;
 +use rustc_ast::ast::RangeLimits;
 +use rustc_errors::Applicability;
 +use rustc_hir::{BinOpKind, Expr, ExprKind, HirId};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::ty;
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::source_map::{Span, Spanned};
 +use std::cmp::Ordering;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for exclusive ranges where 1 is added to the
 +    /// upper bound, e.g., `x..(y+1)`.
 +    ///
 +    /// ### Why is this bad?
 +    /// The code is more readable with an inclusive range
 +    /// like `x..=y`.
 +    ///
 +    /// ### Known problems
 +    /// Will add unnecessary pair of parentheses when the
 +    /// expression is not wrapped in a pair but starts with an opening parenthesis
 +    /// and ends with a closing one.
 +    /// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
 +    ///
 +    /// Also in many cases, inclusive ranges are still slower to run than
 +    /// exclusive ranges, because they essentially add an extra branch that
 +    /// LLVM may fail to hoist out of the loop.
 +    ///
 +    /// This will cause a warning that cannot be fixed if the consumer of the
 +    /// range only accepts a specific range type, instead of the generic
 +    /// `RangeBounds` trait
 +    /// ([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)).
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # let x = 0;
 +    /// # let y = 1;
 +    /// for i in x..(y+1) {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// # let x = 0;
 +    /// # let y = 1;
 +    /// for i in x..=y {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub RANGE_PLUS_ONE,
 +    pedantic,
 +    "`x..(y+1)` reads better as `x..=y`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for inclusive ranges where 1 is subtracted from
 +    /// the upper bound, e.g., `x..=(y-1)`.
 +    ///
 +    /// ### Why is this bad?
 +    /// The code is more readable with an exclusive range
 +    /// like `x..y`.
 +    ///
 +    /// ### Known problems
 +    /// This will cause a warning that cannot be fixed if
 +    /// the consumer of the range only accepts a specific range type, instead of
 +    /// the generic `RangeBounds` trait
 +    /// ([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)).
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # let x = 0;
 +    /// # let y = 1;
 +    /// for i in x..=(y-1) {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    ///
 +    /// Use instead:
 +    /// ```rust
 +    /// # let x = 0;
 +    /// # let y = 1;
 +    /// for i in x..y {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub RANGE_MINUS_ONE,
 +    pedantic,
 +    "`x..=(y-1)` reads better as `x..y`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for range expressions `x..y` where both `x` and `y`
++    /// are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop.
 +    ///
 +    /// ### Why is this bad?
 +    /// Empty ranges yield no values so iterating them is a no-op.
 +    /// Moreover, trying to use a reversed range to index a slice will panic at run-time.
 +    ///
 +    /// ### Example
 +    /// ```rust,no_run
 +    /// fn main() {
 +    ///     (10..=0).for_each(|x| println!("{}", x));
 +    ///
 +    ///     let arr = [1, 2, 3, 4, 5];
 +    ///     let sub = &arr[3..1];
 +    /// }
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    /// fn main() {
 +    ///     (0..=10).rev().for_each(|x| println!("{}", x));
 +    ///
 +    ///     let arr = [1, 2, 3, 4, 5];
 +    ///     let sub = &arr[1..3];
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.45.0"]
 +    pub REVERSED_EMPTY_RANGES,
 +    correctness,
 +    "reversing the limits of range expressions, resulting in empty ranges"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for expressions like `x >= 3 && x < 8` that could
 +    /// be more readably expressed as `(3..8).contains(x)`.
 +    ///
 +    /// ### Why is this bad?
 +    /// `contains` expresses the intent better and has less
 +    /// failure modes (such as fencepost errors or using `||` instead of `&&`).
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// // given
 +    /// let x = 6;
 +    ///
 +    /// assert!(x >= 3 && x < 8);
 +    /// ```
 +    /// Use instead:
 +    /// ```rust
 +    ///# let x = 6;
 +    /// assert!((3..8).contains(&x));
 +    /// ```
 +    #[clippy::version = "1.49.0"]
 +    pub MANUAL_RANGE_CONTAINS,
 +    style,
 +    "manually reimplementing {`Range`, `RangeInclusive`}`::contains`"
 +}
 +
 +pub struct Ranges {
 +    msrv: Msrv,
 +}
 +
 +impl Ranges {
 +    #[must_use]
 +    pub fn new(msrv: Msrv) -> Self {
 +        Self { msrv }
 +    }
 +}
 +
 +impl_lint_pass!(Ranges => [
 +    RANGE_PLUS_ONE,
 +    RANGE_MINUS_ONE,
 +    REVERSED_EMPTY_RANGES,
 +    MANUAL_RANGE_CONTAINS,
 +]);
 +
 +impl<'tcx> LateLintPass<'tcx> for Ranges {
 +    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 +        if let ExprKind::Binary(ref op, l, r) = expr.kind {
 +            if self.msrv.meets(msrvs::RANGE_CONTAINS) {
 +                check_possible_range_contains(cx, op.node, l, r, expr, expr.span);
 +            }
 +        }
 +
 +        check_exclusive_range_plus_one(cx, expr);
 +        check_inclusive_range_minus_one(cx, expr);
 +        check_reversed_empty_range(cx, expr);
 +    }
 +    extract_msrv_attr!(LateContext);
 +}
 +
 +fn check_possible_range_contains(
 +    cx: &LateContext<'_>,
 +    op: BinOpKind,
 +    left: &Expr<'_>,
 +    right: &Expr<'_>,
 +    expr: &Expr<'_>,
 +    span: Span,
 +) {
 +    if in_constant(cx, expr.hir_id) {
 +        return;
 +    }
 +
 +    let combine_and = match op {
 +        BinOpKind::And | BinOpKind::BitAnd => true,
 +        BinOpKind::Or | BinOpKind::BitOr => false,
 +        _ => return,
 +    };
 +    // value, name, order (higher/lower), inclusiveness
 +    if let (Some(l), Some(r)) = (check_range_bounds(cx, left), check_range_bounds(cx, right)) {
 +        // we only lint comparisons on the same name and with different
 +        // direction
 +        if l.id != r.id || l.ord == r.ord {
 +            return;
 +        }
 +        let ord = Constant::partial_cmp(cx.tcx, cx.typeck_results().expr_ty(l.expr), &l.val, &r.val);
 +        if combine_and && ord == Some(r.ord) {
 +            // order lower bound and upper bound
 +            let (l_span, u_span, l_inc, u_inc) = if r.ord == Ordering::Less {
 +                (l.val_span, r.val_span, l.inc, r.inc)
 +            } else {
 +                (r.val_span, l.val_span, r.inc, l.inc)
 +            };
 +            // we only lint inclusive lower bounds
 +            if !l_inc {
 +                return;
 +            }
 +            let (range_type, range_op) = if u_inc {
 +                ("RangeInclusive", "..=")
 +            } else {
 +                ("Range", "..")
 +            };
 +            let mut applicability = Applicability::MachineApplicable;
 +            let name = snippet_with_applicability(cx, l.name_span, "_", &mut applicability);
 +            let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);
 +            let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);
 +            let space = if lo.ends_with('.') { " " } else { "" };
 +            span_lint_and_sugg(
 +                cx,
 +                MANUAL_RANGE_CONTAINS,
 +                span,
 +                &format!("manual `{range_type}::contains` implementation"),
 +                "use",
 +                format!("({lo}{space}{range_op}{hi}).contains(&{name})"),
 +                applicability,
 +            );
 +        } else if !combine_and && ord == Some(l.ord) {
 +            // `!_.contains(_)`
 +            // order lower bound and upper bound
 +            let (l_span, u_span, l_inc, u_inc) = if l.ord == Ordering::Less {
 +                (l.val_span, r.val_span, l.inc, r.inc)
 +            } else {
 +                (r.val_span, l.val_span, r.inc, l.inc)
 +            };
 +            if l_inc {
 +                return;
 +            }
 +            let (range_type, range_op) = if u_inc {
 +                ("Range", "..")
 +            } else {
 +                ("RangeInclusive", "..=")
 +            };
 +            let mut applicability = Applicability::MachineApplicable;
 +            let name = snippet_with_applicability(cx, l.name_span, "_", &mut applicability);
 +            let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);
 +            let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);
 +            let space = if lo.ends_with('.') { " " } else { "" };
 +            span_lint_and_sugg(
 +                cx,
 +                MANUAL_RANGE_CONTAINS,
 +                span,
 +                &format!("manual `!{range_type}::contains` implementation"),
 +                "use",
 +                format!("!({lo}{space}{range_op}{hi}).contains(&{name})"),
 +                applicability,
 +            );
 +        }
 +    }
 +
 +    // If the LHS is the same operator, we have to recurse to get the "real" RHS, since they have
 +    // the same operator precedence
 +    if_chain! {
 +        if let ExprKind::Binary(ref lhs_op, _left, new_lhs) = left.kind;
 +        if op == lhs_op.node;
 +        let new_span = Span::new(new_lhs.span.lo(), right.span.hi(), expr.span.ctxt(), expr.span.parent());
 +        if let Some(snip) = &snippet_opt(cx, new_span);
 +        // Do not continue if we have mismatched number of parens, otherwise the suggestion is wrong
 +        if snip.matches('(').count() == snip.matches(')').count();
 +        then {
 +            check_possible_range_contains(cx, op, new_lhs, right, expr, new_span);
 +        }
 +    }
 +}
 +
 +struct RangeBounds<'a> {
 +    val: Constant,
 +    expr: &'a Expr<'a>,
 +    id: HirId,
 +    name_span: Span,
 +    val_span: Span,
 +    ord: Ordering,
 +    inc: bool,
 +}
 +
 +// Takes a binary expression such as x <= 2 as input
 +// Breaks apart into various pieces, such as the value of the number,
 +// hir id of the variable, and direction/inclusiveness of the operator
 +fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<RangeBounds<'a>> {
 +    if let ExprKind::Binary(ref op, l, r) = ex.kind {
 +        let (inclusive, ordering) = match op.node {
 +            BinOpKind::Gt => (false, Ordering::Greater),
 +            BinOpKind::Ge => (true, Ordering::Greater),
 +            BinOpKind::Lt => (false, Ordering::Less),
 +            BinOpKind::Le => (true, Ordering::Less),
 +            _ => return None,
 +        };
 +        if let Some(id) = path_to_local(l) {
 +            if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
 +                return Some(RangeBounds {
 +                    val: c,
 +                    expr: r,
 +                    id,
 +                    name_span: l.span,
 +                    val_span: r.span,
 +                    ord: ordering,
 +                    inc: inclusive,
 +                });
 +            }
 +        } else if let Some(id) = path_to_local(r) {
 +            if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
 +                return Some(RangeBounds {
 +                    val: c,
 +                    expr: l,
 +                    id,
 +                    name_span: r.span,
 +                    val_span: l.span,
 +                    ord: ordering.reverse(),
 +                    inc: inclusive,
 +                });
 +            }
 +        }
 +    }
 +    None
 +}
 +
 +// exclusive range plus one: `x..(y+1)`
 +fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
 +    if_chain! {
 +        if expr.span.can_be_used_for_suggestions();
 +        if let Some(higher::Range {
 +            start,
 +            end: Some(end),
 +            limits: RangeLimits::HalfOpen
 +        }) = higher::Range::hir(expr);
 +        if let Some(y) = y_plus_one(cx, end);
 +        then {
 +            let span = expr.span;
 +            span_lint_and_then(
 +                cx,
 +                RANGE_PLUS_ONE,
 +                span,
 +                "an inclusive range would be more readable",
 +                |diag| {
 +                    let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
 +                    let end = Sugg::hir(cx, y, "y").maybe_par();
 +                    if let Some(is_wrapped) = &snippet_opt(cx, span) {
 +                        if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
 +                            diag.span_suggestion(
 +                                span,
 +                                "use",
 +                                format!("({start}..={end})"),
 +                                Applicability::MaybeIncorrect,
 +                            );
 +                        } else {
 +                            diag.span_suggestion(
 +                                span,
 +                                "use",
 +                                format!("{start}..={end}"),
 +                                Applicability::MachineApplicable, // snippet
 +                            );
 +                        }
 +                    }
 +                },
 +            );
 +        }
 +    }
 +}
 +
 +// inclusive range minus one: `x..=(y-1)`
 +fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
 +    if_chain! {
 +        if expr.span.can_be_used_for_suggestions();
 +        if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::Range::hir(expr);
 +        if let Some(y) = y_minus_one(cx, end);
 +        then {
 +            span_lint_and_then(
 +                cx,
 +                RANGE_MINUS_ONE,
 +                expr.span,
 +                "an exclusive range would be more readable",
 +                |diag| {
 +                    let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
 +                    let end = Sugg::hir(cx, y, "y").maybe_par();
 +                    diag.span_suggestion(
 +                        expr.span,
 +                        "use",
 +                        format!("{start}..{end}"),
 +                        Applicability::MachineApplicable, // snippet
 +                    );
 +                },
 +            );
 +        }
 +    }
 +}
 +
 +fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
 +    fn inside_indexing_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +        matches!(
 +            get_parent_expr(cx, expr),
 +            Some(Expr {
 +                kind: ExprKind::Index(..),
 +                ..
 +            })
 +        )
 +    }
 +
 +    fn is_for_loop_arg(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +        let mut cur_expr = expr;
 +        while let Some(parent_expr) = get_parent_expr(cx, cur_expr) {
 +            match higher::ForLoop::hir(parent_expr) {
 +                Some(higher::ForLoop { arg, .. }) if arg.hir_id == expr.hir_id => return true,
 +                _ => cur_expr = parent_expr,
 +            }
 +        }
 +
 +        false
 +    }
 +
 +    fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
 +        match limits {
 +            RangeLimits::HalfOpen => ordering != Ordering::Less,
 +            RangeLimits::Closed => ordering == Ordering::Greater,
 +        }
 +    }
 +
 +    if_chain! {
 +        if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr);
 +        let ty = cx.typeck_results().expr_ty(start);
 +        if let ty::Int(_) | ty::Uint(_) = ty.kind();
 +        if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start);
 +        if let Some((end_idx, _)) = constant(cx, cx.typeck_results(), end);
 +        if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
 +        if is_empty_range(limits, ordering);
 +        then {
 +            if inside_indexing_expr(cx, expr) {
 +                // Avoid linting `N..N` as it has proven to be useful, see #5689 and #5628 ...
 +                if ordering != Ordering::Equal {
 +                    span_lint(
 +                        cx,
 +                        REVERSED_EMPTY_RANGES,
 +                        expr.span,
 +                        "this range is reversed and using it to index a slice will panic at run-time",
 +                    );
 +                }
 +            // ... except in for loop arguments for backwards compatibility with `reverse_range_loop`
 +            } else if ordering != Ordering::Equal || is_for_loop_arg(cx, expr) {
 +                span_lint_and_then(
 +                    cx,
 +                    REVERSED_EMPTY_RANGES,
 +                    expr.span,
 +                    "this range is empty so it will yield no values",
 +                    |diag| {
 +                        if ordering != Ordering::Equal {
 +                            let start_snippet = snippet(cx, start.span, "_");
 +                            let end_snippet = snippet(cx, end.span, "_");
 +                            let dots = match limits {
 +                                RangeLimits::HalfOpen => "..",
 +                                RangeLimits::Closed => "..="
 +                            };
 +
 +                            diag.span_suggestion(
 +                                expr.span,
 +                                "consider using the following if you are attempting to iterate over this \
 +                                 range in reverse",
 +                                format!("({end_snippet}{dots}{start_snippet}).rev()"),
 +                                Applicability::MaybeIncorrect,
 +                            );
 +                        }
 +                    },
 +                );
 +            }
 +        }
 +    }
 +}
 +
 +fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
 +    match expr.kind {
 +        ExprKind::Binary(
 +            Spanned {
 +                node: BinOpKind::Add, ..
 +            },
 +            lhs,
 +            rhs,
 +        ) => {
 +            if is_integer_const(cx, lhs, 1) {
 +                Some(rhs)
 +            } else if is_integer_const(cx, rhs, 1) {
 +                Some(lhs)
 +            } else {
 +                None
 +            }
 +        },
 +        _ => None,
 +    }
 +}
 +
 +fn y_minus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
 +    match expr.kind {
 +        ExprKind::Binary(
 +            Spanned {
 +                node: BinOpKind::Sub, ..
 +            },
 +            lhs,
 +            rhs,
 +        ) if is_integer_const(cx, rhs, 1) => Some(lhs),
 +        _ => None,
 +    }
 +}
index 0e7c5cca7240bd02ba8a0523905de512d6930b8f,0000000000000000000000000000000000000000..c1677fb3da1c4850215dfd6a88e1ee485d4c54ed
mode 100644,000000..100644
--- /dev/null
@@@ -1,392 -1,0 +1,392 @@@
-                 if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg], cloned, loc) {
 +use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 +use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
 +use clippy_utils::source::snippet_opt;
 +use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
 +use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir::intravisit::FnKind;
 +use rustc_hir::{def_id, Body, FnDecl, HirId, LangItem};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::mir;
 +use rustc_middle::ty::{self, Ty};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::source_map::{BytePos, Span};
 +use rustc_span::sym;
 +
 +macro_rules! unwrap_or_continue {
 +    ($x:expr) => {
 +        match $x {
 +            Some(x) => x,
 +            None => continue,
 +        }
 +    };
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for a redundant `clone()` (and its relatives) which clones an owned
 +    /// value that is going to be dropped without further use.
 +    ///
 +    /// ### Why is this bad?
 +    /// It is not always possible for the compiler to eliminate useless
 +    /// allocations and deallocations generated by redundant `clone()`s.
 +    ///
 +    /// ### Known problems
 +    /// False-negatives: analysis performed by this lint is conservative and limited.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # use std::path::Path;
 +    /// # #[derive(Clone)]
 +    /// # struct Foo;
 +    /// # impl Foo {
 +    /// #     fn new() -> Self { Foo {} }
 +    /// # }
 +    /// # fn call(x: Foo) {}
 +    /// {
 +    ///     let x = Foo::new();
 +    ///     call(x.clone());
 +    ///     call(x.clone()); // this can just pass `x`
 +    /// }
 +    ///
 +    /// ["lorem", "ipsum"].join(" ").to_string();
 +    ///
 +    /// Path::new("/a/b").join("c").to_path_buf();
 +    /// ```
 +    #[clippy::version = "1.32.0"]
 +    pub REDUNDANT_CLONE,
 +    perf,
 +    "`clone()` of an owned value that is going to be dropped immediately"
 +}
 +
 +declare_lint_pass!(RedundantClone => [REDUNDANT_CLONE]);
 +
 +impl<'tcx> LateLintPass<'tcx> for RedundantClone {
 +    #[expect(clippy::too_many_lines)]
 +    fn check_fn(
 +        &mut self,
 +        cx: &LateContext<'tcx>,
 +        _: FnKind<'tcx>,
 +        _: &'tcx FnDecl<'_>,
 +        body: &'tcx Body<'_>,
 +        _: Span,
 +        _: HirId,
 +    ) {
 +        let def_id = cx.tcx.hir().body_owner_def_id(body.id());
 +
 +        // Building MIR for `fn`s with unsatisfiable preds results in ICE.
 +        if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
 +            return;
 +        }
 +
 +        let mir = cx.tcx.optimized_mir(def_id.to_def_id());
 +
 +        let mut possible_borrower = PossibleBorrowerMap::new(cx, mir);
 +
 +        for (bb, bbdata) in mir.basic_blocks.iter_enumerated() {
 +            let terminator = bbdata.terminator();
 +
 +            if terminator.source_info.span.from_expansion() {
 +                continue;
 +            }
 +
 +            // Give up on loops
 +            if terminator.successors().any(|s| s == bb) {
 +                continue;
 +            }
 +
 +            let (fn_def_id, arg, arg_ty, clone_ret) =
 +                unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));
 +
 +            let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD)
 +                || match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD)
 +                || (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD)
 +                    && is_type_lang_item(cx, arg_ty, LangItem::String));
 +
 +            let from_deref = !from_borrow
 +                && (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF)
 +                    || match_def_path(cx, fn_def_id, &paths::OS_STR_TO_OS_STRING));
 +
 +            if !from_borrow && !from_deref {
 +                continue;
 +            }
 +
 +            if let ty::Adt(def, _) = arg_ty.kind() {
 +                if def.is_manually_drop() {
 +                    continue;
 +                }
 +            }
 +
 +            // `{ arg = &cloned; clone(move arg); }` or `{ arg = &cloned; to_path_buf(arg); }`
 +            let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb));
 +
 +            let loc = mir::Location {
 +                block: bb,
 +                statement_index: bbdata.statements.len(),
 +            };
 +
 +            // `Local` to be cloned, and a local of `clone` call's destination
 +            let (local, ret_local) = if from_borrow {
 +                // `res = clone(arg)` can be turned into `res = move arg;`
 +                // if `arg` is the only borrow of `cloned` at this point.
 +
-                 if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg, cloned], local, loc) {
++                if cannot_move_out || !possible_borrower.only_borrowers(&[arg], cloned, loc) {
 +                    continue;
 +                }
 +
 +                (cloned, clone_ret)
 +            } else {
 +                // `arg` is a reference as it is `.deref()`ed in the previous block.
 +                // Look into the predecessor block and find out the source of deref.
 +
 +                let ps = &mir.basic_blocks.predecessors()[bb];
 +                if ps.len() != 1 {
 +                    continue;
 +                }
 +                let pred_terminator = mir[ps[0]].terminator();
 +
 +                // receiver of the `deref()` call
 +                let (pred_arg, deref_clone_ret) = if_chain! {
 +                    if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, res)) =
 +                        is_call_with_ref_arg(cx, mir, &pred_terminator.kind);
 +                    if res == cloned;
 +                    if cx.tcx.is_diagnostic_item(sym::deref_method, pred_fn_def_id);
 +                    if is_type_diagnostic_item(cx, pred_arg_ty, sym::PathBuf)
 +                        || is_type_diagnostic_item(cx, pred_arg_ty, sym::OsString);
 +                    then {
 +                        (pred_arg, res)
 +                    } else {
 +                        continue;
 +                    }
 +                };
 +
 +                let (local, cannot_move_out) =
 +                    unwrap_or_continue!(find_stmt_assigns_to(cx, mir, pred_arg, true, ps[0]));
 +                let loc = mir::Location {
 +                    block: bb,
 +                    statement_index: mir.basic_blocks[bb].statements.len(),
 +                };
 +
 +                // This can be turned into `res = move local` if `arg` and `cloned` are not borrowed
 +                // at the last statement:
 +                //
 +                // ```
 +                // pred_arg = &local;
 +                // cloned = deref(pred_arg);
 +                // arg = &cloned;
 +                // StorageDead(pred_arg);
 +                // res = to_path_buf(cloned);
 +                // ```
++                if cannot_move_out || !possible_borrower.only_borrowers(&[arg, cloned], local, loc) {
 +                    continue;
 +                }
 +
 +                (local, deref_clone_ret)
 +            };
 +
 +            let clone_usage = if local == ret_local {
 +                CloneUsage {
 +                    cloned_used: false,
 +                    cloned_consume_or_mutate_loc: None,
 +                    clone_consumed_or_mutated: true,
 +                }
 +            } else {
 +                let clone_usage = visit_clone_usage(local, ret_local, mir, bb);
 +                if clone_usage.cloned_used && clone_usage.clone_consumed_or_mutated {
 +                    // cloned value is used, and the clone is modified or moved
 +                    continue;
 +                } else if let Some(loc) = clone_usage.cloned_consume_or_mutate_loc {
 +                    // cloned value is mutated, and the clone is alive.
 +                    if possible_borrower.local_is_alive_at(ret_local, loc) {
 +                        continue;
 +                    }
 +                }
 +                clone_usage
 +            };
 +
 +            let span = terminator.source_info.span;
 +            let scope = terminator.source_info.scope;
 +            let node = mir.source_scopes[scope]
 +                .local_data
 +                .as_ref()
 +                .assert_crate_local()
 +                .lint_root;
 +
 +            if_chain! {
 +                if let Some(snip) = snippet_opt(cx, span);
 +                if let Some(dot) = snip.rfind('.');
 +                then {
 +                    let sugg_span = span.with_lo(
 +                        span.lo() + BytePos(u32::try_from(dot).unwrap())
 +                    );
 +                    let mut app = Applicability::MaybeIncorrect;
 +
 +                    let call_snip = &snip[dot + 1..];
 +                    // Machine applicable when `call_snip` looks like `foobar()`
 +                    if let Some(call_snip) = call_snip.strip_suffix("()").map(str::trim) {
 +                        if call_snip.as_bytes().iter().all(|b| b.is_ascii_alphabetic() || *b == b'_') {
 +                            app = Applicability::MachineApplicable;
 +                        }
 +                    }
 +
 +                    span_lint_hir_and_then(cx, REDUNDANT_CLONE, node, sugg_span, "redundant clone", |diag| {
 +                        diag.span_suggestion(
 +                            sugg_span,
 +                            "remove this",
 +                            "",
 +                            app,
 +                        );
 +                        if clone_usage.cloned_used {
 +                            diag.span_note(
 +                                span,
 +                                "cloned value is neither consumed nor mutated",
 +                            );
 +                        } else {
 +                            diag.span_note(
 +                                span.with_hi(span.lo() + BytePos(u32::try_from(dot).unwrap())),
 +                                "this value is dropped without further use",
 +                            );
 +                        }
 +                    });
 +                } else {
 +                    span_lint_hir(cx, REDUNDANT_CLONE, node, span, "redundant clone");
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +/// If `kind` is `y = func(x: &T)` where `T: !Copy`, returns `(DefId of func, x, T, y)`.
 +fn is_call_with_ref_arg<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    mir: &'tcx mir::Body<'tcx>,
 +    kind: &'tcx mir::TerminatorKind<'tcx>,
 +) -> Option<(def_id::DefId, mir::Local, Ty<'tcx>, mir::Local)> {
 +    if_chain! {
 +        if let mir::TerminatorKind::Call { func, args, destination, .. } = kind;
 +        if args.len() == 1;
 +        if let mir::Operand::Move(mir::Place { local, .. }) = &args[0];
 +        if let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind();
 +        if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx));
 +        if !is_copy(cx, inner_ty);
 +        then {
 +            Some((def_id, *local, inner_ty, destination.as_local()?))
 +        } else {
 +            None
 +        }
 +    }
 +}
 +
 +type CannotMoveOut = bool;
 +
 +/// Finds the first `to = (&)from`, and returns
 +/// ``Some((from, whether `from` cannot be moved out))``.
 +fn find_stmt_assigns_to<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    mir: &mir::Body<'tcx>,
 +    to_local: mir::Local,
 +    by_ref: bool,
 +    bb: mir::BasicBlock,
 +) -> Option<(mir::Local, CannotMoveOut)> {
 +    let rvalue = mir.basic_blocks[bb].statements.iter().rev().find_map(|stmt| {
 +        if let mir::StatementKind::Assign(box (mir::Place { local, .. }, v)) = &stmt.kind {
 +            return if *local == to_local { Some(v) } else { None };
 +        }
 +
 +        None
 +    })?;
 +
 +    match (by_ref, rvalue) {
 +        (true, mir::Rvalue::Ref(_, _, place)) | (false, mir::Rvalue::Use(mir::Operand::Copy(place))) => {
 +            Some(base_local_and_movability(cx, mir, *place))
 +        },
 +        (false, mir::Rvalue::Ref(_, _, place)) => {
 +            if let [mir::ProjectionElem::Deref] = place.as_ref().projection {
 +                Some(base_local_and_movability(cx, mir, *place))
 +            } else {
 +                None
 +            }
 +        },
 +        _ => None,
 +    }
 +}
 +
 +/// Extracts and returns the undermost base `Local` of given `place`. Returns `place` itself
 +/// if it is already a `Local`.
 +///
 +/// Also reports whether given `place` cannot be moved out.
 +fn base_local_and_movability<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    mir: &mir::Body<'tcx>,
 +    place: mir::Place<'tcx>,
 +) -> (mir::Local, CannotMoveOut) {
 +    use rustc_middle::mir::PlaceRef;
 +
 +    // Dereference. You cannot move things out from a borrowed value.
 +    let mut deref = false;
 +    // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
 +    let mut field = false;
 +    // If projection is a slice index then clone can be removed only if the
 +    // underlying type implements Copy
 +    let mut slice = false;
 +
 +    let PlaceRef { local, mut projection } = place.as_ref();
 +    while let [base @ .., elem] = projection {
 +        projection = base;
 +        deref |= matches!(elem, mir::ProjectionElem::Deref);
 +        field |= matches!(elem, mir::ProjectionElem::Field(..))
 +            && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
 +        slice |= matches!(elem, mir::ProjectionElem::Index(..))
 +            && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty);
 +    }
 +
 +    (local, deref || field || slice)
 +}
 +
 +#[derive(Default)]
 +struct CloneUsage {
 +    /// Whether the cloned value is used after the clone.
 +    cloned_used: bool,
 +    /// The first location where the cloned value is consumed or mutated, if any.
 +    cloned_consume_or_mutate_loc: Option<mir::Location>,
 +    /// Whether the clone value is mutated.
 +    clone_consumed_or_mutated: bool,
 +}
 +
 +fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage {
 +    if let Some((
 +        LocalUsage {
 +            local_use_locs: cloned_use_locs,
 +            local_consume_or_mutate_locs: cloned_consume_or_mutate_locs,
 +        },
 +        LocalUsage {
 +            local_use_locs: _,
 +            local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
 +        },
 +    )) = visit_local_usage(
 +        &[cloned, clone],
 +        mir,
 +        mir::Location {
 +            block: bb,
 +            statement_index: mir.basic_blocks[bb].statements.len(),
 +        },
 +    )
 +    .map(|mut vec| (vec.remove(0), vec.remove(0)))
 +    {
 +        CloneUsage {
 +            cloned_used: !cloned_use_locs.is_empty(),
 +            cloned_consume_or_mutate_loc: cloned_consume_or_mutate_locs.first().copied(),
 +            // Consider non-temporary clones consumed.
 +            // TODO: Actually check for mutation of non-temporaries.
 +            clone_consumed_or_mutated: mir.local_kind(clone) != mir::LocalKind::Temp
 +                || !clone_consume_or_mutate_locs.is_empty(),
 +        }
 +    } else {
 +        CloneUsage {
 +            cloned_used: true,
 +            cloned_consume_or_mutate_loc: None,
 +            clone_consumed_or_mutated: true,
 +        }
 +    }
 +}
index 72c25592609ba77191f7877134b6c8bff1df90d8,0000000000000000000000000000000000000000..9f487dedb8cb6daf24970e3a7d2d7d99278d7ebd
mode 100644,000000..100644
--- /dev/null
@@@ -1,46 -1,0 +1,47 @@@
 +// This file is managed by `cargo dev rename_lint`. Prefer using that when possible.
 +
 +#[rustfmt::skip]
 +pub static RENAMED_LINTS: &[(&str, &str)] = &[
 +    ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"),
 +    ("clippy::blacklisted_name", "clippy::disallowed_names"),
 +    ("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"),
 +    ("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"),
 +    ("clippy::box_vec", "clippy::box_collection"),
 +    ("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
 +    ("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
++    ("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"),
 +    ("clippy::disallowed_method", "clippy::disallowed_methods"),
 +    ("clippy::disallowed_type", "clippy::disallowed_types"),
 +    ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
 +    ("clippy::identity_conversion", "clippy::useless_conversion"),
 +    ("clippy::if_let_some_result", "clippy::match_result_ok"),
 +    ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
 +    ("clippy::new_without_default_derive", "clippy::new_without_default"),
 +    ("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
 +    ("clippy::option_expect_used", "clippy::expect_used"),
 +    ("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"),
 +    ("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"),
 +    ("clippy::option_unwrap_used", "clippy::unwrap_used"),
 +    ("clippy::ref_in_deref", "clippy::needless_borrow"),
 +    ("clippy::result_expect_used", "clippy::expect_used"),
 +    ("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"),
 +    ("clippy::result_unwrap_used", "clippy::unwrap_used"),
 +    ("clippy::single_char_push_str", "clippy::single_char_add_str"),
 +    ("clippy::stutter", "clippy::module_name_repetitions"),
 +    ("clippy::to_string_in_display", "clippy::recursive_format_impl"),
 +    ("clippy::zero_width_space", "clippy::invisible_characters"),
 +    ("clippy::drop_bounds", "drop_bounds"),
 +    ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
 +    ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
 +    ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
 +    ("clippy::into_iter_on_array", "array_into_iter"),
 +    ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
 +    ("clippy::invalid_ref", "invalid_value"),
 +    ("clippy::let_underscore_drop", "let_underscore_drop"),
 +    ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
 +    ("clippy::panic_params", "non_fmt_panics"),
 +    ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
 +    ("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
 +    ("clippy::unknown_clippy_lints", "unknown_lints"),
 +    ("clippy::unused_label", "unused_labels"),
 +];
index d4d506605206b7734b6e2c0685d57f1bea663d29,0000000000000000000000000000000000000000..bbbd9e4989e97c05f189ddec545cb59d84be67cc
mode 100644,000000..100644
--- /dev/null
@@@ -1,312 -1,0 +1,315 @@@
-                 && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind {
-                     return;
 +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
 +use clippy_utils::source::{snippet_opt, snippet_with_context};
 +use clippy_utils::visitors::{for_each_expr, Descend};
 +use clippy_utils::{fn_def_id, path_to_local_id};
 +use core::ops::ControlFlow;
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir::intravisit::FnKind;
 +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, LangItem, MatchSource, PatKind, QPath, StmtKind};
 +use rustc_lint::{LateContext, LateLintPass, LintContext};
 +use rustc_middle::lint::in_external_macro;
 +use rustc_middle::ty::subst::GenericArgKind;
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::source_map::Span;
 +use rustc_span::{BytePos, Pos};
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for `let`-bindings, which are subsequently
 +    /// returned.
 +    ///
 +    /// ### Why is this bad?
 +    /// It is just extraneous code. Remove it to make your code
 +    /// more rusty.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// fn foo() -> String {
 +    ///     let x = String::new();
 +    ///     x
 +    /// }
 +    /// ```
 +    /// instead, use
 +    /// ```
 +    /// fn foo() -> String {
 +    ///     String::new()
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub LET_AND_RETURN,
 +    style,
 +    "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for return statements at the end of a block.
 +    ///
 +    /// ### Why is this bad?
 +    /// Removing the `return` and semicolon will make the code
 +    /// more rusty.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// fn foo(x: usize) -> usize {
 +    ///     return x;
 +    /// }
 +    /// ```
 +    /// simplify to
 +    /// ```rust
 +    /// fn foo(x: usize) -> usize {
 +    ///     x
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub NEEDLESS_RETURN,
 +    style,
 +    "using a return statement like `return expr;` where an expression would suffice"
 +}
 +
 +#[derive(PartialEq, Eq, Copy, Clone)]
 +enum RetReplacement {
 +    Empty,
 +    Block,
 +    Unit,
 +}
 +
 +impl RetReplacement {
 +    fn sugg_help(self) -> &'static str {
 +        match self {
 +            Self::Empty => "remove `return`",
 +            Self::Block => "replace `return` with an empty block",
 +            Self::Unit => "replace `return` with a unit value",
 +        }
 +    }
 +}
 +
 +impl ToString for RetReplacement {
 +    fn to_string(&self) -> String {
 +        match *self {
 +            Self::Empty => "",
 +            Self::Block => "{}",
 +            Self::Unit => "()",
 +        }
 +        .to_string()
 +    }
 +}
 +
 +declare_lint_pass!(Return => [LET_AND_RETURN, NEEDLESS_RETURN]);
 +
 +impl<'tcx> LateLintPass<'tcx> for Return {
 +    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
 +        // we need both a let-binding stmt and an expr
 +        if_chain! {
 +            if let Some(retexpr) = block.expr;
 +            if let Some(stmt) = block.stmts.iter().last();
 +            if let StmtKind::Local(local) = &stmt.kind;
 +            if local.ty.is_none();
 +            if cx.tcx.hir().attrs(local.hir_id).is_empty();
 +            if let Some(initexpr) = &local.init;
 +            if let PatKind::Binding(_, local_id, _, _) = local.pat.kind;
 +            if path_to_local_id(retexpr, local_id);
 +            if !last_statement_borrows(cx, initexpr);
 +            if !in_external_macro(cx.sess(), initexpr.span);
 +            if !in_external_macro(cx.sess(), retexpr.span);
 +            if !local.span.from_expansion();
 +            then {
 +                span_lint_hir_and_then(
 +                    cx,
 +                    LET_AND_RETURN,
 +                    retexpr.hir_id,
 +                    retexpr.span,
 +                    "returning the result of a `let` binding from a block",
 +                    |err| {
 +                        err.span_label(local.span, "unnecessary `let` binding");
 +
 +                        if let Some(mut snippet) = snippet_opt(cx, initexpr.span) {
 +                            if !cx.typeck_results().expr_adjustments(retexpr).is_empty() {
 +                                snippet.push_str(" as _");
 +                            }
 +                            err.multipart_suggestion(
 +                                "return the expression directly",
 +                                vec![
 +                                    (local.span, String::new()),
 +                                    (retexpr.span, snippet),
 +                                ],
 +                                Applicability::MachineApplicable,
 +                            );
 +                        } else {
 +                            err.span_help(initexpr.span, "this expression can be directly returned");
 +                        }
 +                    },
 +                );
 +            }
 +        }
 +    }
 +
 +    fn check_fn(
 +        &mut self,
 +        cx: &LateContext<'tcx>,
 +        kind: FnKind<'tcx>,
 +        _: &'tcx FnDecl<'tcx>,
 +        body: &'tcx Body<'tcx>,
 +        _: Span,
 +        _: HirId,
 +    ) {
 +        match kind {
 +            FnKind::Closure => {
 +                // when returning without value in closure, replace this `return`
 +                // with an empty block to prevent invalid suggestion (see #6501)
 +                let replacement = if let ExprKind::Ret(None) = &body.value.kind {
 +                    RetReplacement::Block
 +                } else {
 +                    RetReplacement::Empty
 +                };
 +                check_final_expr(cx, body.value, vec![], replacement);
 +            },
 +            FnKind::ItemFn(..) | FnKind::Method(..) => {
 +                check_block_return(cx, &body.value.kind, vec![]);
 +            },
 +        }
 +    }
 +}
 +
 +// if `expr` is a block, check if there are needless returns in it
 +fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, semi_spans: Vec<Span>) {
 +    if let ExprKind::Block(block, _) = expr_kind {
 +        if let Some(block_expr) = block.expr {
 +            check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
 +        } else if let Some(stmt) = block.stmts.iter().last() {
 +            match stmt.kind {
 +                StmtKind::Expr(expr) => {
 +                    check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
 +                },
 +                StmtKind::Semi(semi_expr) => {
 +                    let mut semi_spans_and_this_one = semi_spans;
 +                    // we only want the span containing the semicolon so we can remove it later. From `entry.rs:382`
 +                    if let Some(semicolon_span) = stmt.span.trim_start(semi_expr.span) {
 +                        semi_spans_and_this_one.push(semicolon_span);
 +                        check_final_expr(cx, semi_expr, semi_spans_and_this_one, RetReplacement::Empty);
 +                    }
 +                },
 +                _ => (),
 +            }
 +        }
 +    }
 +}
 +
 +fn check_final_expr<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    expr: &'tcx Expr<'tcx>,
 +    semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
 +                            * needless return */
 +    replacement: RetReplacement,
 +) {
 +    let peeled_drop_expr = expr.peel_drop_temps();
 +    match &peeled_drop_expr.kind {
 +        // simple return is always "bad"
 +        ExprKind::Ret(ref inner) => {
 +            // if desugar of `do yeet`, don't lint
 +            if let Some(inner_expr) = inner
 +                && let ExprKind::Call(path_expr, _) = inner_expr.kind
-             if cx.tcx.hir().attrs(expr.hir_id).is_empty() {
-                 let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
-                 if !borrows {
-                     // check if expr return nothing
-                     let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
-                         extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
-                     } else {
-                         peeled_drop_expr.span
-                     };
-                     emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
-                 }
++                && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
++            {
++                return;
 +            }
-             ControlFlow::Continue(Descend::from(!expr.span.from_expansion()))
++            if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
++                return;
++            }
++            let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
++            if borrows {
++                return;
 +            }
++            // check if expr return nothing
++            let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
++                extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
++            } else {
++                peeled_drop_expr.span
++            };
++
++            emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
 +        },
 +        ExprKind::If(_, then, else_clause_opt) => {
 +            check_block_return(cx, &then.kind, semi_spans.clone());
 +            if let Some(else_clause) = else_clause_opt {
 +                check_block_return(cx, &else_clause.kind, semi_spans);
 +            }
 +        },
 +        // a match expr, check all arms
 +        // an if/if let expr, check both exprs
 +        // note, if without else is going to be a type checking error anyways
 +        // (except for unit type functions) so we don't match it
 +        ExprKind::Match(_, arms, MatchSource::Normal) => {
 +            for arm in arms.iter() {
 +                check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit);
 +            }
 +        },
 +        // if it's a whole block, check it
 +        other_expr_kind => check_block_return(cx, other_expr_kind, semi_spans),
 +    }
 +}
 +
 +fn emit_return_lint(
 +    cx: &LateContext<'_>,
 +    ret_span: Span,
 +    semi_spans: Vec<Span>,
 +    inner_span: Option<Span>,
 +    replacement: RetReplacement,
 +) {
 +    if ret_span.from_expansion() {
 +        return;
 +    }
 +    let mut applicability = Applicability::MachineApplicable;
 +    let return_replacement = inner_span.map_or_else(
 +        || replacement.to_string(),
 +        |inner_span| {
 +            let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
 +            snippet.to_string()
 +        },
 +    );
 +    let sugg_help = if inner_span.is_some() {
 +        "remove `return`"
 +    } else {
 +        replacement.sugg_help()
 +    };
 +    span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| {
 +        diag.span_suggestion_hidden(ret_span, sugg_help, return_replacement, applicability);
 +        // for each parent statement, we need to remove the semicolon
 +        for semi_stmt_span in semi_spans {
 +            diag.tool_only_span_suggestion(semi_stmt_span, "remove this semicolon", "", applicability);
 +        }
 +    });
 +}
 +
 +fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
 +    for_each_expr(expr, |e| {
 +        if let Some(def_id) = fn_def_id(cx, e)
 +            && cx
 +                .tcx
 +                .fn_sig(def_id)
 +                .skip_binder()
 +                .output()
 +                .walk()
 +                .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
 +        {
 +            ControlFlow::Break(())
 +        } else {
++            ControlFlow::Continue(Descend::from(!e.span.from_expansion()))
 +        }
 +    })
 +    .is_some()
 +}
 +
 +// Go backwards while encountering whitespace and extend the given Span to that point.
 +fn extend_span_to_previous_non_ws(cx: &LateContext<'_>, sp: Span) -> Span {
 +    if let Ok(prev_source) = cx.sess().source_map().span_to_prev_source(sp) {
 +        let ws = [' ', '\t', '\n'];
 +        if let Some(non_ws_pos) = prev_source.rfind(|c| !ws.contains(&c)) {
 +            let len = prev_source.len() - non_ws_pos - 1;
 +            return sp.with_lo(sp.lo() - BytePos::from_usize(len));
 +        }
 +    }
 +
 +    sp
 +}
index c14f056a1f2de181d41e47a99bdcbc2c09338ac1,0000000000000000000000000000000000000000..229478b7ce3c9c2b72cf80617fa2f204f3fe38f2
mode 100644,000000..100644
--- /dev/null
@@@ -1,578 -1,0 +1,578 @@@
-     /// Gankro says:
 +mod borrowed_box;
 +mod box_collection;
 +mod linked_list;
 +mod option_option;
 +mod rc_buffer;
 +mod rc_mutex;
 +mod redundant_allocation;
 +mod type_complexity;
 +mod utils;
 +mod vec_box;
 +
 +use rustc_hir as hir;
 +use rustc_hir::intravisit::FnKind;
 +use rustc_hir::{
 +    Body, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem,
 +    TraitItemKind, TyKind,
 +};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::source_map::Span;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for use of `Box<T>` where T is a collection such as Vec anywhere in the code.
 +    /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
 +    ///
 +    /// ### Why is this bad?
 +    /// Collections already keeps their contents in a separate area on
 +    /// the heap. So if you `Box` them, you just add another level of indirection
 +    /// without any benefit whatsoever.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// struct X {
 +    ///     values: Box<Vec<Foo>>,
 +    /// }
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust,ignore
 +    /// struct X {
 +    ///     values: Vec<Foo>,
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.57.0"]
 +    pub BOX_COLLECTION,
 +    perf,
 +    "usage of `Box<Vec<T>>`, vector elements are already on the heap"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for use of `Vec<Box<T>>` where T: Sized anywhere in the code.
 +    /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
 +    ///
 +    /// ### Why is this bad?
 +    /// `Vec` already keeps its contents in a separate area on
 +    /// the heap. So if you `Box` its contents, you just add another level of indirection.
 +    ///
 +    /// ### Known problems
 +    /// Vec<Box<T: Sized>> makes sense if T is a large type (see [#3530](https://github.com/rust-lang/rust-clippy/issues/3530),
 +    /// 1st comment).
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// struct X {
 +    ///     values: Vec<Box<i32>>,
 +    /// }
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust
 +    /// struct X {
 +    ///     values: Vec<i32>,
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.33.0"]
 +    pub VEC_BOX,
 +    complexity,
 +    "usage of `Vec<Box<T>>` where T: Sized, vector elements are already on the heap"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for use of `Option<Option<_>>` in function signatures and type
 +    /// definitions
 +    ///
 +    /// ### Why is this bad?
 +    /// `Option<_>` represents an optional value. `Option<Option<_>>`
 +    /// represents an optional optional value which is logically the same thing as an optional
 +    /// value but has an unneeded extra level of wrapping.
 +    ///
 +    /// If you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases,
 +    /// consider a custom `enum` instead, with clear names for each case.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// fn get_data() -> Option<Option<u32>> {
 +    ///     None
 +    /// }
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust
 +    /// pub enum Contents {
 +    ///     Data(Vec<u8>), // Was Some(Some(Vec<u8>))
 +    ///     NotYetFetched, // Was Some(None)
 +    ///     None,          // Was None
 +    /// }
 +    ///
 +    /// fn get_data() -> Contents {
 +    ///     Contents::None
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub OPTION_OPTION,
 +    pedantic,
 +    "usage of `Option<Option<T>>`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for usage of any `LinkedList`, suggesting to use a
 +    /// `Vec` or a `VecDeque` (formerly called `RingBuf`).
 +    ///
 +    /// ### Why is this bad?
++    /// Gankra says:
 +    ///
 +    /// > The TL;DR of `LinkedList` is that it's built on a massive amount of
 +    /// pointers and indirection.
 +    /// > It wastes memory, it has terrible cache locality, and is all-around slow.
 +    /// `RingBuf`, while
 +    /// > "only" amortized for push/pop, should be faster in the general case for
 +    /// almost every possible
 +    /// > workload, and isn't even amortized at all if you can predict the capacity
 +    /// you need.
 +    /// >
 +    /// > `LinkedList`s are only really good if you're doing a lot of merging or
 +    /// splitting of lists.
 +    /// > This is because they can just mangle some pointers instead of actually
 +    /// copying the data. Even
 +    /// > if you're doing a lot of insertion in the middle of the list, `RingBuf`
 +    /// can still be better
 +    /// > because of how expensive it is to seek to the middle of a `LinkedList`.
 +    ///
 +    /// ### Known problems
 +    /// False positives – the instances where using a
 +    /// `LinkedList` makes sense are few and far between, but they can still happen.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # use std::collections::LinkedList;
 +    /// let x: LinkedList<usize> = LinkedList::new();
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub LINKEDLIST,
 +    pedantic,
 +    "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a `VecDeque`"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for use of `&Box<T>` anywhere in the code.
 +    /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information.
 +    ///
 +    /// ### Why is this bad?
 +    /// A `&Box<T>` parameter requires the function caller to box `T` first before passing it to a function.
 +    /// Using `&T` defines a concrete type for the parameter and generalizes the function, this would also
 +    /// auto-deref to `&T` at the function call site if passed a `&Box<T>`.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// fn foo(bar: &Box<T>) { ... }
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust,ignore
 +    /// fn foo(bar: &T) { ... }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub BORROWED_BOX,
 +    complexity,
 +    "a borrow of a boxed type"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for use of redundant allocations anywhere in the code.
 +    ///
 +    /// ### Why is this bad?
 +    /// Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, `Arc<&T>`, `Arc<Rc<T>>`,
 +    /// `Arc<Arc<T>>`, `Arc<Box<T>>`, `Box<&T>`, `Box<Rc<T>>`, `Box<Arc<T>>`, `Box<Box<T>>`, add an unnecessary level of indirection.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # use std::rc::Rc;
 +    /// fn foo(bar: Rc<&usize>) {}
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust
 +    /// fn foo(bar: &usize) {}
 +    /// ```
 +    #[clippy::version = "1.44.0"]
 +    pub REDUNDANT_ALLOCATION,
 +    perf,
 +    "redundant allocation"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for `Rc<T>` and `Arc<T>` when `T` is a mutable buffer type such as `String` or `Vec`.
 +    ///
 +    /// ### Why is this bad?
 +    /// Expressions such as `Rc<String>` usually have no advantage over `Rc<str>`, since
 +    /// it is larger and involves an extra level of indirection, and doesn't implement `Borrow<str>`.
 +    ///
 +    /// While mutating a buffer type would still be possible with `Rc::get_mut()`, it only
 +    /// works if there are no additional references yet, which usually defeats the purpose of
 +    /// enclosing it in a shared ownership type. Instead, additionally wrapping the inner
 +    /// type with an interior mutable container (such as `RefCell` or `Mutex`) would normally
 +    /// be used.
 +    ///
 +    /// ### Known problems
 +    /// This pattern can be desirable to avoid the overhead of a `RefCell` or `Mutex` for
 +    /// cases where mutation only happens before there are any additional references.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// # use std::rc::Rc;
 +    /// fn foo(interned: Rc<String>) { ... }
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust,ignore
 +    /// fn foo(interned: Rc<str>) { ... }
 +    /// ```
 +    #[clippy::version = "1.48.0"]
 +    pub RC_BUFFER,
 +    restriction,
 +    "shared ownership of a buffer type"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for types used in structs, parameters and `let`
 +    /// declarations above a certain complexity threshold.
 +    ///
 +    /// ### Why is this bad?
 +    /// Too complex types make the code less readable. Consider
 +    /// using a `type` definition to simplify them.
 +    ///
 +    /// ### Example
 +    /// ```rust
 +    /// # use std::rc::Rc;
 +    /// struct Foo {
 +    ///     inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
 +    /// }
 +    /// ```
 +    #[clippy::version = "pre 1.29.0"]
 +    pub TYPE_COMPLEXITY,
 +    complexity,
 +    "usage of very complex types that might be better factored into `type` definitions"
 +}
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks for `Rc<Mutex<T>>`.
 +    ///
 +    /// ### Why is this bad?
 +    /// `Rc` is used in single thread and `Mutex` is used in multi thread.
 +    /// Consider using `Rc<RefCell<T>>` in single thread or `Arc<Mutex<T>>` in multi thread.
 +    ///
 +    /// ### Known problems
 +    /// Sometimes combining generic types can lead to the requirement that a
 +    /// type use Rc in conjunction with Mutex. We must consider those cases false positives, but
 +    /// alas they are quite hard to rule out. Luckily they are also rare.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// use std::rc::Rc;
 +    /// use std::sync::Mutex;
 +    /// fn foo(interned: Rc<Mutex<i32>>) { ... }
 +    /// ```
 +    ///
 +    /// Better:
 +    ///
 +    /// ```rust,ignore
 +    /// use std::rc::Rc;
 +    /// use std::cell::RefCell
 +    /// fn foo(interned: Rc<RefCell<i32>>) { ... }
 +    /// ```
 +    #[clippy::version = "1.55.0"]
 +    pub RC_MUTEX,
 +    restriction,
 +    "usage of `Rc<Mutex<T>>`"
 +}
 +
 +pub struct Types {
 +    vec_box_size_threshold: u64,
 +    type_complexity_threshold: u64,
 +    avoid_breaking_exported_api: bool,
 +}
 +
 +impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
 +
 +impl<'tcx> LateLintPass<'tcx> for Types {
 +    fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
 +        let is_in_trait_impl =
 +            if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id).def_id) {
 +                matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
 +            } else {
 +                false
 +            };
 +
 +        let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(id));
 +
 +        self.check_fn_decl(
 +            cx,
 +            decl,
 +            CheckTyContext {
 +                is_in_trait_impl,
 +                is_exported,
 +                ..CheckTyContext::default()
 +            },
 +        );
 +    }
 +
 +    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
 +        let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
 +
 +        match item.kind {
 +            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(
 +                cx,
 +                ty,
 +                CheckTyContext {
 +                    is_exported,
 +                    ..CheckTyContext::default()
 +                },
 +            ),
 +            // functions, enums, structs, impls and traits are covered
 +            _ => (),
 +        }
 +    }
 +
 +    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
 +        match item.kind {
 +            ImplItemKind::Const(ty, _) => {
 +                let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx
 +                    .tcx
 +                    .hir()
 +                    .find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id)
 +                {
 +                    matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
 +                } else {
 +                    false
 +                };
 +
 +                self.check_ty(
 +                    cx,
 +                    ty,
 +                    CheckTyContext {
 +                        is_in_trait_impl,
 +                        ..CheckTyContext::default()
 +                    },
 +                );
 +            },
 +            // Methods are covered by check_fn.
 +            // Type aliases are ignored because oftentimes it's impossible to
 +            // make type alias declaration in trait simpler, see #1013
 +            ImplItemKind::Fn(..) | ImplItemKind::Type(..) => (),
 +        }
 +    }
 +
 +    fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
 +        let is_exported = cx
 +            .effective_visibilities
 +            .is_exported(cx.tcx.hir().local_def_id(field.hir_id));
 +
 +        self.check_ty(
 +            cx,
 +            field.ty,
 +            CheckTyContext {
 +                is_exported,
 +                ..CheckTyContext::default()
 +            },
 +        );
 +    }
 +
 +    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) {
 +        let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
 +
 +        let context = CheckTyContext {
 +            is_exported,
 +            ..CheckTyContext::default()
 +        };
 +
 +        match item.kind {
 +            TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => {
 +                self.check_ty(cx, ty, context);
 +            },
 +            TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, context),
 +            TraitItemKind::Type(..) => (),
 +        }
 +    }
 +
 +    fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
 +        if let Some(ty) = local.ty {
 +            self.check_ty(
 +                cx,
 +                ty,
 +                CheckTyContext {
 +                    is_local: true,
 +                    ..CheckTyContext::default()
 +                },
 +            );
 +        }
 +    }
 +}
 +
 +impl Types {
 +    pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64, avoid_breaking_exported_api: bool) -> Self {
 +        Self {
 +            vec_box_size_threshold,
 +            type_complexity_threshold,
 +            avoid_breaking_exported_api,
 +        }
 +    }
 +
 +    fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) {
 +        // Ignore functions in trait implementations as they are usually forced by the trait definition.
 +        //
 +        // FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard
 +        // to check.
 +        if context.is_in_trait_impl {
 +            return;
 +        }
 +
 +        for input in decl.inputs {
 +            self.check_ty(cx, input, context);
 +        }
 +
 +        if let FnRetTy::Return(ty) = decl.output {
 +            self.check_ty(cx, ty, context);
 +        }
 +    }
 +
 +    /// Recursively check for `TypePass` lints in the given type. Stop at the first
 +    /// lint found.
 +    ///
 +    /// The parameter `is_local` distinguishes the context of the type.
 +    fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) {
 +        if hir_ty.span.from_expansion() {
 +            return;
 +        }
 +
 +        // Skip trait implementations; see issue #605.
 +        if context.is_in_trait_impl {
 +            return;
 +        }
 +
 +        if !context.is_nested_call && type_complexity::check(cx, hir_ty, self.type_complexity_threshold) {
 +            return;
 +        }
 +
 +        match hir_ty.kind {
 +            TyKind::Path(ref qpath) if !context.is_local => {
 +                let hir_id = hir_ty.hir_id;
 +                let res = cx.qpath_res(qpath, hir_id);
 +                if let Some(def_id) = res.opt_def_id() {
 +                    if self.is_type_change_allowed(context) {
 +                        // All lints that are being checked in this block are guarded by
 +                        // the `avoid_breaking_exported_api` configuration. When adding a
 +                        // new lint, please also add the name to the configuration documentation
 +                        // in `clippy_lints::utils::conf.rs`
 +
 +                        let mut triggered = false;
 +                        triggered |= box_collection::check(cx, hir_ty, qpath, def_id);
 +                        triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id);
 +                        triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id);
 +                        triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
 +                        triggered |= option_option::check(cx, hir_ty, qpath, def_id);
 +                        triggered |= linked_list::check(cx, hir_ty, def_id);
 +                        triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
 +
 +                        if triggered {
 +                            return;
 +                        }
 +                    }
 +                }
 +                match *qpath {
 +                    QPath::Resolved(Some(ty), p) => {
 +                        context.is_nested_call = true;
 +                        self.check_ty(cx, ty, context);
 +                        for ty in p.segments.iter().flat_map(|seg| {
 +                            seg.args
 +                                .as_ref()
 +                                .map_or_else(|| [].iter(), |params| params.args.iter())
 +                                .filter_map(|arg| match arg {
 +                                    GenericArg::Type(ty) => Some(ty),
 +                                    _ => None,
 +                                })
 +                        }) {
 +                            self.check_ty(cx, ty, context);
 +                        }
 +                    },
 +                    QPath::Resolved(None, p) => {
 +                        context.is_nested_call = true;
 +                        for ty in p.segments.iter().flat_map(|seg| {
 +                            seg.args
 +                                .as_ref()
 +                                .map_or_else(|| [].iter(), |params| params.args.iter())
 +                                .filter_map(|arg| match arg {
 +                                    GenericArg::Type(ty) => Some(ty),
 +                                    _ => None,
 +                                })
 +                        }) {
 +                            self.check_ty(cx, ty, context);
 +                        }
 +                    },
 +                    QPath::TypeRelative(ty, seg) => {
 +                        context.is_nested_call = true;
 +                        self.check_ty(cx, ty, context);
 +                        if let Some(params) = seg.args {
 +                            for ty in params.args.iter().filter_map(|arg| match arg {
 +                                GenericArg::Type(ty) => Some(ty),
 +                                _ => None,
 +                            }) {
 +                                self.check_ty(cx, ty, context);
 +                            }
 +                        }
 +                    },
 +                    QPath::LangItem(..) => {},
 +                }
 +            },
 +            TyKind::Ref(lt, ref mut_ty) => {
 +                context.is_nested_call = true;
 +                if !borrowed_box::check(cx, hir_ty, lt, mut_ty) {
 +                    self.check_ty(cx, mut_ty.ty, context);
 +                }
 +            },
 +            TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => {
 +                context.is_nested_call = true;
 +                self.check_ty(cx, ty, context);
 +            },
 +            TyKind::Tup(tys) => {
 +                context.is_nested_call = true;
 +                for ty in tys {
 +                    self.check_ty(cx, ty, context);
 +                }
 +            },
 +            _ => {},
 +        }
 +    }
 +
 +    /// This function checks if the type is allowed to change in the current context
 +    /// based on the `avoid_breaking_exported_api` configuration
 +    fn is_type_change_allowed(&self, context: CheckTyContext) -> bool {
 +        !(context.is_exported && self.avoid_breaking_exported_api)
 +    }
 +}
 +
 +#[allow(clippy::struct_excessive_bools)]
 +#[derive(Clone, Copy, Default)]
 +struct CheckTyContext {
 +    is_in_trait_impl: bool,
 +    /// `true` for types on local variables.
 +    is_local: bool,
 +    /// `true` for types that are part of the public API.
 +    is_exported: bool,
 +    is_nested_call: bool,
 +}
index 42bccc7212b3026216cabd16adefa30286f722db,0000000000000000000000000000000000000000..f864c520302e4a56b294e2b8b66b290f005addfb
mode 100644,000000..100644
--- /dev/null
@@@ -1,80 -1,0 +1,97 @@@
- use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
 +use clippy_utils::diagnostics::span_lint_and_help;
++use clippy_utils::macros::root_macro_call_first_node;
 +use clippy_utils::visitors::is_local_used;
 +use if_chain::if_chain;
-                     "consider refactoring to a associated function",
++use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
++use std::ops::ControlFlow;
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Checks methods that contain a `self` argument but don't use it
 +    ///
 +    /// ### Why is this bad?
 +    /// It may be clearer to define the method as an associated function instead
 +    /// of an instance method if it doesn't require `self`.
 +    ///
 +    /// ### Example
 +    /// ```rust,ignore
 +    /// struct A;
 +    /// impl A {
 +    ///     fn method(&self) {}
 +    /// }
 +    /// ```
 +    ///
 +    /// Could be written:
 +    ///
 +    /// ```rust,ignore
 +    /// struct A;
 +    /// impl A {
 +    ///     fn method() {}
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.40.0"]
 +    pub UNUSED_SELF,
 +    pedantic,
 +    "methods that contain a `self` argument but don't use it"
 +}
 +
 +pub struct UnusedSelf {
 +    avoid_breaking_exported_api: bool,
 +}
 +
 +impl_lint_pass!(UnusedSelf => [UNUSED_SELF]);
 +
 +impl UnusedSelf {
 +    pub fn new(avoid_breaking_exported_api: bool) -> Self {
 +        Self {
 +            avoid_breaking_exported_api,
 +        }
 +    }
 +}
 +
 +impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
 +    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &ImplItem<'_>) {
 +        if impl_item.span.from_expansion() {
 +            return;
 +        }
 +        let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
 +        let parent_item = cx.tcx.hir().expect_item(parent);
 +        let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
++        let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
++            clippy_utils::visitors::for_each_expr(body.value, |e| {
++                if let Some(macro_call) = root_macro_call_first_node(cx, e) {
++                    if cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
++                        ControlFlow::Break(())
++                    } else {
++                        ControlFlow::Continue(())
++                    }
++                } else {
++                    ControlFlow::Continue(())
++                }
++            })
++            .is_some()
++        };
 +        if_chain! {
 +            if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
 +            if assoc_item.fn_has_self_parameter;
 +            if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
 +            if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api;
 +            let body = cx.tcx.hir().body(*body_id);
 +            if let [self_param, ..] = body.params;
 +            if !is_local_used(cx, body, self_param.pat.hir_id);
++            if !contains_todo(cx, body);
 +            then {
 +                span_lint_and_help(
 +                    cx,
 +                    UNUSED_SELF,
 +                    self_param.span,
 +                    "unused `self` argument",
 +                    None,
++                    "consider refactoring to an associated function",
 +                );
 +            }
 +        }
 +    }
 +}
index c86f24cbd3780d5300ad1b4d278668e125d8ddf9,0000000000000000000000000000000000000000..c4d8c28f0606184bfee6ffd13299833935175681
mode 100644,000000..100644
--- /dev/null
@@@ -1,1142 -1,0 +1,1142 @@@
-     match map.find_parent((hir_id)) {
 +//! This lint is used to collect metadata about clippy lints. This metadata is exported as a json
 +//! file and then used to generate the [clippy lint list](https://rust-lang.github.io/rust-clippy/master/index.html)
 +//!
 +//! This module and therefore the entire lint is guarded by a feature flag called `internal`
 +//!
 +//! The module transforms all lint names to ascii lowercase to ensure that we don't have mismatches
 +//! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such
 +//! a simple mistake)
 +
 +use crate::renamed_lints::RENAMED_LINTS;
 +use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
 +
 +use clippy_utils::diagnostics::span_lint;
 +use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
 +use clippy_utils::{last_path_segment, match_def_path, match_function_call, match_path, paths};
 +use if_chain::if_chain;
 +use rustc_ast as ast;
 +use rustc_data_structures::fx::FxHashMap;
 +use rustc_hir::{
 +    self as hir, def::DefKind, intravisit, intravisit::Visitor, Closure, ExprKind, Item, ItemKind, Mutability, QPath,
 +};
 +use rustc_lint::{CheckLintNameResult, LateContext, LateLintPass, LintContext, LintId};
 +use rustc_middle::hir::nested_filter;
 +use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::symbol::Ident;
 +use rustc_span::{sym, Loc, Span, Symbol};
 +use serde::{ser::SerializeStruct, Serialize, Serializer};
 +use std::collections::BinaryHeap;
 +use std::fmt;
 +use std::fmt::Write as _;
 +use std::fs::{self, OpenOptions};
 +use std::io::prelude::*;
 +use std::path::Path;
 +use std::path::PathBuf;
 +use std::process::Command;
 +
 +/// This is the output file of the lint collector.
 +const OUTPUT_FILE: &str = "../util/gh-pages/lints.json";
 +/// These lints are excluded from the export.
 +const BLACK_LISTED_LINTS: &[&str] = &["lint_author", "dump_hir", "internal_metadata_collector"];
 +/// These groups will be ignored by the lint group matcher. This is useful for collections like
 +/// `clippy::all`
 +const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"];
 +/// Lints within this group will be excluded from the collection. These groups
 +/// have to be defined without the `clippy::` prefix.
 +const EXCLUDED_LINT_GROUPS: [&str; 1] = ["internal"];
 +/// Collected deprecated lint will be assigned to this group in the JSON output
 +const DEPRECATED_LINT_GROUP_STR: &str = "deprecated";
 +/// This is the lint level for deprecated lints that will be displayed in the lint list
 +const DEPRECATED_LINT_LEVEL: &str = "none";
 +/// This array holds Clippy's lint groups with their corresponding default lint level. The
 +/// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`.
 +const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[
 +    ("correctness", "deny"),
 +    ("suspicious", "warn"),
 +    ("restriction", "allow"),
 +    ("style", "warn"),
 +    ("pedantic", "allow"),
 +    ("complexity", "warn"),
 +    ("perf", "warn"),
 +    ("cargo", "allow"),
 +    ("nursery", "allow"),
 +];
 +/// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed
 +/// to only keep the actual lint group in the output.
 +const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::";
 +const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
 +    &["clippy_utils", "diagnostics", "span_lint"],
 +    &["clippy_utils", "diagnostics", "span_lint_and_help"],
 +    &["clippy_utils", "diagnostics", "span_lint_and_note"],
 +    &["clippy_utils", "diagnostics", "span_lint_hir"],
 +    &["clippy_utils", "diagnostics", "span_lint_and_sugg"],
 +    &["clippy_utils", "diagnostics", "span_lint_and_then"],
 +    &["clippy_utils", "diagnostics", "span_lint_hir_and_then"],
 +];
 +const SUGGESTION_DIAGNOSTIC_BUILDER_METHODS: [(&str, bool); 9] = [
 +    ("span_suggestion", false),
 +    ("span_suggestion_short", false),
 +    ("span_suggestion_verbose", false),
 +    ("span_suggestion_hidden", false),
 +    ("tool_only_span_suggestion", false),
 +    ("multipart_suggestion", true),
 +    ("multipart_suggestions", true),
 +    ("tool_only_multipart_suggestion", true),
 +    ("span_suggestions", true),
 +];
 +const SUGGESTION_FUNCTIONS: [&[&str]; 2] = [
 +    &["clippy_utils", "diagnostics", "multispan_sugg"],
 +    &["clippy_utils", "diagnostics", "multispan_sugg_with_applicability"],
 +];
 +const DEPRECATED_LINT_TYPE: [&str; 3] = ["clippy_lints", "deprecated_lints", "ClippyDeprecatedLint"];
 +
 +/// The index of the applicability name of `paths::APPLICABILITY_VALUES`
 +const APPLICABILITY_NAME_INDEX: usize = 2;
 +/// This applicability will be set for unresolved applicability values.
 +const APPLICABILITY_UNRESOLVED_STR: &str = "Unresolved";
 +/// The version that will be displayed if none has been defined
 +const VERSION_DEFAULT_STR: &str = "Unknown";
 +
 +declare_clippy_lint! {
 +    /// ### What it does
 +    /// Collects metadata about clippy lints for the website.
 +    ///
 +    /// This lint will be used to report problems of syntax parsing. You should hopefully never
 +    /// see this but never say never I guess ^^
 +    ///
 +    /// ### Why is this bad?
 +    /// This is not a bad thing but definitely a hacky way to do it. See
 +    /// issue [#4310](https://github.com/rust-lang/rust-clippy/issues/4310) for a discussion
 +    /// about the implementation.
 +    ///
 +    /// ### Known problems
 +    /// Hopefully none. It would be pretty uncool to have a problem here :)
 +    ///
 +    /// ### Example output
 +    /// ```json,ignore
 +    /// {
 +    ///     "id": "internal_metadata_collector",
 +    ///     "id_span": {
 +    ///         "path": "clippy_lints/src/utils/internal_lints/metadata_collector.rs",
 +    ///         "line": 1
 +    ///     },
 +    ///     "group": "clippy::internal",
 +    ///     "docs": " ### What it does\nCollects metadata about clippy lints for the website. [...] "
 +    /// }
 +    /// ```
 +    #[clippy::version = "1.56.0"]
 +    pub INTERNAL_METADATA_COLLECTOR,
 +    internal_warn,
 +    "A busy bee collection metadata about lints"
 +}
 +
 +impl_lint_pass!(MetadataCollector => [INTERNAL_METADATA_COLLECTOR]);
 +
 +#[allow(clippy::module_name_repetitions)]
 +#[derive(Debug, Clone)]
 +pub struct MetadataCollector {
 +    /// All collected lints
 +    ///
 +    /// We use a Heap here to have the lints added in alphabetic order in the export
 +    lints: BinaryHeap<LintMetadata>,
 +    applicability_info: FxHashMap<String, ApplicabilityInfo>,
 +    config: Vec<ClippyConfiguration>,
 +    clippy_project_root: PathBuf,
 +}
 +
 +impl MetadataCollector {
 +    pub fn new() -> Self {
 +        Self {
 +            lints: BinaryHeap::<LintMetadata>::default(),
 +            applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(),
 +            config: collect_configs(),
 +            clippy_project_root: std::env::current_dir()
 +                .expect("failed to get current dir")
 +                .ancestors()
 +                .nth(1)
 +                .expect("failed to get project root")
 +                .to_path_buf(),
 +        }
 +    }
 +
 +    fn get_lint_configs(&self, lint_name: &str) -> Option<String> {
 +        self.config
 +            .iter()
 +            .filter(|config| config.lints.iter().any(|lint| lint == lint_name))
 +            .map(ToString::to_string)
 +            .reduce(|acc, x| acc + &x)
 +            .map(|configurations| {
 +                format!(
 +                    r#"
 +### Configuration
 +This lint has the following configuration variables:
 +
 +{configurations}
 +"#
 +                )
 +            })
 +    }
 +}
 +
 +impl Drop for MetadataCollector {
 +    /// You might ask: How hacky is this?
 +    /// My answer:     YES
 +    fn drop(&mut self) {
 +        // The metadata collector gets dropped twice, this makes sure that we only write
 +        // when the list is full
 +        if self.lints.is_empty() {
 +            return;
 +        }
 +
 +        let mut applicability_info = std::mem::take(&mut self.applicability_info);
 +
 +        // Mapping the final data
 +        let mut lints = std::mem::take(&mut self.lints).into_sorted_vec();
 +        for x in &mut lints {
 +            x.applicability = Some(applicability_info.remove(&x.id).unwrap_or_default());
 +            replace_produces(&x.id, &mut x.docs, &self.clippy_project_root);
 +        }
 +
 +        collect_renames(&mut lints);
 +
 +        // Outputting
 +        if Path::new(OUTPUT_FILE).exists() {
 +            fs::remove_file(OUTPUT_FILE).unwrap();
 +        }
 +        let mut file = OpenOptions::new().write(true).create(true).open(OUTPUT_FILE).unwrap();
 +        writeln!(file, "{}", serde_json::to_string_pretty(&lints).unwrap()).unwrap();
 +    }
 +}
 +
 +#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)]
 +struct LintMetadata {
 +    id: String,
 +    id_span: SerializableSpan,
 +    group: String,
 +    level: String,
 +    docs: String,
 +    version: String,
 +    /// This field is only used in the output and will only be
 +    /// mapped shortly before the actual output.
 +    applicability: Option<ApplicabilityInfo>,
 +}
 +
 +impl LintMetadata {
 +    fn new(
 +        id: String,
 +        id_span: SerializableSpan,
 +        group: String,
 +        level: &'static str,
 +        version: String,
 +        docs: String,
 +    ) -> Self {
 +        Self {
 +            id,
 +            id_span,
 +            group,
 +            level: level.to_string(),
 +            version,
 +            docs,
 +            applicability: None,
 +        }
 +    }
 +}
 +
 +fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Path) {
 +    let mut doc_lines = docs.lines().map(ToString::to_string).collect::<Vec<_>>();
 +    let mut lines = doc_lines.iter_mut();
 +
 +    'outer: loop {
 +        // Find the start of the example
 +
 +        // ```rust
 +        loop {
 +            match lines.next() {
 +                Some(line) if line.trim_start().starts_with("```rust") => {
 +                    if line.contains("ignore") || line.contains("no_run") {
 +                        // A {{produces}} marker may have been put on a ignored code block by mistake,
 +                        // just seek to the end of the code block and continue checking.
 +                        if lines.any(|line| line.trim_start().starts_with("```")) {
 +                            continue;
 +                        }
 +
 +                        panic!("lint `{lint_name}` has an unterminated code block")
 +                    }
 +
 +                    break;
 +                },
 +                Some(line) if line.trim_start() == "{{produces}}" => {
 +                    panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block")
 +                },
 +                Some(line) => {
 +                    let line = line.trim();
 +                    // These are the two most common markers of the corrections section
 +                    if line.eq_ignore_ascii_case("Use instead:") || line.eq_ignore_ascii_case("Could be written as:") {
 +                        break 'outer;
 +                    }
 +                },
 +                None => break 'outer,
 +            }
 +        }
 +
 +        // Collect the example
 +        let mut example = Vec::new();
 +        loop {
 +            match lines.next() {
 +                Some(line) if line.trim_start() == "```" => break,
 +                Some(line) => example.push(line),
 +                None => panic!("lint `{lint_name}` has an unterminated code block"),
 +            }
 +        }
 +
 +        // Find the {{produces}} and attempt to generate the output
 +        loop {
 +            match lines.next() {
 +                Some(line) if line.is_empty() => {},
 +                Some(line) if line.trim() == "{{produces}}" => {
 +                    let output = get_lint_output(lint_name, &example, clippy_project_root);
 +                    line.replace_range(
 +                        ..,
 +                        &format!(
 +                            "<details>\
 +                            <summary>Produces</summary>\n\
 +                            \n\
 +                            ```text\n\
 +                            {output}\n\
 +                            ```\n\
 +                        </details>"
 +                        ),
 +                    );
 +
 +                    break;
 +                },
 +                // No {{produces}}, we can move on to the next example
 +                Some(_) => break,
 +                None => break 'outer,
 +            }
 +        }
 +    }
 +
 +    *docs = cleanup_docs(&doc_lines);
 +}
 +
 +fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root: &Path) -> String {
 +    let dir = tempfile::tempdir().unwrap_or_else(|e| panic!("failed to create temp dir: {e}"));
 +    let file = dir.path().join("lint_example.rs");
 +
 +    let mut source = String::new();
 +    let unhidden = example
 +        .iter()
 +        .map(|line| line.trim_start().strip_prefix("# ").unwrap_or(line));
 +
 +    // Get any attributes
 +    let mut lines = unhidden.peekable();
 +    while let Some(line) = lines.peek() {
 +        if line.starts_with("#!") {
 +            source.push_str(line);
 +            source.push('\n');
 +            lines.next();
 +        } else {
 +            break;
 +        }
 +    }
 +
 +    let needs_main = !example.iter().any(|line| line.contains("fn main"));
 +    if needs_main {
 +        source.push_str("fn main() {\n");
 +    }
 +
 +    for line in lines {
 +        source.push_str(line);
 +        source.push('\n');
 +    }
 +
 +    if needs_main {
 +        source.push_str("}\n");
 +    }
 +
 +    if let Err(e) = fs::write(&file, &source) {
 +        panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy());
 +    }
 +
 +    let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}");
 +
 +    let mut cmd = Command::new("cargo");
 +
 +    cmd.current_dir(clippy_project_root)
 +        .env("CARGO_INCREMENTAL", "0")
 +        .env("CLIPPY_ARGS", "")
 +        .env("CLIPPY_DISABLE_DOCS_LINKS", "1")
 +        // We need to disable this to enable all lints
 +        .env("ENABLE_METADATA_COLLECTION", "0")
 +        .args(["run", "--bin", "clippy-driver"])
 +        .args(["--target-dir", "./clippy_lints/target"])
 +        .args(["--", "--error-format=json"])
 +        .args(["--edition", "2021"])
 +        .arg("-Cdebuginfo=0")
 +        .args(["-A", "clippy::all"])
 +        .args(["-W", &prefixed_name])
 +        .args(["-L", "./target/debug"])
 +        .args(["-Z", "no-codegen"]);
 +
 +    let output = cmd
 +        .arg(file.as_path())
 +        .output()
 +        .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
 +
 +    let tmp_file_path = file.to_string_lossy();
 +    let stderr = std::str::from_utf8(&output.stderr).unwrap();
 +    let msgs = stderr
 +        .lines()
 +        .filter(|line| line.starts_with('{'))
 +        .map(|line| serde_json::from_str(line).unwrap())
 +        .collect::<Vec<serde_json::Value>>();
 +
 +    let mut rendered = String::new();
 +    let iter = msgs
 +        .iter()
 +        .filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s == &prefixed_name));
 +
 +    for message in iter {
 +        let rendered_part = message["rendered"].as_str().expect("rendered field should exist");
 +        rendered.push_str(rendered_part);
 +    }
 +
 +    if rendered.is_empty() {
 +        let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
 +        let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
 +        panic!(
 +            "did not find lint `{lint_name}` in output of example, got:\n{}\n{}",
 +            non_json.join("\n"),
 +            rendered.join("\n")
 +        );
 +    }
 +
 +    // The reader doesn't need to see `/tmp/.tmpfiy2Qd/lint_example.rs` :)
 +    rendered.trim_end().replace(&*tmp_file_path, "lint_example.rs")
 +}
 +
 +#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)]
 +struct SerializableSpan {
 +    path: String,
 +    line: usize,
 +}
 +
 +impl fmt::Display for SerializableSpan {
 +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 +        write!(f, "{}:{}", self.path.rsplit('/').next().unwrap_or_default(), self.line)
 +    }
 +}
 +
 +impl SerializableSpan {
 +    fn from_item(cx: &LateContext<'_>, item: &Item<'_>) -> Self {
 +        Self::from_span(cx, item.ident.span)
 +    }
 +
 +    fn from_span(cx: &LateContext<'_>, span: Span) -> Self {
 +        let loc: Loc = cx.sess().source_map().lookup_char_pos(span.lo());
 +
 +        Self {
 +            path: format!("{}", loc.file.name.prefer_remapped()),
 +            line: loc.line,
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
 +struct ApplicabilityInfo {
 +    /// Indicates if any of the lint emissions uses multiple spans. This is related to
 +    /// [rustfix#141](https://github.com/rust-lang/rustfix/issues/141) as such suggestions can
 +    /// currently not be applied automatically.
 +    is_multi_part_suggestion: bool,
 +    applicability: Option<usize>,
 +}
 +
 +impl Serialize for ApplicabilityInfo {
 +    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 +    where
 +        S: Serializer,
 +    {
 +        let mut s = serializer.serialize_struct("ApplicabilityInfo", 2)?;
 +        s.serialize_field("is_multi_part_suggestion", &self.is_multi_part_suggestion)?;
 +        if let Some(index) = self.applicability {
 +            s.serialize_field(
 +                "applicability",
 +                &paths::APPLICABILITY_VALUES[index][APPLICABILITY_NAME_INDEX],
 +            )?;
 +        } else {
 +            s.serialize_field("applicability", APPLICABILITY_UNRESOLVED_STR)?;
 +        }
 +        s.end()
 +    }
 +}
 +
 +// ==================================================================
 +// Configuration
 +// ==================================================================
 +#[derive(Debug, Clone, Default)]
 +pub struct ClippyConfiguration {
 +    name: String,
 +    config_type: &'static str,
 +    default: String,
 +    lints: Vec<String>,
 +    doc: String,
 +    #[allow(dead_code)]
 +    deprecation_reason: Option<&'static str>,
 +}
 +
 +impl ClippyConfiguration {
 +    pub fn new(
 +        name: &'static str,
 +        config_type: &'static str,
 +        default: String,
 +        doc_comment: &'static str,
 +        deprecation_reason: Option<&'static str>,
 +    ) -> Self {
 +        let (lints, doc) = parse_config_field_doc(doc_comment)
 +            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
 +
 +        Self {
 +            name: to_kebab(name),
 +            lints,
 +            doc,
 +            config_type,
 +            default,
 +            deprecation_reason,
 +        }
 +    }
 +}
 +
 +fn collect_configs() -> Vec<ClippyConfiguration> {
 +    crate::utils::conf::metadata::get_configuration_metadata()
 +}
 +
 +/// This parses the field documentation of the config struct.
 +///
 +/// ```rust, ignore
 +/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
 +/// ```
 +///
 +/// Would yield:
 +/// ```rust, ignore
 +/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
 +/// ```
 +fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
 +    const DOC_START: &str = " Lint: ";
 +    if_chain! {
 +        if doc_comment.starts_with(DOC_START);
 +        if let Some(split_pos) = doc_comment.find('.');
 +        then {
 +            let mut doc_comment = doc_comment.to_string();
 +            let mut documentation = doc_comment.split_off(split_pos);
 +
 +            // Extract lints
 +            doc_comment.make_ascii_lowercase();
 +            let lints: Vec<String> = doc_comment
 +                .split_off(DOC_START.len())
 +                .split(", ")
 +                .map(str::to_string)
 +                .collect();
 +
 +            // Format documentation correctly
 +            // split off leading `.` from lint name list and indent for correct formatting
 +            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
 +
 +            Some((lints, documentation))
 +        } else {
 +            None
 +        }
 +    }
 +}
 +
 +/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
 +fn to_kebab(config_name: &str) -> String {
 +    config_name.replace('_', "-")
 +}
 +
 +impl fmt::Display for ClippyConfiguration {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
 +        writeln!(
 +            f,
 +            "* `{}`: `{}`(defaults to `{}`): {}",
 +            self.name, self.config_type, self.default, self.doc
 +        )
 +    }
 +}
 +
 +// ==================================================================
 +// Lint pass
 +// ==================================================================
 +impl<'hir> LateLintPass<'hir> for MetadataCollector {
 +    /// Collecting lint declarations like:
 +    /// ```rust, ignore
 +    /// declare_clippy_lint! {
 +    ///     /// ### What it does
 +    ///     /// Something IDK.
 +    ///     pub SOME_LINT,
 +    ///     internal,
 +    ///     "Who am I?"
 +    /// }
 +    /// ```
 +    fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) {
 +        if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
 +            // Normal lint
 +            if_chain! {
 +                // item validation
 +                if is_lint_ref_type(cx, ty);
 +                // disallow check
 +                let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
 +                if !BLACK_LISTED_LINTS.contains(&lint_name.as_str());
 +                // metadata extraction
 +                if let Some((group, level)) = get_lint_group_and_level_or_lint(cx, &lint_name, item);
 +                if let Some(mut raw_docs) = extract_attr_docs_or_lint(cx, item);
 +                then {
 +                    if let Some(configuration_section) = self.get_lint_configs(&lint_name) {
 +                        raw_docs.push_str(&configuration_section);
 +                    }
 +                    let version = get_lint_version(cx, item);
 +
 +                    self.lints.push(LintMetadata::new(
 +                        lint_name,
 +                        SerializableSpan::from_item(cx, item),
 +                        group,
 +                        level,
 +                        version,
 +                        raw_docs,
 +                    ));
 +                }
 +            }
 +
 +            if_chain! {
 +                if is_deprecated_lint(cx, ty);
 +                // disallow check
 +                let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
 +                if !BLACK_LISTED_LINTS.contains(&lint_name.as_str());
 +                // Metadata the little we can get from a deprecated lint
 +                if let Some(raw_docs) = extract_attr_docs_or_lint(cx, item);
 +                then {
 +                    let version = get_lint_version(cx, item);
 +
 +                    self.lints.push(LintMetadata::new(
 +                        lint_name,
 +                        SerializableSpan::from_item(cx, item),
 +                        DEPRECATED_LINT_GROUP_STR.to_string(),
 +                        DEPRECATED_LINT_LEVEL,
 +                        version,
 +                        raw_docs,
 +                    ));
 +                }
 +            }
 +        }
 +    }
 +
 +    /// Collecting constant applicability from the actual lint emissions
 +    ///
 +    /// Example:
 +    /// ```rust, ignore
 +    /// span_lint_and_sugg(
 +    ///     cx,
 +    ///     SOME_LINT,
 +    ///     item.span,
 +    ///     "Le lint message",
 +    ///     "Here comes help:",
 +    ///     "#![allow(clippy::all)]",
 +    ///     Applicability::MachineApplicable, // <-- Extracts this constant value
 +    /// );
 +    /// ```
 +    fn check_expr(&mut self, cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) {
 +        if let Some(args) = match_lint_emission(cx, expr) {
 +            let emission_info = extract_emission_info(cx, args);
 +            if emission_info.is_empty() {
 +                // See:
 +                // - src/misc.rs:734:9
 +                // - src/methods/mod.rs:3545:13
 +                // - src/methods/mod.rs:3496:13
 +                // We are basically unable to resolve the lint name itself.
 +                return;
 +            }
 +
 +            for (lint_name, applicability, is_multi_part) in emission_info {
 +                let app_info = self.applicability_info.entry(lint_name).or_default();
 +                app_info.applicability = applicability;
 +                app_info.is_multi_part_suggestion = is_multi_part;
 +            }
 +        }
 +    }
 +}
 +
 +// ==================================================================
 +// Lint definition extraction
 +// ==================================================================
 +fn sym_to_string(sym: Symbol) -> String {
 +    sym.as_str().to_string()
 +}
 +
 +fn extract_attr_docs_or_lint(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
 +    extract_attr_docs(cx, item).or_else(|| {
 +        lint_collection_error_item(cx, item, "could not collect the lint documentation");
 +        None
 +    })
 +}
 +
 +/// This function collects all documentation that has been added to an item using
 +/// `#[doc = r""]` attributes. Several attributes are aggravated using line breaks
 +///
 +/// ```ignore
 +/// #[doc = r"Hello world!"]
 +/// #[doc = r"=^.^="]
 +/// struct SomeItem {}
 +/// ```
 +///
 +/// Would result in `Hello world!\n=^.^=\n`
 +fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
 +    let attrs = cx.tcx.hir().attrs(item.hir_id());
 +    let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
 +
 +    if let Some(line) = lines.next() {
 +        let raw_docs = lines.fold(String::from(line.as_str()) + "\n", |s, line| s + line.as_str() + "\n");
 +        return Some(raw_docs);
 +    }
 +
 +    None
 +}
 +
 +/// This function may modify the doc comment to ensure that the string can be displayed using a
 +/// markdown viewer in Clippy's lint list. The following modifications could be applied:
 +/// * Removal of leading space after a new line. (Important to display tables)
 +/// * Ensures that code blocks only contain language information
 +fn cleanup_docs(docs_collection: &Vec<String>) -> String {
 +    let mut in_code_block = false;
 +    let mut is_code_block_rust = false;
 +
 +    let mut docs = String::new();
 +    for line in docs_collection {
 +        // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
 +        if is_code_block_rust && line.trim_start().starts_with("# ") {
 +            continue;
 +        }
 +
 +        // The line should be represented in the lint list, even if it's just an empty line
 +        docs.push('\n');
 +        if let Some(info) = line.trim_start().strip_prefix("```") {
 +            in_code_block = !in_code_block;
 +            is_code_block_rust = false;
 +            if in_code_block {
 +                let lang = info
 +                    .trim()
 +                    .split(',')
 +                    // remove rustdoc directives
 +                    .find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic"))
 +                    // if no language is present, fill in "rust"
 +                    .unwrap_or("rust");
 +                docs.push_str("```");
 +                docs.push_str(lang);
 +
 +                is_code_block_rust = lang == "rust";
 +                continue;
 +            }
 +        }
 +        // This removes the leading space that the macro translation introduces
 +        if let Some(stripped_doc) = line.strip_prefix(' ') {
 +            docs.push_str(stripped_doc);
 +        } else if !line.is_empty() {
 +            docs.push_str(line);
 +        }
 +    }
 +
 +    docs
 +}
 +
 +fn get_lint_version(cx: &LateContext<'_>, item: &Item<'_>) -> String {
 +    extract_clippy_version_value(cx, item).map_or_else(
 +        || VERSION_DEFAULT_STR.to_string(),
 +        |version| version.as_str().to_string(),
 +    )
 +}
 +
 +fn get_lint_group_and_level_or_lint(
 +    cx: &LateContext<'_>,
 +    lint_name: &str,
 +    item: &Item<'_>,
 +) -> Option<(String, &'static str)> {
 +    let result = cx.lint_store.check_lint_name(
 +        lint_name,
 +        Some(sym::clippy),
 +        &std::iter::once(Ident::with_dummy_span(sym::clippy)).collect(),
 +    );
 +    if let CheckLintNameResult::Tool(Ok(lint_lst)) = result {
 +        if let Some(group) = get_lint_group(cx, lint_lst[0]) {
 +            if EXCLUDED_LINT_GROUPS.contains(&group.as_str()) {
 +                return None;
 +            }
 +
 +            if let Some(level) = get_lint_level_from_group(&group) {
 +                Some((group, level))
 +            } else {
 +                lint_collection_error_item(
 +                    cx,
 +                    item,
 +                    &format!("Unable to determine lint level for found group `{group}`"),
 +                );
 +                None
 +            }
 +        } else {
 +            lint_collection_error_item(cx, item, "Unable to determine lint group");
 +            None
 +        }
 +    } else {
 +        lint_collection_error_item(cx, item, "Unable to find lint in lint_store");
 +        None
 +    }
 +}
 +
 +fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> {
 +    for (group_name, lints, _) in cx.lint_store.get_lint_groups() {
 +        if IGNORED_LINT_GROUPS.contains(&group_name) {
 +            continue;
 +        }
 +
 +        if lints.iter().any(|group_lint| *group_lint == lint_id) {
 +            let group = group_name.strip_prefix(CLIPPY_LINT_GROUP_PREFIX).unwrap_or(group_name);
 +            return Some((*group).to_string());
 +        }
 +    }
 +
 +    None
 +}
 +
 +fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> {
 +    DEFAULT_LINT_LEVELS
 +        .iter()
 +        .find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level))
 +}
 +
 +pub(super) fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
 +    if let hir::TyKind::Path(ref path) = ty.kind {
 +        if let hir::def::Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, ty.hir_id) {
 +            return match_def_path(cx, def_id, &DEPRECATED_LINT_TYPE);
 +        }
 +    }
 +
 +    false
 +}
 +
 +fn collect_renames(lints: &mut Vec<LintMetadata>) {
 +    for lint in lints {
 +        let mut collected = String::new();
 +        let mut names = vec![lint.id.clone()];
 +
 +        loop {
 +            if let Some(lint_name) = names.pop() {
 +                for (k, v) in RENAMED_LINTS {
 +                    if_chain! {
 +                        if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
 +                        if name == lint_name;
 +                        if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
 +                        then {
 +                            writeln!(collected, "* `{past_name}`").unwrap();
 +                            names.push(past_name.to_string());
 +                        }
 +                    }
 +                }
 +
 +                continue;
 +            }
 +
 +            break;
 +        }
 +
 +        if !collected.is_empty() {
 +            write!(
 +                &mut lint.docs,
 +                r#"
 +### Past names
 +
 +{collected}
 +"#
 +            )
 +            .unwrap();
 +        }
 +    }
 +}
 +
 +// ==================================================================
 +// Lint emission
 +// ==================================================================
 +fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &str) {
 +    span_lint(
 +        cx,
 +        INTERNAL_METADATA_COLLECTOR,
 +        item.ident.span,
 +        &format!("metadata collection error for `{}`: {message}", item.ident.name),
 +    );
 +}
 +
 +// ==================================================================
 +// Applicability
 +// ==================================================================
 +/// This function checks if a given expression is equal to a simple lint emission function call.
 +/// It will return the function arguments if the emission matched any function.
 +fn match_lint_emission<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) -> Option<&'hir [hir::Expr<'hir>]> {
 +    LINT_EMISSION_FUNCTIONS
 +        .iter()
 +        .find_map(|emission_fn| match_function_call(cx, expr, emission_fn))
 +}
 +
 +fn take_higher_applicability(a: Option<usize>, b: Option<usize>) -> Option<usize> {
 +    a.map_or(b, |a| a.max(b.unwrap_or_default()).into())
 +}
 +
 +fn extract_emission_info<'hir>(
 +    cx: &LateContext<'hir>,
 +    args: &'hir [hir::Expr<'hir>],
 +) -> Vec<(String, Option<usize>, bool)> {
 +    let mut lints = Vec::new();
 +    let mut applicability = None;
 +    let mut multi_part = false;
 +
 +    for arg in args {
 +        let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg));
 +
 +        if match_type(cx, arg_ty, &paths::LINT) {
 +            // If we found the lint arg, extract the lint name
 +            let mut resolved_lints = resolve_lints(cx, arg);
 +            lints.append(&mut resolved_lints);
 +        } else if match_type(cx, arg_ty, &paths::APPLICABILITY) {
 +            applicability = resolve_applicability(cx, arg);
 +        } else if arg_ty.is_closure() {
 +            multi_part |= check_is_multi_part(cx, arg);
 +            applicability = applicability.or_else(|| resolve_applicability(cx, arg));
 +        }
 +    }
 +
 +    lints
 +        .into_iter()
 +        .map(|lint_name| (lint_name, applicability, multi_part))
 +        .collect()
 +}
 +
 +/// Resolves the possible lints that this expression could reference
 +fn resolve_lints<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Vec<String> {
 +    let mut resolver = LintResolver::new(cx);
 +    resolver.visit_expr(expr);
 +    resolver.lints
 +}
 +
 +/// This function tries to resolve the linked applicability to the given expression.
 +fn resolve_applicability<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<usize> {
 +    let mut resolver = ApplicabilityResolver::new(cx);
 +    resolver.visit_expr(expr);
 +    resolver.complete()
 +}
 +
 +fn check_is_multi_part<'hir>(cx: &LateContext<'hir>, closure_expr: &'hir hir::Expr<'hir>) -> bool {
 +    if let ExprKind::Closure(&Closure { body, .. }) = closure_expr.kind {
 +        let mut scanner = IsMultiSpanScanner::new(cx);
 +        intravisit::walk_body(&mut scanner, cx.tcx.hir().body(body));
 +        return scanner.is_multi_part();
 +    } else if let Some(local) = get_parent_local(cx, closure_expr) {
 +        if let Some(local_init) = local.init {
 +            return check_is_multi_part(cx, local_init);
 +        }
 +    }
 +
 +    false
 +}
 +
 +struct LintResolver<'a, 'hir> {
 +    cx: &'a LateContext<'hir>,
 +    lints: Vec<String>,
 +}
 +
 +impl<'a, 'hir> LintResolver<'a, 'hir> {
 +    fn new(cx: &'a LateContext<'hir>) -> Self {
 +        Self {
 +            cx,
 +            lints: Vec::<String>::default(),
 +        }
 +    }
 +}
 +
 +impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
 +    type NestedFilter = nested_filter::All;
 +
 +    fn nested_visit_map(&mut self) -> Self::Map {
 +        self.cx.tcx.hir()
 +    }
 +
 +    fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
 +        if_chain! {
 +            if let ExprKind::Path(qpath) = &expr.kind;
 +            if let QPath::Resolved(_, path) = qpath;
 +
 +            let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
 +            if match_type(self.cx, expr_ty, &paths::LINT);
 +            then {
 +                if let hir::def::Res::Def(DefKind::Static(..), _) = path.res {
 +                    let lint_name = last_path_segment(qpath).ident.name;
 +                    self.lints.push(sym_to_string(lint_name).to_ascii_lowercase());
 +                } else if let Some(local) = get_parent_local(self.cx, expr) {
 +                    if let Some(local_init) = local.init {
 +                        intravisit::walk_expr(self, local_init);
 +                    }
 +                }
 +            }
 +        }
 +
 +        intravisit::walk_expr(self, expr);
 +    }
 +}
 +
 +/// This visitor finds the highest applicability value in the visited expressions
 +struct ApplicabilityResolver<'a, 'hir> {
 +    cx: &'a LateContext<'hir>,
 +    /// This is the index of highest `Applicability` for `paths::APPLICABILITY_VALUES`
 +    applicability_index: Option<usize>,
 +}
 +
 +impl<'a, 'hir> ApplicabilityResolver<'a, 'hir> {
 +    fn new(cx: &'a LateContext<'hir>) -> Self {
 +        Self {
 +            cx,
 +            applicability_index: None,
 +        }
 +    }
 +
 +    fn add_new_index(&mut self, new_index: usize) {
 +        self.applicability_index = take_higher_applicability(self.applicability_index, Some(new_index));
 +    }
 +
 +    fn complete(self) -> Option<usize> {
 +        self.applicability_index
 +    }
 +}
 +
 +impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
 +    type NestedFilter = nested_filter::All;
 +
 +    fn nested_visit_map(&mut self) -> Self::Map {
 +        self.cx.tcx.hir()
 +    }
 +
 +    fn visit_path(&mut self, path: &hir::Path<'hir>, _id: hir::HirId) {
 +        for (index, enum_value) in paths::APPLICABILITY_VALUES.iter().enumerate() {
 +            if match_path(path, enum_value) {
 +                self.add_new_index(index);
 +                return;
 +            }
 +        }
 +    }
 +
 +    fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
 +        let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
 +
 +        if_chain! {
 +            if match_type(self.cx, expr_ty, &paths::APPLICABILITY);
 +            if let Some(local) = get_parent_local(self.cx, expr);
 +            if let Some(local_init) = local.init;
 +            then {
 +                intravisit::walk_expr(self, local_init);
 +            }
 +        };
 +
 +        intravisit::walk_expr(self, expr);
 +    }
 +}
 +
 +/// This returns the parent local node if the expression is a reference one
 +fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::Local<'hir>> {
 +    if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind {
 +        if let hir::def::Res::Local(local_hir) = path.res {
 +            return get_parent_local_hir_id(cx, local_hir);
 +        }
 +    }
 +
 +    None
 +}
 +
 +fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
 +    let map = cx.tcx.hir();
 +
++    match map.find_parent(hir_id) {
 +        Some(hir::Node::Local(local)) => Some(local),
 +        Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id),
 +        _ => None,
 +    }
 +}
 +
 +/// This visitor finds the highest applicability value in the visited expressions
 +struct IsMultiSpanScanner<'a, 'hir> {
 +    cx: &'a LateContext<'hir>,
 +    suggestion_count: usize,
 +}
 +
 +impl<'a, 'hir> IsMultiSpanScanner<'a, 'hir> {
 +    fn new(cx: &'a LateContext<'hir>) -> Self {
 +        Self {
 +            cx,
 +            suggestion_count: 0,
 +        }
 +    }
 +
 +    /// Add a new single expression suggestion to the counter
 +    fn add_single_span_suggestion(&mut self) {
 +        self.suggestion_count += 1;
 +    }
 +
 +    /// Signals that a suggestion with possible multiple spans was found
 +    fn add_multi_part_suggestion(&mut self) {
 +        self.suggestion_count += 2;
 +    }
 +
 +    /// Checks if the suggestions include multiple spans
 +    fn is_multi_part(&self) -> bool {
 +        self.suggestion_count > 1
 +    }
 +}
 +
 +impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
 +    type NestedFilter = nested_filter::All;
 +
 +    fn nested_visit_map(&mut self) -> Self::Map {
 +        self.cx.tcx.hir()
 +    }
 +
 +    fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
 +        // Early return if the lint is already multi span
 +        if self.is_multi_part() {
 +            return;
 +        }
 +
 +        match &expr.kind {
 +            ExprKind::Call(fn_expr, _args) => {
 +                let found_function = SUGGESTION_FUNCTIONS
 +                    .iter()
 +                    .any(|func_path| match_function_call(self.cx, fn_expr, func_path).is_some());
 +                if found_function {
 +                    // These functions are all multi part suggestions
 +                    self.add_single_span_suggestion();
 +                }
 +            },
 +            ExprKind::MethodCall(path, recv, _, _arg_span) => {
 +                let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv));
 +                if match_type(self.cx, self_ty, &paths::DIAGNOSTIC_BUILDER) {
 +                    let called_method = path.ident.name.as_str().to_string();
 +                    for (method_name, is_multi_part) in &SUGGESTION_DIAGNOSTIC_BUILDER_METHODS {
 +                        if *method_name == called_method {
 +                            if *is_multi_part {
 +                                self.add_multi_part_suggestion();
 +                            } else {
 +                                self.add_single_span_suggestion();
 +                            }
 +                            break;
 +                        }
 +                    }
 +                }
 +            },
 +            _ => {},
 +        }
 +
 +        intravisit::walk_expr(self, expr);
 +    }
 +}
index 8290fe9ecb4c64593098395ff34389aa30ec4c06,0000000000000000000000000000000000000000..7a4a9036dd3639ed82de815331ee68897ed37003
mode 100644,000000..100644
--- /dev/null
@@@ -1,2494 -1,0 +1,2523 @@@
- pub struct ContainsName {
 +#![feature(array_chunks)]
 +#![feature(box_patterns)]
 +#![feature(control_flow_enum)]
 +#![feature(let_chains)]
 +#![feature(lint_reasons)]
 +#![feature(never_type)]
 +#![feature(once_cell)]
 +#![feature(rustc_private)]
 +#![recursion_limit = "512"]
 +#![cfg_attr(feature = "deny-warnings", deny(warnings))]
 +#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
 +// warn on the same lints as `clippy_lints`
 +#![warn(trivial_casts, trivial_numeric_casts)]
 +// warn on lints, that are included in `rust-lang/rust`s bootstrap
 +#![warn(rust_2018_idioms, unused_lifetimes)]
 +// warn on rustc internal lints
 +#![warn(rustc::internal)]
 +
 +// FIXME: switch to something more ergonomic here, once available.
 +// (Currently there is no way to opt into sysroot crates without `extern crate`.)
 +extern crate rustc_ast;
 +extern crate rustc_ast_pretty;
 +extern crate rustc_attr;
 +extern crate rustc_data_structures;
++// The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate.
++#[allow(unused_extern_crates)]
++extern crate rustc_driver;
 +extern crate rustc_errors;
 +extern crate rustc_hir;
 +extern crate rustc_hir_typeck;
 +extern crate rustc_index;
 +extern crate rustc_infer;
 +extern crate rustc_lexer;
 +extern crate rustc_lint;
 +extern crate rustc_middle;
 +extern crate rustc_mir_dataflow;
 +extern crate rustc_parse_format;
 +extern crate rustc_session;
 +extern crate rustc_span;
 +extern crate rustc_target;
 +extern crate rustc_trait_selection;
 +
 +#[macro_use]
 +pub mod sym_helper;
 +
 +pub mod ast_utils;
 +pub mod attrs;
 +mod check_proc_macro;
 +pub mod comparisons;
 +pub mod consts;
 +pub mod diagnostics;
 +pub mod eager_or_lazy;
 +pub mod higher;
 +mod hir_utils;
 +pub mod macros;
 +pub mod mir;
 +pub mod msrvs;
 +pub mod numeric_literal;
 +pub mod paths;
 +pub mod ptr;
 +pub mod qualify_min_const_fn;
 +pub mod source;
 +pub mod str_utils;
 +pub mod sugg;
 +pub mod ty;
 +pub mod usage;
 +pub mod visitors;
 +
 +pub use self::attrs::*;
 +pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match};
 +pub use self::hir_utils::{
 +    both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
 +};
 +
 +use core::ops::ControlFlow;
 +use std::collections::hash_map::Entry;
 +use std::hash::BuildHasherDefault;
 +use std::sync::OnceLock;
 +use std::sync::{Mutex, MutexGuard};
 +
 +use if_chain::if_chain;
 +use rustc_ast::ast::{self, LitKind};
 +use rustc_ast::Attribute;
 +use rustc_data_structures::fx::FxHashMap;
 +use rustc_data_structures::unhash::UnhashMap;
 +use rustc_hir::def::{DefKind, Res};
 +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 +use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 +use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 +use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
 +use rustc_hir::{
 +    self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, Destination,
 +    Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local,
 +    MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind,
 +    TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
 +};
 +use rustc_lexer::{tokenize, TokenKind};
 +use rustc_lint::{LateContext, Level, Lint, LintContext};
 +use rustc_middle::hir::place::PlaceBase;
 +use rustc_middle::ty as rustc_ty;
 +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 +use rustc_middle::ty::binding::BindingMode;
 +use rustc_middle::ty::fast_reject::SimplifiedType::{
 +    ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
 +    PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
 +};
 +use rustc_middle::ty::{
 +    layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitable, UpvarCapture,
 +};
 +use rustc_middle::ty::{FloatTy, IntTy, UintTy};
 +use rustc_span::hygiene::{ExpnKind, MacroKind};
 +use rustc_span::source_map::SourceMap;
 +use rustc_span::sym;
 +use rustc_span::symbol::{kw, Ident, Symbol};
 +use rustc_span::Span;
 +use rustc_target::abi::Integer;
 +
 +use crate::consts::{constant, Constant};
 +use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
 +use crate::visitors::for_each_expr;
 +
++use rustc_middle::hir::nested_filter;
++
 +#[macro_export]
 +macro_rules! extract_msrv_attr {
 +    ($context:ident) => {
 +        fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
 +            let sess = rustc_lint::LintContext::sess(cx);
 +            self.msrv.enter_lint_attrs(sess, attrs);
 +        }
 +
 +        fn exit_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
 +            let sess = rustc_lint::LintContext::sess(cx);
 +            self.msrv.exit_lint_attrs(sess, attrs);
 +        }
 +    };
 +}
 +
 +/// If the given expression is a local binding, find the initializer expression.
 +/// If that initializer expression is another local binding, find its initializer again.
 +/// This process repeats as long as possible (but usually no more than once). Initializer
 +/// expressions with adjustments are ignored. If this is not desired, use [`find_binding_init`]
 +/// instead.
 +///
 +/// Examples:
 +/// ```
 +/// let abc = 1;
 +/// //        ^ output
 +/// let def = abc;
 +/// dbg!(def);
 +/// //   ^^^ input
 +///
 +/// // or...
 +/// let abc = 1;
 +/// let def = abc + 2;
 +/// //        ^^^^^^^ output
 +/// dbg!(def);
 +/// //   ^^^ input
 +/// ```
 +pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr<'b>) -> &'a Expr<'b> {
 +    while let Some(init) = path_to_local(expr)
 +        .and_then(|id| find_binding_init(cx, id))
 +        .filter(|init| cx.typeck_results().expr_adjustments(init).is_empty())
 +    {
 +        expr = init;
 +    }
 +    expr
 +}
 +
 +/// Finds the initializer expression for a local binding. Returns `None` if the binding is mutable.
 +/// By only considering immutable bindings, we guarantee that the returned expression represents the
 +/// value of the binding wherever it is referenced.
 +///
 +/// Example: For `let x = 1`, if the `HirId` of `x` is provided, the `Expr` `1` is returned.
 +/// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the
 +/// canonical binding `HirId`.
 +pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
 +    let hir = cx.tcx.hir();
 +    if_chain! {
 +        if let Some(Node::Pat(pat)) = hir.find(hir_id);
 +        if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..));
 +        let parent = hir.parent_id(hir_id);
 +        if let Some(Node::Local(local)) = hir.find(parent);
 +        then {
 +            return local.init;
 +        }
 +    }
 +    None
 +}
 +
 +/// Returns `true` if the given `NodeId` is inside a constant context
 +///
 +/// # Example
 +///
 +/// ```rust,ignore
 +/// if in_constant(cx, expr.hir_id) {
 +///     // Do something
 +/// }
 +/// ```
 +pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
 +    let parent_id = cx.tcx.hir().get_parent_item(id).def_id;
 +    match cx.tcx.hir().get_by_def_id(parent_id) {
 +        Node::Item(&Item {
 +            kind: ItemKind::Const(..) | ItemKind::Static(..) | ItemKind::Enum(..),
 +            ..
 +        })
 +        | Node::TraitItem(&TraitItem {
 +            kind: TraitItemKind::Const(..),
 +            ..
 +        })
 +        | Node::ImplItem(&ImplItem {
 +            kind: ImplItemKind::Const(..),
 +            ..
 +        })
 +        | Node::AnonConst(_) => true,
 +        Node::Item(&Item {
 +            kind: ItemKind::Fn(ref sig, ..),
 +            ..
 +        })
 +        | Node::ImplItem(&ImplItem {
 +            kind: ImplItemKind::Fn(ref sig, _),
 +            ..
 +        }) => sig.header.constness == Constness::Const,
 +        _ => false,
 +    }
 +}
 +
 +/// Checks if a `Res` refers to a constructor of a `LangItem`
 +/// For example, use this to check whether a function call or a pattern is `Some(..)`.
 +pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
 +    if let Res::Def(DefKind::Ctor(..), id) = res
 +        && let Some(lang_id) = cx.tcx.lang_items().get(lang_item)
 +        && let Some(id) = cx.tcx.opt_parent(id)
 +    {
 +        id == lang_id
 +    } else {
 +        false
 +    }
 +}
 +
 +pub fn is_res_diagnostic_ctor(cx: &LateContext<'_>, res: Res, diag_item: Symbol) -> bool {
 +    if let Res::Def(DefKind::Ctor(..), id) = res
 +        && let Some(id) = cx.tcx.opt_parent(id)
 +    {
 +        cx.tcx.is_diagnostic_item(diag_item, id)
 +    } else {
 +        false
 +    }
 +}
 +
 +/// Checks if a `QPath` resolves to a constructor of a diagnostic item.
 +pub fn is_diagnostic_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, diagnostic_item: Symbol) -> bool {
 +    if let QPath::Resolved(_, path) = qpath {
 +        if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
 +            return cx.tcx.is_diagnostic_item(diagnostic_item, cx.tcx.parent(ctor_id));
 +        }
 +    }
 +    false
 +}
 +
 +/// Checks if the `DefId` matches the given diagnostic item or it's constructor.
 +pub fn is_diagnostic_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: Symbol) -> bool {
 +    let did = match cx.tcx.def_kind(did) {
 +        DefKind::Ctor(..) => cx.tcx.parent(did),
 +        // Constructors for types in external crates seem to have `DefKind::Variant`
 +        DefKind::Variant => match cx.tcx.opt_parent(did) {
 +            Some(did) if matches!(cx.tcx.def_kind(did), DefKind::Variant) => did,
 +            _ => did,
 +        },
 +        _ => did,
 +    };
 +
 +    cx.tcx.is_diagnostic_item(item, did)
 +}
 +
 +/// Checks if the `DefId` matches the given `LangItem` or it's constructor.
 +pub fn is_lang_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: LangItem) -> bool {
 +    let did = match cx.tcx.def_kind(did) {
 +        DefKind::Ctor(..) => cx.tcx.parent(did),
 +        // Constructors for types in external crates seem to have `DefKind::Variant`
 +        DefKind::Variant => match cx.tcx.opt_parent(did) {
 +            Some(did) if matches!(cx.tcx.def_kind(did), DefKind::Variant) => did,
 +            _ => did,
 +        },
 +        _ => did,
 +    };
 +
 +    cx.tcx.lang_items().get(item) == Some(did)
 +}
 +
 +pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
 +    matches!(
 +        expr.kind,
 +        ExprKind::Block(
 +            Block {
 +                stmts: [],
 +                expr: None,
 +                ..
 +            },
 +            _
 +        ) | ExprKind::Tup([])
 +    )
 +}
 +
 +/// Checks if given pattern is a wildcard (`_`)
 +pub fn is_wild(pat: &Pat<'_>) -> bool {
 +    matches!(pat.kind, PatKind::Wild)
 +}
 +
 +/// Checks if the method call given in `expr` belongs to the given trait.
 +/// This is a deprecated function, consider using [`is_trait_method`].
 +pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
 +    let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
 +    let trt_id = cx.tcx.trait_of_item(def_id);
 +    trt_id.map_or(false, |trt_id| match_def_path(cx, trt_id, path))
 +}
 +
 +/// Checks if a method is defined in an impl of a diagnostic item
 +pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
 +    if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
 +        if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
 +            return cx.tcx.is_diagnostic_item(diag_item, adt.did());
 +        }
 +    }
 +    false
 +}
 +
 +/// Checks if a method is in a diagnostic item trait
 +pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
 +    if let Some(trait_did) = cx.tcx.trait_of_item(def_id) {
 +        return cx.tcx.is_diagnostic_item(diag_item, trait_did);
 +    }
 +    false
 +}
 +
 +/// Checks if the method call given in `expr` belongs to the given trait.
 +pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
 +    cx.typeck_results()
 +        .type_dependent_def_id(expr.hir_id)
 +        .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
 +}
 +
 +/// Checks if the given expression is a path referring an item on the trait
 +/// that is marked with the given diagnostic item.
 +///
 +/// For checking method call expressions instead of path expressions, use
 +/// [`is_trait_method`].
 +///
 +/// For example, this can be used to find if an expression like `u64::default`
 +/// refers to an item of the trait `Default`, which is associated with the
 +/// `diag_item` of `sym::Default`.
 +pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
 +    if let hir::ExprKind::Path(ref qpath) = expr.kind {
 +        cx.qpath_res(qpath, expr.hir_id)
 +            .opt_def_id()
 +            .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
 +    } else {
 +        false
 +    }
 +}
 +
 +pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
 +    match *path {
 +        QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
 +        QPath::TypeRelative(_, seg) => seg,
 +        QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
 +    }
 +}
 +
 +pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tcx hir::Ty<'tcx>> {
 +    last_path_segment(qpath)
 +        .args
 +        .map_or(&[][..], |a| a.args)
 +        .iter()
 +        .filter_map(|a| match a {
 +            hir::GenericArg::Type(ty) => Some(*ty),
 +            _ => None,
 +        })
 +}
 +
 +/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
 +/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
 +/// `QPath::Resolved.1.res.opt_def_id()`.
 +///
 +/// Matches a `QPath` against a slice of segment string literals.
 +///
 +/// There is also `match_path` if you are dealing with a `rustc_hir::Path` instead of a
 +/// `rustc_hir::QPath`.
 +///
 +/// # Examples
 +/// ```rust,ignore
 +/// match_qpath(path, &["std", "rt", "begin_unwind"])
 +/// ```
 +pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
 +    match *path {
 +        QPath::Resolved(_, path) => match_path(path, segments),
 +        QPath::TypeRelative(ty, segment) => match ty.kind {
 +            TyKind::Path(ref inner_path) => {
 +                if let [prefix @ .., end] = segments {
 +                    if match_qpath(inner_path, prefix) {
 +                        return segment.ident.name.as_str() == *end;
 +                    }
 +                }
 +                false
 +            },
 +            _ => false,
 +        },
 +        QPath::LangItem(..) => false,
 +    }
 +}
 +
 +/// If the expression is a path, resolves it to a `DefId` and checks if it matches the given path.
 +///
 +/// Please use `is_path_diagnostic_item` if the target is a diagnostic item.
 +pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool {
 +    path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, segments))
 +}
 +
 +/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
 +/// it matches the given lang item.
 +pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool {
 +    path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.lang_items().get(lang_item) == Some(id))
 +}
 +
 +/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
 +/// it matches the given diagnostic item.
 +pub fn is_path_diagnostic_item<'tcx>(
 +    cx: &LateContext<'_>,
 +    maybe_path: &impl MaybePath<'tcx>,
 +    diag_item: Symbol,
 +) -> bool {
 +    path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id))
 +}
 +
 +/// THIS METHOD IS DEPRECATED and will eventually be removed since it does not match against the
 +/// entire path or resolved `DefId`. Prefer using `match_def_path`. Consider getting a `DefId` from
 +/// `QPath::Resolved.1.res.opt_def_id()`.
 +///
 +/// Matches a `Path` against a slice of segment string literals.
 +///
 +/// There is also `match_qpath` if you are dealing with a `rustc_hir::QPath` instead of a
 +/// `rustc_hir::Path`.
 +///
 +/// # Examples
 +///
 +/// ```rust,ignore
 +/// if match_path(&trait_ref.path, &paths::HASH) {
 +///     // This is the `std::hash::Hash` trait.
 +/// }
 +///
 +/// if match_path(ty_path, &["rustc", "lint", "Lint"]) {
 +///     // This is a `rustc_middle::lint::Lint`.
 +/// }
 +/// ```
 +pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
 +    path.segments
 +        .iter()
 +        .rev()
 +        .zip(segments.iter().rev())
 +        .all(|(a, b)| a.ident.name.as_str() == *b)
 +}
 +
 +/// If the expression is a path to a local, returns the canonical `HirId` of the local.
 +pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
 +    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
 +        if let Res::Local(id) = path.res {
 +            return Some(id);
 +        }
 +    }
 +    None
 +}
 +
 +/// Returns true if the expression is a path to a local with the specified `HirId`.
 +/// Use this function to see if an expression matches a function argument or a match binding.
 +pub fn path_to_local_id(expr: &Expr<'_>, id: HirId) -> bool {
 +    path_to_local(expr) == Some(id)
 +}
 +
 +pub trait MaybePath<'hir> {
 +    fn hir_id(&self) -> HirId;
 +    fn qpath_opt(&self) -> Option<&QPath<'hir>>;
 +}
 +
 +macro_rules! maybe_path {
 +    ($ty:ident, $kind:ident) => {
 +        impl<'hir> MaybePath<'hir> for hir::$ty<'hir> {
 +            fn hir_id(&self) -> HirId {
 +                self.hir_id
 +            }
 +            fn qpath_opt(&self) -> Option<&QPath<'hir>> {
 +                match &self.kind {
 +                    hir::$kind::Path(qpath) => Some(qpath),
 +                    _ => None,
 +                }
 +            }
 +        }
 +    };
 +}
 +maybe_path!(Expr, ExprKind);
 +maybe_path!(Pat, PatKind);
 +maybe_path!(Ty, TyKind);
 +
 +/// If `maybe_path` is a path node, resolves it, otherwise returns `Res::Err`
 +pub fn path_res<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>) -> Res {
 +    match maybe_path.qpath_opt() {
 +        None => Res::Err,
 +        Some(qpath) => cx.qpath_res(qpath, maybe_path.hir_id()),
 +    }
 +}
 +
 +/// If `maybe_path` is a path node which resolves to an item, retrieves the item ID
 +pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>) -> Option<DefId> {
 +    path_res(cx, maybe_path).opt_def_id()
 +}
 +
 +fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
 +    let ty = match name {
 +        "bool" => BoolSimplifiedType,
 +        "char" => CharSimplifiedType,
 +        "str" => StrSimplifiedType,
 +        "array" => ArraySimplifiedType,
 +        "slice" => SliceSimplifiedType,
 +        // FIXME: rustdoc documents these two using just `pointer`.
 +        //
 +        // Maybe this is something we should do here too.
 +        "const_ptr" => PtrSimplifiedType(Mutability::Not),
 +        "mut_ptr" => PtrSimplifiedType(Mutability::Mut),
 +        "isize" => IntSimplifiedType(IntTy::Isize),
 +        "i8" => IntSimplifiedType(IntTy::I8),
 +        "i16" => IntSimplifiedType(IntTy::I16),
 +        "i32" => IntSimplifiedType(IntTy::I32),
 +        "i64" => IntSimplifiedType(IntTy::I64),
 +        "i128" => IntSimplifiedType(IntTy::I128),
 +        "usize" => UintSimplifiedType(UintTy::Usize),
 +        "u8" => UintSimplifiedType(UintTy::U8),
 +        "u16" => UintSimplifiedType(UintTy::U16),
 +        "u32" => UintSimplifiedType(UintTy::U32),
 +        "u64" => UintSimplifiedType(UintTy::U64),
 +        "u128" => UintSimplifiedType(UintTy::U128),
 +        "f32" => FloatSimplifiedType(FloatTy::F32),
 +        "f64" => FloatSimplifiedType(FloatTy::F64),
 +        _ => return [].iter().copied(),
 +    };
 +
 +    tcx.incoherent_impls(ty).iter().copied()
 +}
 +
 +fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
 +    match tcx.def_kind(def_id) {
 +        DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
 +            .module_children(def_id)
 +            .iter()
 +            .filter(|item| item.ident.name == name)
 +            .map(|child| child.res.expect_non_local())
 +            .collect(),
 +        DefKind::Impl => tcx
 +            .associated_item_def_ids(def_id)
 +            .iter()
 +            .copied()
 +            .filter(|assoc_def_id| tcx.item_name(*assoc_def_id) == name)
 +            .map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id))
 +            .collect(),
 +        _ => Vec::new(),
 +    }
 +}
 +
 +fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symbol) -> Vec<Res> {
 +    let hir = tcx.hir();
 +
 +    let root_mod;
 +    let item_kind = match hir.find_by_def_id(local_id) {
 +        Some(Node::Crate(r#mod)) => {
 +            root_mod = ItemKind::Mod(r#mod);
 +            &root_mod
 +        },
 +        Some(Node::Item(item)) => &item.kind,
 +        _ => return Vec::new(),
 +    };
 +
 +    let res = |ident: Ident, owner_id: OwnerId| {
 +        if ident.name == name {
 +            let def_id = owner_id.to_def_id();
 +            Some(Res::Def(tcx.def_kind(def_id), def_id))
 +        } else {
 +            None
 +        }
 +    };
 +
 +    match item_kind {
 +        ItemKind::Mod(r#mod) => r#mod
 +            .item_ids
 +            .iter()
 +            .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
 +            .collect(),
 +        ItemKind::Impl(r#impl) => r#impl
 +            .items
 +            .iter()
 +            .filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.owner_id))
 +            .collect(),
 +        ItemKind::Trait(.., trait_item_refs) => trait_item_refs
 +            .iter()
 +            .filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.owner_id))
 +            .collect(),
 +        _ => Vec::new(),
 +    }
 +}
 +
 +fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
 +    if let Some(local_id) = def_id.as_local() {
 +        local_item_children_by_name(tcx, local_id, name)
 +    } else {
 +        non_local_item_children_by_name(tcx, def_id, name)
 +    }
 +}
 +
 +/// Resolves a def path like `std::vec::Vec`.
 +///
 +/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
 +/// `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0.
 +///
 +/// Also returns multiple results when there are mulitple paths under the same name e.g. `std::vec`
 +/// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
 +///
 +/// This function is expensive and should be used sparingly.
 +pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
 +    fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
 +        tcx.crates(())
 +            .iter()
 +            .copied()
 +            .filter(move |&num| tcx.crate_name(num) == name)
 +            .map(CrateNum::as_def_id)
 +    }
 +
 +    let tcx = cx.tcx;
 +
 +    let (base, mut path) = match *path {
 +        [primitive] => {
 +            return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
 +        },
 +        [base, ref path @ ..] => (base, path),
 +        _ => return Vec::new(),
 +    };
 +
 +    let base_sym = Symbol::intern(base);
 +
 +    let local_crate = if tcx.crate_name(LOCAL_CRATE) == base_sym {
 +        Some(LOCAL_CRATE.as_def_id())
 +    } else {
 +        None
 +    };
 +
 +    let starts = find_primitive_impls(tcx, base)
 +        .chain(find_crates(tcx, base_sym))
 +        .chain(local_crate)
 +        .map(|id| Res::Def(tcx.def_kind(id), id));
 +
 +    let mut resolutions: Vec<Res> = starts.collect();
 +
 +    while let [segment, rest @ ..] = path {
 +        path = rest;
 +        let segment = Symbol::intern(segment);
 +
 +        resolutions = resolutions
 +            .into_iter()
 +            .filter_map(|res| res.opt_def_id())
 +            .flat_map(|def_id| {
 +                // When the current def_id is e.g. `struct S`, check the impl items in
 +                // `impl S { ... }`
 +                let inherent_impl_children = tcx
 +                    .inherent_impls(def_id)
 +                    .iter()
 +                    .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
 +
 +                let direct_children = item_children_by_name(tcx, def_id, segment);
 +
 +                inherent_impl_children.chain(direct_children)
 +            })
 +            .collect();
 +    }
 +
 +    resolutions
 +}
 +
 +/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
 +pub fn def_path_def_ids(cx: &LateContext<'_>, path: &[&str]) -> impl Iterator<Item = DefId> {
 +    def_path_res(cx, path).into_iter().filter_map(|res| res.opt_def_id())
 +}
 +
 +/// Convenience function to get the `DefId` of a trait by path.
 +/// It could be a trait or trait alias.
 +///
 +/// This function is expensive and should be used sparingly.
 +pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
 +    def_path_res(cx, path).into_iter().find_map(|res| match res {
 +        Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
 +        _ => None,
 +    })
 +}
 +
 +/// Gets the `hir::TraitRef` of the trait the given method is implemented for.
 +///
 +/// Use this if you want to find the `TraitRef` of the `Add` trait in this example:
 +///
 +/// ```rust
 +/// struct Point(isize, isize);
 +///
 +/// impl std::ops::Add for Point {
 +///     type Output = Self;
 +///
 +///     fn add(self, other: Self) -> Self {
 +///         Point(0, 0)
 +///     }
 +/// }
 +/// ```
 +pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> Option<&'tcx TraitRef<'tcx>> {
 +    // Get the implemented trait for the current function
 +    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
 +    let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
 +    if_chain! {
 +        if parent_impl != hir::CRATE_OWNER_ID;
 +        if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id);
 +        if let hir::ItemKind::Impl(impl_) = &item.kind;
 +        then {
 +            return impl_.of_trait.as_ref();
 +        }
 +    }
 +    None
 +}
 +
 +/// This method will return tuple of projection stack and root of the expression,
 +/// used in `can_mut_borrow_both`.
 +///
 +/// For example, if `e` represents the `v[0].a.b[x]`
 +/// this method will return a tuple, composed of a `Vec`
 +/// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
 +/// and an `Expr` for root of them, `v`
 +fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
 +    let mut result = vec![];
 +    let root = loop {
 +        match e.kind {
 +            ExprKind::Index(ep, _) | ExprKind::Field(ep, _) => {
 +                result.push(e);
 +                e = ep;
 +            },
 +            _ => break e,
 +        };
 +    };
 +    result.reverse();
 +    (result, root)
 +}
 +
 +/// Gets the mutability of the custom deref adjustment, if any.
 +pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<Mutability> {
 +    cx.typeck_results()
 +        .expr_adjustments(e)
 +        .iter()
 +        .find_map(|a| match a.kind {
 +            Adjust::Deref(Some(d)) => Some(Some(d.mutbl)),
 +            Adjust::Deref(None) => None,
 +            _ => Some(None),
 +        })
 +        .and_then(|x| x)
 +}
 +
 +/// Checks if two expressions can be mutably borrowed simultaneously
 +/// and they aren't dependent on borrowing same thing twice
 +pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool {
 +    let (s1, r1) = projection_stack(e1);
 +    let (s2, r2) = projection_stack(e2);
 +    if !eq_expr_value(cx, r1, r2) {
 +        return true;
 +    }
 +    if expr_custom_deref_adjustment(cx, r1).is_some() || expr_custom_deref_adjustment(cx, r2).is_some() {
 +        return false;
 +    }
 +
 +    for (x1, x2) in s1.iter().zip(s2.iter()) {
 +        if expr_custom_deref_adjustment(cx, x1).is_some() || expr_custom_deref_adjustment(cx, x2).is_some() {
 +            return false;
 +        }
 +
 +        match (&x1.kind, &x2.kind) {
 +            (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => {
 +                if i1 != i2 {
 +                    return true;
 +                }
 +            },
 +            (ExprKind::Index(_, i1), ExprKind::Index(_, i2)) => {
 +                if !eq_expr_value(cx, i1, i2) {
 +                    return false;
 +                }
 +            },
 +            _ => return false,
 +        }
 +    }
 +    false
 +}
 +
 +/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent"
 +/// constructor from the std library
 +fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
 +    let std_types_symbols = &[
 +        sym::Vec,
 +        sym::VecDeque,
 +        sym::LinkedList,
 +        sym::HashMap,
 +        sym::BTreeMap,
 +        sym::HashSet,
 +        sym::BTreeSet,
 +        sym::BinaryHeap,
 +    ];
 +
 +    if let QPath::TypeRelative(_, method) = path {
 +        if method.ident.name == sym::new {
 +            if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
 +                if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
 +                    return std_types_symbols.iter().any(|&symbol| {
 +                        cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
 +                    });
 +                }
 +            }
 +        }
 +    }
 +    false
 +}
 +
 +/// Return true if the expr is equal to `Default::default` when evaluated.
 +pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool {
 +    if_chain! {
 +        if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
 +        if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
 +        if is_diag_trait_item(cx, repl_def_id, sym::Default)
 +            || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
 +        then { true } else { false }
 +    }
 +}
 +
 +/// Returns true if the expr is equal to `Default::default()` of it's type when evaluated.
 +/// It doesn't cover all cases, for example indirect function calls (some of std
 +/// functions are supported) but it is the best we have.
 +pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 +    match &e.kind {
 +        ExprKind::Lit(lit) => match lit.node {
 +            LitKind::Bool(false) | LitKind::Int(0, _) => true,
 +            LitKind::Str(s, _) => s.is_empty(),
 +            _ => false,
 +        },
 +        ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
 +        ExprKind::Repeat(x, ArrayLen::Body(len)) => if_chain! {
 +            if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind;
 +            if let LitKind::Int(v, _) = const_lit.node;
 +            if v <= 32 && is_default_equivalent(cx, x);
 +            then {
 +                true
 +            }
 +            else {
 +                false
 +            }
 +        },
 +        ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func),
 +        ExprKind::Call(from_func, [ref arg]) => is_default_equivalent_from(cx, from_func, arg),
 +        ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
 +        ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
 +        _ => false,
 +    }
 +}
 +
 +fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &Expr<'_>) -> bool {
 +    if let ExprKind::Path(QPath::TypeRelative(ty, seg)) = from_func.kind &&
 +        seg.ident.name == sym::from
 +    {
 +        match arg.kind {
 +            ExprKind::Lit(hir::Lit {
 +                node: LitKind::Str(ref sym, _),
 +                ..
 +            }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
 +            ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
 +            ExprKind::Repeat(_, ArrayLen::Body(len)) => {
 +                if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind &&
 +                    let LitKind::Int(v, _) = const_lit.node
 +                {
 +                        return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
 +                }
 +            }
 +            _ => (),
 +        }
 +    }
 +    false
 +}
 +
 +/// Checks if the top level expression can be moved into a closure as is.
 +/// Currently checks for:
 +/// * Break/Continue outside the given loop HIR ids.
 +/// * Yield/Return statements.
 +/// * Inline assembly.
 +/// * Usages of a field of a local where the type of the local can be partially moved.
 +///
 +/// For example, given the following function:
 +///
 +/// ```
 +/// fn f<'a>(iter: &mut impl Iterator<Item = (usize, &'a mut String)>) {
 +///     for item in iter {
 +///         let s = item.1;
 +///         if item.0 > 10 {
 +///             continue;
 +///         } else {
 +///             s.clear();
 +///         }
 +///     }
 +/// }
 +/// ```
 +///
 +/// When called on the expression `item.0` this will return false unless the local `item` is in the
 +/// `ignore_locals` set. The type `(usize, &mut String)` can have the second element moved, so it
 +/// isn't always safe to move into a closure when only a single field is needed.
 +///
 +/// When called on the `continue` expression this will return false unless the outer loop expression
 +/// is in the `loop_ids` set.
 +///
 +/// Note that this check is not recursive, so passing the `if` expression will always return true
 +/// even though sub-expressions might return false.
 +pub fn can_move_expr_to_closure_no_visit<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    expr: &'tcx Expr<'_>,
 +    loop_ids: &[HirId],
 +    ignore_locals: &HirIdSet,
 +) -> bool {
 +    match expr.kind {
 +        ExprKind::Break(Destination { target_id: Ok(id), .. }, _)
 +        | ExprKind::Continue(Destination { target_id: Ok(id), .. })
 +            if loop_ids.contains(&id) =>
 +        {
 +            true
 +        },
 +        ExprKind::Break(..)
 +        | ExprKind::Continue(_)
 +        | ExprKind::Ret(_)
 +        | ExprKind::Yield(..)
 +        | ExprKind::InlineAsm(_) => false,
 +        // Accessing a field of a local value can only be done if the type isn't
 +        // partially moved.
 +        ExprKind::Field(
 +            &Expr {
 +                hir_id,
 +                kind:
 +                    ExprKind::Path(QPath::Resolved(
 +                        _,
 +                        Path {
 +                            res: Res::Local(local_id),
 +                            ..
 +                        },
 +                    )),
 +                ..
 +            },
 +            _,
 +        ) if !ignore_locals.contains(local_id) && can_partially_move_ty(cx, cx.typeck_results().node_type(hir_id)) => {
 +            // TODO: check if the local has been partially moved. Assume it has for now.
 +            false
 +        },
 +        _ => true,
 +    }
 +}
 +
 +/// How a local is captured by a closure
 +#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 +pub enum CaptureKind {
 +    Value,
 +    Ref(Mutability),
 +}
 +impl CaptureKind {
 +    pub fn is_imm_ref(self) -> bool {
 +        self == Self::Ref(Mutability::Not)
 +    }
 +}
 +impl std::ops::BitOr for CaptureKind {
 +    type Output = Self;
 +    fn bitor(self, rhs: Self) -> Self::Output {
 +        match (self, rhs) {
 +            (CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
 +            (CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
 +            | (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
 +            (CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
 +        }
 +    }
 +}
 +impl std::ops::BitOrAssign for CaptureKind {
 +    fn bitor_assign(&mut self, rhs: Self) {
 +        *self = *self | rhs;
 +    }
 +}
 +
 +/// Given an expression referencing a local, determines how it would be captured in a closure.
 +/// Note as this will walk up to parent expressions until the capture can be determined it should
 +/// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
 +/// function argument (other than a receiver).
 +pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
 +    fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
 +        let mut capture = CaptureKind::Ref(Mutability::Not);
 +        pat.each_binding_or_first(&mut |_, id, span, _| match cx
 +            .typeck_results()
 +            .extract_binding_mode(cx.sess(), id, span)
 +            .unwrap()
 +        {
 +            BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => {
 +                capture = CaptureKind::Value;
 +            },
 +            BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => {
 +                capture = CaptureKind::Ref(Mutability::Mut);
 +            },
 +            _ => (),
 +        });
 +        capture
 +    }
 +
 +    debug_assert!(matches!(
 +        e.kind,
 +        ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
 +    ));
 +
 +    let mut child_id = e.hir_id;
 +    let mut capture = CaptureKind::Value;
 +    let mut capture_expr_ty = e;
 +
 +    for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
 +        if let [
 +            Adjustment {
 +                kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
 +                target,
 +            },
 +            ref adjust @ ..,
 +        ] = *cx
 +            .typeck_results()
 +            .adjustments()
 +            .get(child_id)
 +            .map_or(&[][..], |x| &**x)
 +        {
 +            if let rustc_ty::RawPtr(TypeAndMut { mutbl: mutability, .. }) | rustc_ty::Ref(_, _, mutability) =
 +                *adjust.last().map_or(target, |a| a.target).kind()
 +            {
 +                return CaptureKind::Ref(mutability);
 +            }
 +        }
 +
 +        match parent {
 +            Node::Expr(e) => match e.kind {
 +                ExprKind::AddrOf(_, mutability, _) => return CaptureKind::Ref(mutability),
 +                ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, _) => capture = CaptureKind::Ref(Mutability::Not),
 +                ExprKind::Assign(lhs, ..) | ExprKind::AssignOp(_, lhs, _) if lhs.hir_id == child_id => {
 +                    return CaptureKind::Ref(Mutability::Mut);
 +                },
 +                ExprKind::Field(..) => {
 +                    if capture == CaptureKind::Value {
 +                        capture_expr_ty = e;
 +                    }
 +                },
 +                ExprKind::Let(let_expr) => {
 +                    let mutability = match pat_capture_kind(cx, let_expr.pat) {
 +                        CaptureKind::Value => Mutability::Not,
 +                        CaptureKind::Ref(m) => m,
 +                    };
 +                    return CaptureKind::Ref(mutability);
 +                },
 +                ExprKind::Match(_, arms, _) => {
 +                    let mut mutability = Mutability::Not;
 +                    for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
 +                        match capture {
 +                            CaptureKind::Value => break,
 +                            CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
 +                            CaptureKind::Ref(Mutability::Not) => (),
 +                        }
 +                    }
 +                    return CaptureKind::Ref(mutability);
 +                },
 +                _ => break,
 +            },
 +            Node::Local(l) => match pat_capture_kind(cx, l.pat) {
 +                CaptureKind::Value => break,
 +                capture @ CaptureKind::Ref(_) => return capture,
 +            },
 +            _ => break,
 +        }
 +
 +        child_id = parent_id;
 +    }
 +
 +    if capture == CaptureKind::Value && is_copy(cx, cx.typeck_results().expr_ty(capture_expr_ty)) {
 +        // Copy types are never automatically captured by value.
 +        CaptureKind::Ref(Mutability::Not)
 +    } else {
 +        capture
 +    }
 +}
 +
 +/// Checks if the expression can be moved into a closure as is. This will return a list of captures
 +/// if so, otherwise, `None`.
 +pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<HirIdMap<CaptureKind>> {
 +    struct V<'cx, 'tcx> {
 +        cx: &'cx LateContext<'tcx>,
 +        // Stack of potential break targets contained in the expression.
 +        loops: Vec<HirId>,
 +        /// Local variables created in the expression. These don't need to be captured.
 +        locals: HirIdSet,
 +        /// Whether this expression can be turned into a closure.
 +        allow_closure: bool,
 +        /// Locals which need to be captured, and whether they need to be by value, reference, or
 +        /// mutable reference.
 +        captures: HirIdMap<CaptureKind>,
 +    }
 +    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
 +        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
 +            if !self.allow_closure {
 +                return;
 +            }
 +
 +            match e.kind {
 +                ExprKind::Path(QPath::Resolved(None, &Path { res: Res::Local(l), .. })) => {
 +                    if !self.locals.contains(&l) {
 +                        let cap = capture_local_usage(self.cx, e);
 +                        self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
 +                    }
 +                },
 +                ExprKind::Closure { .. } => {
 +                    let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id);
 +                    for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
 +                        let local_id = match capture.place.base {
 +                            PlaceBase::Local(id) => id,
 +                            PlaceBase::Upvar(var) => var.var_path.hir_id,
 +                            _ => continue,
 +                        };
 +                        if !self.locals.contains(&local_id) {
 +                            let capture = match capture.info.capture_kind {
 +                                UpvarCapture::ByValue => CaptureKind::Value,
 +                                UpvarCapture::ByRef(kind) => match kind {
 +                                    BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
 +                                    BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
 +                                        CaptureKind::Ref(Mutability::Mut)
 +                                    },
 +                                },
 +                            };
 +                            self.captures
 +                                .entry(local_id)
 +                                .and_modify(|e| *e |= capture)
 +                                .or_insert(capture);
 +                        }
 +                    }
 +                },
 +                ExprKind::Loop(b, ..) => {
 +                    self.loops.push(e.hir_id);
 +                    self.visit_block(b);
 +                    self.loops.pop();
 +                },
 +                _ => {
 +                    self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops, &self.locals);
 +                    walk_expr(self, e);
 +                },
 +            }
 +        }
 +
 +        fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
 +            p.each_binding_or_first(&mut |_, id, _, _| {
 +                self.locals.insert(id);
 +            });
 +        }
 +    }
 +
 +    let mut v = V {
 +        cx,
 +        allow_closure: true,
 +        loops: Vec::new(),
 +        locals: HirIdSet::default(),
 +        captures: HirIdMap::default(),
 +    };
 +    v.visit_expr(expr);
 +    v.allow_closure.then_some(v.captures)
 +}
 +
 +/// Arguments of a method: the receiver and all the additional arguments.
 +pub type MethodArguments<'tcx> = Vec<(&'tcx Expr<'tcx>, &'tcx [Expr<'tcx>])>;
 +
 +/// Returns the method names and argument list of nested method call expressions that make up
 +/// `expr`. method/span lists are sorted with the most recent call first.
 +pub fn method_calls<'tcx>(expr: &'tcx Expr<'tcx>, max_depth: usize) -> (Vec<Symbol>, MethodArguments<'tcx>, Vec<Span>) {
 +    let mut method_names = Vec::with_capacity(max_depth);
 +    let mut arg_lists = Vec::with_capacity(max_depth);
 +    let mut spans = Vec::with_capacity(max_depth);
 +
 +    let mut current = expr;
 +    for _ in 0..max_depth {
 +        if let ExprKind::MethodCall(path, receiver, args, _) = &current.kind {
 +            if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
 +                break;
 +            }
 +            method_names.push(path.ident.name);
 +            arg_lists.push((*receiver, &**args));
 +            spans.push(path.ident.span);
 +            current = receiver;
 +        } else {
 +            break;
 +        }
 +    }
 +
 +    (method_names, arg_lists, spans)
 +}
 +
 +/// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
 +///
 +/// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
 +/// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
 +/// containing the `Expr`s for
 +/// `.bar()` and `.baz()`
 +pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<(&'a Expr<'a>, &'a [Expr<'a>])>> {
 +    let mut current = expr;
 +    let mut matched = Vec::with_capacity(methods.len());
 +    for method_name in methods.iter().rev() {
 +        // method chains are stored last -> first
 +        if let ExprKind::MethodCall(path, receiver, args, _) = current.kind {
 +            if path.ident.name.as_str() == *method_name {
 +                if receiver.span.from_expansion() || args.iter().any(|e| e.span.from_expansion()) {
 +                    return None;
 +                }
 +                matched.push((receiver, args)); // build up `matched` backwards
 +                current = receiver; // go to parent expression
 +            } else {
 +                return None;
 +            }
 +        } else {
 +            return None;
 +        }
 +    }
 +    // Reverse `matched` so that it is in the same order as `methods`.
 +    matched.reverse();
 +    Some(matched)
 +}
 +
 +/// Returns `true` if the provided `def_id` is an entrypoint to a program.
 +pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
 +    cx.tcx
 +        .entry_fn(())
 +        .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id)
 +}
 +
 +/// Returns `true` if the expression is in the program's `#[panic_handler]`.
 +pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 +    let parent = cx.tcx.hir().get_parent_item(e.hir_id);
 +    Some(parent.to_def_id()) == cx.tcx.lang_items().panic_impl()
 +}
 +
 +/// Gets the name of the item the expression is in, if available.
 +pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
 +    let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
 +    match cx.tcx.hir().find_by_def_id(parent_id) {
 +        Some(
 +            Node::Item(Item { ident, .. })
 +            | Node::TraitItem(TraitItem { ident, .. })
 +            | Node::ImplItem(ImplItem { ident, .. }),
 +        ) => Some(ident.name),
 +        _ => None,
 +    }
 +}
 +
- impl<'tcx> Visitor<'tcx> for ContainsName {
++pub struct ContainsName<'a, 'tcx> {
++    pub cx: &'a LateContext<'tcx>,
 +    pub name: Symbol,
 +    pub result: bool,
 +}
 +
- pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
-     let mut cn = ContainsName { name, result: false };
++impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
++    type NestedFilter = nested_filter::OnlyBodies;
++
 +    fn visit_name(&mut self, name: Symbol) {
 +        if self.name == name {
 +            self.result = true;
 +        }
 +    }
++
++    fn nested_visit_map(&mut self) -> Self::Map {
++        self.cx.tcx.hir()
++    }
 +}
 +
 +/// Checks if an `Expr` contains a certain name.
++pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
++    let mut cn = ContainsName {
++        name,
++        result: false,
++        cx,
++    };
 +    cn.visit_expr(expr);
 +    cn.result
 +}
 +
 +/// Returns `true` if `expr` contains a return expression
 +pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
 +    for_each_expr(expr, |e| {
 +        if matches!(e.kind, hir::ExprKind::Ret(..)) {
 +            ControlFlow::Break(())
 +        } else {
 +            ControlFlow::Continue(())
 +        }
 +    })
 +    .is_some()
 +}
 +
 +/// Gets the parent node, if any.
 +pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
 +    tcx.hir().find_parent(id)
 +}
 +
 +/// Gets the parent expression, if any –- this is useful to constrain a lint.
 +pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
 +    get_parent_expr_for_hir(cx, e.hir_id)
 +}
 +
 +/// This retrieves the parent for the given `HirId` if it's an expression. This is useful for
 +/// constraint lints
 +pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> {
 +    match get_parent_node(cx.tcx, hir_id) {
 +        Some(Node::Expr(parent)) => Some(parent),
 +        _ => None,
 +    }
 +}
 +
++/// Gets the enclosing block, if any.
 +pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
 +    let map = &cx.tcx.hir();
 +    let enclosing_node = map
 +        .get_enclosing_scope(hir_id)
 +        .and_then(|enclosing_id| map.find(enclosing_id));
 +    enclosing_node.and_then(|node| match node {
 +        Node::Block(block) => Some(block),
 +        Node::Item(&Item {
 +            kind: ItemKind::Fn(_, _, eid),
 +            ..
 +        })
 +        | Node::ImplItem(&ImplItem {
 +            kind: ImplItemKind::Fn(_, eid),
 +            ..
 +        }) => match cx.tcx.hir().body(eid).value.kind {
 +            ExprKind::Block(block, _) => Some(block),
 +            _ => None,
 +        },
 +        _ => None,
 +    })
 +}
 +
 +/// Gets the loop or closure enclosing the given expression, if any.
 +pub fn get_enclosing_loop_or_multi_call_closure<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    expr: &Expr<'_>,
 +) -> Option<&'tcx Expr<'tcx>> {
 +    for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) {
 +        match node {
 +            Node::Expr(e) => match e.kind {
 +                ExprKind::Closure { .. } => {
 +                    if let rustc_ty::Closure(_, subs) = cx.typeck_results().expr_ty(e).kind()
 +                        && subs.as_closure().kind() == ClosureKind::FnOnce
 +                    {
 +                        continue;
 +                    }
 +                    let is_once = walk_to_expr_usage(cx, e, |node, id| {
 +                        let Node::Expr(e) = node else {
 +                            return None;
 +                        };
 +                        match e.kind {
 +                            ExprKind::Call(f, _) if f.hir_id == id => Some(()),
 +                            ExprKind::Call(f, args) => {
 +                                let i = args.iter().position(|arg| arg.hir_id == id)?;
 +                                let sig = expr_sig(cx, f)?;
 +                                let predicates = sig
 +                                    .predicates_id()
 +                                    .map_or(cx.param_env, |id| cx.tcx.param_env(id))
 +                                    .caller_bounds();
 +                                sig.input(i).and_then(|ty| {
 +                                    ty_is_fn_once_param(cx.tcx, ty.skip_binder(), predicates).then_some(())
 +                                })
 +                            },
 +                            ExprKind::MethodCall(_, receiver, args, _) => {
 +                                let i = std::iter::once(receiver)
 +                                    .chain(args.iter())
 +                                    .position(|arg| arg.hir_id == id)?;
 +                                let id = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
 +                                let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
 +                                ty_is_fn_once_param(cx.tcx, ty, cx.tcx.param_env(id).caller_bounds()).then_some(())
 +                            },
 +                            _ => None,
 +                        }
 +                    })
 +                    .is_some();
 +                    if !is_once {
 +                        return Some(e);
 +                    }
 +                },
 +                ExprKind::Loop(..) => return Some(e),
 +                _ => (),
 +            },
 +            Node::Stmt(_) | Node::Block(_) | Node::Local(_) | Node::Arm(_) => (),
 +            _ => break,
 +        }
 +    }
 +    None
 +}
 +
 +/// Gets the parent node if it's an impl block.
 +pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
 +    match tcx.hir().parent_iter(id).next() {
 +        Some((
 +            _,
 +            Node::Item(Item {
 +                kind: ItemKind::Impl(imp),
 +                ..
 +            }),
 +        )) => Some(imp),
 +        _ => None,
 +    }
 +}
 +
 +/// Removes blocks around an expression, only if the block contains just one expression
 +/// and no statements. Unsafe blocks are not removed.
 +///
 +/// Examples:
 +///  * `{}`               -> `{}`
 +///  * `{ x }`            -> `x`
 +///  * `{{ x }}`          -> `x`
 +///  * `{ x; }`           -> `{ x; }`
 +///  * `{ x; y }`         -> `{ x; y }`
 +///  * `{ unsafe { x } }` -> `unsafe { x }`
 +pub fn peel_blocks<'a>(mut expr: &'a Expr<'a>) -> &'a Expr<'a> {
 +    while let ExprKind::Block(
 +        Block {
 +            stmts: [],
 +            expr: Some(inner),
 +            rules: BlockCheckMode::DefaultBlock,
 +            ..
 +        },
 +        _,
 +    ) = expr.kind
 +    {
 +        expr = inner;
 +    }
 +    expr
 +}
 +
 +/// Removes blocks around an expression, only if the block contains just one expression
 +/// or just one expression statement with a semicolon. Unsafe blocks are not removed.
 +///
 +/// Examples:
 +///  * `{}`               -> `{}`
 +///  * `{ x }`            -> `x`
 +///  * `{ x; }`           -> `x`
 +///  * `{{ x; }}`         -> `x`
 +///  * `{ x; y }`         -> `{ x; y }`
 +///  * `{ unsafe { x } }` -> `unsafe { x }`
 +pub fn peel_blocks_with_stmt<'a>(mut expr: &'a Expr<'a>) -> &'a Expr<'a> {
 +    while let ExprKind::Block(
 +        Block {
 +            stmts: [],
 +            expr: Some(inner),
 +            rules: BlockCheckMode::DefaultBlock,
 +            ..
 +        }
 +        | Block {
 +            stmts:
 +                [
 +                    Stmt {
 +                        kind: StmtKind::Expr(inner) | StmtKind::Semi(inner),
 +                        ..
 +                    },
 +                ],
 +            expr: None,
 +            rules: BlockCheckMode::DefaultBlock,
 +            ..
 +        },
 +        _,
 +    ) = expr.kind
 +    {
 +        expr = inner;
 +    }
 +    expr
 +}
 +
 +/// Checks if the given expression is the else clause of either an `if` or `if let` expression.
 +pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
 +    let mut iter = tcx.hir().parent_iter(expr.hir_id);
 +    match iter.next() {
 +        Some((
 +            _,
 +            Node::Expr(Expr {
 +                kind: ExprKind::If(_, _, Some(else_expr)),
 +                ..
 +            }),
 +        )) => else_expr.hir_id == expr.hir_id,
 +        _ => false,
 +    }
 +}
 +
 +/// Checks whether the given expression is a constant integer of the given value.
 +/// unlike `is_integer_literal`, this version does const folding
 +pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
 +    if is_integer_literal(e, value) {
 +        return true;
 +    }
 +    let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
 +    if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
 +        return value == v;
 +    }
 +    false
 +}
 +
 +/// Checks whether the given expression is a constant literal of the given value.
 +pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
 +    // FIXME: use constant folding
 +    if let ExprKind::Lit(ref spanned) = expr.kind {
 +        if let LitKind::Int(v, _) = spanned.node {
 +            return v == value;
 +        }
 +    }
 +    false
 +}
 +
 +/// Returns `true` if the given `Expr` has been coerced before.
 +///
 +/// Examples of coercions can be found in the Nomicon at
 +/// <https://doc.rust-lang.org/nomicon/coercions.html>.
 +///
 +/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_hir_analysis::check::coercion` for
 +/// more information on adjustments and coercions.
 +pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
 +    cx.typeck_results().adjustments().get(e.hir_id).is_some()
 +}
 +
 +/// Returns the pre-expansion span if this comes from an expansion of the
 +/// macro `name`.
 +/// See also [`is_direct_expn_of`].
 +#[must_use]
 +pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
 +    loop {
 +        if span.from_expansion() {
 +            let data = span.ctxt().outer_expn_data();
 +            let new_span = data.call_site;
 +
 +            if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
 +                if mac_name.as_str() == name {
 +                    return Some(new_span);
 +                }
 +            }
 +
 +            span = new_span;
 +        } else {
 +            return None;
 +        }
 +    }
 +}
 +
 +/// Returns the pre-expansion span if the span directly comes from an expansion
 +/// of the macro `name`.
 +/// The difference with [`is_expn_of`] is that in
 +/// ```rust
 +/// # macro_rules! foo { ($name:tt!$args:tt) => { $name!$args } }
 +/// # macro_rules! bar { ($e:expr) => { $e } }
 +/// foo!(bar!(42));
 +/// ```
 +/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
 +/// from `bar!` by `is_direct_expn_of`.
 +#[must_use]
 +pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
 +    if span.from_expansion() {
 +        let data = span.ctxt().outer_expn_data();
 +        let new_span = data.call_site;
 +
 +        if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
 +            if mac_name.as_str() == name {
 +                return Some(new_span);
 +            }
 +        }
 +    }
 +
 +    None
 +}
 +
 +/// Convenience function to get the return type of a function.
 +pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
 +    let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
 +    let ret_ty = cx.tcx.fn_sig(fn_def_id).output();
 +    cx.tcx.erase_late_bound_regions(ret_ty)
 +}
 +
 +/// Convenience function to get the nth argument type of a function.
 +pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId, nth: usize) -> Ty<'tcx> {
 +    let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
 +    let arg = cx.tcx.fn_sig(fn_def_id).input(nth);
 +    cx.tcx.erase_late_bound_regions(arg)
 +}
 +
 +/// Checks if an expression is constructing a tuple-like enum variant or struct
 +pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +    if let ExprKind::Call(fun, _) = expr.kind {
 +        if let ExprKind::Path(ref qp) = fun.kind {
 +            let res = cx.qpath_res(qp, fun.hir_id);
 +            return match res {
 +                def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
 +                def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
 +                _ => false,
 +            };
 +        }
 +    }
 +    false
 +}
 +
 +/// Returns `true` if a pattern is refutable.
 +// TODO: should be implemented using rustc/mir_build/thir machinery
 +pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
 +    fn is_enum_variant(cx: &LateContext<'_>, qpath: &QPath<'_>, id: HirId) -> bool {
 +        matches!(
 +            cx.qpath_res(qpath, id),
 +            def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
 +        )
 +    }
 +
 +    fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>, i: I) -> bool {
 +        i.into_iter().any(|pat| is_refutable(cx, pat))
 +    }
 +
 +    match pat.kind {
 +        PatKind::Wild => false,
 +        PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
 +        PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
 +        PatKind::Lit(..) | PatKind::Range(..) => true,
 +        PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
 +        PatKind::Or(pats) => {
 +            // TODO: should be the honest check, that pats is exhaustive set
 +            are_refutable(cx, pats)
 +        },
 +        PatKind::Tuple(pats, _) => are_refutable(cx, pats),
 +        PatKind::Struct(ref qpath, fields, _) => {
 +            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
 +        },
 +        PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
 +        PatKind::Slice(head, middle, tail) => {
 +            match &cx.typeck_results().node_type(pat.hir_id).kind() {
 +                rustc_ty::Slice(..) => {
 +                    // [..] is the only irrefutable slice pattern.
 +                    !head.is_empty() || middle.is_none() || !tail.is_empty()
 +                },
 +                rustc_ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter())),
 +                _ => {
 +                    // unreachable!()
 +                    true
 +                },
 +            }
 +        },
 +    }
 +}
 +
 +/// If the pattern is an `or` pattern, call the function once for each sub pattern. Otherwise, call
 +/// the function once on the given pattern.
 +pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
 +    if let PatKind::Or(pats) = pat.kind {
 +        pats.iter().for_each(f);
 +    } else {
 +        f(pat);
 +    }
 +}
 +
 +pub fn is_self(slf: &Param<'_>) -> bool {
 +    if let PatKind::Binding(.., name, _) = slf.pat.kind {
 +        name.name == kw::SelfLower
 +    } else {
 +        false
 +    }
 +}
 +
 +pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
 +    if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind {
 +        if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res {
 +            return true;
 +        }
 +    }
 +    false
 +}
 +
 +pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl Iterator<Item = &'tcx Param<'tcx>> {
 +    (0..decl.inputs.len()).map(move |i| &body.params[i])
 +}
 +
 +/// Checks if a given expression is a match expression expanded from the `?`
 +/// operator or the `try` macro.
 +pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 +    fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
 +        if_chain! {
 +            if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
 +            if ddpos.as_opt_usize().is_none();
 +            if is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk);
 +            if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
 +            if path_to_local_id(arm.body, hir_id);
 +            then {
 +                return true;
 +            }
 +        }
 +        false
 +    }
 +
 +    fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
 +        if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
 +            is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultErr)
 +        } else {
 +            false
 +        }
 +    }
 +
 +    if let ExprKind::Match(_, arms, ref source) = expr.kind {
 +        // desugared from a `?` operator
 +        if *source == MatchSource::TryDesugar {
 +            return Some(expr);
 +        }
 +
 +        if_chain! {
 +            if arms.len() == 2;
 +            if arms[0].guard.is_none();
 +            if arms[1].guard.is_none();
 +            if (is_ok(cx, &arms[0]) && is_err(cx, &arms[1])) || (is_ok(cx, &arms[1]) && is_err(cx, &arms[0]));
 +            then {
 +                return Some(expr);
 +            }
 +        }
 +    }
 +
 +    None
 +}
 +
 +/// Returns `true` if the lint is allowed in the current context. This is useful for
 +/// skipping long running code when it's unnecessary
 +///
 +/// This function should check the lint level for the same node, that the lint will
 +/// be emitted at. If the information is buffered to be emitted at a later point, please
 +/// make sure to use `span_lint_hir` functions to emit the lint. This ensures that
 +/// expectations at the checked nodes will be fulfilled.
 +pub fn is_lint_allowed(cx: &LateContext<'_>, lint: &'static Lint, id: HirId) -> bool {
 +    cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
 +}
 +
 +pub fn strip_pat_refs<'hir>(mut pat: &'hir Pat<'hir>) -> &'hir Pat<'hir> {
 +    while let PatKind::Ref(subpat, _) = pat.kind {
 +        pat = subpat;
 +    }
 +    pat
 +}
 +
 +pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 {
 +    Integer::from_int_ty(&tcx, ity).size().bits()
 +}
 +
 +#[expect(clippy::cast_possible_wrap)]
 +/// Turn a constant int byte representation into an i128
 +pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 {
 +    let amt = 128 - int_bits(tcx, ity);
 +    ((u as i128) << amt) >> amt
 +}
 +
 +#[expect(clippy::cast_sign_loss)]
 +/// clip unused bytes
 +pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 {
 +    let amt = 128 - int_bits(tcx, ity);
 +    ((u as u128) << amt) >> amt
 +}
 +
 +/// clip unused bytes
 +pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::UintTy) -> u128 {
 +    let bits = Integer::from_uint_ty(&tcx, ity).size().bits();
 +    let amt = 128 - bits;
 +    (u << amt) >> amt
 +}
 +
 +pub fn has_attr(attrs: &[ast::Attribute], symbol: Symbol) -> bool {
 +    attrs.iter().any(|attr| attr.has_name(symbol))
 +}
 +
 +pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
 +    has_attr(cx.tcx.hir().attrs(hir_id), sym::repr)
 +}
 +
 +pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
 +    let map = &tcx.hir();
 +    let mut prev_enclosing_node = None;
 +    let mut enclosing_node = node;
 +    while Some(enclosing_node) != prev_enclosing_node {
 +        if has_attr(map.attrs(enclosing_node), symbol) {
 +            return true;
 +        }
 +        prev_enclosing_node = Some(enclosing_node);
 +        enclosing_node = map.get_parent_item(enclosing_node).into();
 +    }
 +
 +    false
 +}
 +
 +pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
 +    any_parent_has_attr(tcx, node, sym::automatically_derived)
 +}
 +
 +/// Matches a function call with the given path and returns the arguments.
 +///
 +/// Usage:
 +///
 +/// ```rust,ignore
 +/// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
 +/// ```
 +/// This function is deprecated. Use [`match_function_call_with_def_id`].
 +pub fn match_function_call<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    expr: &'tcx Expr<'_>,
 +    path: &[&str],
 +) -> Option<&'tcx [Expr<'tcx>]> {
 +    if_chain! {
 +        if let ExprKind::Call(fun, args) = expr.kind;
 +        if let ExprKind::Path(ref qpath) = fun.kind;
 +        if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
 +        if match_def_path(cx, fun_def_id, path);
 +        then {
 +            return Some(args);
 +        }
 +    };
 +    None
 +}
 +
 +pub fn match_function_call_with_def_id<'tcx>(
 +    cx: &LateContext<'tcx>,
 +    expr: &'tcx Expr<'_>,
 +    fun_def_id: DefId,
 +) -> Option<&'tcx [Expr<'tcx>]> {
 +    if_chain! {
 +        if let ExprKind::Call(fun, args) = expr.kind;
 +        if let ExprKind::Path(ref qpath) = fun.kind;
 +        if cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id);
 +        then {
 +            return Some(args);
 +        }
 +    };
 +    None
 +}
 +
 +/// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
 +/// any.
 +///
 +/// Please use `tcx.get_diagnostic_name` if the targets are all diagnostic items.
 +pub fn match_any_def_paths(cx: &LateContext<'_>, did: DefId, paths: &[&[&str]]) -> Option<usize> {
 +    let search_path = cx.get_def_path(did);
 +    paths
 +        .iter()
 +        .position(|p| p.iter().map(|x| Symbol::intern(x)).eq(search_path.iter().copied()))
 +}
 +
 +/// Checks if the given `DefId` matches the path.
 +pub fn match_def_path(cx: &LateContext<'_>, did: DefId, syms: &[&str]) -> bool {
 +    // We should probably move to Symbols in Clippy as well rather than interning every time.
 +    let path = cx.get_def_path(did);
 +    syms.iter().map(|x| Symbol::intern(x)).eq(path.iter().copied())
 +}
 +
 +/// Checks if the given `DefId` matches the `libc` item.
 +pub fn match_libc_symbol(cx: &LateContext<'_>, did: DefId, name: &str) -> bool {
 +    let path = cx.get_def_path(did);
 +    // libc is meant to be used as a flat list of names, but they're all actually defined in different
 +    // modules based on the target platform. Ignore everything but crate name and the item name.
 +    path.first().map_or(false, |s| s.as_str() == "libc") && path.last().map_or(false, |s| s.as_str() == name)
 +}
 +
 +/// Returns the list of condition expressions and the list of blocks in a
 +/// sequence of `if/else`.
 +/// E.g., this returns `([a, b], [c, d, e])` for the expression
 +/// `if a { c } else if b { d } else { e }`.
 +pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, Vec<&'tcx Block<'tcx>>) {
 +    let mut conds = Vec::new();
 +    let mut blocks: Vec<&Block<'_>> = Vec::new();
 +
 +    while let Some(higher::IfOrIfLet { cond, then, r#else }) = higher::IfOrIfLet::hir(expr) {
 +        conds.push(cond);
 +        if let ExprKind::Block(block, _) = then.kind {
 +            blocks.push(block);
 +        } else {
 +            panic!("ExprKind::If node is not an ExprKind::Block");
 +        }
 +
 +        if let Some(else_expr) = r#else {
 +            expr = else_expr;
 +        } else {
 +            break;
 +        }
 +    }
 +
 +    // final `else {..}`
 +    if !blocks.is_empty() {
 +        if let ExprKind::Block(block, _) = expr.kind {
 +            blocks.push(block);
 +        }
 +    }
 +
 +    (conds, blocks)
 +}
 +
 +/// Checks if the given function kind is an async function.
 +pub fn is_async_fn(kind: FnKind<'_>) -> bool {
 +    match kind {
 +        FnKind::ItemFn(_, _, header) => header.asyncness == IsAsync::Async,
 +        FnKind::Method(_, sig) => sig.header.asyncness == IsAsync::Async,
 +        FnKind::Closure => false,
 +    }
 +}
 +
 +/// Peels away all the compiler generated code surrounding the body of an async function,
 +pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
 +    if let ExprKind::Call(
 +        _,
 +        &[
 +            Expr {
 +                kind: ExprKind::Closure(&Closure { body, .. }),
 +                ..
 +            },
 +        ],
 +    ) = body.value.kind
 +    {
 +        if let ExprKind::Block(
 +            Block {
 +                stmts: [],
 +                expr:
 +                    Some(Expr {
 +                        kind: ExprKind::DropTemps(expr),
 +                        ..
 +                    }),
 +                ..
 +            },
 +            _,
 +        ) = tcx.hir().body(body).value.kind
 +        {
 +            return Some(expr);
 +        }
 +    };
 +    None
 +}
 +
 +// check if expr is calling method or function with #[must_use] attribute
 +pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +    let did = match expr.kind {
 +        ExprKind::Call(path, _) => if_chain! {
 +            if let ExprKind::Path(ref qpath) = path.kind;
 +            if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
 +            then {
 +                Some(did)
 +            } else {
 +                None
 +            }
 +        },
 +        ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
 +        _ => None,
 +    };
 +
 +    did.map_or(false, |did| cx.tcx.has_attr(did, sym::must_use))
 +}
 +
 +/// Checks if an expression represents the identity function
 +/// Only examines closures and `std::convert::identity`
 +pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 +    /// Checks if a function's body represents the identity function. Looks for bodies of the form:
 +    /// * `|x| x`
 +    /// * `|x| return x`
 +    /// * `|x| { return x }`
 +    /// * `|x| { return x; }`
 +    fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
 +        let id = if_chain! {
 +            if let [param] = func.params;
 +            if let PatKind::Binding(_, id, _, _) = param.pat.kind;
 +            then {
 +                id
 +            } else {
 +                return false;
 +            }
 +        };
 +
 +        let mut expr = func.value;
 +        loop {
 +            match expr.kind {
 +                #[rustfmt::skip]
 +                ExprKind::Block(&Block { stmts: [], expr: Some(e), .. }, _, )
 +                | ExprKind::Ret(Some(e)) => expr = e,
 +                #[rustfmt::skip]
 +                ExprKind::Block(&Block { stmts: [stmt], expr: None, .. }, _) => {
 +                    if_chain! {
 +                        if let StmtKind::Semi(e) | StmtKind::Expr(e) = stmt.kind;
 +                        if let ExprKind::Ret(Some(ret_val)) = e.kind;
 +                        then {
 +                            expr = ret_val;
 +                        } else {
 +                            return false;
 +                        }
 +                    }
 +                },
 +                _ => return path_to_local_id(expr, id) && cx.typeck_results().expr_adjustments(expr).is_empty(),
 +            }
 +        }
 +    }
 +
 +    match expr.kind {
 +        ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
 +        _ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
 +    }
 +}
 +
 +/// Gets the node where an expression is either used, or it's type is unified with another branch.
 +/// Returns both the node and the `HirId` of the closest child node.
 +pub fn get_expr_use_or_unification_node<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<(Node<'tcx>, HirId)> {
 +    let mut child_id = expr.hir_id;
 +    let mut iter = tcx.hir().parent_iter(child_id);
 +    loop {
 +        match iter.next() {
 +            None => break None,
 +            Some((id, Node::Block(_))) => child_id = id,
 +            Some((id, Node::Arm(arm))) if arm.body.hir_id == child_id => child_id = id,
 +            Some((_, Node::Expr(expr))) => match expr.kind {
 +                ExprKind::Match(_, [arm], _) if arm.hir_id == child_id => child_id = expr.hir_id,
 +                ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = expr.hir_id,
 +                ExprKind::If(_, then_expr, None) if then_expr.hir_id == child_id => break None,
 +                _ => break Some((Node::Expr(expr), child_id)),
 +            },
 +            Some((_, node)) => break Some((node, child_id)),
 +        }
 +    }
 +}
 +
 +/// Checks if the result of an expression is used, or it's type is unified with another branch.
 +pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
 +    !matches!(
 +        get_expr_use_or_unification_node(tcx, expr),
 +        None | Some((
 +            Node::Stmt(Stmt {
 +                kind: StmtKind::Expr(_)
 +                    | StmtKind::Semi(_)
 +                    | StmtKind::Local(Local {
 +                        pat: Pat {
 +                            kind: PatKind::Wild,
 +                            ..
 +                        },
 +                        ..
 +                    }),
 +                ..
 +            }),
 +            _
 +        ))
 +    )
 +}
 +
 +/// Checks if the expression is the final expression returned from a block.
 +pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
 +    matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..)))
 +}
 +
 +pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
 +    if !is_no_std_crate(cx) {
 +        Some("std")
 +    } else if !is_no_core_crate(cx) {
 +        Some("core")
 +    } else {
 +        None
 +    }
 +}
 +
 +pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
 +    cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
 +        if let ast::AttrKind::Normal(ref normal) = attr.kind {
 +            normal.item.path == sym::no_std
 +        } else {
 +            false
 +        }
 +    })
 +}
 +
 +pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
 +    cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
 +        if let ast::AttrKind::Normal(ref normal) = attr.kind {
 +            normal.item.path == sym::no_core
 +        } else {
 +            false
 +        }
 +    })
 +}
 +
 +/// Check if parent of a hir node is a trait implementation block.
 +/// For example, `f` in
 +/// ```rust
 +/// # struct S;
 +/// # trait Trait { fn f(); }
 +/// impl Trait for S {
 +///     fn f() {}
 +/// }
 +/// ```
 +pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
 +    if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
 +        matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
 +    } else {
 +        false
 +    }
 +}
 +
 +/// Check if it's even possible to satisfy the `where` clause for the item.
 +///
 +/// `trivial_bounds` feature allows functions with unsatisfiable bounds, for example:
 +///
 +/// ```ignore
 +/// fn foo() where i32: Iterator {
 +///     for _ in 2i32 {}
 +/// }
 +/// ```
 +pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
 +    use rustc_trait_selection::traits;
 +    let predicates = cx
 +        .tcx
 +        .predicates_of(did)
 +        .predicates
 +        .iter()
 +        .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
 +    traits::impossible_predicates(
 +        cx.tcx,
 +        traits::elaborate_predicates(cx.tcx, predicates)
 +            .map(|o| o.predicate)
 +            .collect::<Vec<_>>(),
 +    )
 +}
 +
 +/// Returns the `DefId` of the callee if the given expression is a function or method call.
 +pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
 +    match &expr.kind {
 +        ExprKind::MethodCall(..) => cx.typeck_results().type_dependent_def_id(expr.hir_id),
 +        ExprKind::Call(
 +            Expr {
 +                kind: ExprKind::Path(qpath),
 +                hir_id: path_hir_id,
 +                ..
 +            },
 +            ..,
 +        ) => {
 +            // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or
 +            // deref to fn pointers, dyn Fn, impl Fn - #8850
 +            if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) =
 +                cx.typeck_results().qpath_res(qpath, *path_hir_id)
 +            {
 +                Some(id)
 +            } else {
 +                None
 +            }
 +        },
 +        _ => None,
 +    }
 +}
 +
 +/// Returns `Option<String>` where String is a textual representation of the type encapsulated in
 +/// the slice iff the given expression is a slice of primitives (as defined in the
 +/// `is_recursively_primitive_type` function) and `None` otherwise.
 +pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
 +    let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
 +    let expr_kind = expr_type.kind();
 +    let is_primitive = match expr_kind {
 +        rustc_ty::Slice(element_type) => is_recursively_primitive_type(*element_type),
 +        rustc_ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), &rustc_ty::Slice(_)) => {
 +            if let rustc_ty::Slice(element_type) = inner_ty.kind() {
 +                is_recursively_primitive_type(*element_type)
 +            } else {
 +                unreachable!()
 +            }
 +        },
 +        _ => false,
 +    };
 +
 +    if is_primitive {
 +        // if we have wrappers like Array, Slice or Tuple, print these
 +        // and get the type enclosed in the slice ref
 +        match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
 +            rustc_ty::Slice(..) => return Some("slice".into()),
 +            rustc_ty::Array(..) => return Some("array".into()),
 +            rustc_ty::Tuple(..) => return Some("tuple".into()),
 +            _ => {
 +                // is_recursively_primitive_type() should have taken care
 +                // of the rest and we can rely on the type that is found
 +                let refs_peeled = expr_type.peel_refs();
 +                return Some(refs_peeled.walk().last().unwrap().to_string());
 +            },
 +        }
 +    }
 +    None
 +}
 +
 +/// returns list of all pairs (a, b) from `exprs` such that `eq(a, b)`
 +/// `hash` must be comformed with `eq`
 +pub fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
 +where
 +    Hash: Fn(&T) -> u64,
 +    Eq: Fn(&T, &T) -> bool,
 +{
 +    match exprs {
 +        [a, b] if eq(a, b) => return vec![(a, b)],
 +        _ if exprs.len() <= 2 => return vec![],
 +        _ => {},
 +    }
 +
 +    let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
 +
 +    let mut map: UnhashMap<u64, Vec<&_>> =
 +        UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
 +
 +    for expr in exprs {
 +        match map.entry(hash(expr)) {
 +            Entry::Occupied(mut o) => {
 +                for o in o.get() {
 +                    if eq(o, expr) {
 +                        match_expr_list.push((o, expr));
 +                    }
 +                }
 +                o.get_mut().push(expr);
 +            },
 +            Entry::Vacant(v) => {
 +                v.insert(vec![expr]);
 +            },
 +        }
 +    }
 +
 +    match_expr_list
 +}
 +
 +/// Peels off all references on the pattern. Returns the underlying pattern and the number of
 +/// references removed.
 +pub fn peel_hir_pat_refs<'a>(pat: &'a Pat<'a>) -> (&'a Pat<'a>, usize) {
 +    fn peel<'a>(pat: &'a Pat<'a>, count: usize) -> (&'a Pat<'a>, usize) {
 +        if let PatKind::Ref(pat, _) = pat.kind {
 +            peel(pat, count + 1)
 +        } else {
 +            (pat, count)
 +        }
 +    }
 +    peel(pat, 0)
 +}
 +
 +/// Peels of expressions while the given closure returns `Some`.
 +pub fn peel_hir_expr_while<'tcx>(
 +    mut expr: &'tcx Expr<'tcx>,
 +    mut f: impl FnMut(&'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>>,
 +) -> &'tcx Expr<'tcx> {
 +    while let Some(e) = f(expr) {
 +        expr = e;
 +    }
 +    expr
 +}
 +
 +/// Peels off up to the given number of references on the expression. Returns the underlying
 +/// expression and the number of references removed.
 +pub fn peel_n_hir_expr_refs<'a>(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
 +    let mut remaining = count;
 +    let e = peel_hir_expr_while(expr, |e| match e.kind {
 +        ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) if remaining != 0 => {
 +            remaining -= 1;
 +            Some(e)
 +        },
 +        _ => None,
 +    });
 +    (e, count - remaining)
 +}
 +
++/// Peels off all unary operators of an expression. Returns the underlying expression and the number
++/// of operators removed.
++pub fn peel_hir_expr_unary<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
++    let mut count: usize = 0;
++    let mut curr_expr = expr;
++    while let ExprKind::Unary(_, local_expr) = curr_expr.kind {
++        count = count.wrapping_add(1);
++        curr_expr = local_expr;
++    }
++    (curr_expr, count)
++}
++
 +/// Peels off all references on the expression. Returns the underlying expression and the number of
 +/// references removed.
 +pub fn peel_hir_expr_refs<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
 +    let mut count = 0;
 +    let e = peel_hir_expr_while(expr, |e| match e.kind {
 +        ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) => {
 +            count += 1;
 +            Some(e)
 +        },
 +        _ => None,
 +    });
 +    (e, count)
 +}
 +
 +/// Peels off all references on the type. Returns the underlying type and the number of references
 +/// removed.
 +pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) {
 +    let mut count = 0;
 +    loop {
 +        match &ty.kind {
 +            TyKind::Ref(_, ref_ty) => {
 +                ty = ref_ty.ty;
 +                count += 1;
 +            },
 +            _ => break (ty, count),
 +        }
 +    }
 +}
 +
 +/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
 +/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
 +pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
 +    loop {
 +        match expr.kind {
 +            ExprKind::AddrOf(_, _, e) => expr = e,
 +            ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty(e).is_ref() => expr = e,
 +            _ => break,
 +        }
 +    }
 +    expr
 +}
 +
 +pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
 +    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
 +        if let Res::Def(_, def_id) = path.res {
 +            return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
 +        }
 +    }
 +    false
 +}
 +
 +static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = OnceLock::new();
 +
 +fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
 +    let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
 +    let mut map: MutexGuard<'_, FxHashMap<LocalDefId, Vec<Symbol>>> = cache.lock().unwrap();
 +    let value = map.entry(module);
 +    match value {
 +        Entry::Occupied(entry) => f(entry.get()),
 +        Entry::Vacant(entry) => {
 +            let mut names = Vec::new();
 +            for id in tcx.hir().module_items(module) {
 +                if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
 +                    && let item = tcx.hir().item(id)
 +                    && let ItemKind::Const(ty, _body) = item.kind {
 +                    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
 +                        // We could also check for the type name `test::TestDescAndFn`
 +                        if let Res::Def(DefKind::Struct, _) = path.res {
 +                            let has_test_marker = tcx
 +                                .hir()
 +                                .attrs(item.hir_id())
 +                                .iter()
 +                                .any(|a| a.has_name(sym::rustc_test_marker));
 +                            if has_test_marker {
 +                                names.push(item.ident.name);
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +            names.sort_unstable();
 +            f(entry.insert(names))
 +        },
 +    }
 +}
 +
 +/// Checks if the function containing the given `HirId` is a `#[test]` function
 +///
 +/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function
 +pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 +    with_test_item_names(tcx, tcx.parent_module(id), |names| {
 +        tcx.hir()
 +            .parent_iter(id)
 +            // Since you can nest functions we need to collect all until we leave
 +            // function scope
 +            .any(|(_id, node)| {
 +                if let Node::Item(item) = node {
 +                    if let ItemKind::Fn(_, _, _) = item.kind {
 +                        // Note that we have sorted the item names in the visitor,
 +                        // so the binary_search gets the same as `contains`, but faster.
 +                        return names.binary_search(&item.ident.name).is_ok();
 +                    }
 +                }
 +                false
 +            })
 +    })
 +}
 +
 +/// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied
 +///
 +/// Note: Add `// compile-flags: --test` to UI tests with a `#[cfg(test)]` function
 +pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 +    fn is_cfg_test(attr: &Attribute) -> bool {
 +        if attr.has_name(sym::cfg)
 +            && let Some(items) = attr.meta_item_list()
 +            && let [item] = &*items
 +            && item.has_name(sym::test)
 +        {
 +            true
 +        } else {
 +            false
 +        }
 +    }
 +    tcx.hir()
 +        .parent_iter(id)
 +        .flat_map(|(parent_id, _)| tcx.hir().attrs(parent_id))
 +        .any(is_cfg_test)
 +}
 +
 +/// Checks whether item either has `test` attribute applied, or
 +/// is a module with `test` in its name.
 +///
 +/// Note: Add `// compile-flags: --test` to UI tests with a `#[test]` function
 +pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool {
 +    is_in_test_function(tcx, item.hir_id())
 +        || matches!(item.kind, ItemKind::Mod(..))
 +            && item.ident.name.as_str().split('_').any(|a| a == "test" || a == "tests")
 +}
 +
 +/// Walks the HIR tree from the given expression, up to the node where the value produced by the
 +/// expression is consumed. Calls the function for every node encountered this way until it returns
 +/// `Some`.
 +///
 +/// This allows walking through `if`, `match`, `break`, block expressions to find where the value
 +/// produced by the expression is consumed.
 +pub fn walk_to_expr_usage<'tcx, T>(
 +    cx: &LateContext<'tcx>,
 +    e: &Expr<'tcx>,
 +    mut f: impl FnMut(Node<'tcx>, HirId) -> Option<T>,
 +) -> Option<T> {
 +    let map = cx.tcx.hir();
 +    let mut iter = map.parent_iter(e.hir_id);
 +    let mut child_id = e.hir_id;
 +
 +    while let Some((parent_id, parent)) = iter.next() {
 +        if let Some(x) = f(parent, child_id) {
 +            return Some(x);
 +        }
 +        let parent = match parent {
 +            Node::Expr(e) => e,
 +            Node::Block(Block { expr: Some(body), .. }) | Node::Arm(Arm { body, .. }) if body.hir_id == child_id => {
 +                child_id = parent_id;
 +                continue;
 +            },
 +            Node::Arm(a) if a.body.hir_id == child_id => {
 +                child_id = parent_id;
 +                continue;
 +            },
 +            _ => return None,
 +        };
 +        match parent.kind {
 +            ExprKind::If(child, ..) | ExprKind::Match(child, ..) if child.hir_id != child_id => child_id = parent_id,
 +            ExprKind::Break(Destination { target_id: Ok(id), .. }, _) => {
 +                child_id = id;
 +                iter = map.parent_iter(id);
 +            },
 +            ExprKind::Block(..) => child_id = parent_id,
 +            _ => return None,
 +        }
 +    }
 +    None
 +}
 +
 +/// Checks whether a given span has any comment token
 +/// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
 +pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
 +    let Ok(snippet) = sm.span_to_snippet(span) else { return false };
 +    return tokenize(&snippet).any(|token| {
 +        matches!(
 +            token.kind,
 +            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }
 +        )
 +    });
 +}
 +
 +/// Return all the comments a given span contains
 +/// Comments are returned wrapped with their relevant delimiters
 +pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
 +    let snippet = sm.span_to_snippet(span).unwrap_or_default();
 +    let mut comments_buf: Vec<String> = Vec::new();
 +    let mut index: usize = 0;
 +
 +    for token in tokenize(&snippet) {
 +        let token_range = index..(index + token.len as usize);
 +        index += token.len as usize;
 +        match token.kind {
 +            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => {
 +                if let Some(comment) = snippet.get(token_range) {
 +                    comments_buf.push(comment.to_string());
 +                }
 +            },
 +            _ => (),
 +        }
 +    }
 +
 +    comments_buf.join("\n")
 +}
 +
 +macro_rules! op_utils {
 +    ($($name:ident $assign:ident)*) => {
 +        /// Binary operation traits like `LangItem::Add`
 +        pub static BINOP_TRAITS: &[LangItem] = &[$(LangItem::$name,)*];
 +
 +        /// Operator-Assign traits like `LangItem::AddAssign`
 +        pub static OP_ASSIGN_TRAITS: &[LangItem] = &[$(LangItem::$assign,)*];
 +
 +        /// Converts `BinOpKind::Add` to `(LangItem::Add, LangItem::AddAssign)`, for example
 +        pub fn binop_traits(kind: hir::BinOpKind) -> Option<(LangItem, LangItem)> {
 +            match kind {
 +                $(hir::BinOpKind::$name => Some((LangItem::$name, LangItem::$assign)),)*
 +                _ => None,
 +            }
 +        }
 +    };
 +}
 +
 +op_utils! {
 +    Add    AddAssign
 +    Sub    SubAssign
 +    Mul    MulAssign
 +    Div    DivAssign
 +    Rem    RemAssign
 +    BitXor BitXorAssign
 +    BitAnd BitAndAssign
 +    BitOr  BitOrAssign
 +    Shl    ShlAssign
 +    Shr    ShrAssign
 +}
index 395d46e7a2f8af088f359177ebe4ebf4f4e08c39,0000000000000000000000000000000000000000..9adae7733894580fec10663a47c9ab9a69ebb635
mode 100644,000000..100644
--- /dev/null
@@@ -1,311 -1,0 +1,239 @@@
- use super::possible_origin::PossibleOriginVisitor;
++use super::{possible_origin::PossibleOriginVisitor, transitive_relation::TransitiveRelation};
 +use crate::ty::is_copy;
- use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
++use rustc_data_structures::fx::FxHashMap;
 +use rustc_index::bit_set::{BitSet, HybridBitSet};
 +use rustc_lint::LateContext;
- use rustc_middle::mir::{
-     self, visit::Visitor as _, BasicBlock, Local, Location, Mutability, Statement, StatementKind, Terminator,
- };
- use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt};
- use rustc_mir_dataflow::{
-     fmt::DebugWithContext, impls::MaybeStorageLive, lattice::JoinSemiLattice, Analysis, AnalysisDomain,
-     CallReturnPlaces, ResultsCursor,
- };
++use rustc_middle::mir::{self, visit::Visitor as _, Mutability};
++use rustc_middle::ty::{self, visit::TypeVisitor};
++use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor};
 +use std::borrow::Cow;
 +use std::ops::ControlFlow;
 +
 +/// Collects the possible borrowers of each local.
 +/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
 +/// possible borrowers of `a`.
 +#[allow(clippy::module_name_repetitions)]
- struct PossibleBorrowerAnalysis<'b, 'tcx> {
-     tcx: TyCtxt<'tcx>,
++struct PossibleBorrowerVisitor<'a, 'b, 'tcx> {
++    possible_borrower: TransitiveRelation,
 +    body: &'b mir::Body<'tcx>,
++    cx: &'a LateContext<'tcx>,
 +    possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
 +}
 +
- #[derive(Clone, Debug, Eq, PartialEq)]
- struct PossibleBorrowerState {
-     map: FxIndexMap<Local, BitSet<Local>>,
-     domain_size: usize,
- }
- impl PossibleBorrowerState {
-     fn new(domain_size: usize) -> Self {
++impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
++    fn new(
++        cx: &'a LateContext<'tcx>,
++        body: &'b mir::Body<'tcx>,
++        possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
++    ) -> Self {
 +        Self {
-             map: FxIndexMap::default(),
-             domain_size,
++            possible_borrower: TransitiveRelation::default(),
++            cx,
++            body,
++            possible_origin,
 +        }
 +    }
 +
-     #[allow(clippy::similar_names)]
-     fn add(&mut self, borrowed: Local, borrower: Local) {
-         self.map
-             .entry(borrowed)
-             .or_insert(BitSet::new_empty(self.domain_size))
-             .insert(borrower);
-     }
- }
- impl<C> DebugWithContext<C> for PossibleBorrowerState {
-     fn fmt_with(&self, _ctxt: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-         <_ as std::fmt::Debug>::fmt(self, f)
-     }
-     fn fmt_diff_with(&self, _old: &Self, _ctxt: &C, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-         unimplemented!()
-     }
- }
++    fn into_map(
++        self,
++        cx: &'a LateContext<'tcx>,
++        maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
++    ) -> PossibleBorrowerMap<'b, 'tcx> {
++        let mut map = FxHashMap::default();
++        for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
++            if is_copy(cx, self.body.local_decls[row].ty) {
++                continue;
++            }
 +
- impl JoinSemiLattice for PossibleBorrowerState {
-     fn join(&mut self, other: &Self) -> bool {
-         let mut changed = false;
-         for (&borrowed, borrowers) in other.map.iter() {
++            let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len());
++            borrowers.remove(mir::Local::from_usize(0));
 +            if !borrowers.is_empty() {
-                 changed |= self
-                     .map
-                     .entry(borrowed)
-                     .or_insert(BitSet::new_empty(self.domain_size))
-                     .union(borrowers);
++                map.insert(row, borrowers);
 +            }
 +        }
-         changed
-     }
- }
- impl<'b, 'tcx> AnalysisDomain<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
-     type Domain = PossibleBorrowerState;
-     const NAME: &'static str = "possible_borrower";
-     fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
-         PossibleBorrowerState::new(body.local_decls.len())
-     }
-     fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _entry_set: &mut Self::Domain) {}
- }
 +
- impl<'b, 'tcx> PossibleBorrowerAnalysis<'b, 'tcx> {
-     fn new(
-         tcx: TyCtxt<'tcx>,
-         body: &'b mir::Body<'tcx>,
-         possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
-     ) -> Self {
-         Self {
-             tcx,
-             body,
-             possible_origin,
++        let bs = BitSet::new_empty(self.body.local_decls.len());
++        PossibleBorrowerMap {
++            map,
++            maybe_live,
++            bitset: (bs.clone(), bs),
 +        }
 +    }
 +}
 +
- impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> {
-     fn apply_call_return_effect(
-         &self,
-         _state: &mut Self::Domain,
-         _block: BasicBlock,
-         _return_places: CallReturnPlaces<'_, 'tcx>,
-     ) {
-     }
-     fn apply_statement_effect(&self, state: &mut Self::Domain, statement: &Statement<'tcx>, _location: Location) {
-         if let StatementKind::Assign(box (place, rvalue)) = &statement.kind {
-             let lhs = place.local;
-             match rvalue {
-                 mir::Rvalue::Ref(_, _, borrowed) => {
-                     state.add(borrowed.local, lhs);
-                 },
-                 other => {
-                     if ContainsRegion
-                         .visit_ty(place.ty(&self.body.local_decls, self.tcx).ty)
-                         .is_continue()
-                     {
-                         return;
++impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> {
++    fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
++        let lhs = place.local;
++        match rvalue {
++            mir::Rvalue::Ref(_, _, borrowed) => {
++                self.possible_borrower.add(borrowed.local, lhs);
++            },
++            other => {
++                if ContainsRegion
++                    .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
++                    .is_continue()
++                {
++                    return;
++                }
++                rvalue_locals(other, |rhs| {
++                    if lhs != rhs {
++                        self.possible_borrower.add(rhs, lhs);
 +                    }
-                     rvalue_locals(other, |rhs| {
-                         if lhs != rhs {
-                             state.add(rhs, lhs);
-                         }
-                     });
-                 },
-             }
++                });
++            },
 +        }
 +    }
 +
-     fn apply_terminator_effect(&self, state: &mut Self::Domain, terminator: &Terminator<'tcx>, _location: Location) {
++    fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) {
 +        if let mir::TerminatorKind::Call {
 +            args,
 +            destination: mir::Place { local: dest, .. },
 +            ..
 +        } = &terminator.kind
 +        {
 +            // TODO add doc
 +            // If the call returns something with lifetimes,
 +            // let's conservatively assume the returned value contains lifetime of all the arguments.
 +            // For example, given `let y: Foo<'a> = foo(x)`, `y` is considered to be a possible borrower of `x`.
 +
 +            let mut immutable_borrowers = vec![];
 +            let mut mutable_borrowers = vec![];
 +
 +            for op in args {
 +                match op {
 +                    mir::Operand::Copy(p) | mir::Operand::Move(p) => {
 +                        if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() {
 +                            mutable_borrowers.push(p.local);
 +                        } else {
 +                            immutable_borrowers.push(p.local);
 +                        }
 +                    },
 +                    mir::Operand::Constant(..) => (),
 +                }
 +            }
 +
 +            let mut mutable_variables: Vec<mir::Local> = mutable_borrowers
 +                .iter()
 +                .filter_map(|r| self.possible_origin.get(r))
 +                .flat_map(HybridBitSet::iter)
 +                .collect();
 +
 +            if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
 +                mutable_variables.push(*dest);
 +            }
 +
 +            for y in mutable_variables {
 +                for x in &immutable_borrowers {
-                     state.add(*x, y);
++                    self.possible_borrower.add(*x, y);
 +                }
 +                for x in &mutable_borrowers {
-                     state.add(*x, y);
++                    self.possible_borrower.add(*x, y);
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +struct ContainsRegion;
 +
 +impl TypeVisitor<'_> for ContainsRegion {
 +    type BreakTy = ();
 +
 +    fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
 +        ControlFlow::BREAK
 +    }
 +}
 +
 +fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
 +    use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use};
 +
 +    let mut visit_op = |op: &mir::Operand<'_>| match op {
 +        mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local),
 +        mir::Operand::Constant(..) => (),
 +    };
 +
 +    match rvalue {
 +        Use(op) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op),
 +        Aggregate(_, ops) => ops.iter().for_each(visit_op),
 +        BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
 +            visit_op(lhs);
 +            visit_op(rhs);
 +        },
 +        _ => (),
 +    }
 +}
 +
- /// Result of `PossibleBorrowerAnalysis`.
++/// Result of `PossibleBorrowerVisitor`.
 +#[allow(clippy::module_name_repetitions)]
 +pub struct PossibleBorrowerMap<'b, 'tcx> {
-     body: &'b mir::Body<'tcx>,
-     possible_borrower: ResultsCursor<'b, 'tcx, PossibleBorrowerAnalysis<'b, 'tcx>>,
-     maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'b>>,
-     pushed: BitSet<Local>,
-     stack: Vec<Local>,
++    /// Mapping `Local -> its possible borrowers`
++    pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
++    maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
++    // Caches to avoid allocation of `BitSet` on every query
++    pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
 +}
 +
- impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
-     pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
++impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
++    pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
 +        let possible_origin = {
 +            let mut vis = PossibleOriginVisitor::new(mir);
 +            vis.visit_body(mir);
 +            vis.into_map(cx)
 +        };
-         let possible_borrower = PossibleBorrowerAnalysis::new(cx.tcx, mir, possible_origin)
++        let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
 +            .into_engine(cx.tcx, mir)
-             .pass_name("possible_borrower")
++            .pass_name("redundant_clone")
 +            .iterate_to_fixpoint()
 +            .into_results_cursor(mir);
-         let maybe_live = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
-             .into_engine(cx.tcx, mir)
-             .pass_name("possible_borrower")
-             .iterate_to_fixpoint()
-             .into_results_cursor(mir);
-         PossibleBorrowerMap {
-             body: mir,
-             possible_borrower,
-             maybe_live,
-             pushed: BitSet::new_empty(mir.local_decls.len()),
-             stack: Vec::with_capacity(mir.local_decls.len()),
-         }
++        let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
++        vis.visit_body(mir);
++        vis.into_map(cx, maybe_storage_live_result)
 +    }
 +
-     /// Returns true if the set of borrowers of `borrowed` living at `at` includes no more than
-     /// `borrowers`.
-     /// Notes:
-     /// 1. It would be nice if `PossibleBorrowerMap` could store `cx` so that `at_most_borrowers`
-     /// would not require it to be passed in. But a `PossibleBorrowerMap` is stored in `LintPass`
-     /// `Dereferencing`, which outlives any `LateContext`.
-     /// 2. In all current uses of `at_most_borrowers`, `borrowers` is a slice of at most two
-     /// elements. Thus, `borrowers.contains(...)` is effectively a constant-time operation. If
-     /// `at_most_borrowers`'s uses were to expand beyond this, its implementation might have to be
-     /// adjusted.
-     pub fn at_most_borrowers(
++    /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
++    pub fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
++        self.bounded_borrowers(borrowers, borrowers, borrowed, at)
++    }
++
++    /// Returns true if the set of borrowers of `borrowed` living at `at` includes at least `below`
++    /// but no more than `above`.
++    pub fn bounded_borrowers(
 +        &mut self,
-         cx: &LateContext<'tcx>,
-         borrowers: &[mir::Local],
++        below: &[mir::Local],
++        above: &[mir::Local],
 +        borrowed: mir::Local,
 +        at: mir::Location,
 +    ) -> bool {
-         if is_copy(cx, self.body.local_decls[borrowed].ty) {
-             return true;
-         }
-         self.possible_borrower.seek_before_primary_effect(at);
-         self.maybe_live.seek_before_primary_effect(at);
-         let possible_borrower = &self.possible_borrower.get().map;
-         let maybe_live = &self.maybe_live;
-         self.pushed.clear();
-         self.stack.clear();
++        self.maybe_live.seek_after_primary_effect(at);
 +
-         if let Some(borrowers) = possible_borrower.get(&borrowed) {
-             for b in borrowers.iter() {
-                 if self.pushed.insert(b) {
-                     self.stack.push(b);
-                 }
++        self.bitset.0.clear();
++        let maybe_live = &mut self.maybe_live;
++        if let Some(bitset) = self.map.get(&borrowed) {
++            for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) {
++                self.bitset.0.insert(b);
 +            }
 +        } else {
-             // Nothing borrows `borrowed` at `at`.
-             return true;
++            return false;
 +        }
 +
-         while let Some(borrower) = self.stack.pop() {
-             if maybe_live.contains(borrower) && !borrowers.contains(&borrower) {
-                 return false;
-             }
++        self.bitset.1.clear();
++        for b in below {
++            self.bitset.1.insert(*b);
++        }
 +
-             if let Some(borrowers) = possible_borrower.get(&borrower) {
-                 for b in borrowers.iter() {
-                     if self.pushed.insert(b) {
-                         self.stack.push(b);
-                     }
-                 }
-             }
++        if !self.bitset.0.superset(&self.bitset.1) {
++            return false;
++        }
++
++        for b in above {
++            self.bitset.0.remove(*b);
 +        }
 +
-         true
++        self.bitset.0.is_empty()
 +    }
 +
 +    pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool {
 +        self.maybe_live.seek_after_primary_effect(at);
 +        self.maybe_live.contains(local)
 +    }
 +}
index ba5bc9c3135daa8ca34a9eddf552dafb332af796,0000000000000000000000000000000000000000..dbf9f3b621d7aaa3c4c5531f64a4eb4b09a702e1
mode 100644,000000..100644
--- /dev/null
@@@ -1,143 -1,0 +1,143 @@@
-     1,62,0 { BOOL_THEN_SOME }
 +use std::sync::OnceLock;
 +
 +use rustc_ast::Attribute;
 +use rustc_semver::RustcVersion;
 +use rustc_session::Session;
 +use rustc_span::Span;
 +
 +use crate::attrs::get_unique_attr;
 +
 +macro_rules! msrv_aliases {
 +    ($($major:literal,$minor:literal,$patch:literal {
 +        $($name:ident),* $(,)?
 +    })*) => {
 +        $($(
 +        pub const $name: RustcVersion = RustcVersion::new($major, $minor, $patch);
 +        )*)*
 +    };
 +}
 +
 +// names may refer to stabilized feature flags or library items
 +msrv_aliases! {
 +    1,65,0 { LET_ELSE }
-     1,55,0 { SEEK_REWIND }
++    1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
 +    1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
++    1,55,0 { SEEK_REWIND }
 +    1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
 +    1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
 +    1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
 +    1,50,0 { BOOL_THEN, CLAMP }
 +    1,47,0 { TAU, IS_ASCII_DIGIT_CONST }
 +    1,46,0 { CONST_IF_MATCH }
 +    1,45,0 { STR_STRIP_PREFIX }
 +    1,43,0 { LOG2_10, LOG10_2 }
 +    1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS }
 +    1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE }
 +    1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF }
 +    1,38,0 { POINTER_CAST, REM_EUCLID }
 +    1,37,0 { TYPE_ALIAS_ENUM_VARIANTS }
 +    1,36,0 { ITERATOR_COPIED }
 +    1,35,0 { OPTION_COPIED, RANGE_CONTAINS }
 +    1,34,0 { TRY_FROM }
 +    1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
 +    1,28,0 { FROM_BOOL }
 +    1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN }
 +    1,24,0 { IS_ASCII_DIGIT }
 +    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 }
 +}
 +
 +fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
 +    if let Ok(version) = RustcVersion::parse(msrv) {
 +        return Some(version);
 +    } else if let Some(sess) = sess {
 +        if let Some(span) = span {
 +            sess.span_err(span, format!("`{msrv}` is not a valid Rust version"));
 +        }
 +    }
 +    None
 +}
 +
 +/// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]`
 +#[derive(Debug, Clone, Default)]
 +pub struct Msrv {
 +    stack: Vec<RustcVersion>,
 +}
 +
 +impl Msrv {
 +    fn new(initial: Option<RustcVersion>) -> Self {
 +        Self {
 +            stack: Vec::from_iter(initial),
 +        }
 +    }
 +
 +    fn read_inner(conf_msrv: &Option<String>, sess: &Session) -> Self {
 +        let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
 +            .ok()
 +            .and_then(|v| parse_msrv(&v, None, None));
 +        let clippy_msrv = conf_msrv.as_ref().and_then(|s| {
 +            parse_msrv(s, None, None).or_else(|| {
 +                sess.err(format!(
 +                    "error reading Clippy's configuration file. `{s}` is not a valid Rust version"
 +                ));
 +                None
 +            })
 +        });
 +
 +        // if both files have an msrv, let's compare them and emit a warning if they differ
 +        if let Some(cargo_msrv) = cargo_msrv
 +            && let Some(clippy_msrv) = clippy_msrv
 +            && clippy_msrv != cargo_msrv
 +        {
 +            sess.warn(format!(
 +                "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
 +            ));
 +        }
 +
 +        Self::new(clippy_msrv.or(cargo_msrv))
 +    }
 +
 +    /// Set the initial MSRV from the Clippy config file or from Cargo due to the `rust-version`
 +    /// field in `Cargo.toml`
 +    ///
 +    /// Returns a `&'static Msrv` as `Copy` types are more easily passed to the
 +    /// `register_{late,early}_pass` callbacks
 +    pub fn read(conf_msrv: &Option<String>, sess: &Session) -> &'static Self {
 +        static PARSED: OnceLock<Msrv> = OnceLock::new();
 +
 +        PARSED.get_or_init(|| Self::read_inner(conf_msrv, sess))
 +    }
 +
 +    pub fn current(&self) -> Option<RustcVersion> {
 +        self.stack.last().copied()
 +    }
 +
 +    pub fn meets(&self, required: RustcVersion) -> bool {
 +        self.current().map_or(true, |version| version.meets(required))
 +    }
 +
 +    fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
 +        if let Some(msrv_attr) = get_unique_attr(sess, attrs, "msrv") {
 +            if let Some(msrv) = msrv_attr.value_str() {
 +                return parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span));
 +            }
 +
 +            sess.span_err(msrv_attr.span, "bad clippy attribute");
 +        }
 +
 +        None
 +    }
 +
 +    pub fn enter_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) {
 +        if let Some(version) = Self::parse_attr(sess, attrs) {
 +            self.stack.push(version);
 +        }
 +    }
 +
 +    pub fn exit_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) {
 +        if Self::parse_attr(sess, attrs).is_some() {
 +            self.stack.pop();
 +        }
 +    }
 +}
index 9ca50105ae57d0e93c96f7b48d1030bb10011c85,0000000000000000000000000000000000000000..95eebab7567762cedd6f1606ffeef7cf61088650
mode 100644,000000..100644
--- /dev/null
@@@ -1,158 -1,0 +1,157 @@@
- pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"];
 +//! This module contains paths to types and functions Clippy needs to know
 +//! about.
 +//!
 +//! Whenever possible, please consider diagnostic items over hardcoded paths.
 +//! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information.
 +
 +#[cfg(feature = "internal")]
 +pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"];
 +#[cfg(feature = "internal")]
 +pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
 +    ["rustc_lint_defs", "Applicability", "Unspecified"],
 +    ["rustc_lint_defs", "Applicability", "HasPlaceholders"],
 +    ["rustc_lint_defs", "Applicability", "MaybeIncorrect"],
 +    ["rustc_lint_defs", "Applicability", "MachineApplicable"],
 +];
 +#[cfg(feature = "internal")]
 +pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
 +pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"];
 +pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
 +pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
 +pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
 +pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
 +pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
 +pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
 +pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
 +pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 +pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
 +pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
 +#[cfg(feature = "internal")]
 +pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 +#[cfg(feature = "internal")]
 +pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
 +pub const EXIT: [&str; 3] = ["std", "process", "exit"];
 +pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
 +pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
 +pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"];
 +pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"];
 +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 +pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
 +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 +pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
 +pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"];
 +pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"];
 +pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"];
 +#[cfg(feature = "internal")]
 +pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 +#[cfg(feature = "internal")]
 +pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
 +pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
 +pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
 +pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 +#[cfg(feature = "internal")]
 +pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 +#[cfg(feature = "internal")]
 +pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 +#[cfg(feature = "internal")]
 +pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 +#[cfg(feature = "internal")]
 +pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
 +pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
 +#[cfg(feature = "internal")]
 +pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
 +pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
 +pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
 +pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
 +pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 +pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 +pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
 +pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 +pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
 +pub const PEEKABLE: [&str; 5] = ["core", "iter", "adapters", "peekable", "Peekable"];
 +pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
 +#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
 +pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
 +pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
 +pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
 +pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
 +pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"];
 +pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"];
 +pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
 +pub const PTR_READ: [&str; 3] = ["core", "ptr", "read"];
 +pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"];
 +pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"];
 +pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"];
 +pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"];
 +pub const PTR_UNALIGNED_VOLATILE_LOAD: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_load"];
 +pub const PTR_UNALIGNED_VOLATILE_STORE: [&str; 3] = ["core", "intrinsics", "unaligned_volatile_store"];
 +pub const PTR_WRITE: [&str; 3] = ["core", "ptr", "write"];
 +pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"];
 +pub const PTR_WRITE_UNALIGNED: [&str; 3] = ["core", "ptr", "write_unaligned"];
 +pub const PTR_WRITE_VOLATILE: [&str; 3] = ["core", "ptr", "write_volatile"];
 +pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
 +pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
 +pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
 +pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
 +pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
 +pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
 +pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
 +pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
 +pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
 +pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
 +pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
 +pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 +pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 +pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
 +pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
 +pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"];
 +pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 +pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"];
 +pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
 +pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
 +pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
 +pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"];
 +pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
 +pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
 +pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 +pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
 +pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
 +pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 +pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
 +pub const STR_BYTES: [&str; 4] = ["core", "str", "<impl str>", "bytes"];
 +pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"];
 +pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
 +pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
 +pub const STR_FROM_UTF8_UNCHECKED: [&str; 4] = ["core", "str", "converts", "from_utf8_unchecked"];
 +pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
 +pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
 +#[cfg(feature = "internal")]
 +pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
 +#[cfg(feature = "internal")]
 +pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
 +#[cfg(feature = "internal")]
 +pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
 +#[cfg(feature = "internal")]
 +pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
 +#[cfg(feature = "internal")]
 +pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
 +#[cfg(feature = "internal")]
 +pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
 +pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
 +pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
 +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 +pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"];
 +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 +pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"];
 +pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
 +pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
 +pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
 +pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"];
 +pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
 +pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 +pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];
 +pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
 +pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
 +pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"];
 +pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
 +pub const INSTANT: [&str; 3] = ["std", "time", "Instant"];
index 863fb60fcfca1fb09aee2de418dcd9c0743d7855,0000000000000000000000000000000000000000..14c01a60b4c32b775e7aa5cce1ce9a242b363fd7
mode 100644,000000..100644
--- /dev/null
@@@ -1,726 -1,0 +1,737 @@@
 +use crate::ty::needs_ordered_drop;
 +use crate::{get_enclosing_block, path_to_local_id};
 +use core::ops::ControlFlow;
 +use rustc_hir as hir;
 +use rustc_hir::def::{CtorKind, DefKind, Res};
 +use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
 +use rustc_hir::{
 +    AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Let, Pat, QPath,
 +    Stmt, UnOp, UnsafeSource, Unsafety,
 +};
 +use rustc_lint::LateContext;
 +use rustc_middle::hir::nested_filter;
 +use rustc_middle::ty::adjustment::Adjust;
 +use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults};
 +use rustc_span::Span;
 +
 +mod internal {
 +    /// Trait for visitor functions to control whether or not to descend to child nodes. Implemented
 +    /// for only two types. `()` always descends. `Descend` allows controlled descent.
 +    pub trait Continue {
 +        fn descend(&self) -> bool;
 +    }
 +}
 +use internal::Continue;
 +
 +impl Continue for () {
 +    fn descend(&self) -> bool {
 +        true
 +    }
 +}
 +
 +/// Allows for controlled descent when using visitor functions. Use `()` instead when always
 +/// descending into child nodes.
 +#[derive(Clone, Copy)]
 +pub enum Descend {
 +    Yes,
 +    No,
 +}
 +impl From<bool> for Descend {
 +    fn from(from: bool) -> Self {
 +        if from { Self::Yes } else { Self::No }
 +    }
 +}
 +impl Continue for Descend {
 +    fn descend(&self) -> bool {
 +        matches!(self, Self::Yes)
 +    }
 +}
 +
 +/// A type which can be visited.
 +pub trait Visitable<'tcx> {
 +    /// Calls the corresponding `visit_*` function on the visitor.
 +    fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
 +}
 +macro_rules! visitable_ref {
 +    ($t:ident, $f:ident) => {
 +        impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
 +            fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
 +                visitor.$f(self);
 +            }
 +        }
 +    };
 +}
 +visitable_ref!(Arm, visit_arm);
 +visitable_ref!(Block, visit_block);
 +visitable_ref!(Body, visit_body);
 +visitable_ref!(Expr, visit_expr);
 +visitable_ref!(Stmt, visit_stmt);
 +
 +/// Calls the given function once for each expression contained. This does not enter any bodies or
 +/// nested items.
 +pub fn for_each_expr<'tcx, B, C: Continue>(
 +    node: impl Visitable<'tcx>,
 +    f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
 +) -> Option<B> {
 +    struct V<B, F> {
 +        f: F,
 +        res: Option<B>,
 +    }
 +    impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<B, F> {
 +        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
 +            if self.res.is_some() {
 +                return;
 +            }
 +            match (self.f)(e) {
 +                ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
 +                ControlFlow::Break(b) => self.res = Some(b),
 +                ControlFlow::Continue(_) => (),
 +            }
 +        }
 +
 +        // Avoid unnecessary `walk_*` calls.
 +        fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {}
 +        fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
 +        fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
 +        // Avoid monomorphising all `visit_*` functions.
 +        fn visit_nested_item(&mut self, _: ItemId) {}
 +    }
 +    let mut v = V { f, res: None };
 +    node.visit(&mut v);
 +    v.res
 +}
 +
 +/// Calls the given function once for each expression contained. This will enter bodies, but not
 +/// nested items.
 +pub fn for_each_expr_with_closures<'tcx, B, C: Continue>(
 +    cx: &LateContext<'tcx>,
 +    node: impl Visitable<'tcx>,
 +    f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
 +) -> Option<B> {
 +    struct V<'tcx, B, F> {
 +        tcx: TyCtxt<'tcx>,
 +        f: F,
 +        res: Option<B>,
 +    }
 +    impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, B, F> {
 +        type NestedFilter = nested_filter::OnlyBodies;
 +        fn nested_visit_map(&mut self) -> Self::Map {
 +            self.tcx.hir()
 +        }
 +
 +        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
 +            if self.res.is_some() {
 +                return;
 +            }
 +            match (self.f)(e) {
 +                ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
 +                ControlFlow::Break(b) => self.res = Some(b),
 +                ControlFlow::Continue(_) => (),
 +            }
 +        }
 +
 +        // Only walk closures
 +        fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
 +        // Avoid unnecessary `walk_*` calls.
 +        fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {}
 +        fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
 +        fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
 +        // Avoid monomorphising all `visit_*` functions.
 +        fn visit_nested_item(&mut self, _: ItemId) {}
 +    }
 +    let mut v = V {
 +        tcx: cx.tcx,
 +        f,
 +        res: None,
 +    };
 +    node.visit(&mut v);
 +    v.res
 +}
 +
 +/// returns `true` if expr contains match expr desugared from try
 +fn contains_try(expr: &hir::Expr<'_>) -> bool {
 +    for_each_expr(expr, |e| {
 +        if matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar)) {
 +            ControlFlow::Break(())
 +        } else {
 +            ControlFlow::Continue(())
 +        }
 +    })
 +    .is_some()
 +}
 +
 +pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool
 +where
 +    F: FnMut(&'hir hir::Expr<'hir>) -> bool,
 +{
 +    struct RetFinder<F> {
 +        in_stmt: bool,
 +        failed: bool,
 +        cb: F,
 +    }
 +
 +    struct WithStmtGuard<'a, F> {
 +        val: &'a mut RetFinder<F>,
 +        prev_in_stmt: bool,
 +    }
 +
 +    impl<F> RetFinder<F> {
 +        fn inside_stmt(&mut self, in_stmt: bool) -> WithStmtGuard<'_, F> {
 +            let prev_in_stmt = std::mem::replace(&mut self.in_stmt, in_stmt);
 +            WithStmtGuard {
 +                val: self,
 +                prev_in_stmt,
 +            }
 +        }
 +    }
 +
 +    impl<F> std::ops::Deref for WithStmtGuard<'_, F> {
 +        type Target = RetFinder<F>;
 +
 +        fn deref(&self) -> &Self::Target {
 +            self.val
 +        }
 +    }
 +
 +    impl<F> std::ops::DerefMut for WithStmtGuard<'_, F> {
 +        fn deref_mut(&mut self) -> &mut Self::Target {
 +            self.val
 +        }
 +    }
 +
 +    impl<F> Drop for WithStmtGuard<'_, F> {
 +        fn drop(&mut self) {
 +            self.val.in_stmt = self.prev_in_stmt;
 +        }
 +    }
 +
 +    impl<'hir, F: FnMut(&'hir hir::Expr<'hir>) -> bool> intravisit::Visitor<'hir> for RetFinder<F> {
 +        fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) {
 +            intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt);
 +        }
 +
 +        fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) {
 +            if self.failed {
 +                return;
 +            }
 +            if self.in_stmt {
 +                match expr.kind {
 +                    hir::ExprKind::Ret(Some(expr)) => self.inside_stmt(false).visit_expr(expr),
 +                    _ => intravisit::walk_expr(self, expr),
 +                }
 +            } else {
 +                match expr.kind {
 +                    hir::ExprKind::If(cond, then, else_opt) => {
 +                        self.inside_stmt(true).visit_expr(cond);
 +                        self.visit_expr(then);
 +                        if let Some(el) = else_opt {
 +                            self.visit_expr(el);
 +                        }
 +                    },
 +                    hir::ExprKind::Match(cond, arms, _) => {
 +                        self.inside_stmt(true).visit_expr(cond);
 +                        for arm in arms {
 +                            self.visit_expr(arm.body);
 +                        }
 +                    },
 +                    hir::ExprKind::Block(..) => intravisit::walk_expr(self, expr),
 +                    hir::ExprKind::Ret(Some(expr)) => self.visit_expr(expr),
 +                    _ => self.failed |= !(self.cb)(expr),
 +                }
 +            }
 +        }
 +    }
 +
 +    !contains_try(expr) && {
 +        let mut ret_finder = RetFinder {
 +            in_stmt: false,
 +            failed: false,
 +            cb: callback,
 +        };
 +        ret_finder.visit_expr(expr);
 +        !ret_finder.failed
 +    }
 +}
 +
 +/// Checks if the given resolved path is used in the given body.
 +pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
 +    for_each_expr_with_closures(cx, cx.tcx.hir().body(body).value, |e| {
 +        if let ExprKind::Path(p) = &e.kind {
 +            if cx.qpath_res(p, e.hir_id) == res {
 +                return ControlFlow::Break(());
 +            }
 +        }
 +        ControlFlow::Continue(())
 +    })
 +    .is_some()
 +}
 +
 +/// Checks if the given local is used.
 +pub fn is_local_used<'tcx>(cx: &LateContext<'tcx>, visitable: impl Visitable<'tcx>, id: HirId) -> bool {
 +    for_each_expr_with_closures(cx, visitable, |e| {
 +        if path_to_local_id(e, id) {
 +            ControlFlow::Break(())
 +        } else {
 +            ControlFlow::Continue(())
 +        }
 +    })
 +    .is_some()
 +}
 +
 +/// Checks if the given expression is a constant.
 +pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
 +    struct V<'a, 'tcx> {
 +        cx: &'a LateContext<'tcx>,
 +        is_const: bool,
 +    }
 +    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
 +        type NestedFilter = nested_filter::OnlyBodies;
 +        fn nested_visit_map(&mut self) -> Self::Map {
 +            self.cx.tcx.hir()
 +        }
 +
 +        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
 +            if !self.is_const {
 +                return;
 +            }
 +            match e.kind {
 +                ExprKind::ConstBlock(_) => return,
 +                ExprKind::Call(
 +                    &Expr {
 +                        kind: ExprKind::Path(ref p),
 +                        hir_id,
 +                        ..
 +                    },
 +                    _,
 +                ) if self
 +                    .cx
 +                    .qpath_res(p, hir_id)
 +                    .opt_def_id()
 +                    .map_or(false, |id| self.cx.tcx.is_const_fn_raw(id)) => {},
 +                ExprKind::MethodCall(..)
 +                    if self
 +                        .cx
 +                        .typeck_results()
 +                        .type_dependent_def_id(e.hir_id)
 +                        .map_or(false, |id| self.cx.tcx.is_const_fn_raw(id)) => {},
 +                ExprKind::Binary(_, lhs, rhs)
 +                    if self.cx.typeck_results().expr_ty(lhs).peel_refs().is_primitive_ty()
 +                        && self.cx.typeck_results().expr_ty(rhs).peel_refs().is_primitive_ty() => {},
 +                ExprKind::Unary(UnOp::Deref, e) if self.cx.typeck_results().expr_ty(e).is_ref() => (),
 +                ExprKind::Unary(_, e) if self.cx.typeck_results().expr_ty(e).peel_refs().is_primitive_ty() => (),
 +                ExprKind::Index(base, _)
 +                    if matches!(
 +                        self.cx.typeck_results().expr_ty(base).peel_refs().kind(),
 +                        ty::Slice(_) | ty::Array(..)
 +                    ) => {},
 +                ExprKind::Path(ref p)
 +                    if matches!(
 +                        self.cx.qpath_res(p, e.hir_id),
 +                        Res::Def(
 +                            DefKind::Const
 +                                | DefKind::AssocConst
 +                                | DefKind::AnonConst
 +                                | DefKind::ConstParam
 +                                | DefKind::Ctor(..)
 +                                | DefKind::Fn
 +                                | DefKind::AssocFn,
 +                            _
 +                        ) | Res::SelfCtor(_)
 +                    ) => {},
 +
 +                ExprKind::AddrOf(..)
 +                | ExprKind::Array(_)
 +                | ExprKind::Block(..)
 +                | ExprKind::Cast(..)
 +                | ExprKind::DropTemps(_)
 +                | ExprKind::Field(..)
 +                | ExprKind::If(..)
 +                | ExprKind::Let(..)
 +                | ExprKind::Lit(_)
 +                | ExprKind::Match(..)
 +                | ExprKind::Repeat(..)
 +                | ExprKind::Struct(..)
 +                | ExprKind::Tup(_)
 +                | ExprKind::Type(..) => (),
 +
 +                _ => {
 +                    self.is_const = false;
 +                    return;
 +                },
 +            }
 +            walk_expr(self, e);
 +        }
 +    }
 +
 +    let mut v = V { cx, is_const: true };
 +    v.visit_expr(e);
 +    v.is_const
 +}
 +
 +/// Checks if the given expression performs an unsafe operation outside of an unsafe block.
 +pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
 +    struct V<'a, 'tcx> {
 +        cx: &'a LateContext<'tcx>,
 +        is_unsafe: bool,
 +    }
 +    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
 +        type NestedFilter = nested_filter::OnlyBodies;
 +        fn nested_visit_map(&mut self) -> Self::Map {
 +            self.cx.tcx.hir()
 +        }
 +        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
 +            if self.is_unsafe {
 +                return;
 +            }
 +            match e.kind {
 +                ExprKind::Unary(UnOp::Deref, e) if self.cx.typeck_results().expr_ty(e).is_unsafe_ptr() => {
 +                    self.is_unsafe = true;
 +                },
 +                ExprKind::MethodCall(..)
 +                    if self
 +                        .cx
 +                        .typeck_results()
 +                        .type_dependent_def_id(e.hir_id)
 +                        .map_or(false, |id| self.cx.tcx.fn_sig(id).unsafety() == Unsafety::Unsafe) =>
 +                {
 +                    self.is_unsafe = true;
 +                },
 +                ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() {
 +                    ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
 +                    ty::FnPtr(sig) if sig.unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
 +                    _ => walk_expr(self, e),
 +                },
 +                ExprKind::Path(ref p)
 +                    if self
 +                        .cx
 +                        .qpath_res(p, e.hir_id)
 +                        .opt_def_id()
 +                        .map_or(false, |id| self.cx.tcx.is_mutable_static(id)) =>
 +                {
 +                    self.is_unsafe = true;
 +                },
 +                _ => walk_expr(self, e),
 +            }
 +        }
 +        fn visit_block(&mut self, b: &'tcx Block<'_>) {
 +            if !matches!(b.rules, BlockCheckMode::UnsafeBlock(_)) {
 +                walk_block(self, b);
 +            }
 +        }
 +        fn visit_nested_item(&mut self, id: ItemId) {
 +            if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind {
 +                self.is_unsafe = i.unsafety == Unsafety::Unsafe;
 +            }
 +        }
 +    }
 +    let mut v = V { cx, is_unsafe: false };
 +    v.visit_expr(e);
 +    v.is_unsafe
 +}
 +
 +/// Checks if the given expression contains an unsafe block
 +pub fn contains_unsafe_block<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
 +    struct V<'cx, 'tcx> {
 +        cx: &'cx LateContext<'tcx>,
 +        found_unsafe: bool,
 +    }
 +    impl<'tcx> Visitor<'tcx> for V<'_, 'tcx> {
 +        type NestedFilter = nested_filter::OnlyBodies;
 +        fn nested_visit_map(&mut self) -> Self::Map {
 +            self.cx.tcx.hir()
 +        }
 +
 +        fn visit_block(&mut self, b: &'tcx Block<'_>) {
 +            if self.found_unsafe {
 +                return;
 +            }
 +            if b.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) {
 +                self.found_unsafe = true;
 +                return;
 +            }
 +            walk_block(self, b);
 +        }
 +    }
 +    let mut v = V {
 +        cx,
 +        found_unsafe: false,
 +    };
 +    v.visit_expr(e);
 +    v.found_unsafe
 +}
 +
 +/// Runs the given function for each sub-expression producing the final value consumed by the parent
 +/// of the give expression.
 +///
 +/// e.g. for the following expression
 +/// ```rust,ignore
 +/// if foo {
 +///     f(0)
 +/// } else {
 +///     1 + 1
 +/// }
 +/// ```
 +/// this will pass both `f(0)` and `1+1` to the given function.
 +pub fn for_each_value_source<'tcx, B>(
 +    e: &'tcx Expr<'tcx>,
 +    f: &mut impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
 +) -> ControlFlow<B> {
 +    match e.kind {
 +        ExprKind::Block(Block { expr: Some(e), .. }, _) => for_each_value_source(e, f),
 +        ExprKind::Match(_, arms, _) => {
 +            for arm in arms {
 +                for_each_value_source(arm.body, f)?;
 +            }
 +            ControlFlow::Continue(())
 +        },
 +        ExprKind::If(_, if_expr, Some(else_expr)) => {
 +            for_each_value_source(if_expr, f)?;
 +            for_each_value_source(else_expr, f)
 +        },
 +        ExprKind::DropTemps(e) => for_each_value_source(e, f),
 +        _ => f(e),
 +    }
 +}
 +
 +/// Runs the given function for each path expression referencing the given local which occur after
 +/// the given expression.
 +pub fn for_each_local_use_after_expr<'tcx, B>(
 +    cx: &LateContext<'tcx>,
 +    local_id: HirId,
 +    expr_id: HirId,
 +    f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
 +) -> ControlFlow<B> {
 +    struct V<'cx, 'tcx, F, B> {
 +        cx: &'cx LateContext<'tcx>,
 +        local_id: HirId,
 +        expr_id: HirId,
 +        found: bool,
 +        res: ControlFlow<B>,
 +        f: F,
 +    }
 +    impl<'cx, 'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'cx, 'tcx, F, B> {
 +        type NestedFilter = nested_filter::OnlyBodies;
 +        fn nested_visit_map(&mut self) -> Self::Map {
 +            self.cx.tcx.hir()
 +        }
 +
 +        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
 +            if !self.found {
 +                if e.hir_id == self.expr_id {
 +                    self.found = true;
 +                } else {
 +                    walk_expr(self, e);
 +                }
 +                return;
 +            }
 +            if self.res.is_break() {
 +                return;
 +            }
 +            if path_to_local_id(e, self.local_id) {
 +                self.res = (self.f)(e);
 +            } else {
 +                walk_expr(self, e);
 +            }
 +        }
 +    }
 +
 +    if let Some(b) = get_enclosing_block(cx, local_id) {
 +        let mut v = V {
 +            cx,
 +            local_id,
 +            expr_id,
 +            found: false,
 +            res: ControlFlow::Continue(()),
 +            f,
 +        };
 +        v.visit_block(b);
 +        v.res
 +    } else {
 +        ControlFlow::Continue(())
 +    }
 +}
 +
 +// Calls the given function for every unconsumed temporary created by the expression. Note the
 +// function is only guaranteed to be called for types which need to be dropped, but it may be called
 +// for other types.
 +#[allow(clippy::too_many_lines)]
 +pub fn for_each_unconsumed_temporary<'tcx, B>(
 +    cx: &LateContext<'tcx>,
 +    e: &'tcx Expr<'tcx>,
 +    mut f: impl FnMut(Ty<'tcx>) -> ControlFlow<B>,
 +) -> ControlFlow<B> {
 +    // Todo: Handle partially consumed values.
 +    fn helper<'tcx, B>(
 +        typeck: &'tcx TypeckResults<'tcx>,
 +        consume: bool,
 +        e: &'tcx Expr<'tcx>,
 +        f: &mut impl FnMut(Ty<'tcx>) -> ControlFlow<B>,
 +    ) -> ControlFlow<B> {
 +        if !consume
 +            || matches!(
 +                typeck.expr_adjustments(e),
 +                [adjust, ..] if matches!(adjust.kind, Adjust::Borrow(_) | Adjust::Deref(_))
 +            )
 +        {
 +            match e.kind {
 +                ExprKind::Path(QPath::Resolved(None, p))
 +                    if matches!(p.res, Res::Def(DefKind::Ctor(_, CtorKind::Const), _)) =>
 +                {
 +                    f(typeck.expr_ty(e))?;
 +                },
 +                ExprKind::Path(_)
 +                | ExprKind::Unary(UnOp::Deref, _)
 +                | ExprKind::Index(..)
 +                | ExprKind::Field(..)
 +                | ExprKind::AddrOf(..) => (),
 +                _ => f(typeck.expr_ty(e))?,
 +            }
 +        }
 +        match e.kind {
 +            ExprKind::AddrOf(_, _, e)
 +            | ExprKind::Field(e, _)
 +            | ExprKind::Unary(UnOp::Deref, e)
 +            | ExprKind::Match(e, ..)
 +            | ExprKind::Let(&Let { init: e, .. }) => {
 +                helper(typeck, false, e, f)?;
 +            },
 +            ExprKind::Block(&Block { expr: Some(e), .. }, _)
 +            | ExprKind::Box(e)
 +            | ExprKind::Cast(e, _)
 +            | ExprKind::Unary(_, e) => {
 +                helper(typeck, true, e, f)?;
 +            },
 +            ExprKind::Call(callee, args) => {
 +                helper(typeck, true, callee, f)?;
 +                for arg in args {
 +                    helper(typeck, true, arg, f)?;
 +                }
 +            },
 +            ExprKind::MethodCall(_, receiver, args, _) => {
 +                helper(typeck, true, receiver, f)?;
 +                for arg in args {
 +                    helper(typeck, true, arg, f)?;
 +                }
 +            },
 +            ExprKind::Tup(args) | ExprKind::Array(args) => {
 +                for arg in args {
 +                    helper(typeck, true, arg, f)?;
 +                }
 +            },
 +            ExprKind::Index(borrowed, consumed)
 +            | ExprKind::Assign(borrowed, consumed, _)
 +            | ExprKind::AssignOp(_, borrowed, consumed) => {
 +                helper(typeck, false, borrowed, f)?;
 +                helper(typeck, true, consumed, f)?;
 +            },
 +            ExprKind::Binary(_, lhs, rhs) => {
 +                helper(typeck, true, lhs, f)?;
 +                helper(typeck, true, rhs, f)?;
 +            },
 +            ExprKind::Struct(_, fields, default) => {
 +                for field in fields {
 +                    helper(typeck, true, field.expr, f)?;
 +                }
 +                if let Some(default) = default {
 +                    helper(typeck, false, default, f)?;
 +                }
 +            },
 +            ExprKind::If(cond, then, else_expr) => {
 +                helper(typeck, true, cond, f)?;
 +                helper(typeck, true, then, f)?;
 +                if let Some(else_expr) = else_expr {
 +                    helper(typeck, true, else_expr, f)?;
 +                }
 +            },
 +            ExprKind::Type(e, _) => {
 +                helper(typeck, consume, e, f)?;
 +            },
 +
 +            // Either drops temporaries, jumps out of the current expression, or has no sub expression.
 +            ExprKind::DropTemps(_)
 +            | ExprKind::Ret(_)
 +            | ExprKind::Break(..)
 +            | ExprKind::Yield(..)
 +            | ExprKind::Block(..)
 +            | ExprKind::Loop(..)
 +            | ExprKind::Repeat(..)
 +            | ExprKind::Lit(_)
 +            | ExprKind::ConstBlock(_)
 +            | ExprKind::Closure { .. }
 +            | ExprKind::Path(_)
 +            | ExprKind::Continue(_)
 +            | ExprKind::InlineAsm(_)
 +            | ExprKind::Err => (),
 +        }
 +        ControlFlow::Continue(())
 +    }
 +    helper(cx.typeck_results(), true, e, &mut f)
 +}
 +
 +pub fn any_temporaries_need_ordered_drop<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
 +    for_each_unconsumed_temporary(cx, e, |ty| {
 +        if needs_ordered_drop(cx, ty) {
 +            ControlFlow::Break(())
 +        } else {
 +            ControlFlow::Continue(())
 +        }
 +    })
 +    .is_break()
 +}
 +
 +/// Runs the given function for each path expression referencing the given local which occur after
 +/// the given expression.
 +pub fn for_each_local_assignment<'tcx, B>(
 +    cx: &LateContext<'tcx>,
 +    local_id: HirId,
 +    f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
 +) -> ControlFlow<B> {
 +    struct V<'cx, 'tcx, F, B> {
 +        cx: &'cx LateContext<'tcx>,
 +        local_id: HirId,
 +        res: ControlFlow<B>,
 +        f: F,
 +    }
 +    impl<'cx, 'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'cx, 'tcx, F, B> {
 +        type NestedFilter = nested_filter::OnlyBodies;
 +        fn nested_visit_map(&mut self) -> Self::Map {
 +            self.cx.tcx.hir()
 +        }
 +
 +        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
 +            if let ExprKind::Assign(lhs, rhs, _) = e.kind
 +                && self.res.is_continue()
 +                && path_to_local_id(lhs, self.local_id)
 +            {
 +                self.res = (self.f)(rhs);
 +                self.visit_expr(rhs);
 +            } else {
 +                walk_expr(self, e);
 +            }
 +        }
 +    }
 +
 +    if let Some(b) = get_enclosing_block(cx, local_id) {
 +        let mut v = V {
 +            cx,
 +            local_id,
 +            res: ControlFlow::Continue(()),
 +            f,
 +        };
 +        v.visit_block(b);
 +        v.res
 +    } else {
 +        ControlFlow::Continue(())
 +    }
 +}
++
++pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool {
++    for_each_expr(expr, |e| {
++        if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) {
++            ControlFlow::Break(())
++        } else {
++            ControlFlow::Continue(())
++        }
++    })
++    .is_some()
++}
index 9399d422036d47e3662958ad992b8fd2080ef989,0000000000000000000000000000000000000000..40a6f47095ec2e59705f4f889ff1250a5af7065d
mode 100644,000000..100644
--- /dev/null
@@@ -1,3 -1,0 +1,3 @@@
- channel = "nightly-2022-12-29"
 +[toolchain]
++channel = "nightly-2023-01-12"
 +components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
index bcc096c570e1b7013524d3b20048903cc3d85780,0000000000000000000000000000000000000000..d521e8d883983da345bd4df530e242a97d67f186
mode 100644,000000..100644
--- /dev/null
@@@ -1,337 -1,0 +1,340 @@@
-                 args.extend(vec!["--sysroot".into(), sys_root]);
 +#![feature(rustc_private)]
 +#![feature(let_chains)]
 +#![feature(once_cell)]
 +#![feature(lint_reasons)]
 +#![cfg_attr(feature = "deny-warnings", deny(warnings))]
 +// warn on lints, that are included in `rust-lang/rust`s bootstrap
 +#![warn(rust_2018_idioms, unused_lifetimes)]
 +// warn on rustc internal lints
 +#![warn(rustc::internal)]
 +
 +// FIXME: switch to something more ergonomic here, once available.
 +// (Currently there is no way to opt into sysroot crates without `extern crate`.)
 +extern crate rustc_driver;
 +extern crate rustc_errors;
 +extern crate rustc_interface;
 +extern crate rustc_session;
 +extern crate rustc_span;
 +
 +use rustc_interface::interface;
 +use rustc_session::parse::ParseSess;
 +use rustc_span::symbol::Symbol;
 +
 +use std::borrow::Cow;
 +use std::env;
 +use std::ops::Deref;
 +use std::panic;
 +use std::path::Path;
 +use std::process::exit;
 +use std::sync::LazyLock;
 +
 +/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
 +/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
 +fn arg_value<'a, T: Deref<Target = str>>(
 +    args: &'a [T],
 +    find_arg: &str,
 +    pred: impl Fn(&str) -> bool,
 +) -> Option<&'a str> {
 +    let mut args = args.iter().map(Deref::deref);
 +    while let Some(arg) = args.next() {
 +        let mut arg = arg.splitn(2, '=');
 +        if arg.next() != Some(find_arg) {
 +            continue;
 +        }
 +
 +        match arg.next().or_else(|| args.next()) {
 +            Some(v) if pred(v) => return Some(v),
 +            _ => {},
 +        }
 +    }
 +    None
 +}
 +
 +#[test]
 +fn test_arg_value() {
 +    let args = &["--bar=bar", "--foobar", "123", "--foo"];
 +
 +    assert_eq!(arg_value(&[] as &[&str], "--foobar", |_| true), None);
 +    assert_eq!(arg_value(args, "--bar", |_| false), None);
 +    assert_eq!(arg_value(args, "--bar", |_| true), Some("bar"));
 +    assert_eq!(arg_value(args, "--bar", |p| p == "bar"), Some("bar"));
 +    assert_eq!(arg_value(args, "--bar", |p| p == "foo"), None);
 +    assert_eq!(arg_value(args, "--foobar", |p| p == "foo"), None);
 +    assert_eq!(arg_value(args, "--foobar", |p| p == "123"), Some("123"));
 +    assert_eq!(arg_value(args, "--foobar", |p| p.contains("12")), Some("123"));
 +    assert_eq!(arg_value(args, "--foo", |_| true), None);
 +}
 +
 +fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>) {
 +    parse_sess.env_depinfo.get_mut().insert((
 +        Symbol::intern("CLIPPY_ARGS"),
 +        args_env_var.as_deref().map(Symbol::intern),
 +    ));
 +}
 +
 +/// Track files that may be accessed at runtime in `file_depinfo` so that cargo will re-run clippy
 +/// when any of them are modified
 +fn track_files(parse_sess: &mut ParseSess, conf_path_string: Option<String>) {
 +    let file_depinfo = parse_sess.file_depinfo.get_mut();
 +
 +    // Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver`
 +    // with the current directory set to `CARGO_MANIFEST_DIR` so a relative path is fine
 +    if Path::new("Cargo.toml").exists() {
 +        file_depinfo.insert(Symbol::intern("Cargo.toml"));
 +    }
 +
 +    // `clippy.toml`
 +    if let Some(path) = conf_path_string {
 +        file_depinfo.insert(Symbol::intern(&path));
 +    }
 +
 +    // During development track the `clippy-driver` executable so that cargo will re-run clippy whenever
 +    // it is rebuilt
 +    #[expect(
 +        clippy::collapsible_if,
 +        reason = "Due to a bug in let_chains this if statement can't be collapsed"
 +    )]
 +    if cfg!(debug_assertions) {
 +        if let Ok(current_exe) = env::current_exe()
 +            && let Some(current_exe) = current_exe.to_str()
 +        {
 +            file_depinfo.insert(Symbol::intern(current_exe));
 +        }
 +    }
 +}
 +
 +struct DefaultCallbacks;
 +impl rustc_driver::Callbacks for DefaultCallbacks {}
 +
 +/// This is different from `DefaultCallbacks` that it will inform Cargo to track the value of
 +/// `CLIPPY_ARGS` environment variable.
 +struct RustcCallbacks {
 +    clippy_args_var: Option<String>,
 +}
 +
 +impl rustc_driver::Callbacks for RustcCallbacks {
 +    fn config(&mut self, config: &mut interface::Config) {
 +        let clippy_args_var = self.clippy_args_var.take();
 +        config.parse_sess_created = Some(Box::new(move |parse_sess| {
 +            track_clippy_args(parse_sess, &clippy_args_var);
 +        }));
 +    }
 +}
 +
 +struct ClippyCallbacks {
 +    clippy_args_var: Option<String>,
 +}
 +
 +impl rustc_driver::Callbacks for ClippyCallbacks {
 +    // JUSTIFICATION: necessary in clippy driver to set `mir_opt_level`
 +    #[allow(rustc::bad_opt_access)]
 +    fn config(&mut self, config: &mut interface::Config) {
 +        let conf_path = clippy_lints::lookup_conf_file();
 +        let conf_path_string = if let Ok(Some(path)) = &conf_path {
 +            path.to_str().map(String::from)
 +        } else {
 +            None
 +        };
 +
 +        let previous = config.register_lints.take();
 +        let clippy_args_var = self.clippy_args_var.take();
 +        config.parse_sess_created = Some(Box::new(move |parse_sess| {
 +            track_clippy_args(parse_sess, &clippy_args_var);
 +            track_files(parse_sess, conf_path_string);
 +        }));
 +        config.register_lints = Some(Box::new(move |sess, lint_store| {
 +            // technically we're ~guaranteed that this is none but might as well call anything that
 +            // is there already. Certainly it can't hurt.
 +            if let Some(previous) = &previous {
 +                (previous)(sess, lint_store);
 +            }
 +
 +            let conf = clippy_lints::read_conf(sess, &conf_path);
 +            clippy_lints::register_plugins(lint_store, sess, &conf);
 +            clippy_lints::register_pre_expansion_lints(lint_store, sess, &conf);
 +            clippy_lints::register_renamed(lint_store);
 +        }));
 +
 +        // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
 +        // run on the unoptimized MIR. On the other hand this results in some false negatives. If
 +        // MIR passes can be enabled / disabled separately, we should figure out, what passes to
 +        // use for Clippy.
 +        config.opts.unstable_opts.mir_opt_level = Some(0);
 +    }
 +}
 +
 +fn display_help() {
 +    println!(
 +        "\
 +Checks a package to catch common mistakes and improve your Rust code.
 +
 +Usage:
 +    cargo clippy [options] [--] [<opts>...]
 +
 +Common options:
 +    -h, --help               Print this message
 +        --rustc              Pass all args to rustc
 +    -V, --version            Print version info and exit
 +
 +Other options are the same as `cargo check`.
 +
 +To allow or deny a lint from the command line you can use `cargo clippy --`
 +with:
 +
 +    -W --warn OPT       Set lint warnings
 +    -A --allow OPT      Set lint allowed
 +    -D --deny OPT       Set lint denied
 +    -F --forbid OPT     Set lint forbidden
 +
 +You can use tool lints to allow or deny lints from your code, eg.:
 +
 +    #[allow(clippy::needless_lifetimes)]
 +"
 +    );
 +}
 +
 +const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new";
 +
 +type PanicCallback = dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static;
 +static ICE_HOOK: LazyLock<Box<PanicCallback>> = LazyLock::new(|| {
 +    let hook = panic::take_hook();
 +    panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
 +    hook
 +});
 +
 +fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
 +    // Invoke our ICE handler, which prints the actual panic message and optionally a backtrace
 +    (*ICE_HOOK)(info);
 +
 +    // Separate the output with an empty line
 +    eprintln!();
 +
 +    let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
 +    let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
 +        rustc_errors::ColorConfig::Auto,
 +        None,
 +        None,
 +        fallback_bundle,
 +        false,
 +        false,
 +        None,
 +        false,
 +        false,
 +    ));
 +    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
 +
 +    // a .span_bug or .bug call has already printed what
 +    // it wants to print.
 +    if !info.payload().is::<rustc_errors::ExplicitBug>() {
 +        let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
 +        handler.emit_diagnostic(&mut d);
 +    }
 +
 +    let version_info = rustc_tools_util::get_version_info!();
 +
 +    let xs: Vec<Cow<'static, str>> = vec![
 +        "the compiler unexpectedly panicked. this is a bug.".into(),
 +        format!("we would appreciate a bug report: {bug_report_url}").into(),
 +        format!("Clippy version: {version_info}").into(),
 +    ];
 +
 +    for note in &xs {
 +        handler.note_without_error(note.as_ref());
 +    }
 +
 +    // If backtraces are enabled, also print the query stack
 +    let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
 +
 +    let num_frames = if backtrace { None } else { Some(2) };
 +
 +    interface::try_print_query_stack(&handler, num_frames);
 +}
 +
 +#[allow(clippy::too_many_lines)]
 +pub fn main() {
 +    rustc_driver::init_rustc_env_logger();
 +    LazyLock::force(&ICE_HOOK);
 +    exit(rustc_driver::catch_with_exit_code(move || {
 +        let mut orig_args: Vec<String> = env::args().collect();
++        let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some();
 +
 +        let sys_root_env = std::env::var("SYSROOT").ok();
 +        let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
 +            if let Some(sys_root) = sys_root_env {
++                if !has_sysroot_arg {
++                    args.extend(vec!["--sysroot".into(), sys_root]);
++                }
 +            };
 +        };
 +
 +        // make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc"
 +        // for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver
 +        // uses
 +        if let Some(pos) = orig_args.iter().position(|arg| arg == "--rustc") {
 +            orig_args.remove(pos);
 +            orig_args[0] = "rustc".to_string();
 +
 +            let mut args: Vec<String> = orig_args.clone();
 +            pass_sysroot_env_if_given(&mut args, sys_root_env);
 +
 +            return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
 +        }
 +
 +        if orig_args.iter().any(|a| a == "--version" || a == "-V") {
 +            let version_info = rustc_tools_util::get_version_info!();
 +            println!("{version_info}");
 +            exit(0);
 +        }
 +
 +        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
 +        // We're invoking the compiler programmatically, so we ignore this/
 +        let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref());
 +
 +        if wrapper_mode {
 +            // we still want to be able to invoke it normally though
 +            orig_args.remove(1);
 +        }
 +
 +        if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
 +            display_help();
 +            exit(0);
 +        }
 +
 +        let mut args: Vec<String> = orig_args.clone();
 +        pass_sysroot_env_if_given(&mut args, sys_root_env);
 +
 +        let mut no_deps = false;
 +        let clippy_args_var = env::var("CLIPPY_ARGS").ok();
 +        let clippy_args = clippy_args_var
 +            .as_deref()
 +            .unwrap_or_default()
 +            .split("__CLIPPY_HACKERY__")
 +            .filter_map(|s| match s {
 +                "" => None,
 +                "--no-deps" => {
 +                    no_deps = true;
 +                    None
 +                },
 +                _ => Some(s.to_string()),
 +            })
 +            .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()])
 +            .collect::<Vec<String>>();
 +
 +        // We enable Clippy if one of the following conditions is met
 +        // - IF Clippy is run on its test suite OR
 +        // - IF Clippy is run on the main crate, not on deps (`!cap_lints_allow`) THEN
 +        //    - IF `--no-deps` is not set (`!no_deps`) OR
 +        //    - IF `--no-deps` is set and Clippy is run on the specified primary package
 +        let cap_lints_allow = arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_some()
 +            && arg_value(&orig_args, "--force-warn", |val| val.contains("clippy::")).is_none();
 +        let in_primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok();
 +
 +        let clippy_enabled = !cap_lints_allow && (!no_deps || in_primary_package);
 +        if clippy_enabled {
 +            args.extend(clippy_args);
 +            rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }).run()
 +        } else {
 +            rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }).run()
 +        }
 +    }))
 +}
index 818ff70b33f4d0b04cac4d75206b08ede5671c1f,0000000000000000000000000000000000000000..a771d8b87c81a4bcec3b0ed4cd14829bcad2f191
mode 100644,000000..100644
--- /dev/null
@@@ -1,92 -1,0 +1,101 @@@
++//! This test is meant to only be run in CI. To run it locally use:
++//!
++//! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
++//!
++//! You can use a different `INTEGRATION` value to test different repositories.
++//!
++//! This test will clone the specified repository and run Clippy on it. The test succeeds, if
++//! Clippy doesn't produce an ICE. Lint warnings are ignored by this test.
++
 +#![cfg(feature = "integration")]
 +#![cfg_attr(feature = "deny-warnings", deny(warnings))]
 +#![warn(rust_2018_idioms, unused_lifetimes)]
 +
 +use std::env;
 +use std::ffi::OsStr;
 +use std::process::Command;
 +
 +#[cfg(not(windows))]
 +const CARGO_CLIPPY: &str = "cargo-clippy";
 +#[cfg(windows)]
 +const CARGO_CLIPPY: &str = "cargo-clippy.exe";
 +
 +#[cfg_attr(feature = "integration", test)]
 +fn integration_test() {
 +    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
 +    let repo_url = format!("https://github.com/{repo_name}");
 +    let crate_name = repo_name
 +        .split('/')
 +        .nth(1)
 +        .expect("repo name should have format `<org>/<name>`");
 +
 +    let mut repo_dir = tempfile::tempdir().expect("couldn't create temp dir").into_path();
 +    repo_dir.push(crate_name);
 +
 +    let st = Command::new("git")
 +        .args([
 +            OsStr::new("clone"),
 +            OsStr::new("--depth=1"),
 +            OsStr::new(&repo_url),
 +            OsStr::new(&repo_dir),
 +        ])
 +        .status()
 +        .expect("unable to run git");
 +    assert!(st.success());
 +
 +    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
 +    let target_dir = std::path::Path::new(&root_dir).join("target");
 +    let clippy_binary = target_dir.join(env!("PROFILE")).join(CARGO_CLIPPY);
 +
 +    let output = Command::new(clippy_binary)
 +        .current_dir(repo_dir)
 +        .env("RUST_BACKTRACE", "full")
 +        .env("CARGO_TARGET_DIR", target_dir)
 +        .args([
 +            "clippy",
 +            "--all-targets",
 +            "--all-features",
 +            "--",
 +            "--cap-lints",
 +            "warn",
 +            "-Wclippy::pedantic",
 +            "-Wclippy::nursery",
 +        ])
 +        .output()
 +        .expect("unable to run clippy");
 +
 +    let stderr = String::from_utf8_lossy(&output.stderr);
 +    if let Some(backtrace_start) = stderr.find("error: internal compiler error") {
 +        static BACKTRACE_END_MSG: &str = "end of query stack";
 +        let backtrace_end = stderr[backtrace_start..]
 +            .find(BACKTRACE_END_MSG)
 +            .expect("end of backtrace not found");
 +
 +        panic!(
 +            "internal compiler error\nBacktrace:\n\n{}",
 +            &stderr[backtrace_start..backtrace_start + backtrace_end + BACKTRACE_END_MSG.len()]
 +        );
 +    } else if stderr.contains("query stack during panic") {
 +        panic!("query stack during panic in the output");
 +    } else if stderr.contains("E0463") {
 +        // Encountering E0463 (can't find crate for `x`) did _not_ cause the build to fail in the
 +        // past. Even though it should have. That's why we explicitly panic here.
 +        // See PR #3552 and issue #3523 for more background.
 +        panic!("error: E0463");
 +    } else if stderr.contains("E0514") {
 +        panic!("incompatible crate versions");
 +    } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
 +        panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
 +    } else {
 +        assert!(
 +            !stderr.contains("toolchain") || !stderr.contains("is not installed"),
 +            "missing required toolchain"
 +        );
 +    }
 +
 +    match output.status.code() {
 +        Some(0) => println!("Compilation successful"),
 +        Some(code) => eprintln!("Compilation failed. Exit code: {code}"),
 +        None => panic!("Process terminated by signal"),
 +    }
 +}
index 36db9e54a228854ac09f5953faedbc07e6ee90ec,0000000000000000000000000000000000000000..fb5b1b193f8415b012b0756e48bb3d86200d4e68
mode 100644,000000..100644
--- /dev/null
@@@ -1,118 -1,0 +1,118 @@@
-     // is specifically on the list
 +#![warn(clippy::arithmetic_side_effects)]
 +
 +use core::ops::{Add, Neg};
 +
 +macro_rules! create {
 +    ($name:ident) => {
 +        #[allow(clippy::arithmetic_side_effects)]
 +        #[derive(Clone, Copy)]
 +        struct $name;
 +
 +        impl Add<$name> for $name {
 +            type Output = $name;
 +            fn add(self, other: $name) -> Self::Output {
 +                todo!()
 +            }
 +        }
 +
 +        impl Add<i32> for $name {
 +            type Output = $name;
 +            fn add(self, other: i32) -> Self::Output {
 +                todo!()
 +            }
 +        }
 +
 +        impl Add<$name> for i32 {
 +            type Output = $name;
 +            fn add(self, other: $name) -> Self::Output {
 +                todo!()
 +            }
 +        }
 +
 +        impl Add<i64> for $name {
 +            type Output = $name;
 +            fn add(self, other: i64) -> Self::Output {
 +                todo!()
 +            }
 +        }
 +
 +        impl Add<$name> for i64 {
 +            type Output = $name;
 +            fn add(self, other: $name) -> Self::Output {
 +                todo!()
 +            }
 +        }
 +
 +        impl Neg for $name {
 +            type Output = $name;
 +            fn neg(self) -> Self::Output {
 +                todo!()
 +            }
 +        }
 +    };
 +}
 +
 +create!(Foo);
 +create!(Bar);
 +create!(Baz);
 +create!(OutOfNames);
 +
 +fn lhs_and_rhs_are_equal() {
 +    // is explicitly on the list
 +    let _ = OutOfNames + OutOfNames;
 +    // is explicitly on the list
 +    let _ = Foo + Foo;
 +    // is implicitly on the list
 +    let _ = Bar + Bar;
 +    // not on the list
 +    let _ = Baz + Baz;
 +}
 +
 +fn lhs_is_different() {
 +    // is explicitly on the list
 +    let _ = 1i32 + OutOfNames;
 +    // is explicitly on the list
 +    let _ = 1i32 + Foo;
 +    // is implicitly on the list
 +    let _ = 1i32 + Bar;
 +    // not on the list
 +    let _ = 1i32 + Baz;
 +
 +    // not on the list
 +    let _ = 1i64 + Foo;
 +    // is implicitly on the list
 +    let _ = 1i64 + Bar;
 +    // not on the list
 +    let _ = 1i64 + Baz;
 +}
 +
 +fn rhs_is_different() {
 +    // is explicitly on the list
 +    let _ = OutOfNames + 1i32;
 +    // is explicitly on the list
 +    let _ = Foo + 1i32;
 +    // is implicitly on the list
 +    let _ = Bar + 1i32;
 +    // not on the list
 +    let _ = Baz + 1i32;
 +
 +    // not on the list
 +    let _ = Foo + 1i64;
 +    // is implicitly on the list
 +    let _ = Bar + 1i64;
 +    // not on the list
 +    let _ = Baz + 1i64;
 +}
 +
 +fn unary() {
 +    // is explicitly on the list
 +    let _ = -OutOfNames;
++    // is explicitly on the list
 +    let _ = -Foo;
 +    // not on the list
 +    let _ = -Bar;
 +    // not on the list
 +    let _ = -Baz;
 +}
 +
 +fn main() {}
index 46efb86dcfc5f5c1384b81628302619c396d53cb,0000000000000000000000000000000000000000..859383a71194fd2d64d62241f7a574d9c1204096
mode 100644,000000..100644
--- /dev/null
@@@ -1,102 -1,0 +1,102 @@@
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:5:22
 +   |
 +LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
 +   |                      ^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = note: `-D clippy::dbg-macro` implied by `-D warnings`
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
 +   |                      ~~~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:9:8
 +   |
 +LL |     if dbg!(n <= 1) {
 +   |        ^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     if n <= 1 {
 +   |        ~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:10:9
 +   |
 +LL |         dbg!(1)
 +   |         ^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |         1
 +   |
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:12:9
 +   |
 +LL |         dbg!(n * factorial(n - 1))
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |         n * factorial(n - 1)
 +   |
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:17:5
 +   |
 +LL |     dbg!(42);
 +   |     ^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     42;
 +   |     ~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:18:5
 +   |
 +LL |     dbg!(dbg!(dbg!(42)));
 +   |     ^^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     dbg!(dbg!(42));
 +   |     ~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:19:14
 +   |
 +LL |     foo(3) + dbg!(factorial(4));
 +   |              ^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     foo(3) + factorial(4);
 +   |              ~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:20:5
 +   |
 +LL |     dbg!(1, 2, dbg!(3, 4));
 +   |     ^^^^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     (1, 2, dbg!(3, 4));
 +   |     ~~~~~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:21:5
 +   |
 +LL |     dbg!(1, 2, 3, 4, 5);
 +   |     ^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     (1, 2, 3, 4, 5);
 +   |     ~~~~~~~~~~~~~~~
 +
 +error: aborting due to 9 previous errors
 +
index b5ed8988a518ff9299bc679ce8a5c0d9efb4f104,0000000000000000000000000000000000000000..918cf81c600af08db4573d83b6ca2dcceb3b4310
mode 100644,000000..100644
--- /dev/null
@@@ -1,228 -1,0 +1,373 @@@
-     ( $( $_trait:ident, $ty:ty, $method:ident; )* ) => {
 +#![allow(
 +    clippy::assign_op_pattern,
 +    clippy::erasing_op,
 +    clippy::identity_op,
++    clippy::no_effect,
 +    clippy::op_ref,
 +    clippy::unnecessary_owned_empty_strings,
 +    arithmetic_overflow,
 +    unconditional_panic
 +)]
 +#![feature(const_mut_refs, inline_const, saturating_int_impl)]
 +#![warn(clippy::arithmetic_side_effects)]
 +
 +use core::num::{Saturating, Wrapping};
 +
++#[derive(Clone, Copy)]
 +pub struct Custom;
 +
 +macro_rules! impl_arith {
-             impl core::ops::$_trait<$ty> for Custom {
-                 type Output = Self;
-                 fn $method(self, _: $ty) -> Self::Output { Self }
++    ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
 +        $(
-     Add, i32, add;
-     Div, i32, div;
-     Mul, i32, mul;
-     Sub, i32, sub;
-     Add, f64, add;
-     Div, f64, div;
-     Mul, f64, mul;
-     Sub, f64, sub;
++            impl core::ops::$_trait<$lhs> for $rhs {
++                type Output = Custom;
++                fn $method(self, _: $lhs) -> Self::Output { todo!() }
++            }
++        )*
++    }
++}
++
++macro_rules! impl_assign_arith {
++    ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
++        $(
++            impl core::ops::$_trait<$lhs> for $rhs {
++                fn $method(&mut self, _: $lhs) {}
 +            }
 +        )*
 +    }
 +}
 +
 +impl_arith!(
- pub fn runtime_ops() {
++    Add, Custom, Custom, add;
++    Div, Custom, Custom, div;
++    Mul, Custom, Custom, mul;
++    Rem, Custom, Custom, rem;
++    Sub, Custom, Custom, sub;
++
++    Add, Custom, &Custom, add;
++    Div, Custom, &Custom, div;
++    Mul, Custom, &Custom, mul;
++    Rem, Custom, &Custom, rem;
++    Sub, Custom, &Custom, sub;
++
++    Add, &Custom, Custom, add;
++    Div, &Custom, Custom, div;
++    Mul, &Custom, Custom, mul;
++    Rem, &Custom, Custom, rem;
++    Sub, &Custom, Custom, sub;
++
++    Add, &Custom, &Custom, add;
++    Div, &Custom, &Custom, div;
++    Mul, &Custom, &Custom, mul;
++    Rem, &Custom, &Custom, rem;
++    Sub, &Custom, &Custom, sub;
++);
++
++impl_assign_arith!(
++    AddAssign, Custom, Custom, add_assign;
++    DivAssign, Custom, Custom, div_assign;
++    MulAssign, Custom, Custom, mul_assign;
++    RemAssign, Custom, Custom, rem_assign;
++    SubAssign, Custom, Custom, sub_assign;
++
++    AddAssign, Custom, &Custom, add_assign;
++    DivAssign, Custom, &Custom, div_assign;
++    MulAssign, Custom, &Custom, mul_assign;
++    RemAssign, Custom, &Custom, rem_assign;
++    SubAssign, Custom, &Custom, sub_assign;
++
++    AddAssign, &Custom, Custom, add_assign;
++    DivAssign, &Custom, Custom, div_assign;
++    MulAssign, &Custom, Custom, mul_assign;
++    RemAssign, &Custom, Custom, rem_assign;
++    SubAssign, &Custom, Custom, sub_assign;
++
++    AddAssign, &Custom, &Custom, add_assign;
++    DivAssign, &Custom, &Custom, div_assign;
++    MulAssign, &Custom, &Custom, mul_assign;
++    RemAssign, &Custom, &Custom, rem_assign;
++    SubAssign, &Custom, &Custom, sub_assign;
 +);
 +
++impl core::ops::Neg for Custom {
++    type Output = Custom;
++    fn neg(self) -> Self::Output {
++        todo!()
++    }
++}
++impl core::ops::Neg for &Custom {
++    type Output = Custom;
++    fn neg(self) -> Self::Output {
++        todo!()
++    }
++}
++
 +pub fn association_with_structures_should_not_trigger_the_lint() {
 +    enum Foo {
 +        Bar = -2,
 +    }
 +
 +    impl Trait for Foo {
 +        const ASSOC: i32 = {
 +            let _: [i32; 1 + 1];
 +            fn foo() {}
 +            1 + 1
 +        };
 +    }
 +
 +    struct Baz([i32; 1 + 1]);
 +
 +    trait Trait {
 +        const ASSOC: i32 = 1 + 1;
 +    }
 +
 +    type Alias = [i32; 1 + 1];
 +
 +    union Qux {
 +        field: [i32; 1 + 1],
 +    }
 +
 +    let _: [i32; 1 + 1] = [0, 0];
 +
 +    let _: [i32; 1 + 1] = {
 +        let a: [i32; 1 + 1] = [0, 0];
 +        a
 +    };
 +}
 +
 +pub fn hard_coded_allowed() {
 +    let _ = 1f32 + 1f32;
 +    let _ = 1f64 + 1f64;
 +
 +    let _ = Saturating(0u32) + Saturating(0u32);
 +    let _ = String::new() + "";
 +    let _ = Wrapping(0u32) + Wrapping(0u32);
 +
 +    let saturating: Saturating<u32> = Saturating(0u32);
 +    let string: String = String::new();
 +    let wrapping: Wrapping<u32> = Wrapping(0u32);
 +
 +    let inferred_saturating = saturating + saturating;
 +    let inferred_string = string + "";
 +    let inferred_wrapping = wrapping + wrapping;
 +
 +    let _ = inferred_saturating + inferred_saturating;
 +    let _ = inferred_string + "";
 +    let _ = inferred_wrapping + inferred_wrapping;
 +}
 +
 +#[rustfmt::skip]
 +pub fn const_ops_should_not_trigger_the_lint() {
 +    const _: i32 = { let mut n = 1; n += 1; n };
 +    let _ = const { let mut n = 1; n += 1; n };
 +
 +    const _: i32 = { let mut n = 1; n = n + 1; n };
 +    let _ = const { let mut n = 1; n = n + 1; n };
 +
 +    const _: i32 = { let mut n = 1; n = 1 + n; n };
 +    let _ = const { let mut n = 1; n = 1 + n; n };
 +
 +    const _: i32 = 1 + 1;
 +    let _ = const { 1 + 1 };
 +
 +    const _: i32 = { let mut n = 1; n = -1; n = -(-1); n = -n; n };
 +    let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
 +}
 +
 +pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_trigger_the_lint() {
 +    let mut _n = i32::MAX;
 +
 +    // Assign
 +    _n += 0;
 +    _n += &0;
 +    _n -= 0;
 +    _n -= &0;
 +    _n /= 99;
 +    _n /= &99;
 +    _n %= 99;
 +    _n %= &99;
 +    _n *= 0;
 +    _n *= &0;
 +    _n *= 1;
 +    _n *= &1;
++    _n += -0;
++    _n += &-0;
++    _n -= -0;
++    _n -= &-0;
++    _n /= -99;
++    _n /= &-99;
++    _n %= -99;
++    _n %= &-99;
++    _n *= -0;
++    _n *= &-0;
++    _n *= -1;
++    _n *= &-1;
 +
 +    // Binary
 +    _n = _n + 0;
 +    _n = _n + &0;
 +    _n = 0 + _n;
 +    _n = &0 + _n;
 +    _n = _n - 0;
 +    _n = _n - &0;
 +    _n = 0 - _n;
 +    _n = &0 - _n;
 +    _n = _n / 99;
 +    _n = _n / &99;
 +    _n = _n % 99;
 +    _n = _n % &99;
 +    _n = _n * 0;
 +    _n = _n * &0;
 +    _n = 0 * _n;
 +    _n = &0 * _n;
 +    _n = _n * 1;
 +    _n = _n * &1;
 +    _n = 1 * _n;
 +    _n = &1 * _n;
 +    _n = 23 + 85;
 +
 +    // Unary
 +    _n = -2147483647;
 +    _n = -i32::MAX;
 +    _n = -i32::MIN;
 +    _n = -&2147483647;
 +    _n = -&i32::MAX;
 +    _n = -&i32::MIN;
 +}
 +
-     // Custom
-     let _ = Custom + 0;
-     let _ = Custom + 1;
-     let _ = Custom + 2;
-     let _ = Custom + 0.0;
-     let _ = Custom + 1.0;
-     let _ = Custom + 2.0;
-     let _ = Custom - 0;
-     let _ = Custom - 1;
-     let _ = Custom - 2;
-     let _ = Custom - 0.0;
-     let _ = Custom - 1.0;
-     let _ = Custom - 2.0;
-     let _ = Custom / 0;
-     let _ = Custom / 1;
-     let _ = Custom / 2;
-     let _ = Custom / 0.0;
-     let _ = Custom / 1.0;
-     let _ = Custom / 2.0;
-     let _ = Custom * 0;
-     let _ = Custom * 1;
-     let _ = Custom * 2;
-     let _ = Custom * 0.0;
-     let _ = Custom * 1.0;
-     let _ = Custom * 2.0;
++pub fn unknown_ops_or_runtime_ops_that_can_overflow() {
 +    let mut _n = i32::MAX;
++    let mut _custom = Custom;
 +
 +    // Assign
 +    _n += 1;
 +    _n += &1;
 +    _n -= 1;
 +    _n -= &1;
 +    _n /= 0;
 +    _n /= &0;
 +    _n %= 0;
 +    _n %= &0;
 +    _n *= 2;
 +    _n *= &2;
++    _n += -1;
++    _n += &-1;
++    _n -= -1;
++    _n -= &-1;
++    _n /= -0;
++    _n /= &-0;
++    _n %= -0;
++    _n %= &-0;
++    _n *= -2;
++    _n *= &-2;
++    _custom += Custom;
++    _custom += &Custom;
++    _custom -= Custom;
++    _custom -= &Custom;
++    _custom /= Custom;
++    _custom /= &Custom;
++    _custom %= Custom;
++    _custom %= &Custom;
++    _custom *= Custom;
++    _custom *= &Custom;
++    _custom += -Custom;
++    _custom += &-Custom;
++    _custom -= -Custom;
++    _custom -= &-Custom;
++    _custom /= -Custom;
++    _custom /= &-Custom;
++    _custom %= -Custom;
++    _custom %= &-Custom;
++    _custom *= -Custom;
++    _custom *= &-Custom;
 +
 +    // Binary
 +    _n = _n + 1;
 +    _n = _n + &1;
 +    _n = 1 + _n;
 +    _n = &1 + _n;
 +    _n = _n - 1;
 +    _n = _n - &1;
 +    _n = 1 - _n;
 +    _n = &1 - _n;
 +    _n = _n / 0;
 +    _n = _n / &0;
 +    _n = _n % 0;
 +    _n = _n % &0;
 +    _n = _n * 2;
 +    _n = _n * &2;
 +    _n = 2 * _n;
 +    _n = &2 * _n;
 +    _n = 23 + &85;
 +    _n = &23 + 85;
 +    _n = &23 + &85;
++    _custom = _custom + _custom;
++    _custom = _custom + &_custom;
++    _custom = Custom + _custom;
++    _custom = &Custom + _custom;
++    _custom = _custom - Custom;
++    _custom = _custom - &Custom;
++    _custom = Custom - _custom;
++    _custom = &Custom - _custom;
++    _custom = _custom / Custom;
++    _custom = _custom / &Custom;
++    _custom = _custom % Custom;
++    _custom = _custom % &Custom;
++    _custom = _custom * Custom;
++    _custom = _custom * &Custom;
++    _custom = Custom * _custom;
++    _custom = &Custom * _custom;
++    _custom = Custom + &Custom;
++    _custom = &Custom + Custom;
++    _custom = &Custom + &Custom;
 +
 +    // Unary
 +    _n = -_n;
 +    _n = -&_n;
++    _custom = -_custom;
++    _custom = -&_custom;
++}
++
++// Copied and pasted from the `integer_arithmetic` lint for comparison.
++pub fn integer_arithmetic() {
++    let mut i = 1i32;
++    let mut var1 = 0i32;
++    let mut var2 = -1i32;
++
++    1 + i;
++    i * 2;
++    1 % i / 2;
++    i - 2 + 2 - i;
++    -i;
++    i >> 1;
++    i << 1;
++
++    -1;
++    -(-1);
++
++    i & 1;
++    i | 1;
++    i ^ 1;
++
++    i += 1;
++    i -= 1;
++    i *= 2;
++    i /= 2;
++    i /= 0;
++    i /= -1;
++    i /= var1;
++    i /= var2;
++    i %= 2;
++    i %= 0;
++    i %= -1;
++    i %= var1;
++    i %= var2;
++    i <<= 3;
++    i >>= 2;
++
++    i |= 1;
++    i &= 1;
++    i ^= i;
 +}
 +
 +fn main() {}
index 9fe4b7cf28d8d3fc4ee574fa194d060adc6f3d8f,0000000000000000000000000000000000000000..5e349f6b497cd00e19c82bb49088be1173115577
mode 100644,000000..100644
--- /dev/null
@@@ -1,334 -1,0 +1,598 @@@
-   --> $DIR/arithmetic_side_effects.rs:165:5
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:166:5
++  --> $DIR/arithmetic_side_effects.rs:243:5
 +   |
 +LL |     _n += 1;
 +   |     ^^^^^^^
 +   |
 +   = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:167:5
++  --> $DIR/arithmetic_side_effects.rs:244:5
 +   |
 +LL |     _n += &1;
 +   |     ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:168:5
++  --> $DIR/arithmetic_side_effects.rs:245:5
 +   |
 +LL |     _n -= 1;
 +   |     ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:169:5
++  --> $DIR/arithmetic_side_effects.rs:246:5
 +   |
 +LL |     _n -= &1;
 +   |     ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:170:5
++  --> $DIR/arithmetic_side_effects.rs:247:5
 +   |
 +LL |     _n /= 0;
 +   |     ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:171:5
++  --> $DIR/arithmetic_side_effects.rs:248:5
 +   |
 +LL |     _n /= &0;
 +   |     ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:172:5
++  --> $DIR/arithmetic_side_effects.rs:249:5
 +   |
 +LL |     _n %= 0;
 +   |     ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:173:5
++  --> $DIR/arithmetic_side_effects.rs:250:5
 +   |
 +LL |     _n %= &0;
 +   |     ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:174:5
++  --> $DIR/arithmetic_side_effects.rs:251:5
 +   |
 +LL |     _n *= 2;
 +   |     ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:177:10
++  --> $DIR/arithmetic_side_effects.rs:252:5
 +   |
 +LL |     _n *= &2;
 +   |     ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:178:10
++  --> $DIR/arithmetic_side_effects.rs:253:5
++   |
++LL |     _n += -1;
++   |     ^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:254:5
++   |
++LL |     _n += &-1;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:255:5
++   |
++LL |     _n -= -1;
++   |     ^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:256:5
++   |
++LL |     _n -= &-1;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:257:5
++   |
++LL |     _n /= -0;
++   |     ^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:258:5
++   |
++LL |     _n /= &-0;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:259:5
++   |
++LL |     _n %= -0;
++   |     ^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:260:5
++   |
++LL |     _n %= &-0;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:261:5
++   |
++LL |     _n *= -2;
++   |     ^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:262:5
++   |
++LL |     _n *= &-2;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:263:5
++   |
++LL |     _custom += Custom;
++   |     ^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:264:5
++   |
++LL |     _custom += &Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:265:5
++   |
++LL |     _custom -= Custom;
++   |     ^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:266:5
++   |
++LL |     _custom -= &Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:267:5
++   |
++LL |     _custom /= Custom;
++   |     ^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:268:5
++   |
++LL |     _custom /= &Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:269:5
++   |
++LL |     _custom %= Custom;
++   |     ^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:270:5
++   |
++LL |     _custom %= &Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:271:5
++   |
++LL |     _custom *= Custom;
++   |     ^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:272:5
++   |
++LL |     _custom *= &Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:273:5
++   |
++LL |     _custom += -Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:274:5
++   |
++LL |     _custom += &-Custom;
++   |     ^^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:275:5
++   |
++LL |     _custom -= -Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:276:5
++   |
++LL |     _custom -= &-Custom;
++   |     ^^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:277:5
++   |
++LL |     _custom /= -Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:278:5
++   |
++LL |     _custom /= &-Custom;
++   |     ^^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:279:5
++   |
++LL |     _custom %= -Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:280:5
++   |
++LL |     _custom %= &-Custom;
++   |     ^^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:281:5
++   |
++LL |     _custom *= -Custom;
++   |     ^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:282:5
++   |
++LL |     _custom *= &-Custom;
++   |     ^^^^^^^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:285:10
 +   |
 +LL |     _n = _n + 1;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:179:10
++  --> $DIR/arithmetic_side_effects.rs:286:10
 +   |
 +LL |     _n = _n + &1;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:180:10
++  --> $DIR/arithmetic_side_effects.rs:287:10
 +   |
 +LL |     _n = 1 + _n;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:181:10
++  --> $DIR/arithmetic_side_effects.rs:288:10
 +   |
 +LL |     _n = &1 + _n;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:182:10
++  --> $DIR/arithmetic_side_effects.rs:289:10
 +   |
 +LL |     _n = _n - 1;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:183:10
++  --> $DIR/arithmetic_side_effects.rs:290:10
 +   |
 +LL |     _n = _n - &1;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:184:10
++  --> $DIR/arithmetic_side_effects.rs:291:10
 +   |
 +LL |     _n = 1 - _n;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:185:10
++  --> $DIR/arithmetic_side_effects.rs:292:10
 +   |
 +LL |     _n = &1 - _n;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:186:10
++  --> $DIR/arithmetic_side_effects.rs:293:10
 +   |
 +LL |     _n = _n / 0;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:187:10
++  --> $DIR/arithmetic_side_effects.rs:294:10
 +   |
 +LL |     _n = _n / &0;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:188:10
++  --> $DIR/arithmetic_side_effects.rs:295:10
 +   |
 +LL |     _n = _n % 0;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:189:10
++  --> $DIR/arithmetic_side_effects.rs:296:10
 +   |
 +LL |     _n = _n % &0;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:190:10
++  --> $DIR/arithmetic_side_effects.rs:297:10
 +   |
 +LL |     _n = _n * 2;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:191:10
++  --> $DIR/arithmetic_side_effects.rs:298:10
 +   |
 +LL |     _n = _n * &2;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:192:10
++  --> $DIR/arithmetic_side_effects.rs:299:10
 +   |
 +LL |     _n = 2 * _n;
 +   |          ^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:193:10
++  --> $DIR/arithmetic_side_effects.rs:300:10
 +   |
 +LL |     _n = &2 * _n;
 +   |          ^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:194:10
++  --> $DIR/arithmetic_side_effects.rs:301:10
 +   |
 +LL |     _n = 23 + &85;
 +   |          ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:195:10
++  --> $DIR/arithmetic_side_effects.rs:302:10
 +   |
 +LL |     _n = &23 + 85;
 +   |          ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
-   --> $DIR/arithmetic_side_effects.rs:198:13
++  --> $DIR/arithmetic_side_effects.rs:303:10
 +   |
 +LL |     _n = &23 + &85;
 +   |          ^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom + 0;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:304:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:199:13
++LL |     _custom = _custom + _custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom + 1;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:305:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:200:13
++LL |     _custom = _custom + &_custom;
++   |               ^^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom + 2;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:306:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:201:13
++LL |     _custom = Custom + _custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom + 0.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:307:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:202:13
++LL |     _custom = &Custom + _custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom + 1.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:308:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:203:13
++LL |     _custom = _custom - Custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom + 2.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:309:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:204:13
++LL |     _custom = _custom - &Custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom - 0;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:310:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:205:13
++LL |     _custom = Custom - _custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom - 1;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:311:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:206:13
++LL |     _custom = &Custom - _custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom - 2;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:312:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:207:13
++LL |     _custom = _custom / Custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom - 0.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:313:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:208:13
++LL |     _custom = _custom / &Custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom - 1.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:314:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:209:13
++LL |     _custom = _custom % Custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom - 2.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:315:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:210:13
++LL |     _custom = _custom % &Custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom / 0;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:316:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:211:13
++LL |     _custom = _custom * Custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom / 1;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:317:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:212:13
++LL |     _custom = _custom * &Custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom / 2;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:318:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:213:13
++LL |     _custom = Custom * _custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom / 0.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:319:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:214:13
++LL |     _custom = &Custom * _custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom / 1.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:320:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:215:13
++LL |     _custom = Custom + &Custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom / 2.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:321:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:216:13
++LL |     _custom = &Custom + Custom;
++   |               ^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom * 0;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:322:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:217:13
++LL |     _custom = &Custom + &Custom;
++   |               ^^^^^^^^^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom * 1;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:325:10
 +   |
-   --> $DIR/arithmetic_side_effects.rs:218:13
++LL |     _n = -_n;
++   |          ^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom * 2;
-    |             ^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:326:10
 +   |
-   --> $DIR/arithmetic_side_effects.rs:219:13
++LL |     _n = -&_n;
++   |          ^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom * 0.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:327:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:220:13
++LL |     _custom = -_custom;
++   |               ^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom * 1.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:328:15
 +   |
-   --> $DIR/arithmetic_side_effects.rs:221:13
++LL |     _custom = -&_custom;
++   |               ^^^^^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     let _ = Custom * 2.0;
-    |             ^^^^^^^^^^^^
++  --> $DIR/arithmetic_side_effects.rs:337:5
 +   |
-   --> $DIR/arithmetic_side_effects.rs:224:10
++LL |     1 + i;
++   |     ^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     _n = -_n;
-    |          ^^^
++  --> $DIR/arithmetic_side_effects.rs:338:5
 +   |
-   --> $DIR/arithmetic_side_effects.rs:225:10
++LL |     i * 2;
++   |     ^^^^^
 +
 +error: arithmetic operation that can potentially result in unexpected side-effects
- LL |     _n = -&_n;
-    |          ^^^^
++  --> $DIR/arithmetic_side_effects.rs:340:5
 +   |
- error: aborting due to 55 previous errors
++LL |     i - 2 + 2 - i;
++   |     ^^^^^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:341:5
++   |
++LL |     -i;
++   |     ^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:342:5
++   |
++LL |     i >> 1;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:343:5
++   |
++LL |     i << 1;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:352:5
++   |
++LL |     i += 1;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:353:5
++   |
++LL |     i -= 1;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:354:5
++   |
++LL |     i *= 2;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:356:5
++   |
++LL |     i /= 0;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:358:5
++   |
++LL |     i /= var1;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:359:5
++   |
++LL |     i /= var2;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:361:5
++   |
++LL |     i %= 0;
++   |     ^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:363:5
++   |
++LL |     i %= var1;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:364:5
++   |
++LL |     i %= var2;
++   |     ^^^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:365:5
++   |
++LL |     i <<= 3;
++   |     ^^^^^^^
++
++error: arithmetic operation that can potentially result in unexpected side-effects
++  --> $DIR/arithmetic_side_effects.rs:366:5
++   |
++LL |     i >>= 2;
++   |     ^^^^^^^
 +
++error: aborting due to 99 previous errors
 +
index 911fa856aa0a3f790591e4187581e90c740ab41a,0000000000000000000000000000000000000000..7e9f074fdcabd24f9e97019139ebedc60e7b36a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,57 -1,0 +1,67 @@@
-     let _vec = Box::<std::vec::Vec<u8>>::default();
 +// run-rustfix
 +#![warn(clippy::box_default)]
 +
 +#[derive(Default)]
 +struct ImplementsDefault;
 +
 +struct OwnDefault;
 +
 +impl OwnDefault {
 +    fn default() -> Self {
 +        Self
 +    }
 +}
 +
 +macro_rules! outer {
 +    ($e: expr) => {
 +        $e
 +    };
 +}
 +
 +fn main() {
 +    let _string: Box<String> = Box::default();
 +    let _byte = Box::<u8>::default();
-     let _in_macro = outer!(Box::<std::string::String>::default());
-     let _string_default = outer!(Box::<std::string::String>::default());
++    let _vec = Box::<Vec<u8>>::default();
 +    let _impl = Box::<ImplementsDefault>::default();
 +    let _impl2 = Box::<ImplementsDefault>::default();
 +    let _impl3: Box<ImplementsDefault> = Box::default();
 +    let _own = Box::new(OwnDefault::default()); // should not lint
-     let _vec4: Box<_> = Box::<std::vec::Vec<bool>>::default();
++    let _in_macro = outer!(Box::<String>::default());
++    let _string_default = outer!(Box::<String>::default());
 +    let _vec2: Box<Vec<ImplementsDefault>> = Box::default();
 +    let _vec3: Box<Vec<bool>> = Box::default();
++    let _vec4: Box<_> = Box::<Vec<bool>>::default();
 +    let _more = ret_ty_fn();
 +    call_ty_fn(Box::default());
 +}
 +
 +fn ret_ty_fn() -> Box<bool> {
 +    Box::<bool>::default()
 +}
 +
 +#[allow(clippy::boxed_local)]
 +fn call_ty_fn(_b: Box<u8>) {
 +    issue_9621_dyn_trait();
 +}
 +
 +use std::io::{Read, Result};
 +
 +impl Read for ImplementsDefault {
 +    fn read(&mut self, _: &mut [u8]) -> Result<usize> {
 +        Ok(0)
 +    }
 +}
 +
 +fn issue_9621_dyn_trait() {
 +    let _: Box<dyn Read> = Box::<ImplementsDefault>::default();
++    issue_10089();
++}
++
++fn issue_10089() {
++    let _closure = || {
++        #[derive(Default)]
++        struct WeirdPathed;
++
++        let _ = Box::<WeirdPathed>::default();
++    };
 +}
index 20019c2ee5a07a550042311cdfc1bf5b0beffeed,0000000000000000000000000000000000000000..5c8d0b8354cccf6eb7d3512399d3d1a54ff0082a
mode 100644,000000..100644
--- /dev/null
@@@ -1,57 -1,0 +1,67 @@@
 +// run-rustfix
 +#![warn(clippy::box_default)]
 +
 +#[derive(Default)]
 +struct ImplementsDefault;
 +
 +struct OwnDefault;
 +
 +impl OwnDefault {
 +    fn default() -> Self {
 +        Self
 +    }
 +}
 +
 +macro_rules! outer {
 +    ($e: expr) => {
 +        $e
 +    };
 +}
 +
 +fn main() {
 +    let _string: Box<String> = Box::new(Default::default());
 +    let _byte = Box::new(u8::default());
 +    let _vec = Box::new(Vec::<u8>::new());
 +    let _impl = Box::new(ImplementsDefault::default());
 +    let _impl2 = Box::new(<ImplementsDefault as Default>::default());
 +    let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
 +    let _own = Box::new(OwnDefault::default()); // should not lint
 +    let _in_macro = outer!(Box::new(String::new()));
 +    let _string_default = outer!(Box::new(String::from("")));
 +    let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
 +    let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
 +    let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
 +    let _more = ret_ty_fn();
 +    call_ty_fn(Box::new(u8::default()));
 +}
 +
 +fn ret_ty_fn() -> Box<bool> {
 +    Box::new(bool::default())
 +}
 +
 +#[allow(clippy::boxed_local)]
 +fn call_ty_fn(_b: Box<u8>) {
 +    issue_9621_dyn_trait();
 +}
 +
 +use std::io::{Read, Result};
 +
 +impl Read for ImplementsDefault {
 +    fn read(&mut self, _: &mut [u8]) -> Result<usize> {
 +        Ok(0)
 +    }
 +}
 +
 +fn issue_9621_dyn_trait() {
 +    let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
++    issue_10089();
++}
++
++fn issue_10089() {
++    let _closure = || {
++        #[derive(Default)]
++        struct WeirdPathed;
++
++        let _ = Box::new(WeirdPathed::default());
++    };
 +}
index 5ea410331afb309757dee4fa1d6ee579ce87904c,0000000000000000000000000000000000000000..249eb340f96cbd75b4b7991adbe39a1b733295dc
mode 100644,000000..100644
--- /dev/null
@@@ -1,88 -1,0 +1,94 @@@
-    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<u8>>::default()`
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:22:32
 +   |
 +LL |     let _string: Box<String> = Box::new(Default::default());
 +   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 +   |
 +   = note: `-D clippy::box-default` implied by `-D warnings`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:23:17
 +   |
 +LL |     let _byte = Box::new(u8::default());
 +   |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<u8>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:24:16
 +   |
 +LL |     let _vec = Box::new(Vec::<u8>::new());
-    |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
++   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<u8>>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:25:17
 +   |
 +LL |     let _impl = Box::new(ImplementsDefault::default());
 +   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:26:18
 +   |
 +LL |     let _impl2 = Box::new(<ImplementsDefault as Default>::default());
 +   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:27:42
 +   |
 +LL |     let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
 +   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:29:28
 +   |
 +LL |     let _in_macro = outer!(Box::new(String::new()));
-    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
++   |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:30:34
 +   |
 +LL |     let _string_default = outer!(Box::new(String::from("")));
-    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<bool>>::default()`
++   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:31:46
 +   |
 +LL |     let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
 +   |                                              ^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:32:33
 +   |
 +LL |     let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
 +   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:33:25
 +   |
 +LL |     let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
- error: aborting due to 14 previous errors
++   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<bool>>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:35:16
 +   |
 +LL |     call_ty_fn(Box::new(u8::default()));
 +   |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:39:5
 +   |
 +LL |     Box::new(bool::default())
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
 +
 +error: `Box::new(_)` of default value
 +  --> $DIR/box_default.rs:56:28
 +   |
 +LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
 +   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 +
++error: `Box::new(_)` of default value
++  --> $DIR/box_default.rs:65:17
++   |
++LL |         let _ = Box::new(WeirdPathed::default());
++   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
++
++error: aborting due to 15 previous errors
 +
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5fbaa64db39edb8406855012a3c1ef35e83cce28
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,67 @@@
++// run-rustfix
++#![warn(clippy::case_sensitive_file_extension_comparisons)]
++
++use std::string::String;
++
++struct TestStruct;
++
++impl TestStruct {
++    fn ends_with(self, _arg: &str) {}
++}
++
++#[allow(dead_code)]
++fn is_rust_file(filename: &str) -> bool {
++    std::path::Path::new(filename)
++        .extension()
++        .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
++}
++
++fn main() {
++    // std::string::String and &str should trigger the lint failure with .ext12
++    let _ = std::path::Path::new(&String::new())
++        .extension()
++        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
++    let _ = std::path::Path::new("str")
++        .extension()
++        .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
++
++    // The fixup should preserve the indentation level
++    {
++        let _ = std::path::Path::new("str")
++            .extension()
++            .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
++    }
++
++    // The test struct should not trigger the lint failure with .ext12
++    TestStruct {}.ends_with(".ext12");
++
++    // std::string::String and &str should trigger the lint failure with .EXT12
++    let _ = std::path::Path::new(&String::new())
++        .extension()
++        .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
++    let _ = std::path::Path::new("str")
++        .extension()
++        .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
++
++    // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
++    let _ = String::new().to_lowercase().ends_with(".EXT12");
++    let _ = String::new().to_uppercase().ends_with(".EXT12");
++
++    // The test struct should not trigger the lint failure with .EXT12
++    TestStruct {}.ends_with(".EXT12");
++
++    // Should not trigger the lint failure with .eXT12
++    let _ = String::new().ends_with(".eXT12");
++    let _ = "str".ends_with(".eXT12");
++    TestStruct {}.ends_with(".eXT12");
++
++    // Should not trigger the lint failure with .EXT123 (too long)
++    let _ = String::new().ends_with(".EXT123");
++    let _ = "str".ends_with(".EXT123");
++    TestStruct {}.ends_with(".EXT123");
++
++    // Shouldn't fail if it doesn't start with a dot
++    let _ = String::new().ends_with("a.ext");
++    let _ = "str".ends_with("a.extA");
++    TestStruct {}.ends_with("a.ext");
++}
index 6f0485b5279b1112c173c8a5d07cfcbb872bd0d3,0000000000000000000000000000000000000000..3c0d4821f9f3a8ee9ff18b66e51e855cadc3655b
mode 100644,000000..100644
--- /dev/null
@@@ -1,44 -1,0 +1,55 @@@
-     fn ends_with(self, arg: &str) {}
++// run-rustfix
 +#![warn(clippy::case_sensitive_file_extension_comparisons)]
 +
 +use std::string::String;
 +
 +struct TestStruct;
 +
 +impl TestStruct {
++    fn ends_with(self, _arg: &str) {}
 +}
 +
++#[allow(dead_code)]
 +fn is_rust_file(filename: &str) -> bool {
 +    filename.ends_with(".rs")
 +}
 +
 +fn main() {
 +    // std::string::String and &str should trigger the lint failure with .ext12
 +    let _ = String::new().ends_with(".ext12");
 +    let _ = "str".ends_with(".ext12");
 +
++    // The fixup should preserve the indentation level
++    {
++        let _ = "str".ends_with(".ext12");
++    }
++
 +    // The test struct should not trigger the lint failure with .ext12
 +    TestStruct {}.ends_with(".ext12");
 +
 +    // std::string::String and &str should trigger the lint failure with .EXT12
 +    let _ = String::new().ends_with(".EXT12");
 +    let _ = "str".ends_with(".EXT12");
 +
++    // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
++    let _ = String::new().to_lowercase().ends_with(".EXT12");
++    let _ = String::new().to_uppercase().ends_with(".EXT12");
++
 +    // The test struct should not trigger the lint failure with .EXT12
 +    TestStruct {}.ends_with(".EXT12");
 +
 +    // Should not trigger the lint failure with .eXT12
 +    let _ = String::new().ends_with(".eXT12");
 +    let _ = "str".ends_with(".eXT12");
 +    TestStruct {}.ends_with(".eXT12");
 +
 +    // Should not trigger the lint failure with .EXT123 (too long)
 +    let _ = String::new().ends_with(".EXT123");
 +    let _ = "str".ends_with(".EXT123");
 +    TestStruct {}.ends_with(".EXT123");
 +
 +    // Shouldn't fail if it doesn't start with a dot
 +    let _ = String::new().ends_with("a.ext");
 +    let _ = "str".ends_with("a.extA");
 +    TestStruct {}.ends_with("a.ext");
 +}
index a28dd8bd5ad3fc7912047bdd298fadd5c2e0c850,0000000000000000000000000000000000000000..44c8e3fdf7403d05c6eba7101d231cc6c89d7e14
mode 100644,000000..100644
--- /dev/null
@@@ -1,43 -1,0 +1,87 @@@
-   --> $DIR/case_sensitive_file_extension_comparisons.rs:12:14
 +error: case-sensitive file extension comparison
-    |              ^^^^^^^^^^^^^^^^
++  --> $DIR/case_sensitive_file_extension_comparisons.rs:14:5
 +   |
 +LL |     filename.ends_with(".rs")
-   --> $DIR/case_sensitive_file_extension_comparisons.rs:17:27
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: consider using a case-insensitive comparison instead
 +   = note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings`
++help: use std::path::Path
++   |
++LL ~     std::path::Path::new(filename)
++LL +         .extension()
++LL +         .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
++   |
 +
 +error: case-sensitive file extension comparison
-    |                           ^^^^^^^^^^^^^^^^^^^
++  --> $DIR/case_sensitive_file_extension_comparisons.rs:19:13
 +   |
 +LL |     let _ = String::new().ends_with(".ext12");
-   --> $DIR/case_sensitive_file_extension_comparisons.rs:18:19
++   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: consider using a case-insensitive comparison instead
++help: use std::path::Path
++   |
++LL ~     let _ = std::path::Path::new(&String::new())
++LL +         .extension()
++LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
++   |
 +
 +error: case-sensitive file extension comparison
-    |                   ^^^^^^^^^^^^^^^^^^^
++  --> $DIR/case_sensitive_file_extension_comparisons.rs:20:13
 +   |
 +LL |     let _ = "str".ends_with(".ext12");
-   --> $DIR/case_sensitive_file_extension_comparisons.rs:24:27
++   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: consider using a case-insensitive comparison instead
++help: use std::path::Path
++   |
++LL ~     let _ = std::path::Path::new("str")
++LL +         .extension()
++LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
++   |
 +
 +error: case-sensitive file extension comparison
-    |                           ^^^^^^^^^^^^^^^^^^^
++  --> $DIR/case_sensitive_file_extension_comparisons.rs:24:17
++   |
++LL |         let _ = "str".ends_with(".ext12");
++   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++   = help: consider using a case-insensitive comparison instead
++help: use std::path::Path
++   |
++LL ~         let _ = std::path::Path::new("str")
++LL +             .extension()
++LL ~             .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
++   |
++
++error: case-sensitive file extension comparison
++  --> $DIR/case_sensitive_file_extension_comparisons.rs:31:13
 +   |
 +LL |     let _ = String::new().ends_with(".EXT12");
-   --> $DIR/case_sensitive_file_extension_comparisons.rs:25:19
++   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: consider using a case-insensitive comparison instead
++help: use std::path::Path
++   |
++LL ~     let _ = std::path::Path::new(&String::new())
++LL +         .extension()
++LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
++   |
 +
 +error: case-sensitive file extension comparison
-    |                   ^^^^^^^^^^^^^^^^^^^
++  --> $DIR/case_sensitive_file_extension_comparisons.rs:32:13
 +   |
 +LL |     let _ = "str".ends_with(".EXT12");
- error: aborting due to 5 previous errors
++   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: consider using a case-insensitive comparison instead
++help: use std::path::Path
++   |
++LL ~     let _ = std::path::Path::new("str")
++LL +         .extension()
++LL ~         .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
++   |
 +
++error: aborting due to 6 previous errors
 +
index 42ae227777c7082a20849bfb489b2332850a6ac9,0000000000000000000000000000000000000000..862234d204be355e4fff41dbe4d4e1d474207da5
mode 100644,000000..100644
--- /dev/null
@@@ -1,58 -1,0 +1,58 @@@
- error: using `clone` on type `std::option::Option<i32>` which implements the `Copy` trait
 +error: using `clone` on type `i32` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:25:5
 +   |
 +LL |     42.clone();
 +   |     ^^^^^^^^^^ help: try removing the `clone` call: `42`
 +   |
 +   = note: `-D clippy::clone-on-copy` implied by `-D warnings`
 +
 +error: using `clone` on type `i32` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:29:5
 +   |
 +LL |     (&42).clone();
 +   |     ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)`
 +
 +error: using `clone` on type `i32` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:32:5
 +   |
 +LL |     rc.borrow().clone();
 +   |     ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()`
 +
 +error: using `clone` on type `u32` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:35:5
 +   |
 +LL |     x.clone().rotate_left(1);
 +   |     ^^^^^^^^^ help: try removing the `clone` call: `x`
 +
 +error: using `clone` on type `i32` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:49:5
 +   |
 +LL |     m!(42).clone();
 +   |     ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)`
 +
 +error: using `clone` on type `[u32; 2]` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:59:5
 +   |
 +LL |     x.clone()[0];
 +   |     ^^^^^^^^^ help: try dereferencing it: `(*x)`
 +
 +error: using `clone` on type `char` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:69:14
 +   |
 +LL |     is_ascii('z'.clone());
 +   |              ^^^^^^^^^^^ help: try removing the `clone` call: `'z'`
 +
 +error: using `clone` on type `i32` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:73:14
 +   |
 +LL |     vec.push(42.clone());
 +   |              ^^^^^^^^^^ help: try removing the `clone` call: `42`
 +
++error: using `clone` on type `Option<i32>` which implements the `Copy` trait
 +  --> $DIR/clone_on_copy.rs:77:17
 +   |
 +LL |     let value = opt.clone()?; // operator precedence needed (*opt)?
 +   |                 ^^^^^^^^^^^ help: try dereferencing it: `(*opt)`
 +
 +error: aborting due to 9 previous errors
 +
index e6a65b46d975c80bdeb7eef62144efd45e19b1a7,0000000000000000000000000000000000000000..ddb5f1342e9942a72f2183b9bee79b3a5ef0506b
mode 100644,000000..100644
--- /dev/null
@@@ -1,146 -1,0 +1,146 @@@
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:5:22
 +   |
 +LL |     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
 +   |                      ^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = note: `-D clippy::dbg-macro` implied by `-D warnings`
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
 +   |                      ~~~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:9:8
 +   |
 +LL |     if dbg!(n <= 1) {
 +   |        ^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     if n <= 1 {
 +   |        ~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:10:9
 +   |
 +LL |         dbg!(1)
 +   |         ^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |         1
 +   |
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:12:9
 +   |
 +LL |         dbg!(n * factorial(n - 1))
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |         n * factorial(n - 1)
 +   |
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:17:5
 +   |
 +LL |     dbg!(42);
 +   |     ^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     42;
 +   |     ~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:18:5
 +   |
 +LL |     dbg!(dbg!(dbg!(42)));
 +   |     ^^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     dbg!(dbg!(42));
 +   |     ~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:19:14
 +   |
 +LL |     foo(3) + dbg!(factorial(4));
 +   |              ^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     foo(3) + factorial(4);
 +   |              ~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:20:5
 +   |
 +LL |     dbg!(1, 2, dbg!(3, 4));
 +   |     ^^^^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     (1, 2, dbg!(3, 4));
 +   |     ~~~~~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:21:5
 +   |
 +LL |     dbg!(1, 2, 3, 4, 5);
 +   |     ^^^^^^^^^^^^^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     (1, 2, 3, 4, 5);
 +   |     ~~~~~~~~~~~~~~~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:41:9
 +   |
 +LL |         dbg!(2);
 +   |         ^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |         2;
 +   |         ~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:47:5
 +   |
 +LL |     dbg!(1);
 +   |     ^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     1;
 +   |     ~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:52:5
 +   |
 +LL |     dbg!(1);
 +   |     ^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |     1;
 +   |     ~
 +
- error: `dbg!` macro is intended as a debugging tool
++error: the `dbg!` macro is intended as a debugging tool
 +  --> $DIR/dbg_macro.rs:58:9
 +   |
 +LL |         dbg!(1);
 +   |         ^^^^^^^
 +   |
- help: ensure to avoid having uses of it in version control
++help: remove the invocation before committing it to a version control system
 +   |
 +LL |         1;
 +   |         ~
 +
 +error: aborting due to 13 previous errors
 +
index eedd43619392d67aca02d6877574188cea1e8239,0000000000000000000000000000000000000000..5640599d48ae8b191c95bc77fdd85d6802e774fa
mode 100644,000000..100644
--- /dev/null
@@@ -1,105 -1,0 +1,105 @@@
-     let s1: String = std::string::String::default();
 +// run-rustfix
 +// aux-build: proc_macro_with_span.rs
 +#![deny(clippy::default_trait_access)]
 +#![allow(dead_code, unused_imports)]
 +#![allow(clippy::uninlined_format_args)]
 +
 +extern crate proc_macro_with_span;
 +
 +use proc_macro_with_span::with_span;
 +use std::default;
 +use std::default::Default as D2;
 +use std::string;
 +
 +fn main() {
-     let s3: String = std::string::String::default();
++    let s1: String = String::default();
 +
 +    let s2 = String::default();
 +
-     let s4: String = std::string::String::default();
++    let s3: String = String::default();
 +
-     let s6: String = std::string::String::default();
++    let s4: String = String::default();
 +
 +    let s5 = string::String::default();
 +
++    let s6: String = String::default();
 +
 +    let s7 = std::string::String::default();
 +
 +    let s8: String = DefaultFactory::make_t_badly();
 +
 +    let s9: String = DefaultFactory::make_t_nicely();
 +
 +    let s10 = DerivedDefault::default();
 +
 +    let s11: GenericDerivedDefault<String> = GenericDerivedDefault::default();
 +
 +    let s12 = GenericDerivedDefault::<String>::default();
 +
 +    let s13 = TupleDerivedDefault::default();
 +
 +    let s14: TupleDerivedDefault = TupleDerivedDefault::default();
 +
 +    let s15: ArrayDerivedDefault = ArrayDerivedDefault::default();
 +
 +    let s16 = ArrayDerivedDefault::default();
 +
 +    let s17: TupleStructDerivedDefault = TupleStructDerivedDefault::default();
 +
 +    let s18 = TupleStructDerivedDefault::default();
 +
 +    let s19 = <DerivedDefault as Default>::default();
 +
 +    let s20 = UpdateSyntax {
 +        s: "foo",
 +        ..Default::default()
 +    };
 +
 +    let _s21: String = with_span!(s Default::default());
 +
 +    println!(
 +        "[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]",
 +        s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20,
 +    );
 +}
 +
 +struct DefaultFactory;
 +
 +impl DefaultFactory {
 +    pub fn make_t_badly<T: Default>() -> T {
 +        Default::default()
 +    }
 +
 +    pub fn make_t_nicely<T: Default>() -> T {
 +        T::default()
 +    }
 +}
 +
 +#[derive(Debug, Default)]
 +struct DerivedDefault {
 +    pub s: String,
 +}
 +
 +#[derive(Debug, Default)]
 +struct GenericDerivedDefault<T: Default + std::fmt::Debug> {
 +    pub s: T,
 +}
 +
 +#[derive(Debug, Default)]
 +struct TupleDerivedDefault {
 +    pub s: (String, String),
 +}
 +
 +#[derive(Debug, Default)]
 +struct ArrayDerivedDefault {
 +    pub s: [String; 10],
 +}
 +
 +#[derive(Debug, Default)]
 +struct TupleStructDerivedDefault(String);
 +
 +#[derive(Debug, Default)]
 +struct UpdateSyntax {
 +    pub s: &'static str,
 +    pub u: u64,
 +}
index 49b2dde3f1e8c9e29183085da6850cc6f6c67e11,0000000000000000000000000000000000000000..e4f73c08d190a8844f9feb37303e4db35300f242
mode 100644,000000..100644
--- /dev/null
@@@ -1,56 -1,0 +1,56 @@@
- error: calling `std::string::String::default()` is more clear than this expression
++error: calling `String::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:15:22
 +   |
 +LL |     let s1: String = Default::default();
-    |                      ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
++   |                      ^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
 +   |
 +note: the lint level is defined here
 +  --> $DIR/default_trait_access.rs:3:9
 +   |
 +LL | #![deny(clippy::default_trait_access)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +
- error: calling `std::string::String::default()` is more clear than this expression
++error: calling `String::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:19:22
 +   |
 +LL |     let s3: String = D2::default();
-    |                      ^^^^^^^^^^^^^ help: try: `std::string::String::default()`
++   |                      ^^^^^^^^^^^^^ help: try: `String::default()`
 +
- error: calling `std::string::String::default()` is more clear than this expression
++error: calling `String::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:21:22
 +   |
 +LL |     let s4: String = std::default::Default::default();
-    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
++   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
 +
- error: calling `std::string::String::default()` is more clear than this expression
++error: calling `String::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:25:22
 +   |
 +LL |     let s6: String = default::Default::default();
-    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
++   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
 +
 +error: calling `GenericDerivedDefault::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:35:46
 +   |
 +LL |     let s11: GenericDerivedDefault<String> = Default::default();
 +   |                                              ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault::default()`
 +
 +error: calling `TupleDerivedDefault::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:41:36
 +   |
 +LL |     let s14: TupleDerivedDefault = Default::default();
 +   |                                    ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()`
 +
 +error: calling `ArrayDerivedDefault::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:43:36
 +   |
 +LL |     let s15: ArrayDerivedDefault = Default::default();
 +   |                                    ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()`
 +
 +error: calling `TupleStructDerivedDefault::default()` is more clear than this expression
 +  --> $DIR/default_trait_access.rs:47:42
 +   |
 +LL |     let s17: TupleStructDerivedDefault = Default::default();
 +   |                                          ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()`
 +
 +error: aborting due to 8 previous errors
 +
index 7dcdfb0937e892a6a146bc4218bba298e829100d,0000000000000000000000000000000000000000..ee8456f5deb8ae89f3462f02d2ed2766378c10d6
mode 100644,000000..100644
--- /dev/null
@@@ -1,213 -1,0 +1,234 @@@
 +// run-rustfix
 +
 +#![allow(dead_code)]
 +
 +use std::collections::HashMap;
 +
 +#[derive(Default)]
 +struct FooDefault<'a> {
 +    a: bool,
 +    b: i32,
 +    c: u64,
 +    d: Vec<i32>,
 +    e: FooND1,
 +    f: FooND2,
 +    g: HashMap<i32, i32>,
 +    h: (i32, Vec<i32>),
 +    i: [Vec<i32>; 3],
 +    j: [i32; 5],
 +    k: Option<i32>,
 +    l: &'a [i32],
 +}
 +
 +
 +
 +#[derive(Default)]
 +struct TupleDefault(bool, i32, u64);
 +
 +
 +
 +struct FooND1 {
 +    a: bool,
 +}
 +
 +impl std::default::Default for FooND1 {
 +    fn default() -> Self {
 +        Self { a: true }
 +    }
 +}
 +
 +struct FooND2 {
 +    a: i32,
 +}
 +
 +impl std::default::Default for FooND2 {
 +    fn default() -> Self {
 +        Self { a: 5 }
 +    }
 +}
 +
 +struct FooNDNew {
 +    a: bool,
 +}
 +
 +impl FooNDNew {
 +    fn new() -> Self {
 +        Self { a: true }
 +    }
 +}
 +
 +impl Default for FooNDNew {
 +    fn default() -> Self {
 +        Self::new()
 +    }
 +}
 +
 +struct FooNDVec(Vec<i32>);
 +
 +impl Default for FooNDVec {
 +    fn default() -> Self {
 +        Self(vec![5, 12])
 +    }
 +}
 +
 +#[derive(Default)]
 +struct StrDefault<'a>(&'a str);
 +
 +
 +
 +#[derive(Default)]
 +struct AlreadyDerived(i32, bool);
 +
 +macro_rules! mac {
 +    () => {
 +        0
 +    };
 +    ($e:expr) => {
 +        struct X(u32);
 +        impl Default for X {
 +            fn default() -> Self {
 +                Self($e)
 +            }
 +        }
 +    };
 +}
 +
 +mac!(0);
 +
 +#[derive(Default)]
 +struct Y(u32);
 +
 +
 +struct RustIssue26925<T> {
 +    a: Option<T>,
 +}
 +
 +// We should watch out for cases where a manual impl is needed because a
 +// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
 +// For example, a struct with Option<T> does not require T: Default, but a derive adds
 +// that type bound anyways. So until #26925 get fixed we should disable lint
 +// for the following case
 +impl<T> Default for RustIssue26925<T> {
 +    fn default() -> Self {
 +        Self { a: None }
 +    }
 +}
 +
 +struct SpecializedImpl<A, B> {
 +    a: A,
 +    b: B,
 +}
 +
 +impl<T: Default> Default for SpecializedImpl<T, T> {
 +    fn default() -> Self {
 +        Self {
 +            a: T::default(),
 +            b: T::default(),
 +        }
 +    }
 +}
 +
 +#[derive(Default)]
 +struct WithoutSelfCurly {
 +    a: bool,
 +}
 +
 +
 +
 +#[derive(Default)]
 +struct WithoutSelfParan(bool);
 +
 +
 +
 +// https://github.com/rust-lang/rust-clippy/issues/7655
 +
 +pub struct SpecializedImpl2<T> {
 +    v: Vec<T>,
 +}
 +
 +impl Default for SpecializedImpl2<String> {
 +    fn default() -> Self {
 +        Self { v: Vec::new() }
 +    }
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/7654
 +
 +pub struct Color {
 +    pub r: u8,
 +    pub g: u8,
 +    pub b: u8,
 +}
 +
 +/// `#000000`
 +impl Default for Color {
 +    fn default() -> Self {
 +        Color { r: 0, g: 0, b: 0 }
 +    }
 +}
 +
 +pub struct Color2 {
 +    pub r: u8,
 +    pub g: u8,
 +    pub b: u8,
 +}
 +
 +impl Default for Color2 {
 +    /// `#000000`
 +    fn default() -> Self {
 +        Self { r: 0, g: 0, b: 0 }
 +    }
 +}
 +
 +#[derive(Default)]
 +pub struct RepeatDefault1 {
 +    a: [i8; 32],
 +}
 +
 +
 +
 +pub struct RepeatDefault2 {
 +    a: [i8; 33],
 +}
 +
 +impl Default for RepeatDefault2 {
 +    fn default() -> Self {
 +        RepeatDefault2 { a: [0; 33] }
 +    }
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/7753
 +
 +pub enum IntOrString {
 +    Int(i32),
 +    String(String),
 +}
 +
 +impl Default for IntOrString {
 +    fn default() -> Self {
 +        IntOrString::Int(0)
 +    }
 +}
 +
++#[derive(Default)]
++pub enum SimpleEnum {
++    Foo,
++    #[default]
++    Bar,
++}
++
++
++
++pub enum NonExhaustiveEnum {
++    Foo,
++    #[non_exhaustive]
++    Bar,
++}
++
++impl Default for NonExhaustiveEnum {
++    fn default() -> Self {
++        NonExhaustiveEnum::Bar
++    }
++}
++
 +fn main() {}
index 625cbcdde230ac14e03efefd0769562b56488188,0000000000000000000000000000000000000000..14af419bcad14ad3992a18a14cbd71099bd4afd5
mode 100644,000000..100644
--- /dev/null
@@@ -1,247 -1,0 +1,270 @@@
 +// run-rustfix
 +
 +#![allow(dead_code)]
 +
 +use std::collections::HashMap;
 +
 +struct FooDefault<'a> {
 +    a: bool,
 +    b: i32,
 +    c: u64,
 +    d: Vec<i32>,
 +    e: FooND1,
 +    f: FooND2,
 +    g: HashMap<i32, i32>,
 +    h: (i32, Vec<i32>),
 +    i: [Vec<i32>; 3],
 +    j: [i32; 5],
 +    k: Option<i32>,
 +    l: &'a [i32],
 +}
 +
 +impl std::default::Default for FooDefault<'_> {
 +    fn default() -> Self {
 +        Self {
 +            a: false,
 +            b: 0,
 +            c: 0u64,
 +            d: vec![],
 +            e: Default::default(),
 +            f: FooND2::default(),
 +            g: HashMap::new(),
 +            h: (0, vec![]),
 +            i: [vec![], vec![], vec![]],
 +            j: [0; 5],
 +            k: None,
 +            l: &[],
 +        }
 +    }
 +}
 +
 +struct TupleDefault(bool, i32, u64);
 +
 +impl std::default::Default for TupleDefault {
 +    fn default() -> Self {
 +        Self(false, 0, 0u64)
 +    }
 +}
 +
 +struct FooND1 {
 +    a: bool,
 +}
 +
 +impl std::default::Default for FooND1 {
 +    fn default() -> Self {
 +        Self { a: true }
 +    }
 +}
 +
 +struct FooND2 {
 +    a: i32,
 +}
 +
 +impl std::default::Default for FooND2 {
 +    fn default() -> Self {
 +        Self { a: 5 }
 +    }
 +}
 +
 +struct FooNDNew {
 +    a: bool,
 +}
 +
 +impl FooNDNew {
 +    fn new() -> Self {
 +        Self { a: true }
 +    }
 +}
 +
 +impl Default for FooNDNew {
 +    fn default() -> Self {
 +        Self::new()
 +    }
 +}
 +
 +struct FooNDVec(Vec<i32>);
 +
 +impl Default for FooNDVec {
 +    fn default() -> Self {
 +        Self(vec![5, 12])
 +    }
 +}
 +
 +struct StrDefault<'a>(&'a str);
 +
 +impl Default for StrDefault<'_> {
 +    fn default() -> Self {
 +        Self("")
 +    }
 +}
 +
 +#[derive(Default)]
 +struct AlreadyDerived(i32, bool);
 +
 +macro_rules! mac {
 +    () => {
 +        0
 +    };
 +    ($e:expr) => {
 +        struct X(u32);
 +        impl Default for X {
 +            fn default() -> Self {
 +                Self($e)
 +            }
 +        }
 +    };
 +}
 +
 +mac!(0);
 +
 +struct Y(u32);
 +impl Default for Y {
 +    fn default() -> Self {
 +        Self(mac!())
 +    }
 +}
 +
 +struct RustIssue26925<T> {
 +    a: Option<T>,
 +}
 +
 +// We should watch out for cases where a manual impl is needed because a
 +// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
 +// For example, a struct with Option<T> does not require T: Default, but a derive adds
 +// that type bound anyways. So until #26925 get fixed we should disable lint
 +// for the following case
 +impl<T> Default for RustIssue26925<T> {
 +    fn default() -> Self {
 +        Self { a: None }
 +    }
 +}
 +
 +struct SpecializedImpl<A, B> {
 +    a: A,
 +    b: B,
 +}
 +
 +impl<T: Default> Default for SpecializedImpl<T, T> {
 +    fn default() -> Self {
 +        Self {
 +            a: T::default(),
 +            b: T::default(),
 +        }
 +    }
 +}
 +
 +struct WithoutSelfCurly {
 +    a: bool,
 +}
 +
 +impl Default for WithoutSelfCurly {
 +    fn default() -> Self {
 +        WithoutSelfCurly { a: false }
 +    }
 +}
 +
 +struct WithoutSelfParan(bool);
 +
 +impl Default for WithoutSelfParan {
 +    fn default() -> Self {
 +        WithoutSelfParan(false)
 +    }
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/7655
 +
 +pub struct SpecializedImpl2<T> {
 +    v: Vec<T>,
 +}
 +
 +impl Default for SpecializedImpl2<String> {
 +    fn default() -> Self {
 +        Self { v: Vec::new() }
 +    }
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/7654
 +
 +pub struct Color {
 +    pub r: u8,
 +    pub g: u8,
 +    pub b: u8,
 +}
 +
 +/// `#000000`
 +impl Default for Color {
 +    fn default() -> Self {
 +        Color { r: 0, g: 0, b: 0 }
 +    }
 +}
 +
 +pub struct Color2 {
 +    pub r: u8,
 +    pub g: u8,
 +    pub b: u8,
 +}
 +
 +impl Default for Color2 {
 +    /// `#000000`
 +    fn default() -> Self {
 +        Self { r: 0, g: 0, b: 0 }
 +    }
 +}
 +
 +pub struct RepeatDefault1 {
 +    a: [i8; 32],
 +}
 +
 +impl Default for RepeatDefault1 {
 +    fn default() -> Self {
 +        RepeatDefault1 { a: [0; 32] }
 +    }
 +}
 +
 +pub struct RepeatDefault2 {
 +    a: [i8; 33],
 +}
 +
 +impl Default for RepeatDefault2 {
 +    fn default() -> Self {
 +        RepeatDefault2 { a: [0; 33] }
 +    }
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/7753
 +
 +pub enum IntOrString {
 +    Int(i32),
 +    String(String),
 +}
 +
 +impl Default for IntOrString {
 +    fn default() -> Self {
 +        IntOrString::Int(0)
 +    }
 +}
 +
++pub enum SimpleEnum {
++    Foo,
++    Bar,
++}
++
++impl Default for SimpleEnum {
++    fn default() -> Self {
++        SimpleEnum::Bar
++    }
++}
++
++pub enum NonExhaustiveEnum {
++    Foo,
++    #[non_exhaustive]
++    Bar,
++}
++
++impl Default for NonExhaustiveEnum {
++    fn default() -> Self {
++        NonExhaustiveEnum::Bar
++    }
++}
++
 +fn main() {}
index c1db5a58b1f5196085701cec8fa6e95308f445ce,0000000000000000000000000000000000000000..81963c3be5b5d32478c63c7871e4e24d933f966e
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,138 @@@
- error: aborting due to 7 previous errors
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:22:1
 +   |
 +LL | / impl std::default::Default for FooDefault<'_> {
 +LL | |     fn default() -> Self {
 +LL | |         Self {
 +LL | |             a: false,
 +...  |
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = note: `-D clippy::derivable-impls` implied by `-D warnings`
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:43:1
 +   |
 +LL | / impl std::default::Default for TupleDefault {
 +LL | |     fn default() -> Self {
 +LL | |         Self(false, 0, 0u64)
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:95:1
 +   |
 +LL | / impl Default for StrDefault<'_> {
 +LL | |     fn default() -> Self {
 +LL | |         Self("")
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:121:1
 +   |
 +LL | / impl Default for Y {
 +LL | |     fn default() -> Self {
 +LL | |         Self(mac!())
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:160:1
 +   |
 +LL | / impl Default for WithoutSelfCurly {
 +LL | |     fn default() -> Self {
 +LL | |         WithoutSelfCurly { a: false }
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:168:1
 +   |
 +LL | / impl Default for WithoutSelfParan {
 +LL | |     fn default() -> Self {
 +LL | |         WithoutSelfParan(false)
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
 +error: this `impl` can be derived
 +  --> $DIR/derivable_impls.rs:218:1
 +   |
 +LL | / impl Default for RepeatDefault1 {
 +LL | |     fn default() -> Self {
 +LL | |         RepeatDefault1 { a: [0; 32] }
 +LL | |     }
 +LL | | }
 +   | |_^
 +   |
 +   = help: remove the manual implementation...
 +help: ...and instead derive it
 +   |
 +LL | #[derive(Default)]
 +   |
 +
++error: this `impl` can be derived
++  --> $DIR/derivable_impls.rs:252:1
++   |
++LL | / impl Default for SimpleEnum {
++LL | |     fn default() -> Self {
++LL | |         SimpleEnum::Bar
++LL | |     }
++LL | | }
++   | |_^
++   |
++   = help: remove the manual implementation...
++help: ...and instead derive it...
++   |
++LL | #[derive(Default)]
++   |
++help: ...and mark the default variant
++   |
++LL ~     #[default]
++LL ~     Bar,
++   |
++
++error: aborting due to 8 previous errors
 +
index b276c384c04ea83dfa79f12728fab4c79e07b269,0000000000000000000000000000000000000000..6e0ce55f57d9349c7e353ec6438e04a96afab159
mode 100644,000000..100644
--- /dev/null
@@@ -1,89 -1,0 +1,100 @@@
 +#![allow(dead_code)]
 +#![warn(clippy::expl_impl_clone_on_copy)]
 +
 +
 +#[derive(Copy)]
 +struct Qux;
 +
 +impl Clone for Qux {
 +    fn clone(&self) -> Self {
 +        Qux
 +    }
 +}
 +
 +// looks like unions don't support deriving Clone for now
 +#[derive(Copy)]
 +union Union {
 +    a: u8,
 +}
 +
 +impl Clone for Union {
 +    fn clone(&self) -> Self {
 +        Union { a: 42 }
 +    }
 +}
 +
 +// See #666
 +#[derive(Copy)]
 +struct Lt<'a> {
 +    a: &'a u8,
 +}
 +
 +impl<'a> Clone for Lt<'a> {
 +    fn clone(&self) -> Self {
 +        unimplemented!()
 +    }
 +}
 +
 +#[derive(Copy)]
 +struct BigArray {
 +    a: [u8; 65],
 +}
 +
 +impl Clone for BigArray {
 +    fn clone(&self) -> Self {
 +        unimplemented!()
 +    }
 +}
 +
 +#[derive(Copy)]
 +struct FnPtr {
 +    a: fn() -> !,
 +}
 +
 +impl Clone for FnPtr {
 +    fn clone(&self) -> Self {
 +        unimplemented!()
 +    }
 +}
 +
 +// Ok, Clone trait impl doesn't have constrained generics.
 +#[derive(Copy)]
 +struct Generic<T> {
 +    a: T,
 +}
 +
 +impl<T> Clone for Generic<T> {
 +    fn clone(&self) -> Self {
 +        unimplemented!()
 +    }
 +}
 +
 +#[derive(Copy)]
 +struct Generic2<T>(T);
 +impl<T: Clone> Clone for Generic2<T> {
 +    fn clone(&self) -> Self {
 +        Self(self.0.clone())
 +    }
 +}
 +
 +// Ok, Clone trait impl doesn't have constrained generics.
 +#[derive(Copy)]
 +struct GenericRef<'a, T, U>(T, &'a U);
 +impl<T: Clone, U> Clone for GenericRef<'_, T, U> {
 +    fn clone(&self) -> Self {
 +        Self(self.0.clone(), self.1)
 +    }
 +}
 +
++// https://github.com/rust-lang/rust-clippy/issues/10188
++#[repr(packed)]
++#[derive(Copy)]
++struct Packed<T>(T);
++
++impl<T: Copy> Clone for Packed<T> {
++    fn clone(&self) -> Self {
++        *self
++    }
++}
++
 +fn main() {}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8ad09a8de43d5acad141e03b5cf3b682010105eb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,39 @@@
++#![allow(clippy::derive_partial_eq_without_eq)]
++
++#[derive(PartialEq, Hash)]
++struct Foo;
++
++impl PartialEq<u64> for Foo {
++    fn eq(&self, _: &u64) -> bool {
++        true
++    }
++}
++
++#[derive(Hash)]
++struct Bar;
++
++impl PartialEq for Bar {
++    fn eq(&self, _: &Bar) -> bool {
++        true
++    }
++}
++
++#[derive(Hash)]
++struct Baz;
++
++impl PartialEq<Baz> for Baz {
++    fn eq(&self, _: &Baz) -> bool {
++        true
++    }
++}
++
++// Implementing `Hash` with a derived `PartialEq` is fine. See #2627
++
++#[derive(PartialEq)]
++struct Bah;
++
++impl std::hash::Hash for Bah {
++    fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
++}
++
++fn main() {}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..230940f25fb60ca1bf6c89c74c32a5b9962feb6a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,29 @@@
++error: you are deriving `Hash` but have implemented `PartialEq` explicitly
++  --> $DIR/derived_hash_with_manual_eq.rs:12:10
++   |
++LL | #[derive(Hash)]
++   |          ^^^^
++   |
++note: `PartialEq` implemented here
++  --> $DIR/derived_hash_with_manual_eq.rs:15:1
++   |
++LL | impl PartialEq for Bar {
++   | ^^^^^^^^^^^^^^^^^^^^^^
++   = note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
++   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
++
++error: you are deriving `Hash` but have implemented `PartialEq` explicitly
++  --> $DIR/derived_hash_with_manual_eq.rs:21:10
++   |
++LL | #[derive(Hash)]
++   |          ^^^^
++   |
++note: `PartialEq` implemented here
++  --> $DIR/derived_hash_with_manual_eq.rs:24:1
++   |
++LL | impl PartialEq<Baz> for Baz {
++   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
++
++error: aborting due to 2 previous errors
++
index 7de0b0bbdf9ae8ffdfb4019d695e4a38df8ad197,0000000000000000000000000000000000000000..10044e65f1156bc484ea3de731ed05c0fc97d902
mode 100644,000000..100644
--- /dev/null
@@@ -1,74 -1,0 +1,97 @@@
 +#![warn(clippy::drop_ref)]
 +#![allow(clippy::toplevel_ref_arg)]
 +#![allow(clippy::map_err_ignore)]
 +#![allow(clippy::unnecessary_wraps, clippy::drop_non_drop)]
 +
 +use std::mem::drop;
 +
 +struct SomeStruct;
 +
 +fn main() {
 +    drop(&SomeStruct);
 +
 +    let mut owned1 = SomeStruct;
 +    drop(&owned1);
 +    drop(&&owned1);
 +    drop(&mut owned1);
 +    drop(owned1); //OK
 +
 +    let reference1 = &SomeStruct;
 +    drop(reference1);
 +
 +    let reference2 = &mut SomeStruct;
 +    drop(reference2);
 +
 +    let ref reference3 = SomeStruct;
 +    drop(reference3);
 +}
 +
 +#[allow(dead_code)]
 +fn test_generic_fn_drop<T>(val: T) {
 +    drop(&val);
 +    drop(val); //OK
 +}
 +
 +#[allow(dead_code)]
 +fn test_similarly_named_function() {
 +    fn drop<T>(_val: T) {}
 +    drop(&SomeStruct); //OK; call to unrelated function which happens to have the same name
 +    std::mem::drop(&SomeStruct);
 +}
 +
 +#[derive(Copy, Clone)]
 +pub struct Error;
 +fn produce_half_owl_error() -> Result<(), Error> {
 +    Ok(())
 +}
 +
 +fn produce_half_owl_ok() -> Result<bool, ()> {
 +    Ok(true)
 +}
 +
 +#[allow(dead_code)]
 +fn test_owl_result() -> Result<(), ()> {
 +    produce_half_owl_error().map_err(|_| ())?;
 +    produce_half_owl_ok().map(|_| ())?;
 +    // the following should not be linted,
 +    // we should not force users to use toilet closures
 +    // to produce owl results when drop is more convenient
 +    produce_half_owl_error().map_err(drop)?;
 +    produce_half_owl_ok().map_err(drop)?;
 +    Ok(())
 +}
 +
 +#[allow(dead_code)]
 +fn test_owl_result_2() -> Result<u8, ()> {
 +    produce_half_owl_error().map_err(|_| ())?;
 +    produce_half_owl_ok().map(|_| ())?;
 +    // the following should not be linted,
 +    // we should not force users to use toilet closures
 +    // to produce owl results when drop is more convenient
 +    produce_half_owl_error().map_err(drop)?;
 +    produce_half_owl_ok().map(drop)?;
 +    Ok(1)
 +}
++
++#[allow(unused)]
++#[allow(clippy::unit_cmp)]
++fn issue10122(x: u8) {
++    // This is a function which returns a reference and has a side-effect, which means
++    // that calling drop() on the function is considered an idiomatic way of achieving the side-effect
++    // in a match arm.
++    fn println_and<T>(t: &T) -> &T {
++        println!("foo");
++        t
++    }
++
++    match x {
++        0 => drop(println_and(&12)), // Don't lint (copy type), we only care about side-effects
++        1 => drop(println_and(&String::new())), // Don't lint (no copy type), we only care about side-effects
++        2 => {
++            drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
++        },
++        3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
++        4 => drop(&2),                           // Lint, not a fn/method call
++        _ => (),
++    }
++}
index 4743cf79b5d3cf4dfe1e74d5b0b724df014744f9,0000000000000000000000000000000000000000..293b9f6de832dc5ca5f2f3d5a1eefb67d79f3195
mode 100644,000000..100644
--- /dev/null
@@@ -1,111 -1,0 +1,147 @@@
- error: aborting due to 9 previous errors
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:11:5
 +   |
 +LL |     drop(&SomeStruct);
 +   |     ^^^^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&SomeStruct`
 +  --> $DIR/drop_ref.rs:11:10
 +   |
 +LL |     drop(&SomeStruct);
 +   |          ^^^^^^^^^^^
 +   = note: `-D clippy::drop-ref` implied by `-D warnings`
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:14:5
 +   |
 +LL |     drop(&owned1);
 +   |     ^^^^^^^^^^^^^
 +   |
 +note: argument has type `&SomeStruct`
 +  --> $DIR/drop_ref.rs:14:10
 +   |
 +LL |     drop(&owned1);
 +   |          ^^^^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:15:5
 +   |
 +LL |     drop(&&owned1);
 +   |     ^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&&SomeStruct`
 +  --> $DIR/drop_ref.rs:15:10
 +   |
 +LL |     drop(&&owned1);
 +   |          ^^^^^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:16:5
 +   |
 +LL |     drop(&mut owned1);
 +   |     ^^^^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&mut SomeStruct`
 +  --> $DIR/drop_ref.rs:16:10
 +   |
 +LL |     drop(&mut owned1);
 +   |          ^^^^^^^^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:20:5
 +   |
 +LL |     drop(reference1);
 +   |     ^^^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&SomeStruct`
 +  --> $DIR/drop_ref.rs:20:10
 +   |
 +LL |     drop(reference1);
 +   |          ^^^^^^^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:23:5
 +   |
 +LL |     drop(reference2);
 +   |     ^^^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&mut SomeStruct`
 +  --> $DIR/drop_ref.rs:23:10
 +   |
 +LL |     drop(reference2);
 +   |          ^^^^^^^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:26:5
 +   |
 +LL |     drop(reference3);
 +   |     ^^^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&SomeStruct`
 +  --> $DIR/drop_ref.rs:26:10
 +   |
 +LL |     drop(reference3);
 +   |          ^^^^^^^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:31:5
 +   |
 +LL |     drop(&val);
 +   |     ^^^^^^^^^^
 +   |
 +note: argument has type `&T`
 +  --> $DIR/drop_ref.rs:31:10
 +   |
 +LL |     drop(&val);
 +   |          ^^^^
 +
 +error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
 +  --> $DIR/drop_ref.rs:39:5
 +   |
 +LL |     std::mem::drop(&SomeStruct);
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +note: argument has type `&SomeStruct`
 +  --> $DIR/drop_ref.rs:39:20
 +   |
 +LL |     std::mem::drop(&SomeStruct);
 +   |                    ^^^^^^^^^^^
 +
++error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
++  --> $DIR/drop_ref.rs:91:13
++   |
++LL |             drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
++   |             ^^^^^^^^^^^^^^^^^^^^^^
++   |
++note: argument has type `&i32`
++  --> $DIR/drop_ref.rs:91:18
++   |
++LL |             drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
++   |                  ^^^^^^^^^^^^^^^^
++
++error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
++  --> $DIR/drop_ref.rs:93:14
++   |
++LL |         3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
++   |              ^^^^^^^^^^^^^^^^^^^^^^
++   |
++note: argument has type `&i32`
++  --> $DIR/drop_ref.rs:93:19
++   |
++LL |         3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
++   |                   ^^^^^^^^^^^^^^^^
++
++error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
++  --> $DIR/drop_ref.rs:94:14
++   |
++LL |         4 => drop(&2),                           // Lint, not a fn/method call
++   |              ^^^^^^^^
++   |
++note: argument has type `&i32`
++  --> $DIR/drop_ref.rs:94:19
++   |
++LL |         4 => drop(&2),                           // Lint, not a fn/method call
++   |                   ^^
++
++error: aborting due to 12 previous errors
 +
index 7367910eaa126fdc54319aa3d7232765dcca376d,0000000000000000000000000000000000000000..1f989bb1220525f35807d6d1195ea875707b0e1e
mode 100644,000000..100644
--- /dev/null
@@@ -1,249 -1,0 +1,270 @@@
 +// aux-build:proc_macro_derive.rs
 +// aux-build:macro_rules.rs
 +
 +#![warn(clippy::field_reassign_with_default)]
 +
 +#[macro_use]
 +extern crate proc_macro_derive;
 +#[macro_use]
 +extern crate macro_rules;
 +
 +// Don't lint on derives that derive `Default`
 +// See https://github.com/rust-lang/rust-clippy/issues/6545
 +#[derive(FieldReassignWithDefault)]
 +struct DerivedStruct;
 +
 +#[derive(Default)]
 +struct A {
 +    i: i32,
 +    j: i64,
 +}
 +
 +struct B {
 +    i: i32,
 +    j: i64,
 +}
 +
 +#[derive(Default)]
 +struct C {
 +    i: Vec<i32>,
 +    j: i64,
 +}
 +
 +#[derive(Default)]
 +struct D {
 +    a: Option<i32>,
 +    b: Option<i32>,
 +}
 +
 +macro_rules! m {
 +    ($key:ident: $value:tt) => {{
 +        let mut data = $crate::D::default();
 +        data.$key = Some($value);
 +        data
 +    }};
 +}
 +
 +/// Implements .next() that returns a different number each time.
 +struct SideEffect(i32);
 +
 +impl SideEffect {
 +    fn new() -> SideEffect {
 +        SideEffect(0)
 +    }
 +    fn next(&mut self) -> i32 {
 +        self.0 += 1;
 +        self.0
 +    }
 +}
 +
 +fn main() {
 +    // wrong, produces first error in stderr
 +    let mut a: A = Default::default();
 +    a.i = 42;
 +
 +    // right
 +    let mut a: A = Default::default();
 +
 +    // right
 +    let a = A {
 +        i: 42,
 +        ..Default::default()
 +    };
 +
 +    // right
 +    let mut a: A = Default::default();
 +    if a.i == 0 {
 +        a.j = 12;
 +    }
 +
 +    // right
 +    let mut a: A = Default::default();
 +    let b = 5;
 +
 +    // right
 +    let mut b = 32;
 +    let mut a: A = Default::default();
 +    b = 2;
 +
 +    // right
 +    let b: B = B { i: 42, j: 24 };
 +
 +    // right
 +    let mut b: B = B { i: 42, j: 24 };
 +    b.i = 52;
 +
 +    // right
 +    let mut b = B { i: 15, j: 16 };
 +    let mut a: A = Default::default();
 +    b.i = 2;
 +
 +    // wrong, produces second error in stderr
 +    let mut a: A = Default::default();
 +    a.j = 43;
 +    a.i = 42;
 +
 +    // wrong, produces third error in stderr
 +    let mut a: A = Default::default();
 +    a.i = 42;
 +    a.j = 43;
 +    a.j = 44;
 +
 +    // wrong, produces fourth error in stderr
 +    let mut a = A::default();
 +    a.i = 42;
 +
 +    // wrong, but does not produce an error in stderr, because we can't produce a correct kind of
 +    // suggestion with current implementation
 +    let mut c: (i32, i32) = Default::default();
 +    c.0 = 42;
 +    c.1 = 21;
 +
 +    // wrong, produces the fifth error in stderr
 +    let mut a: A = Default::default();
 +    a.i = Default::default();
 +
 +    // wrong, produces the sixth error in stderr
 +    let mut a: A = Default::default();
 +    a.i = Default::default();
 +    a.j = 45;
 +
 +    // right, because an assignment refers to another field
 +    let mut x = A::default();
 +    x.i = 42;
 +    x.j = 21 + x.i as i64;
 +
 +    // right, we bail out if there's a reassignment to the same variable, since there is a risk of
 +    // side-effects affecting the outcome
 +    let mut x = A::default();
 +    let mut side_effect = SideEffect::new();
 +    x.i = side_effect.next();
 +    x.j = 2;
 +    x.i = side_effect.next();
 +
 +    // don't lint - some private fields
 +    let mut x = m::F::default();
 +    x.a = 1;
 +
 +    // don't expand macros in the suggestion (#6522)
 +    let mut a: C = C::default();
 +    a.i = vec![1];
 +
 +    // Don't lint in external macros
 +    field_reassign_with_default!();
 +
 +    // be sure suggestion is correct with generics
 +    let mut a: Wrapper<bool> = Default::default();
 +    a.i = true;
 +
 +    let mut a: WrapperMulti<i32, i64> = Default::default();
 +    a.i = 42;
 +
 +    // Don't lint in macros
 +    m! {
 +        a: 42
 +    };
 +}
 +
 +mod m {
 +    #[derive(Default)]
 +    pub struct F {
 +        pub a: u64,
 +        b: u64,
 +    }
 +}
 +
 +#[derive(Default)]
 +struct Wrapper<T> {
 +    i: T,
 +}
 +
 +#[derive(Default)]
 +struct WrapperMulti<T, U> {
 +    i: T,
 +    j: U,
 +}
 +
 +mod issue6312 {
 +    use std::sync::atomic::AtomicBool;
 +    use std::sync::Arc;
 +
 +    // do not lint: type implements `Drop` but not all fields are `Copy`
 +    #[derive(Clone, Default)]
 +    pub struct ImplDropNotAllCopy {
 +        name: String,
 +        delay_data_sync: Arc<AtomicBool>,
 +    }
 +
 +    impl Drop for ImplDropNotAllCopy {
 +        fn drop(&mut self) {
 +            self.close()
 +        }
 +    }
 +
 +    impl ImplDropNotAllCopy {
 +        fn new(name: &str) -> Self {
 +            let mut f = ImplDropNotAllCopy::default();
 +            f.name = name.to_owned();
 +            f
 +        }
 +        fn close(&self) {}
 +    }
 +
 +    // lint: type implements `Drop` and all fields are `Copy`
 +    #[derive(Clone, Default)]
 +    pub struct ImplDropAllCopy {
 +        name: usize,
 +        delay_data_sync: bool,
 +    }
 +
 +    impl Drop for ImplDropAllCopy {
 +        fn drop(&mut self) {
 +            self.close()
 +        }
 +    }
 +
 +    impl ImplDropAllCopy {
 +        fn new(name: &str) -> Self {
 +            let mut f = ImplDropAllCopy::default();
 +            f.name = name.len();
 +            f
 +        }
 +        fn close(&self) {}
 +    }
 +
 +    // lint: type does not implement `Drop` though all fields are `Copy`
 +    #[derive(Clone, Default)]
 +    pub struct NoDropAllCopy {
 +        name: usize,
 +        delay_data_sync: bool,
 +    }
 +
 +    impl NoDropAllCopy {
 +        fn new(name: &str) -> Self {
 +            let mut f = NoDropAllCopy::default();
 +            f.name = name.len();
 +            f
 +        }
 +    }
 +}
++
++struct Collection {
++    items: Vec<i32>,
++    len: usize,
++}
++
++impl Default for Collection {
++    fn default() -> Self {
++        Self {
++            items: vec![1, 2, 3],
++            len: 0,
++        }
++    }
++}
++
++#[allow(clippy::redundant_closure_call)]
++fn issue10136() {
++    let mut c = Collection::default();
++    // don't lint, since c.items was used to calculate this value
++    c.len = (|| c.items.len())();
++}
index 83fee04080fa76507d15d19f1376f35ed48caf96,0000000000000000000000000000000000000000..f2a4c284cb16d68d0ccb92bca478c716d309f468
mode 100644,000000..100644
--- /dev/null
@@@ -1,64 -1,0 +1,93 @@@
- #![allow(clippy::redundant_clone)]
- #![allow(clippy::suspicious_map)]
- #![allow(clippy::map_identity)]
 +// run-rustfix
 +
 +#![warn(clippy::iter_kv_map)]
++#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
 +
 +use std::collections::{BTreeMap, HashMap};
 +
 +fn main() {
 +    let get_key = |(key, _val)| key;
++    fn ref_acceptor(v: &u32) -> u32 {
++        *v
++    }
 +
 +    let map: HashMap<u32, u32> = HashMap::new();
 +
 +    let _ = map.keys().collect::<Vec<_>>();
 +    let _ = map.values().collect::<Vec<_>>();
 +    let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_keys().collect::<Vec<_>>();
 +    let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_values().collect::<Vec<_>>();
 +    let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().values().collect::<Vec<_>>();
 +    let _ = map.keys().filter(|x| *x % 2 == 0).count();
 +
 +    // Don't lint
 +    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).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();
 +
 +    // Lint
 +    let _ = map.keys().map(|key| key * 9).count();
 +    let _ = map.values().map(|value| value * 17).count();
 +
++    // Preserve the ref in the fix.
++    let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
++
++    // Preserve the mut in the fix.
++    let _ = map
++        .clone().into_values().map(|mut val| {
++            val += 2;
++            val
++        })
++        .count();
++
++    // Don't let a mut interfere.
++    let _ = map.clone().into_values().count();
++
 +    let map: BTreeMap<u32, u32> = BTreeMap::new();
 +
 +    let _ = map.keys().collect::<Vec<_>>();
 +    let _ = map.values().collect::<Vec<_>>();
 +    let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_keys().collect::<Vec<_>>();
 +    let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_values().collect::<Vec<_>>();
 +    let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().values().collect::<Vec<_>>();
 +    let _ = map.keys().filter(|x| *x % 2 == 0).count();
 +
 +    // Don't lint
 +    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).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();
 +
 +    // Lint
 +    let _ = map.keys().map(|key| key * 9).count();
 +    let _ = map.values().map(|value| value * 17).count();
++
++    // Preserve the ref in the fix.
++    let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
++
++    // Preserve the mut in the fix.
++    let _ = map
++        .clone().into_values().map(|mut val| {
++            val += 2;
++            val
++        })
++        .count();
++
++    // Don't let a mut interfere.
++    let _ = map.clone().into_values().count();
 +}
index 7a1f1fb0198c7a3b160280fb55ec0fd84436b800,0000000000000000000000000000000000000000..ad6564df40846e2e8da197eb592ad5730b67fa17
mode 100644,000000..100644
--- /dev/null
@@@ -1,64 -1,0 +1,97 @@@
- #![allow(clippy::redundant_clone)]
- #![allow(clippy::suspicious_map)]
- #![allow(clippy::map_identity)]
 +// run-rustfix
 +
 +#![warn(clippy::iter_kv_map)]
++#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
 +
 +use std::collections::{BTreeMap, HashMap};
 +
 +fn main() {
 +    let get_key = |(key, _val)| key;
++    fn ref_acceptor(v: &u32) -> u32 {
++        *v
++    }
 +
 +    let map: HashMap<u32, u32> = HashMap::new();
 +
 +    let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
 +    let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
 +    let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
 +    let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
 +    let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
 +    let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
 +
 +    // Don't lint
 +    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).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();
 +
 +    // Lint
 +    let _ = map.iter().map(|(key, _value)| key * 9).count();
 +    let _ = map.iter().map(|(_key, value)| value * 17).count();
 +
++    // Preserve the ref in the fix.
++    let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
++
++    // Preserve the mut in the fix.
++    let _ = map
++        .clone()
++        .into_iter()
++        .map(|(_, mut val)| {
++            val += 2;
++            val
++        })
++        .count();
++
++    // Don't let a mut interfere.
++    let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
++
 +    let map: BTreeMap<u32, u32> = BTreeMap::new();
 +
 +    let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
 +    let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
 +    let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
 +    let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
 +    let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
 +
 +    let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
 +    let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
 +
 +    // Don't lint
 +    let _ = map.iter().filter(|(_, val)| *val % 2 == 0).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();
 +
 +    // Lint
 +    let _ = map.iter().map(|(key, _value)| key * 9).count();
 +    let _ = map.iter().map(|(_key, value)| value * 17).count();
++
++    // Preserve the ref in the fix.
++    let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
++
++    // Preserve the mut in the fix.
++    let _ = map
++        .clone()
++        .into_iter()
++        .map(|(_, mut val)| {
++            val += 2;
++            val
++        })
++        .count();
++
++    // Don't let a mut interfere.
++    let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
 +}
index 9b9b04c97d81ef40e76d8fa4d9bce42639d1400f,0000000000000000000000000000000000000000..e00da223b4dd2193f2f690d7326221fcb2e98e55
mode 100644,000000..100644
--- /dev/null
@@@ -1,136 -1,0 +1,204 @@@
-   --> $DIR/iter_kv_map.rs:15:13
 +error: iterating on a map's keys
-   --> $DIR/iter_kv_map.rs:16:13
++  --> $DIR/iter_kv_map.rs:16:13
 +   |
 +LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 +   |
 +   = note: `-D clippy::iter-kv-map` implied by `-D warnings`
 +
 +error: iterating on a map's values
-   --> $DIR/iter_kv_map.rs:17:13
++  --> $DIR/iter_kv_map.rs:17:13
 +   |
 +LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 +
 +error: iterating on a map's values
-   --> $DIR/iter_kv_map.rs:19:13
++  --> $DIR/iter_kv_map.rs:18: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
-   --> $DIR/iter_kv_map.rs:20:13
++  --> $DIR/iter_kv_map.rs:20: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
-   --> $DIR/iter_kv_map.rs:22:13
++  --> $DIR/iter_kv_map.rs:21: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
-   --> $DIR/iter_kv_map.rs:23:13
++  --> $DIR/iter_kv_map.rs:23: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
-   --> $DIR/iter_kv_map.rs:25:13
++  --> $DIR/iter_kv_map.rs:24: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
-   --> $DIR/iter_kv_map.rs:26:13
++  --> $DIR/iter_kv_map.rs:26:13
 +   |
 +LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 +
 +error: iterating on a map's keys
-   --> $DIR/iter_kv_map.rs:36:13
++  --> $DIR/iter_kv_map.rs:27:13
 +   |
 +LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 +
 +error: iterating on a map's keys
-   --> $DIR/iter_kv_map.rs:37:13
++  --> $DIR/iter_kv_map.rs:37: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
- error: iterating on a map's keys
++  --> $DIR/iter_kv_map.rs:38:13
 +   |
 +LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 +
-   --> $DIR/iter_kv_map.rs:42:13
++error: iterating on a map's values
 +  --> $DIR/iter_kv_map.rs:41: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
++  --> $DIR/iter_kv_map.rs:44:13
++   |
++LL |       let _ = map
++   |  _____________^
++LL | |         .clone()
++LL | |         .into_iter()
++LL | |         .map(|(_, mut val)| {
++LL | |             val += 2;
++LL | |             val
++LL | |         })
++   | |__________^
++   |
++help: try
++   |
++LL ~     let _ = map
++LL +         .clone().into_values().map(|mut val| {
++LL +             val += 2;
++LL +             val
++LL +         })
++   |
++
++error: iterating on a map's values
++  --> $DIR/iter_kv_map.rs:54: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
++  --> $DIR/iter_kv_map.rs:58:13
++   |
 +LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 +
 +error: iterating on a map's values
-   --> $DIR/iter_kv_map.rs:43:13
++  --> $DIR/iter_kv_map.rs:59:13
 +   |
 +LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 +
 +error: iterating on a map's values
-   --> $DIR/iter_kv_map.rs:45:13
++  --> $DIR/iter_kv_map.rs:60: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
-   --> $DIR/iter_kv_map.rs:46:13
++  --> $DIR/iter_kv_map.rs:62: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
-   --> $DIR/iter_kv_map.rs:48:13
++  --> $DIR/iter_kv_map.rs:63: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
-   --> $DIR/iter_kv_map.rs:49:13
++  --> $DIR/iter_kv_map.rs:65: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
-   --> $DIR/iter_kv_map.rs:51:13
++  --> $DIR/iter_kv_map.rs:66: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
-   --> $DIR/iter_kv_map.rs:52:13
++  --> $DIR/iter_kv_map.rs:68:13
 +   |
 +LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 +
 +error: iterating on a map's keys
-   --> $DIR/iter_kv_map.rs:62:13
++  --> $DIR/iter_kv_map.rs:69:13
 +   |
 +LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 +
 +error: iterating on a map's keys
-   --> $DIR/iter_kv_map.rs:63:13
++  --> $DIR/iter_kv_map.rs:79: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
- error: aborting due to 22 previous errors
++  --> $DIR/iter_kv_map.rs:80: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
++  --> $DIR/iter_kv_map.rs:83: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
++  --> $DIR/iter_kv_map.rs:86:13
++   |
++LL |       let _ = map
++   |  _____________^
++LL | |         .clone()
++LL | |         .into_iter()
++LL | |         .map(|(_, mut val)| {
++LL | |             val += 2;
++LL | |             val
++LL | |         })
++   | |__________^
++   |
++help: try
++   |
++LL ~     let _ = map
++LL +         .clone().into_values().map(|mut val| {
++LL +             val += 2;
++LL +             val
++LL +         })
++   |
++
++error: iterating on a map's values
++  --> $DIR/iter_kv_map.rs:96:13
++   |
++LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
++   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
++
++error: aborting due to 28 previous errors
 +
index 31e1cb6c3d7f7efd0e083c67233079d557f11947,0000000000000000000000000000000000000000..4cb7f6b687f1195c3bb429b941c8ca256f6534d3
mode 100644,000000..100644
--- /dev/null
@@@ -1,504 -1,0 +1,493 @@@
- #![feature(custom_inner_attributes, lint_reasons, rustc_private)]
 +// run-rustfix
- extern crate rustc_lint;
- extern crate rustc_span;
- #[allow(dead_code)]
- mod span_lint {
-     use rustc_lint::{LateContext, Lint, LintContext};
-     fn foo(cx: &LateContext<'_>, lint: &'static Lint) {
-         cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(String::new()));
-     }
- }
++#![feature(lint_reasons)]
 +#![allow(
 +    unused,
 +    clippy::uninlined_format_args,
 +    clippy::unnecessary_mut_passed,
 +    clippy::unnecessary_to_owned
 +)]
 +#![warn(clippy::needless_borrow)]
 +
 +fn main() {
 +    let a = 5;
 +    let ref_a = &a;
 +    let _ = x(&a); // no warning
 +    let _ = x(&a); // warn
 +
 +    let mut b = 5;
 +    mut_ref(&mut b); // no warning
 +    mut_ref(&mut b); // warn
 +
 +    let s = &String::from("hi");
 +    let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not
 +    let g_val = g(&Vec::new()); // should not error, because `&Vec<T>` derefs to `&[T]`
 +    let vec = Vec::new();
 +    let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
 +    h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
 +    let garbl = match 42 {
 +        44 => &a,
 +        45 => {
 +            println!("foo");
 +            &a
 +        },
 +        46 => &a,
 +        47 => {
 +            println!("foo");
 +            loop {
 +                println!("{}", a);
 +                if a == 25 {
 +                    break ref_a;
 +                }
 +            }
 +        },
 +        _ => panic!(),
 +    };
 +
 +    let _ = x(&a);
 +    let _ = x(&a);
 +    let _ = x(&mut b);
 +    let _ = x(ref_a);
 +    {
 +        let b = &mut b;
 +        x(b);
 +    }
 +
 +    // Issue #8191
 +    let mut x = 5;
 +    let mut x = &mut x;
 +
 +    mut_ref(x);
 +    mut_ref(x);
 +    let y: &mut i32 = x;
 +    let y: &mut i32 = x;
 +
 +    let y = match 0 {
 +        // Don't lint. Removing the borrow would move 'x'
 +        0 => &mut x,
 +        _ => &mut *x,
 +    };
 +    let y: &mut i32 = match 0 {
 +        // Lint here. The type given above triggers auto-borrow.
 +        0 => x,
 +        _ => &mut *x,
 +    };
 +    fn ref_mut_i32(_: &mut i32) {}
 +    ref_mut_i32(match 0 {
 +        // Lint here. The type given above triggers auto-borrow.
 +        0 => x,
 +        _ => &mut *x,
 +    });
 +    // use 'x' after to make sure it's still usable in the fixed code.
 +    *x = 5;
 +
 +    let s = String::new();
 +    // let _ = (&s).len();
 +    // let _ = (&s).capacity();
 +    // let _ = (&&s).capacity();
 +
 +    let x = (1, 2);
 +    let _ = x.0;
 +    let x = &x as *const (i32, i32);
 +    let _ = unsafe { (*x).0 };
 +
 +    // Issue #8367
 +    trait Foo {
 +        fn foo(self);
 +    }
 +    impl Foo for &'_ () {
 +        fn foo(self) {}
 +    }
 +    (&()).foo(); // Don't lint. `()` doesn't implement `Foo`
 +    (&()).foo();
 +
 +    impl Foo for i32 {
 +        fn foo(self) {}
 +    }
 +    impl Foo for &'_ i32 {
 +        fn foo(self) {}
 +    }
 +    (&5).foo(); // Don't lint. `5` will call `<i32 as Foo>::foo`
 +    (&5).foo();
 +
 +    trait FooRef {
 +        fn foo_ref(&self);
 +    }
 +    impl FooRef for () {
 +        fn foo_ref(&self) {}
 +    }
 +    impl FooRef for &'_ () {
 +        fn foo_ref(&self) {}
 +    }
 +    (&&()).foo_ref(); // Don't lint. `&()` will call `<() as FooRef>::foo_ref`
 +
 +    struct S;
 +    impl From<S> for u32 {
 +        fn from(s: S) -> Self {
 +            (&s).into()
 +        }
 +    }
 +    impl From<&S> for u32 {
 +        fn from(s: &S) -> Self {
 +            0
 +        }
 +    }
 +
 +    let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap();
 +    let _ = std::path::Path::new(".").join(".");
 +    deref_target_is_x(X);
 +    multiple_constraints([[""]]);
 +    multiple_constraints_normalizes_to_same(X, X);
 +    let _ = Some("").unwrap_or("");
 +    let _ = std::fs::write("x", "".to_string());
 +
 +    only_sized(&""); // Don't lint. `Sized` is only bound
 +    let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound
 +    let _ = Box::new(&""); // Don't lint. Type parameter appears in return type
 +    ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter
 +    refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't
 +    multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments
 +}
 +
 +#[allow(clippy::needless_borrowed_reference)]
 +fn x(y: &i32) -> i32 {
 +    *y
 +}
 +
 +fn mut_ref(y: &mut i32) {
 +    *y = 5;
 +}
 +
 +fn f<T: Copy>(y: &T) -> T {
 +    *y
 +}
 +
 +fn g(y: &[u8]) -> u8 {
 +    y[0]
 +}
 +
 +trait Trait {}
 +
 +impl<'a> Trait for &'a str {}
 +
 +fn h(_: &dyn Trait) {}
 +
 +fn check_expect_suppression() {
 +    let a = 5;
 +    #[expect(clippy::needless_borrow)]
 +    let _ = x(&&a);
 +}
 +
 +mod issue9160 {
 +    pub struct S<F> {
 +        f: F,
 +    }
 +
 +    impl<T, F> S<F>
 +    where
 +        F: Fn() -> T,
 +    {
 +        fn calls_field(&self) -> T {
 +            (self.f)()
 +        }
 +    }
 +
 +    impl<T, F> S<F>
 +    where
 +        F: FnMut() -> T,
 +    {
 +        fn calls_mut_field(&mut self) -> T {
 +            (self.f)()
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy)]
 +struct X;
 +
 +impl std::ops::Deref for X {
 +    type Target = X;
 +    fn deref(&self) -> &Self::Target {
 +        self
 +    }
 +}
 +
 +fn deref_target_is_x<T>(_: T)
 +where
 +    T: std::ops::Deref<Target = X>,
 +{
 +}
 +
 +fn multiple_constraints<T, U, V, X, Y>(_: T)
 +where
 +    T: IntoIterator<Item = U> + IntoIterator<Item = X>,
 +    U: IntoIterator<Item = V>,
 +    V: AsRef<str>,
 +    X: IntoIterator<Item = Y>,
 +    Y: AsRef<std::ffi::OsStr>,
 +{
 +}
 +
 +fn multiple_constraints_normalizes_to_same<T, U, V>(_: T, _: V)
 +where
 +    T: std::ops::Deref<Target = U>,
 +    U: std::ops::Deref<Target = V>,
 +{
 +}
 +
 +fn only_sized<T>(_: T) {}
 +
 +fn ref_as_ref_path<T: 'static>(_: &'static T)
 +where
 +    &'static T: AsRef<std::path::Path>,
 +{
 +}
 +
 +trait RefsOnly {
 +    type Referent;
 +}
 +
 +impl<T> RefsOnly for &T {
 +    type Referent = T;
 +}
 +
 +fn refs_only<T, U>(_: T)
 +where
 +    T: RefsOnly<Referent = U>,
 +{
 +}
 +
 +fn multiple_constraints_normalizes_to_different<T, U, V>(_: T, _: U)
 +where
 +    T: IntoIterator<Item = U>,
 +    U: IntoIterator<Item = V>,
 +    V: AsRef<str>,
 +{
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321
 +mod copyable_iterator {
 +    #[derive(Clone, Copy)]
 +    struct Iter;
 +    impl Iterator for Iter {
 +        type Item = ();
 +        fn next(&mut self) -> Option<Self::Item> {
 +            None
 +        }
 +    }
 +    fn takes_iter(_: impl Iterator) {}
 +    fn dont_warn(mut x: Iter) {
 +        takes_iter(&mut x);
 +    }
 +    #[allow(unused_mut)]
 +    fn warn(mut x: &mut Iter) {
 +        takes_iter(x)
 +    }
 +}
 +
 +#[clippy::msrv = "1.52.0"]
 +mod under_msrv {
 +    fn foo() {
 +        let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
 +    }
 +}
 +
 +#[clippy::msrv = "1.53.0"]
 +mod meets_msrv {
 +    fn foo() {
 +        let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap();
 +    }
 +}
 +
 +fn issue9383() {
 +    // Should not lint because unions need explicit deref when accessing field
 +    use std::mem::ManuallyDrop;
 +
 +    union Coral {
 +        crab: ManuallyDrop<Vec<i32>>,
 +    }
 +
 +    union Ocean {
 +        coral: ManuallyDrop<Coral>,
 +    }
 +
 +    let mut ocean = Ocean {
 +        coral: ManuallyDrop::new(Coral {
 +            crab: ManuallyDrop::new(vec![1, 2, 3]),
 +        }),
 +    };
 +
 +    unsafe {
 +        ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
 +
 +        (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
 +        ManuallyDrop::drop(&mut (*ocean.coral).crab);
 +
 +        ManuallyDrop::drop(&mut ocean.coral);
 +    }
 +}
 +
 +fn closure_test() {
 +    let env = "env".to_owned();
 +    let arg = "arg".to_owned();
 +    let f = |arg| {
 +        let loc = "loc".to_owned();
 +        let _ = std::fs::write("x", &env); // Don't lint. In environment
 +        let _ = std::fs::write("x", arg);
 +        let _ = std::fs::write("x", loc);
 +    };
 +    let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
 +    f(arg);
 +}
 +
 +mod significant_drop {
 +    #[derive(Debug)]
 +    struct X;
 +
 +    #[derive(Debug)]
 +    struct Y;
 +
 +    impl Drop for Y {
 +        fn drop(&mut self) {}
 +    }
 +
 +    fn foo(x: X, y: Y) {
 +        debug(x);
 +        debug(&y); // Don't lint. Has significant drop
 +    }
 +
 +    fn debug(_: impl std::fmt::Debug) {}
 +}
 +
 +mod used_exactly_once {
 +    fn foo(x: String) {
 +        use_x(x);
 +    }
 +    fn use_x(_: impl AsRef<str>) {}
 +}
 +
 +mod used_more_than_once {
 +    fn foo(x: String) {
 +        use_x(&x);
 +        use_x_again(&x);
 +    }
 +    fn use_x(_: impl AsRef<str>) {}
 +    fn use_x_again(_: impl AsRef<str>) {}
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
 +mod issue_9111 {
 +    struct A;
 +
 +    impl Extend<u8> for A {
 +        fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
 +            unimplemented!()
 +        }
 +    }
 +
 +    impl<'a> Extend<&'a u8> for A {
 +        fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
 +            unimplemented!()
 +        }
 +    }
 +
 +    fn main() {
 +        let mut a = A;
 +        a.extend(&[]); // vs a.extend([]);
 +    }
 +}
 +
 +mod issue_9710 {
 +    fn main() {
 +        let string = String::new();
 +        for _i in 0..10 {
 +            f(&string);
 +        }
 +    }
 +
 +    fn f<T: AsRef<str>>(_: T) {}
 +}
 +
 +mod issue_9739 {
 +    fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
 +
 +    fn main() {
 +        foo(if std::env::var_os("HI").is_some() {
 +            &[0]
 +        } else {
 +            &[] as &[u32]
 +        });
 +    }
 +}
 +
 +mod issue_9739_method_variant {
 +    struct S;
 +
 +    impl S {
 +        fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
 +    }
 +
 +    fn main() {
 +        S.foo(if std::env::var_os("HI").is_some() {
 +            &[0]
 +        } else {
 +            &[] as &[u32]
 +        });
 +    }
 +}
 +
 +mod issue_9782 {
 +    fn foo<T: AsRef<[u8]>>(t: T) {
 +        println!("{}", std::mem::size_of::<T>());
 +        let _t: &[u8] = t.as_ref();
 +    }
 +
 +    fn main() {
 +        let a: [u8; 100] = [0u8; 100];
 +
 +        // 100
 +        foo::<[u8; 100]>(a);
 +        foo(a);
 +
 +        // 16
 +        foo::<&[u8]>(&a);
 +        foo(a.as_slice());
 +
 +        // 8
 +        foo::<&[u8; 100]>(&a);
 +        foo(a);
 +    }
 +}
 +
 +mod issue_9782_type_relative_variant {
 +    struct S;
 +
 +    impl S {
 +        fn foo<T: AsRef<[u8]>>(t: T) {
 +            println!("{}", std::mem::size_of::<T>());
 +            let _t: &[u8] = t.as_ref();
 +        }
 +    }
 +
 +    fn main() {
 +        let a: [u8; 100] = [0u8; 100];
 +
 +        S::foo::<&[u8; 100]>(&a);
 +    }
 +}
 +
 +mod issue_9782_method_variant {
 +    struct S;
 +
 +    impl S {
 +        fn foo<T: AsRef<[u8]>>(&self, t: T) {
 +            println!("{}", std::mem::size_of::<T>());
 +            let _t: &[u8] = t.as_ref();
 +        }
 +    }
 +
 +    fn main() {
 +        let a: [u8; 100] = [0u8; 100];
 +
 +        S.foo::<&[u8; 100]>(&a);
 +    }
 +}
index 55c2738fcf273c812c30105fc84e8090ea4fe927,0000000000000000000000000000000000000000..9a01190ed8dbd585127276cde688afa19fd07730
mode 100644,000000..100644
--- /dev/null
@@@ -1,504 -1,0 +1,493 @@@
- #![feature(custom_inner_attributes, lint_reasons, rustc_private)]
 +// run-rustfix
- extern crate rustc_lint;
- extern crate rustc_span;
- #[allow(dead_code)]
- mod span_lint {
-     use rustc_lint::{LateContext, Lint, LintContext};
-     fn foo(cx: &LateContext<'_>, lint: &'static Lint) {
-         cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new()));
-     }
- }
++#![feature(lint_reasons)]
 +#![allow(
 +    unused,
 +    clippy::uninlined_format_args,
 +    clippy::unnecessary_mut_passed,
 +    clippy::unnecessary_to_owned
 +)]
 +#![warn(clippy::needless_borrow)]
 +
 +fn main() {
 +    let a = 5;
 +    let ref_a = &a;
 +    let _ = x(&a); // no warning
 +    let _ = x(&&a); // warn
 +
 +    let mut b = 5;
 +    mut_ref(&mut b); // no warning
 +    mut_ref(&mut &mut b); // warn
 +
 +    let s = &String::from("hi");
 +    let s_ident = f(&s); // should not error, because `&String` implements Copy, but `String` does not
 +    let g_val = g(&Vec::new()); // should not error, because `&Vec<T>` derefs to `&[T]`
 +    let vec = Vec::new();
 +    let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
 +    h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
 +    let garbl = match 42 {
 +        44 => &a,
 +        45 => {
 +            println!("foo");
 +            &&a
 +        },
 +        46 => &&a,
 +        47 => {
 +            println!("foo");
 +            loop {
 +                println!("{}", a);
 +                if a == 25 {
 +                    break &ref_a;
 +                }
 +            }
 +        },
 +        _ => panic!(),
 +    };
 +
 +    let _ = x(&&&a);
 +    let _ = x(&mut &&a);
 +    let _ = x(&&&mut b);
 +    let _ = x(&&ref_a);
 +    {
 +        let b = &mut b;
 +        x(&b);
 +    }
 +
 +    // Issue #8191
 +    let mut x = 5;
 +    let mut x = &mut x;
 +
 +    mut_ref(&mut x);
 +    mut_ref(&mut &mut x);
 +    let y: &mut i32 = &mut x;
 +    let y: &mut i32 = &mut &mut x;
 +
 +    let y = match 0 {
 +        // Don't lint. Removing the borrow would move 'x'
 +        0 => &mut x,
 +        _ => &mut *x,
 +    };
 +    let y: &mut i32 = match 0 {
 +        // Lint here. The type given above triggers auto-borrow.
 +        0 => &mut x,
 +        _ => &mut *x,
 +    };
 +    fn ref_mut_i32(_: &mut i32) {}
 +    ref_mut_i32(match 0 {
 +        // Lint here. The type given above triggers auto-borrow.
 +        0 => &mut x,
 +        _ => &mut *x,
 +    });
 +    // use 'x' after to make sure it's still usable in the fixed code.
 +    *x = 5;
 +
 +    let s = String::new();
 +    // let _ = (&s).len();
 +    // let _ = (&s).capacity();
 +    // let _ = (&&s).capacity();
 +
 +    let x = (1, 2);
 +    let _ = (&x).0;
 +    let x = &x as *const (i32, i32);
 +    let _ = unsafe { (&*x).0 };
 +
 +    // Issue #8367
 +    trait Foo {
 +        fn foo(self);
 +    }
 +    impl Foo for &'_ () {
 +        fn foo(self) {}
 +    }
 +    (&()).foo(); // Don't lint. `()` doesn't implement `Foo`
 +    (&&()).foo();
 +
 +    impl Foo for i32 {
 +        fn foo(self) {}
 +    }
 +    impl Foo for &'_ i32 {
 +        fn foo(self) {}
 +    }
 +    (&5).foo(); // Don't lint. `5` will call `<i32 as Foo>::foo`
 +    (&&5).foo();
 +
 +    trait FooRef {
 +        fn foo_ref(&self);
 +    }
 +    impl FooRef for () {
 +        fn foo_ref(&self) {}
 +    }
 +    impl FooRef for &'_ () {
 +        fn foo_ref(&self) {}
 +    }
 +    (&&()).foo_ref(); // Don't lint. `&()` will call `<() as FooRef>::foo_ref`
 +
 +    struct S;
 +    impl From<S> for u32 {
 +        fn from(s: S) -> Self {
 +            (&s).into()
 +        }
 +    }
 +    impl From<&S> for u32 {
 +        fn from(s: &S) -> Self {
 +            0
 +        }
 +    }
 +
 +    let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
 +    let _ = std::path::Path::new(".").join(&&".");
 +    deref_target_is_x(&X);
 +    multiple_constraints(&[[""]]);
 +    multiple_constraints_normalizes_to_same(&X, X);
 +    let _ = Some("").unwrap_or(&"");
 +    let _ = std::fs::write("x", &"".to_string());
 +
 +    only_sized(&""); // Don't lint. `Sized` is only bound
 +    let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound
 +    let _ = Box::new(&""); // Don't lint. Type parameter appears in return type
 +    ref_as_ref_path(&""); // Don't lint. Argument type is not a type parameter
 +    refs_only(&()); // Don't lint. `&T` implements trait, but `T` doesn't
 +    multiple_constraints_normalizes_to_different(&[[""]], &[""]); // Don't lint. Projected type appears in arguments
 +}
 +
 +#[allow(clippy::needless_borrowed_reference)]
 +fn x(y: &i32) -> i32 {
 +    *y
 +}
 +
 +fn mut_ref(y: &mut i32) {
 +    *y = 5;
 +}
 +
 +fn f<T: Copy>(y: &T) -> T {
 +    *y
 +}
 +
 +fn g(y: &[u8]) -> u8 {
 +    y[0]
 +}
 +
 +trait Trait {}
 +
 +impl<'a> Trait for &'a str {}
 +
 +fn h(_: &dyn Trait) {}
 +
 +fn check_expect_suppression() {
 +    let a = 5;
 +    #[expect(clippy::needless_borrow)]
 +    let _ = x(&&a);
 +}
 +
 +mod issue9160 {
 +    pub struct S<F> {
 +        f: F,
 +    }
 +
 +    impl<T, F> S<F>
 +    where
 +        F: Fn() -> T,
 +    {
 +        fn calls_field(&self) -> T {
 +            (&self.f)()
 +        }
 +    }
 +
 +    impl<T, F> S<F>
 +    where
 +        F: FnMut() -> T,
 +    {
 +        fn calls_mut_field(&mut self) -> T {
 +            (&mut self.f)()
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy)]
 +struct X;
 +
 +impl std::ops::Deref for X {
 +    type Target = X;
 +    fn deref(&self) -> &Self::Target {
 +        self
 +    }
 +}
 +
 +fn deref_target_is_x<T>(_: T)
 +where
 +    T: std::ops::Deref<Target = X>,
 +{
 +}
 +
 +fn multiple_constraints<T, U, V, X, Y>(_: T)
 +where
 +    T: IntoIterator<Item = U> + IntoIterator<Item = X>,
 +    U: IntoIterator<Item = V>,
 +    V: AsRef<str>,
 +    X: IntoIterator<Item = Y>,
 +    Y: AsRef<std::ffi::OsStr>,
 +{
 +}
 +
 +fn multiple_constraints_normalizes_to_same<T, U, V>(_: T, _: V)
 +where
 +    T: std::ops::Deref<Target = U>,
 +    U: std::ops::Deref<Target = V>,
 +{
 +}
 +
 +fn only_sized<T>(_: T) {}
 +
 +fn ref_as_ref_path<T: 'static>(_: &'static T)
 +where
 +    &'static T: AsRef<std::path::Path>,
 +{
 +}
 +
 +trait RefsOnly {
 +    type Referent;
 +}
 +
 +impl<T> RefsOnly for &T {
 +    type Referent = T;
 +}
 +
 +fn refs_only<T, U>(_: T)
 +where
 +    T: RefsOnly<Referent = U>,
 +{
 +}
 +
 +fn multiple_constraints_normalizes_to_different<T, U, V>(_: T, _: U)
 +where
 +    T: IntoIterator<Item = U>,
 +    U: IntoIterator<Item = V>,
 +    V: AsRef<str>,
 +{
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321
 +mod copyable_iterator {
 +    #[derive(Clone, Copy)]
 +    struct Iter;
 +    impl Iterator for Iter {
 +        type Item = ();
 +        fn next(&mut self) -> Option<Self::Item> {
 +            None
 +        }
 +    }
 +    fn takes_iter(_: impl Iterator) {}
 +    fn dont_warn(mut x: Iter) {
 +        takes_iter(&mut x);
 +    }
 +    #[allow(unused_mut)]
 +    fn warn(mut x: &mut Iter) {
 +        takes_iter(&mut x)
 +    }
 +}
 +
 +#[clippy::msrv = "1.52.0"]
 +mod under_msrv {
 +    fn foo() {
 +        let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
 +    }
 +}
 +
 +#[clippy::msrv = "1.53.0"]
 +mod meets_msrv {
 +    fn foo() {
 +        let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
 +    }
 +}
 +
 +fn issue9383() {
 +    // Should not lint because unions need explicit deref when accessing field
 +    use std::mem::ManuallyDrop;
 +
 +    union Coral {
 +        crab: ManuallyDrop<Vec<i32>>,
 +    }
 +
 +    union Ocean {
 +        coral: ManuallyDrop<Coral>,
 +    }
 +
 +    let mut ocean = Ocean {
 +        coral: ManuallyDrop::new(Coral {
 +            crab: ManuallyDrop::new(vec![1, 2, 3]),
 +        }),
 +    };
 +
 +    unsafe {
 +        ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
 +
 +        (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
 +        ManuallyDrop::drop(&mut (*ocean.coral).crab);
 +
 +        ManuallyDrop::drop(&mut ocean.coral);
 +    }
 +}
 +
 +fn closure_test() {
 +    let env = "env".to_owned();
 +    let arg = "arg".to_owned();
 +    let f = |arg| {
 +        let loc = "loc".to_owned();
 +        let _ = std::fs::write("x", &env); // Don't lint. In environment
 +        let _ = std::fs::write("x", &arg);
 +        let _ = std::fs::write("x", &loc);
 +    };
 +    let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
 +    f(arg);
 +}
 +
 +mod significant_drop {
 +    #[derive(Debug)]
 +    struct X;
 +
 +    #[derive(Debug)]
 +    struct Y;
 +
 +    impl Drop for Y {
 +        fn drop(&mut self) {}
 +    }
 +
 +    fn foo(x: X, y: Y) {
 +        debug(&x);
 +        debug(&y); // Don't lint. Has significant drop
 +    }
 +
 +    fn debug(_: impl std::fmt::Debug) {}
 +}
 +
 +mod used_exactly_once {
 +    fn foo(x: String) {
 +        use_x(&x);
 +    }
 +    fn use_x(_: impl AsRef<str>) {}
 +}
 +
 +mod used_more_than_once {
 +    fn foo(x: String) {
 +        use_x(&x);
 +        use_x_again(&x);
 +    }
 +    fn use_x(_: impl AsRef<str>) {}
 +    fn use_x_again(_: impl AsRef<str>) {}
 +}
 +
 +// https://github.com/rust-lang/rust-clippy/issues/9111#issuecomment-1277114280
 +mod issue_9111 {
 +    struct A;
 +
 +    impl Extend<u8> for A {
 +        fn extend<T: IntoIterator<Item = u8>>(&mut self, _: T) {
 +            unimplemented!()
 +        }
 +    }
 +
 +    impl<'a> Extend<&'a u8> for A {
 +        fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, _: T) {
 +            unimplemented!()
 +        }
 +    }
 +
 +    fn main() {
 +        let mut a = A;
 +        a.extend(&[]); // vs a.extend([]);
 +    }
 +}
 +
 +mod issue_9710 {
 +    fn main() {
 +        let string = String::new();
 +        for _i in 0..10 {
 +            f(&string);
 +        }
 +    }
 +
 +    fn f<T: AsRef<str>>(_: T) {}
 +}
 +
 +mod issue_9739 {
 +    fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
 +
 +    fn main() {
 +        foo(if std::env::var_os("HI").is_some() {
 +            &[0]
 +        } else {
 +            &[] as &[u32]
 +        });
 +    }
 +}
 +
 +mod issue_9739_method_variant {
 +    struct S;
 +
 +    impl S {
 +        fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
 +    }
 +
 +    fn main() {
 +        S.foo(if std::env::var_os("HI").is_some() {
 +            &[0]
 +        } else {
 +            &[] as &[u32]
 +        });
 +    }
 +}
 +
 +mod issue_9782 {
 +    fn foo<T: AsRef<[u8]>>(t: T) {
 +        println!("{}", std::mem::size_of::<T>());
 +        let _t: &[u8] = t.as_ref();
 +    }
 +
 +    fn main() {
 +        let a: [u8; 100] = [0u8; 100];
 +
 +        // 100
 +        foo::<[u8; 100]>(a);
 +        foo(a);
 +
 +        // 16
 +        foo::<&[u8]>(&a);
 +        foo(a.as_slice());
 +
 +        // 8
 +        foo::<&[u8; 100]>(&a);
 +        foo(&a);
 +    }
 +}
 +
 +mod issue_9782_type_relative_variant {
 +    struct S;
 +
 +    impl S {
 +        fn foo<T: AsRef<[u8]>>(t: T) {
 +            println!("{}", std::mem::size_of::<T>());
 +            let _t: &[u8] = t.as_ref();
 +        }
 +    }
 +
 +    fn main() {
 +        let a: [u8; 100] = [0u8; 100];
 +
 +        S::foo::<&[u8; 100]>(&a);
 +    }
 +}
 +
 +mod issue_9782_method_variant {
 +    struct S;
 +
 +    impl S {
 +        fn foo<T: AsRef<[u8]>>(&self, t: T) {
 +            println!("{}", std::mem::size_of::<T>());
 +            let _t: &[u8] = t.as_ref();
 +        }
 +    }
 +
 +    fn main() {
 +        let a: [u8; 100] = [0u8; 100];
 +
 +        S.foo::<&[u8; 100]>(&a);
 +    }
 +}
index 98a48d68317b495e9b50713d97aa4d470e2ab4ed,0000000000000000000000000000000000000000..d26c317124b8d18d3dc900d31c8badce92e20af1
mode 100644,000000..100644
--- /dev/null
@@@ -1,226 -1,0 +1,220 @@@
- error: the borrowed expression implements the required traits
-   --> $DIR/needless_borrow.rs:502:85
-    |
- LL |         cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new()));
-    |                                                                                     ^^^^^^^^^^^^^^ help: change this to: `String::new()`
- error: aborting due to 37 previous errors
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:15:15
 +   |
 +LL |     let _ = x(&&a); // warn
 +   |               ^^^ help: change this to: `&a`
 +   |
 +   = note: `-D clippy::needless-borrow` implied by `-D warnings`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:19:13
 +   |
 +LL |     mut_ref(&mut &mut b); // warn
 +   |             ^^^^^^^^^^^ help: change this to: `&mut b`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:31:13
 +   |
 +LL |             &&a
 +   |             ^^^ help: change this to: `&a`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:33:15
 +   |
 +LL |         46 => &&a,
 +   |               ^^^ help: change this to: `&a`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:39:27
 +   |
 +LL |                     break &ref_a;
 +   |                           ^^^^^^ help: change this to: `ref_a`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:46:15
 +   |
 +LL |     let _ = x(&&&a);
 +   |               ^^^^ help: change this to: `&a`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:47:15
 +   |
 +LL |     let _ = x(&mut &&a);
 +   |               ^^^^^^^^ help: change this to: `&a`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:48:15
 +   |
 +LL |     let _ = x(&&&mut b);
 +   |               ^^^^^^^^ help: change this to: `&mut b`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:49:15
 +   |
 +LL |     let _ = x(&&ref_a);
 +   |               ^^^^^^^ help: change this to: `ref_a`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:52:11
 +   |
 +LL |         x(&b);
 +   |           ^^ help: change this to: `b`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:59:13
 +   |
 +LL |     mut_ref(&mut x);
 +   |             ^^^^^^ help: change this to: `x`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:60:13
 +   |
 +LL |     mut_ref(&mut &mut x);
 +   |             ^^^^^^^^^^^ help: change this to: `x`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:61:23
 +   |
 +LL |     let y: &mut i32 = &mut x;
 +   |                       ^^^^^^ help: change this to: `x`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:62:23
 +   |
 +LL |     let y: &mut i32 = &mut &mut x;
 +   |                       ^^^^^^^^^^^ help: change this to: `x`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:71:14
 +   |
 +LL |         0 => &mut x,
 +   |              ^^^^^^ help: change this to: `x`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:77:14
 +   |
 +LL |         0 => &mut x,
 +   |              ^^^^^^ help: change this to: `x`
 +
 +error: this expression borrows a value the compiler would automatically borrow
 +  --> $DIR/needless_borrow.rs:89:13
 +   |
 +LL |     let _ = (&x).0;
 +   |             ^^^^ help: change this to: `x`
 +
 +error: this expression borrows a value the compiler would automatically borrow
 +  --> $DIR/needless_borrow.rs:91:22
 +   |
 +LL |     let _ = unsafe { (&*x).0 };
 +   |                      ^^^^^ help: change this to: `(*x)`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:101:5
 +   |
 +LL |     (&&()).foo();
 +   |     ^^^^^^ help: change this to: `(&())`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:110:5
 +   |
 +LL |     (&&5).foo();
 +   |     ^^^^^ help: change this to: `(&5)`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:135:51
 +   |
 +LL |     let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
 +   |                                                   ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:136:44
 +   |
 +LL |     let _ = std::path::Path::new(".").join(&&".");
 +   |                                            ^^^^^ help: change this to: `"."`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:137:23
 +   |
 +LL |     deref_target_is_x(&X);
 +   |                       ^^ help: change this to: `X`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:138:26
 +   |
 +LL |     multiple_constraints(&[[""]]);
 +   |                          ^^^^^^^ help: change this to: `[[""]]`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:139:45
 +   |
 +LL |     multiple_constraints_normalizes_to_same(&X, X);
 +   |                                             ^^ help: change this to: `X`
 +
 +error: this expression creates a reference which is immediately dereferenced by the compiler
 +  --> $DIR/needless_borrow.rs:140:32
 +   |
 +LL |     let _ = Some("").unwrap_or(&"");
 +   |                                ^^^ help: change this to: `""`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:141:33
 +   |
 +LL |     let _ = std::fs::write("x", &"".to_string());
 +   |                                 ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()`
 +
 +error: this expression borrows a value the compiler would automatically borrow
 +  --> $DIR/needless_borrow.rs:190:13
 +   |
 +LL |             (&self.f)()
 +   |             ^^^^^^^^^ help: change this to: `(self.f)`
 +
 +error: this expression borrows a value the compiler would automatically borrow
 +  --> $DIR/needless_borrow.rs:199:13
 +   |
 +LL |             (&mut self.f)()
 +   |             ^^^^^^^^^^^^^ help: change this to: `(self.f)`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:283:20
 +   |
 +LL |         takes_iter(&mut x)
 +   |                    ^^^^^^ help: change this to: `x`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:297:55
 +   |
 +LL |         let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
 +   |                                                       ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:335:37
 +   |
 +LL |         let _ = std::fs::write("x", &arg);
 +   |                                     ^^^^ help: change this to: `arg`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:336:37
 +   |
 +LL |         let _ = std::fs::write("x", &loc);
 +   |                                     ^^^^ help: change this to: `loc`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:354:15
 +   |
 +LL |         debug(&x);
 +   |               ^^ help: change this to: `x`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:363:15
 +   |
 +LL |         use_x(&x);
 +   |               ^^ help: change this to: `x`
 +
 +error: the borrowed expression implements the required traits
 +  --> $DIR/needless_borrow.rs:457:13
 +   |
 +LL |         foo(&a);
 +   |             ^^ help: change this to: `a`
 +
++error: aborting due to 36 previous errors
 +
index d451be1f389a7b50a2b3c0201e8ace18d4f0668b,0000000000000000000000000000000000000000..ab1c0e590bbc7ca317ea0568eebee557090b7623
mode 100644,000000..100644
--- /dev/null
@@@ -1,280 -1,0 +1,290 @@@
 +// run-rustfix
 +
 +#![feature(lint_reasons)]
 +#![feature(yeet_expr)]
 +#![allow(unused)]
 +#![allow(
 +    clippy::if_same_then_else,
 +    clippy::single_match,
 +    clippy::needless_bool,
 +    clippy::equatable_if_let
 +)]
 +#![warn(clippy::needless_return)]
 +
 +use std::cell::RefCell;
 +
 +macro_rules! the_answer {
 +    () => {
 +        42
 +    };
 +}
 +
 +fn test_end_of_fn() -> bool {
 +    if true {
 +        // no error!
 +        return true;
 +    }
 +    true
 +}
 +
 +fn test_no_semicolon() -> bool {
 +    true
 +}
 +
 +fn test_if_block() -> bool {
 +    if true {
 +        true
 +    } else {
 +        false
 +    }
 +}
 +
 +fn test_match(x: bool) -> bool {
 +    match x {
 +        true => false,
 +        false => {
 +            true
 +        },
 +    }
 +}
 +
 +fn test_closure() {
 +    let _ = || {
 +        true
 +    };
 +    let _ = || true;
 +}
 +
 +fn test_macro_call() -> i32 {
 +    the_answer!()
 +}
 +
 +fn test_void_fun() {
 +}
 +
 +fn test_void_if_fun(b: bool) {
 +    if b {
 +    } else {
 +    }
 +}
 +
 +fn test_void_match(x: u32) {
 +    match x {
 +        0 => (),
 +        _ => (),
 +    }
 +}
 +
 +fn test_nested_match(x: u32) {
 +    match x {
 +        0 => (),
 +        1 => {
 +            let _ = 42;
 +        },
 +        _ => (),
 +    }
 +}
 +
 +fn temporary_outlives_local() -> String {
 +    let x = RefCell::<String>::default();
 +    return x.borrow().clone();
 +}
 +
 +fn borrows_but_not_last(value: bool) -> String {
 +    if value {
 +        let x = RefCell::<String>::default();
 +        let _a = x.borrow().clone();
 +        String::from("test")
 +    } else {
 +        String::new()
 +    }
 +}
 +
 +macro_rules! needed_return {
 +    ($e:expr) => {
 +        if $e > 3 {
 +            return;
 +        }
 +    };
 +}
 +
 +fn test_return_in_macro() {
 +    // This will return and the macro below won't be executed. Removing the `return` from the macro
 +    // will change semantics.
 +    needed_return!(10);
 +    needed_return!(0);
 +}
 +
 +mod issue6501 {
 +    #[allow(clippy::unnecessary_lazy_evaluations)]
 +    fn foo(bar: Result<(), ()>) {
 +        bar.unwrap_or_else(|_| {})
 +    }
 +
 +    fn test_closure() {
 +        let _ = || {
 +        };
 +        let _ = || {};
 +    }
 +
 +    struct Foo;
 +    #[allow(clippy::unnecessary_lazy_evaluations)]
 +    fn bar(res: Result<Foo, u8>) -> Foo {
 +        res.unwrap_or_else(|_| Foo)
 +    }
 +}
 +
 +async fn async_test_end_of_fn() -> bool {
 +    if true {
 +        // no error!
 +        return true;
 +    }
 +    true
 +}
 +
 +async fn async_test_no_semicolon() -> bool {
 +    true
 +}
 +
 +async fn async_test_if_block() -> bool {
 +    if true {
 +        true
 +    } else {
 +        false
 +    }
 +}
 +
 +async fn async_test_match(x: bool) -> bool {
 +    match x {
 +        true => false,
 +        false => {
 +            true
 +        },
 +    }
 +}
 +
 +async fn async_test_closure() {
 +    let _ = || {
 +        true
 +    };
 +    let _ = || true;
 +}
 +
 +async fn async_test_macro_call() -> i32 {
 +    the_answer!()
 +}
 +
 +async fn async_test_void_fun() {
 +}
 +
 +async fn async_test_void_if_fun(b: bool) {
 +    if b {
 +    } else {
 +    }
 +}
 +
 +async fn async_test_void_match(x: u32) {
 +    match x {
 +        0 => (),
 +        _ => (),
 +    }
 +}
 +
 +async fn async_temporary_outlives_local() -> String {
 +    let x = RefCell::<String>::default();
 +    return x.borrow().clone();
 +}
 +
 +async fn async_borrows_but_not_last(value: bool) -> String {
 +    if value {
 +        let x = RefCell::<String>::default();
 +        let _a = x.borrow().clone();
 +        String::from("test")
 +    } else {
 +        String::new()
 +    }
 +}
 +
 +async fn async_test_return_in_macro() {
 +    needed_return!(10);
 +    needed_return!(0);
 +}
 +
 +fn let_else() {
 +    let Some(1) = Some(1) else { return };
 +}
 +
 +fn needless_return_macro() -> String {
 +    let _ = "foo";
 +    let _ = "bar";
 +    format!("Hello {}", "world!")
 +}
 +
 +fn issue_9361() -> i32 {
 +    #[allow(clippy::integer_arithmetic)]
 +    return 1 + 2;
 +}
 +
 +fn issue8336(x: i32) -> bool {
 +    if x > 0 {
 +        println!("something");
 +        true
 +    } else {
 +        false
 +    }
 +}
 +
 +fn issue8156(x: u8) -> u64 {
 +    match x {
 +        80 => {
 +            10
 +        },
 +        _ => {
 +            100
 +        },
 +    }
 +}
 +
 +// Ideally the compiler should throw `unused_braces` in this case
 +fn issue9192() -> i32 {
 +    {
 +        0
 +    }
 +}
 +
 +fn issue9503(x: usize) -> isize {
 +    unsafe {
 +        if x > 12 {
 +            *(x as *const isize)
 +        } else {
 +            !*(x as *const isize)
 +        }
 +    }
 +}
 +
 +mod issue9416 {
 +    pub fn with_newline() {
 +        let _ = 42;
 +    }
 +
 +    #[rustfmt::skip]
 +    pub fn oneline() {
 +        let _ = 42;
 +    }
 +}
 +
 +fn issue9947() -> Result<(), String> {
 +    do yeet "hello";
 +}
 +
++// without anyhow, but triggers the same bug I believe
++#[expect(clippy::useless_format)]
++fn issue10051() -> Result<String, String> {
++    if true {
++        Ok(format!("ok!"))
++    } else {
++        Err(format!("err!"))
++    }
++}
++
 +fn main() {}
index e1a1bea2c0b85f19f769a4c4ea0b904d348f4cf9,0000000000000000000000000000000000000000..abed338bb9b297c415a2cf0115728cd54e6f29a5
mode 100644,000000..100644
--- /dev/null
@@@ -1,290 -1,0 +1,300 @@@
 +// run-rustfix
 +
 +#![feature(lint_reasons)]
 +#![feature(yeet_expr)]
 +#![allow(unused)]
 +#![allow(
 +    clippy::if_same_then_else,
 +    clippy::single_match,
 +    clippy::needless_bool,
 +    clippy::equatable_if_let
 +)]
 +#![warn(clippy::needless_return)]
 +
 +use std::cell::RefCell;
 +
 +macro_rules! the_answer {
 +    () => {
 +        42
 +    };
 +}
 +
 +fn test_end_of_fn() -> bool {
 +    if true {
 +        // no error!
 +        return true;
 +    }
 +    return true;
 +}
 +
 +fn test_no_semicolon() -> bool {
 +    return true;
 +}
 +
 +fn test_if_block() -> bool {
 +    if true {
 +        return true;
 +    } else {
 +        return false;
 +    }
 +}
 +
 +fn test_match(x: bool) -> bool {
 +    match x {
 +        true => return false,
 +        false => {
 +            return true;
 +        },
 +    }
 +}
 +
 +fn test_closure() {
 +    let _ = || {
 +        return true;
 +    };
 +    let _ = || return true;
 +}
 +
 +fn test_macro_call() -> i32 {
 +    return the_answer!();
 +}
 +
 +fn test_void_fun() {
 +    return;
 +}
 +
 +fn test_void_if_fun(b: bool) {
 +    if b {
 +        return;
 +    } else {
 +        return;
 +    }
 +}
 +
 +fn test_void_match(x: u32) {
 +    match x {
 +        0 => (),
 +        _ => return,
 +    }
 +}
 +
 +fn test_nested_match(x: u32) {
 +    match x {
 +        0 => (),
 +        1 => {
 +            let _ = 42;
 +            return;
 +        },
 +        _ => return,
 +    }
 +}
 +
 +fn temporary_outlives_local() -> String {
 +    let x = RefCell::<String>::default();
 +    return x.borrow().clone();
 +}
 +
 +fn borrows_but_not_last(value: bool) -> String {
 +    if value {
 +        let x = RefCell::<String>::default();
 +        let _a = x.borrow().clone();
 +        return String::from("test");
 +    } else {
 +        return String::new();
 +    }
 +}
 +
 +macro_rules! needed_return {
 +    ($e:expr) => {
 +        if $e > 3 {
 +            return;
 +        }
 +    };
 +}
 +
 +fn test_return_in_macro() {
 +    // This will return and the macro below won't be executed. Removing the `return` from the macro
 +    // will change semantics.
 +    needed_return!(10);
 +    needed_return!(0);
 +}
 +
 +mod issue6501 {
 +    #[allow(clippy::unnecessary_lazy_evaluations)]
 +    fn foo(bar: Result<(), ()>) {
 +        bar.unwrap_or_else(|_| return)
 +    }
 +
 +    fn test_closure() {
 +        let _ = || {
 +            return;
 +        };
 +        let _ = || return;
 +    }
 +
 +    struct Foo;
 +    #[allow(clippy::unnecessary_lazy_evaluations)]
 +    fn bar(res: Result<Foo, u8>) -> Foo {
 +        res.unwrap_or_else(|_| return Foo)
 +    }
 +}
 +
 +async fn async_test_end_of_fn() -> bool {
 +    if true {
 +        // no error!
 +        return true;
 +    }
 +    return true;
 +}
 +
 +async fn async_test_no_semicolon() -> bool {
 +    return true;
 +}
 +
 +async fn async_test_if_block() -> bool {
 +    if true {
 +        return true;
 +    } else {
 +        return false;
 +    }
 +}
 +
 +async fn async_test_match(x: bool) -> bool {
 +    match x {
 +        true => return false,
 +        false => {
 +            return true;
 +        },
 +    }
 +}
 +
 +async fn async_test_closure() {
 +    let _ = || {
 +        return true;
 +    };
 +    let _ = || return true;
 +}
 +
 +async fn async_test_macro_call() -> i32 {
 +    return the_answer!();
 +}
 +
 +async fn async_test_void_fun() {
 +    return;
 +}
 +
 +async fn async_test_void_if_fun(b: bool) {
 +    if b {
 +        return;
 +    } else {
 +        return;
 +    }
 +}
 +
 +async fn async_test_void_match(x: u32) {
 +    match x {
 +        0 => (),
 +        _ => return,
 +    }
 +}
 +
 +async fn async_temporary_outlives_local() -> String {
 +    let x = RefCell::<String>::default();
 +    return x.borrow().clone();
 +}
 +
 +async fn async_borrows_but_not_last(value: bool) -> String {
 +    if value {
 +        let x = RefCell::<String>::default();
 +        let _a = x.borrow().clone();
 +        return String::from("test");
 +    } else {
 +        return String::new();
 +    }
 +}
 +
 +async fn async_test_return_in_macro() {
 +    needed_return!(10);
 +    needed_return!(0);
 +}
 +
 +fn let_else() {
 +    let Some(1) = Some(1) else { return };
 +}
 +
 +fn needless_return_macro() -> String {
 +    let _ = "foo";
 +    let _ = "bar";
 +    return format!("Hello {}", "world!");
 +}
 +
 +fn issue_9361() -> i32 {
 +    #[allow(clippy::integer_arithmetic)]
 +    return 1 + 2;
 +}
 +
 +fn issue8336(x: i32) -> bool {
 +    if x > 0 {
 +        println!("something");
 +        return true;
 +    } else {
 +        return false;
 +    };
 +}
 +
 +fn issue8156(x: u8) -> u64 {
 +    match x {
 +        80 => {
 +            return 10;
 +        },
 +        _ => {
 +            return 100;
 +        },
 +    };
 +}
 +
 +// Ideally the compiler should throw `unused_braces` in this case
 +fn issue9192() -> i32 {
 +    {
 +        return 0;
 +    };
 +}
 +
 +fn issue9503(x: usize) -> isize {
 +    unsafe {
 +        if x > 12 {
 +            return *(x as *const isize);
 +        } else {
 +            return !*(x as *const isize);
 +        };
 +    };
 +}
 +
 +mod issue9416 {
 +    pub fn with_newline() {
 +        let _ = 42;
 +
 +        return;
 +    }
 +
 +    #[rustfmt::skip]
 +    pub fn oneline() {
 +        let _ = 42; return;
 +    }
 +}
 +
 +fn issue9947() -> Result<(), String> {
 +    do yeet "hello";
 +}
 +
++// without anyhow, but triggers the same bug I believe
++#[expect(clippy::useless_format)]
++fn issue10051() -> Result<String, String> {
++    if true {
++        return Ok(format!("ok!"));
++    } else {
++        return Err(format!("err!"));
++    }
++}
++
 +fn main() {}
index ca2253e6586379ecb543929782956299a6a08da8,0000000000000000000000000000000000000000..52eabf6e1370dd2235f22cfbb958464e03d3e746
mode 100644,000000..100644
--- /dev/null
@@@ -1,390 -1,0 +1,406 @@@
- error: aborting due to 46 previous errors
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:27:5
 +   |
 +LL |     return true;
 +   |     ^^^^^^^^^^^
 +   |
 +   = note: `-D clippy::needless-return` implied by `-D warnings`
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:31:5
 +   |
 +LL |     return true;
 +   |     ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:36:9
 +   |
 +LL |         return true;
 +   |         ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:38:9
 +   |
 +LL |         return false;
 +   |         ^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:44:17
 +   |
 +LL |         true => return false,
 +   |                 ^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:46:13
 +   |
 +LL |             return true;
 +   |             ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:53:9
 +   |
 +LL |         return true;
 +   |         ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:55:16
 +   |
 +LL |     let _ = || return true;
 +   |                ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:59:5
 +   |
 +LL |     return the_answer!();
 +   |     ^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:62:21
 +   |
 +LL |   fn test_void_fun() {
 +   |  _____________________^
 +LL | |     return;
 +   | |__________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:67:11
 +   |
 +LL |       if b {
 +   |  ___________^
 +LL | |         return;
 +   | |______________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:69:13
 +   |
 +LL |       } else {
 +   |  _____________^
 +LL | |         return;
 +   | |______________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:77:14
 +   |
 +LL |         _ => return,
 +   |              ^^^^^^
 +   |
 +   = help: replace `return` with a unit value
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:85:24
 +   |
 +LL |               let _ = 42;
 +   |  ________________________^
 +LL | |             return;
 +   | |__________________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:88:14
 +   |
 +LL |         _ => return,
 +   |              ^^^^^^
 +   |
 +   = help: replace `return` with a unit value
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:101:9
 +   |
 +LL |         return String::from("test");
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:103:9
 +   |
 +LL |         return String::new();
 +   |         ^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:125:32
 +   |
 +LL |         bar.unwrap_or_else(|_| return)
 +   |                                ^^^^^^
 +   |
 +   = help: replace `return` with an empty block
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:129:21
 +   |
 +LL |           let _ = || {
 +   |  _____________________^
 +LL | |             return;
 +   | |__________________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:132:20
 +   |
 +LL |         let _ = || return;
 +   |                    ^^^^^^
 +   |
 +   = help: replace `return` with an empty block
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:138:32
 +   |
 +LL |         res.unwrap_or_else(|_| return Foo)
 +   |                                ^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:147:5
 +   |
 +LL |     return true;
 +   |     ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:151:5
 +   |
 +LL |     return true;
 +   |     ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:156:9
 +   |
 +LL |         return true;
 +   |         ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:158:9
 +   |
 +LL |         return false;
 +   |         ^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:164:17
 +   |
 +LL |         true => return false,
 +   |                 ^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:166:13
 +   |
 +LL |             return true;
 +   |             ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:173:9
 +   |
 +LL |         return true;
 +   |         ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:175:16
 +   |
 +LL |     let _ = || return true;
 +   |                ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:179:5
 +   |
 +LL |     return the_answer!();
 +   |     ^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:182:33
 +   |
 +LL |   async fn async_test_void_fun() {
 +   |  _________________________________^
 +LL | |     return;
 +   | |__________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:187:11
 +   |
 +LL |       if b {
 +   |  ___________^
 +LL | |         return;
 +   | |______________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:189:13
 +   |
 +LL |       } else {
 +   |  _____________^
 +LL | |         return;
 +   | |______________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:197:14
 +   |
 +LL |         _ => return,
 +   |              ^^^^^^
 +   |
 +   = help: replace `return` with a unit value
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:210:9
 +   |
 +LL |         return String::from("test");
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:212:9
 +   |
 +LL |         return String::new();
 +   |         ^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:228:5
 +   |
 +LL |     return format!("Hello {}", "world!");
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:239:9
 +   |
 +LL |         return true;
 +   |         ^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:241:9
 +   |
 +LL |         return false;
 +   |         ^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:248:13
 +   |
 +LL |             return 10;
 +   |             ^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:251:13
 +   |
 +LL |             return 100;
 +   |             ^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:259:9
 +   |
 +LL |         return 0;
 +   |         ^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:266:13
 +   |
 +LL |             return *(x as *const isize);
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:268:13
 +   |
 +LL |             return !*(x as *const isize);
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:275:20
 +   |
 +LL |           let _ = 42;
 +   |  ____________________^
 +LL | |
 +LL | |         return;
 +   | |______________^
 +   |
 +   = help: remove `return`
 +
 +error: unneeded `return` statement
 +  --> $DIR/needless_return.rs:282:20
 +   |
 +LL |         let _ = 42; return;
 +   |                    ^^^^^^^
 +   |
 +   = help: remove `return`
 +
++error: unneeded `return` statement
++  --> $DIR/needless_return.rs:294:9
++   |
++LL |         return Ok(format!("ok!"));
++   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++   = help: remove `return`
++
++error: unneeded `return` statement
++  --> $DIR/needless_return.rs:296:9
++   |
++LL |         return Err(format!("err!"));
++   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++   = help: remove `return`
++
++error: aborting due to 48 previous errors
 +
index a157b6a6f9adbfd417b10fd0ed51734ab7f63f6f,0000000000000000000000000000000000000000..00b427450935d5077a7ff947a78da65c5221ef2b
mode 100644,000000..100644
--- /dev/null
@@@ -1,247 -1,0 +1,241 @@@
- #[allow(unused, clippy::manual_retain)]
- fn possible_borrower_improvements() {
-     let mut s = String::from("foobar");
-     s = s.chars().filter(|&c| c != 'o').collect();
- }
 +// run-rustfix
 +// rustfix-only-machine-applicable
 +#![feature(lint_reasons)]
 +#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
 +
 +use std::ffi::OsString;
 +use std::path::Path;
 +
 +fn main() {
 +    let _s = ["lorem", "ipsum"].join(" ");
 +
 +    let s = String::from("foo");
 +    let _s = s;
 +
 +    let s = String::from("foo");
 +    let _s = s;
 +
 +    let s = String::from("foo");
 +    let _s = s;
 +
 +    let _s = Path::new("/a/b/").join("c");
 +
 +    let _s = Path::new("/a/b/").join("c");
 +
 +    let _s = OsString::new();
 +
 +    let _s = OsString::new();
 +
 +    // Check that lint level works
 +    #[allow(clippy::redundant_clone)]
 +    let _s = String::new().to_string();
 +
 +    // Check that lint level works
 +    #[expect(clippy::redundant_clone)]
 +    let _s = String::new().to_string();
 +
 +    let tup = (String::from("foo"),);
 +    let _t = tup.0;
 +
 +    let tup_ref = &(String::from("foo"),);
 +    let _s = tup_ref.0.clone(); // this `.clone()` cannot be removed
 +
 +    {
 +        let x = String::new();
 +        let y = &x;
 +
 +        let _x = x.clone(); // ok; `x` is borrowed by `y`
 +
 +        let _ = y.len();
 +    }
 +
 +    let x = (String::new(),);
 +    let _ = Some(String::new()).unwrap_or_else(|| x.0.clone()); // ok; closure borrows `x`
 +
 +    with_branch(Alpha, true);
 +    cannot_double_move(Alpha);
 +    cannot_move_from_type_with_drop();
 +    borrower_propagation();
 +    not_consumed();
 +    issue_5405();
 +    manually_drop();
 +    clone_then_move_cloned();
 +    hashmap_neg();
 +    false_negative_5707();
 +}
 +
 +#[derive(Clone)]
 +struct Alpha;
 +fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) {
 +    if b { (a.clone(), a) } else { (Alpha, a) }
 +}
 +
 +fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) {
 +    (a.clone(), a)
 +}
 +
 +struct TypeWithDrop {
 +    x: String,
 +}
 +
 +impl Drop for TypeWithDrop {
 +    fn drop(&mut self) {}
 +}
 +
 +fn cannot_move_from_type_with_drop() -> String {
 +    let s = TypeWithDrop { x: String::new() };
 +    s.x.clone() // removing this `clone()` summons E0509
 +}
 +
 +fn borrower_propagation() {
 +    let s = String::new();
 +    let t = String::new();
 +
 +    {
 +        fn b() -> bool {
 +            unimplemented!()
 +        }
 +        let _u = if b() { &s } else { &t };
 +
 +        // ok; `s` and `t` are possibly borrowed
 +        let _s = s.clone();
 +        let _t = t.clone();
 +    }
 +
 +    {
 +        let _u = || s.len();
 +        let _v = [&t; 32];
 +        let _s = s.clone(); // ok
 +        let _t = t.clone(); // ok
 +    }
 +
 +    {
 +        let _u = {
 +            let u = Some(&s);
 +            let _ = s.clone(); // ok
 +            u
 +        };
 +        let _s = s.clone(); // ok
 +    }
 +
 +    {
 +        use std::convert::identity as id;
 +        let _u = id(id(&s));
 +        let _s = s.clone(); // ok, `u` borrows `s`
 +    }
 +
 +    let _s = s;
 +    let _t = t;
 +
 +    #[derive(Clone)]
 +    struct Foo {
 +        x: usize,
 +    }
 +
 +    {
 +        let f = Foo { x: 123 };
 +        let _x = Some(f.x);
 +        let _f = f;
 +    }
 +
 +    {
 +        let f = Foo { x: 123 };
 +        let _x = &f.x;
 +        let _f = f.clone(); // ok
 +    }
 +}
 +
 +fn not_consumed() {
 +    let x = std::path::PathBuf::from("home");
 +    let y = x.join("matthias");
 +    // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is
 +    // redundant. (It also does not consume the PathBuf)
 +
 +    println!("x: {:?}, y: {:?}", x, y);
 +
 +    let mut s = String::new();
 +    s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior.
 +    s.push_str("bar");
 +    assert_eq!(s, "bar");
 +
 +    let t = Some(s);
 +    // OK
 +    if let Some(x) = t.clone() {
 +        println!("{}", x);
 +    }
 +    if let Some(x) = t {
 +        println!("{}", x);
 +    }
 +}
 +
 +#[allow(clippy::clone_on_copy)]
 +fn issue_5405() {
 +    let a: [String; 1] = [String::from("foo")];
 +    let _b: String = a[0].clone();
 +
 +    let c: [usize; 2] = [2, 3];
 +    let _d: usize = c[1].clone();
 +}
 +
 +fn manually_drop() {
 +    use std::mem::ManuallyDrop;
 +    use std::sync::Arc;
 +
 +    let a = ManuallyDrop::new(Arc::new("Hello!".to_owned()));
 +    let _ = a.clone(); // OK
 +
 +    let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a));
 +    unsafe {
 +        Arc::from_raw(p);
 +        Arc::from_raw(p);
 +    }
 +}
 +
 +fn clone_then_move_cloned() {
 +    // issue #5973
 +    let x = Some(String::new());
 +    // ok, x is moved while the clone is in use.
 +    assert_eq!(x.clone(), None, "not equal {}", x.unwrap());
 +
 +    // issue #5595
 +    fn foo<F: Fn()>(_: &Alpha, _: F) {}
 +    let x = Alpha;
 +    // ok, data is moved while the clone is in use.
 +    foo(&x, move || {
 +        let _ = x;
 +    });
 +
 +    // issue #6998
 +    struct S(String);
 +    impl S {
 +        fn m(&mut self) {}
 +    }
 +    let mut x = S(String::new());
 +    x.0.clone().chars().for_each(|_| x.m());
 +}
 +
 +fn hashmap_neg() {
 +    // issue 5707
 +    use std::collections::HashMap;
 +    use std::path::PathBuf;
 +
 +    let p = PathBuf::from("/");
 +
 +    let mut h: HashMap<&str, &str> = HashMap::new();
 +    h.insert("orig-p", p.to_str().unwrap());
 +
 +    let mut q = p.clone();
 +    q.push("foo");
 +
 +    println!("{:?} {}", h, q.display());
 +}
 +
 +fn false_negative_5707() {
 +    fn foo(_x: &Alpha, _y: &mut Alpha) {}
 +
 +    let x = Alpha;
 +    let mut y = Alpha;
 +    foo(&x, &mut y);
 +    let _z = x.clone(); // pr 7346 can't lint on `x`
 +    drop(y);
 +}
index 430672e8b8df2ffc470a47146ffd59db0b35fbe6,0000000000000000000000000000000000000000..f899127db8d04674fab4e5d5282106da2e7721d8
mode 100644,000000..100644
--- /dev/null
@@@ -1,247 -1,0 +1,241 @@@
- #[allow(unused, clippy::manual_retain)]
- fn possible_borrower_improvements() {
-     let mut s = String::from("foobar");
-     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
- }
 +// run-rustfix
 +// rustfix-only-machine-applicable
 +#![feature(lint_reasons)]
 +#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
 +
 +use std::ffi::OsString;
 +use std::path::Path;
 +
 +fn main() {
 +    let _s = ["lorem", "ipsum"].join(" ").to_string();
 +
 +    let s = String::from("foo");
 +    let _s = s.clone();
 +
 +    let s = String::from("foo");
 +    let _s = s.to_string();
 +
 +    let s = String::from("foo");
 +    let _s = s.to_owned();
 +
 +    let _s = Path::new("/a/b/").join("c").to_owned();
 +
 +    let _s = Path::new("/a/b/").join("c").to_path_buf();
 +
 +    let _s = OsString::new().to_owned();
 +
 +    let _s = OsString::new().to_os_string();
 +
 +    // Check that lint level works
 +    #[allow(clippy::redundant_clone)]
 +    let _s = String::new().to_string();
 +
 +    // Check that lint level works
 +    #[expect(clippy::redundant_clone)]
 +    let _s = String::new().to_string();
 +
 +    let tup = (String::from("foo"),);
 +    let _t = tup.0.clone();
 +
 +    let tup_ref = &(String::from("foo"),);
 +    let _s = tup_ref.0.clone(); // this `.clone()` cannot be removed
 +
 +    {
 +        let x = String::new();
 +        let y = &x;
 +
 +        let _x = x.clone(); // ok; `x` is borrowed by `y`
 +
 +        let _ = y.len();
 +    }
 +
 +    let x = (String::new(),);
 +    let _ = Some(String::new()).unwrap_or_else(|| x.0.clone()); // ok; closure borrows `x`
 +
 +    with_branch(Alpha, true);
 +    cannot_double_move(Alpha);
 +    cannot_move_from_type_with_drop();
 +    borrower_propagation();
 +    not_consumed();
 +    issue_5405();
 +    manually_drop();
 +    clone_then_move_cloned();
 +    hashmap_neg();
 +    false_negative_5707();
 +}
 +
 +#[derive(Clone)]
 +struct Alpha;
 +fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) {
 +    if b { (a.clone(), a.clone()) } else { (Alpha, a) }
 +}
 +
 +fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) {
 +    (a.clone(), a)
 +}
 +
 +struct TypeWithDrop {
 +    x: String,
 +}
 +
 +impl Drop for TypeWithDrop {
 +    fn drop(&mut self) {}
 +}
 +
 +fn cannot_move_from_type_with_drop() -> String {
 +    let s = TypeWithDrop { x: String::new() };
 +    s.x.clone() // removing this `clone()` summons E0509
 +}
 +
 +fn borrower_propagation() {
 +    let s = String::new();
 +    let t = String::new();
 +
 +    {
 +        fn b() -> bool {
 +            unimplemented!()
 +        }
 +        let _u = if b() { &s } else { &t };
 +
 +        // ok; `s` and `t` are possibly borrowed
 +        let _s = s.clone();
 +        let _t = t.clone();
 +    }
 +
 +    {
 +        let _u = || s.len();
 +        let _v = [&t; 32];
 +        let _s = s.clone(); // ok
 +        let _t = t.clone(); // ok
 +    }
 +
 +    {
 +        let _u = {
 +            let u = Some(&s);
 +            let _ = s.clone(); // ok
 +            u
 +        };
 +        let _s = s.clone(); // ok
 +    }
 +
 +    {
 +        use std::convert::identity as id;
 +        let _u = id(id(&s));
 +        let _s = s.clone(); // ok, `u` borrows `s`
 +    }
 +
 +    let _s = s.clone();
 +    let _t = t.clone();
 +
 +    #[derive(Clone)]
 +    struct Foo {
 +        x: usize,
 +    }
 +
 +    {
 +        let f = Foo { x: 123 };
 +        let _x = Some(f.x);
 +        let _f = f.clone();
 +    }
 +
 +    {
 +        let f = Foo { x: 123 };
 +        let _x = &f.x;
 +        let _f = f.clone(); // ok
 +    }
 +}
 +
 +fn not_consumed() {
 +    let x = std::path::PathBuf::from("home");
 +    let y = x.clone().join("matthias");
 +    // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is
 +    // redundant. (It also does not consume the PathBuf)
 +
 +    println!("x: {:?}, y: {:?}", x, y);
 +
 +    let mut s = String::new();
 +    s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior.
 +    s.push_str("bar");
 +    assert_eq!(s, "bar");
 +
 +    let t = Some(s);
 +    // OK
 +    if let Some(x) = t.clone() {
 +        println!("{}", x);
 +    }
 +    if let Some(x) = t {
 +        println!("{}", x);
 +    }
 +}
 +
 +#[allow(clippy::clone_on_copy)]
 +fn issue_5405() {
 +    let a: [String; 1] = [String::from("foo")];
 +    let _b: String = a[0].clone();
 +
 +    let c: [usize; 2] = [2, 3];
 +    let _d: usize = c[1].clone();
 +}
 +
 +fn manually_drop() {
 +    use std::mem::ManuallyDrop;
 +    use std::sync::Arc;
 +
 +    let a = ManuallyDrop::new(Arc::new("Hello!".to_owned()));
 +    let _ = a.clone(); // OK
 +
 +    let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a));
 +    unsafe {
 +        Arc::from_raw(p);
 +        Arc::from_raw(p);
 +    }
 +}
 +
 +fn clone_then_move_cloned() {
 +    // issue #5973
 +    let x = Some(String::new());
 +    // ok, x is moved while the clone is in use.
 +    assert_eq!(x.clone(), None, "not equal {}", x.unwrap());
 +
 +    // issue #5595
 +    fn foo<F: Fn()>(_: &Alpha, _: F) {}
 +    let x = Alpha;
 +    // ok, data is moved while the clone is in use.
 +    foo(&x.clone(), move || {
 +        let _ = x;
 +    });
 +
 +    // issue #6998
 +    struct S(String);
 +    impl S {
 +        fn m(&mut self) {}
 +    }
 +    let mut x = S(String::new());
 +    x.0.clone().chars().for_each(|_| x.m());
 +}
 +
 +fn hashmap_neg() {
 +    // issue 5707
 +    use std::collections::HashMap;
 +    use std::path::PathBuf;
 +
 +    let p = PathBuf::from("/");
 +
 +    let mut h: HashMap<&str, &str> = HashMap::new();
 +    h.insert("orig-p", p.to_str().unwrap());
 +
 +    let mut q = p.clone();
 +    q.push("foo");
 +
 +    println!("{:?} {}", h, q.display());
 +}
 +
 +fn false_negative_5707() {
 +    fn foo(_x: &Alpha, _y: &mut Alpha) {}
 +
 +    let x = Alpha;
 +    let mut y = Alpha;
 +    foo(&x, &mut y);
 +    let _z = x.clone(); // pr 7346 can't lint on `x`
 +    drop(y);
 +}
index 1bacc2c76af1597f3b044506ed4e4f081a3b9251,0000000000000000000000000000000000000000..782590034d051cb07c2486e07983958809029a77
mode 100644,000000..100644
--- /dev/null
@@@ -1,195 -1,0 +1,183 @@@
- error: redundant clone
-   --> $DIR/redundant_clone.rs:246:40
-    |
- LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
-    |                                        ^^^^^^^^^^^ help: remove this
-    |
- note: this value is dropped without further use
-   --> $DIR/redundant_clone.rs:246:9
-    |
- LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
-    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- error: aborting due to 16 previous errors
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:10:42
 +   |
 +LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
 +   |                                          ^^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:10:14
 +   |
 +LL |     let _s = ["lorem", "ipsum"].join(" ").to_string();
 +   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +   = note: `-D clippy::redundant-clone` implied by `-D warnings`
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:13:15
 +   |
 +LL |     let _s = s.clone();
 +   |               ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:13:14
 +   |
 +LL |     let _s = s.clone();
 +   |              ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:16:15
 +   |
 +LL |     let _s = s.to_string();
 +   |               ^^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:16:14
 +   |
 +LL |     let _s = s.to_string();
 +   |              ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:19:15
 +   |
 +LL |     let _s = s.to_owned();
 +   |               ^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:19:14
 +   |
 +LL |     let _s = s.to_owned();
 +   |              ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:21:42
 +   |
 +LL |     let _s = Path::new("/a/b/").join("c").to_owned();
 +   |                                          ^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:21:14
 +   |
 +LL |     let _s = Path::new("/a/b/").join("c").to_owned();
 +   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:23:42
 +   |
 +LL |     let _s = Path::new("/a/b/").join("c").to_path_buf();
 +   |                                          ^^^^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:23:14
 +   |
 +LL |     let _s = Path::new("/a/b/").join("c").to_path_buf();
 +   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:25:29
 +   |
 +LL |     let _s = OsString::new().to_owned();
 +   |                             ^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:25:14
 +   |
 +LL |     let _s = OsString::new().to_owned();
 +   |              ^^^^^^^^^^^^^^^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:27:29
 +   |
 +LL |     let _s = OsString::new().to_os_string();
 +   |                             ^^^^^^^^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:27:14
 +   |
 +LL |     let _s = OsString::new().to_os_string();
 +   |              ^^^^^^^^^^^^^^^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:38:19
 +   |
 +LL |     let _t = tup.0.clone();
 +   |                   ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:38:14
 +   |
 +LL |     let _t = tup.0.clone();
 +   |              ^^^^^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:70:25
 +   |
 +LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
 +   |                         ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:70:24
 +   |
 +LL |     if b { (a.clone(), a.clone()) } else { (Alpha, a) }
 +   |                        ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:127:15
 +   |
 +LL |     let _s = s.clone();
 +   |               ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:127:14
 +   |
 +LL |     let _s = s.clone();
 +   |              ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:128:15
 +   |
 +LL |     let _t = t.clone();
 +   |               ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:128:14
 +   |
 +LL |     let _t = t.clone();
 +   |              ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:138:19
 +   |
 +LL |         let _f = f.clone();
 +   |                   ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:138:18
 +   |
 +LL |         let _f = f.clone();
 +   |                  ^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:150:14
 +   |
 +LL |     let y = x.clone().join("matthias");
 +   |              ^^^^^^^^ help: remove this
 +   |
 +note: cloned value is neither consumed nor mutated
 +  --> $DIR/redundant_clone.rs:150:13
 +   |
 +LL |     let y = x.clone().join("matthias");
 +   |             ^^^^^^^^^
 +
 +error: redundant clone
 +  --> $DIR/redundant_clone.rs:204:11
 +   |
 +LL |     foo(&x.clone(), move || {
 +   |           ^^^^^^^^ help: remove this
 +   |
 +note: this value is dropped without further use
 +  --> $DIR/redundant_clone.rs:204:10
 +   |
 +LL |     foo(&x.clone(), move || {
 +   |          ^
 +
++error: aborting due to 15 previous errors
 +
index 2f76b57529607a14ed3165dea40c3ddf0dd9975d,0000000000000000000000000000000000000000..5076f61334d67d32d75d7720896f4f8a1a6e34e2
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,85 @@@
 +// This file was generated by `cargo dev update_lints`.
 +// Use that command to update this file and do not edit by hand.
 +// Manual edits will be overwritten.
 +
 +// run-rustfix
 +
 +#![allow(clippy::almost_complete_range)]
 +#![allow(clippy::disallowed_names)]
 +#![allow(clippy::blocks_in_if_conditions)]
 +#![allow(clippy::box_collection)]
 +#![allow(clippy::redundant_static_lifetimes)]
 +#![allow(clippy::cognitive_complexity)]
++#![allow(clippy::derived_hash_with_manual_eq)]
 +#![allow(clippy::disallowed_methods)]
 +#![allow(clippy::disallowed_types)]
 +#![allow(clippy::mixed_read_write_in_expression)]
 +#![allow(clippy::useless_conversion)]
 +#![allow(clippy::match_result_ok)]
 +#![allow(clippy::overly_complex_bool_expr)]
 +#![allow(clippy::new_without_default)]
 +#![allow(clippy::bind_instead_of_map)]
 +#![allow(clippy::expect_used)]
 +#![allow(clippy::map_unwrap_or)]
 +#![allow(clippy::unwrap_used)]
 +#![allow(clippy::needless_borrow)]
 +#![allow(clippy::single_char_add_str)]
 +#![allow(clippy::module_name_repetitions)]
 +#![allow(clippy::recursive_format_impl)]
 +#![allow(clippy::invisible_characters)]
 +#![allow(drop_bounds)]
 +#![allow(for_loops_over_fallibles)]
 +#![allow(array_into_iter)]
 +#![allow(invalid_atomic_ordering)]
 +#![allow(invalid_value)]
 +#![allow(let_underscore_drop)]
 +#![allow(enum_intrinsics_non_enums)]
 +#![allow(non_fmt_panics)]
 +#![allow(named_arguments_used_positionally)]
 +#![allow(temporary_cstring_as_ptr)]
 +#![allow(unknown_lints)]
 +#![allow(unused_labels)]
 +#![warn(clippy::almost_complete_range)]
 +#![warn(clippy::disallowed_names)]
 +#![warn(clippy::blocks_in_if_conditions)]
 +#![warn(clippy::blocks_in_if_conditions)]
 +#![warn(clippy::box_collection)]
 +#![warn(clippy::redundant_static_lifetimes)]
 +#![warn(clippy::cognitive_complexity)]
++#![warn(clippy::derived_hash_with_manual_eq)]
 +#![warn(clippy::disallowed_methods)]
 +#![warn(clippy::disallowed_types)]
 +#![warn(clippy::mixed_read_write_in_expression)]
 +#![warn(clippy::useless_conversion)]
 +#![warn(clippy::match_result_ok)]
 +#![warn(clippy::overly_complex_bool_expr)]
 +#![warn(clippy::new_without_default)]
 +#![warn(clippy::bind_instead_of_map)]
 +#![warn(clippy::expect_used)]
 +#![warn(clippy::map_unwrap_or)]
 +#![warn(clippy::map_unwrap_or)]
 +#![warn(clippy::unwrap_used)]
 +#![warn(clippy::needless_borrow)]
 +#![warn(clippy::expect_used)]
 +#![warn(clippy::map_unwrap_or)]
 +#![warn(clippy::unwrap_used)]
 +#![warn(clippy::single_char_add_str)]
 +#![warn(clippy::module_name_repetitions)]
 +#![warn(clippy::recursive_format_impl)]
 +#![warn(clippy::invisible_characters)]
 +#![warn(drop_bounds)]
 +#![warn(for_loops_over_fallibles)]
 +#![warn(for_loops_over_fallibles)]
 +#![warn(for_loops_over_fallibles)]
 +#![warn(array_into_iter)]
 +#![warn(invalid_atomic_ordering)]
 +#![warn(invalid_value)]
 +#![warn(let_underscore_drop)]
 +#![warn(enum_intrinsics_non_enums)]
 +#![warn(non_fmt_panics)]
 +#![warn(named_arguments_used_positionally)]
 +#![warn(temporary_cstring_as_ptr)]
 +#![warn(unknown_lints)]
 +#![warn(unused_labels)]
 +
 +fn main() {}
index 699c0ff464e9fb247989fd0b559c8a35576b63f4,0000000000000000000000000000000000000000..64bc1ca7116c535d118d3a49626f4e40637e1f92
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,85 @@@
 +// This file was generated by `cargo dev update_lints`.
 +// Use that command to update this file and do not edit by hand.
 +// Manual edits will be overwritten.
 +
 +// run-rustfix
 +
 +#![allow(clippy::almost_complete_range)]
 +#![allow(clippy::disallowed_names)]
 +#![allow(clippy::blocks_in_if_conditions)]
 +#![allow(clippy::box_collection)]
 +#![allow(clippy::redundant_static_lifetimes)]
 +#![allow(clippy::cognitive_complexity)]
++#![allow(clippy::derived_hash_with_manual_eq)]
 +#![allow(clippy::disallowed_methods)]
 +#![allow(clippy::disallowed_types)]
 +#![allow(clippy::mixed_read_write_in_expression)]
 +#![allow(clippy::useless_conversion)]
 +#![allow(clippy::match_result_ok)]
 +#![allow(clippy::overly_complex_bool_expr)]
 +#![allow(clippy::new_without_default)]
 +#![allow(clippy::bind_instead_of_map)]
 +#![allow(clippy::expect_used)]
 +#![allow(clippy::map_unwrap_or)]
 +#![allow(clippy::unwrap_used)]
 +#![allow(clippy::needless_borrow)]
 +#![allow(clippy::single_char_add_str)]
 +#![allow(clippy::module_name_repetitions)]
 +#![allow(clippy::recursive_format_impl)]
 +#![allow(clippy::invisible_characters)]
 +#![allow(drop_bounds)]
 +#![allow(for_loops_over_fallibles)]
 +#![allow(array_into_iter)]
 +#![allow(invalid_atomic_ordering)]
 +#![allow(invalid_value)]
 +#![allow(let_underscore_drop)]
 +#![allow(enum_intrinsics_non_enums)]
 +#![allow(non_fmt_panics)]
 +#![allow(named_arguments_used_positionally)]
 +#![allow(temporary_cstring_as_ptr)]
 +#![allow(unknown_lints)]
 +#![allow(unused_labels)]
 +#![warn(clippy::almost_complete_letter_range)]
 +#![warn(clippy::blacklisted_name)]
 +#![warn(clippy::block_in_if_condition_expr)]
 +#![warn(clippy::block_in_if_condition_stmt)]
 +#![warn(clippy::box_vec)]
 +#![warn(clippy::const_static_lifetime)]
 +#![warn(clippy::cyclomatic_complexity)]
++#![warn(clippy::derive_hash_xor_eq)]
 +#![warn(clippy::disallowed_method)]
 +#![warn(clippy::disallowed_type)]
 +#![warn(clippy::eval_order_dependence)]
 +#![warn(clippy::identity_conversion)]
 +#![warn(clippy::if_let_some_result)]
 +#![warn(clippy::logic_bug)]
 +#![warn(clippy::new_without_default_derive)]
 +#![warn(clippy::option_and_then_some)]
 +#![warn(clippy::option_expect_used)]
 +#![warn(clippy::option_map_unwrap_or)]
 +#![warn(clippy::option_map_unwrap_or_else)]
 +#![warn(clippy::option_unwrap_used)]
 +#![warn(clippy::ref_in_deref)]
 +#![warn(clippy::result_expect_used)]
 +#![warn(clippy::result_map_unwrap_or_else)]
 +#![warn(clippy::result_unwrap_used)]
 +#![warn(clippy::single_char_push_str)]
 +#![warn(clippy::stutter)]
 +#![warn(clippy::to_string_in_display)]
 +#![warn(clippy::zero_width_space)]
 +#![warn(clippy::drop_bounds)]
 +#![warn(clippy::for_loop_over_option)]
 +#![warn(clippy::for_loop_over_result)]
 +#![warn(clippy::for_loops_over_fallibles)]
 +#![warn(clippy::into_iter_on_array)]
 +#![warn(clippy::invalid_atomic_ordering)]
 +#![warn(clippy::invalid_ref)]
 +#![warn(clippy::let_underscore_drop)]
 +#![warn(clippy::mem_discriminant_non_enum)]
 +#![warn(clippy::panic_params)]
 +#![warn(clippy::positional_named_format_parameters)]
 +#![warn(clippy::temporary_cstring_as_ptr)]
 +#![warn(clippy::unknown_clippy_lints)]
 +#![warn(clippy::unused_label)]
 +
 +fn main() {}
index 9af58dc75a68f41daff7f88a050856295b19ec29,0000000000000000000000000000000000000000..27a0263292ef1a37104fe047dd5570e27600f181
mode 100644,000000..100644
--- /dev/null
@@@ -1,250 -1,0 +1,256 @@@
-   --> $DIR/rename.rs:41:9
 +error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-   --> $DIR/rename.rs:42:9
++  --> $DIR/rename.rs:42:9
 +   |
 +LL | #![warn(clippy::almost_complete_letter_range)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
 +   |
 +   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 +
 +error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-   --> $DIR/rename.rs:43:9
++  --> $DIR/rename.rs:43:9
 +   |
 +LL | #![warn(clippy::blacklisted_name)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 +
 +error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-   --> $DIR/rename.rs:44:9
++  --> $DIR/rename.rs:44:9
 +   |
 +LL | #![warn(clippy::block_in_if_condition_expr)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 +
 +error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-   --> $DIR/rename.rs:45:9
++  --> $DIR/rename.rs:45:9
 +   |
 +LL | #![warn(clippy::block_in_if_condition_stmt)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 +
 +error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-   --> $DIR/rename.rs:46:9
++  --> $DIR/rename.rs:46:9
 +   |
 +LL | #![warn(clippy::box_vec)]
 +   |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 +
 +error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-   --> $DIR/rename.rs:47:9
++  --> $DIR/rename.rs:47:9
 +   |
 +LL | #![warn(clippy::const_static_lifetime)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 +
 +error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-   --> $DIR/rename.rs:48:9
++  --> $DIR/rename.rs:48:9
 +   |
 +LL | #![warn(clippy::cyclomatic_complexity)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 +
++error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
++  --> $DIR/rename.rs:49:9
++   |
++LL | #![warn(clippy::derive_hash_xor_eq)]
++   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
++
 +error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-   --> $DIR/rename.rs:49:9
++  --> $DIR/rename.rs:50:9
 +   |
 +LL | #![warn(clippy::disallowed_method)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 +
 +error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-   --> $DIR/rename.rs:50:9
++  --> $DIR/rename.rs:51:9
 +   |
 +LL | #![warn(clippy::disallowed_type)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 +
 +error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-   --> $DIR/rename.rs:51:9
++  --> $DIR/rename.rs:52:9
 +   |
 +LL | #![warn(clippy::eval_order_dependence)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 +
 +error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-   --> $DIR/rename.rs:52:9
++  --> $DIR/rename.rs:53:9
 +   |
 +LL | #![warn(clippy::identity_conversion)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 +
 +error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-   --> $DIR/rename.rs:53:9
++  --> $DIR/rename.rs:54:9
 +   |
 +LL | #![warn(clippy::if_let_some_result)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 +
 +error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-   --> $DIR/rename.rs:54:9
++  --> $DIR/rename.rs:55:9
 +   |
 +LL | #![warn(clippy::logic_bug)]
 +   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 +
 +error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-   --> $DIR/rename.rs:55:9
++  --> $DIR/rename.rs:56:9
 +   |
 +LL | #![warn(clippy::new_without_default_derive)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 +
 +error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-   --> $DIR/rename.rs:56:9
++  --> $DIR/rename.rs:57:9
 +   |
 +LL | #![warn(clippy::option_and_then_some)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 +
 +error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-   --> $DIR/rename.rs:57:9
++  --> $DIR/rename.rs:58:9
 +   |
 +LL | #![warn(clippy::option_expect_used)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 +
 +error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-   --> $DIR/rename.rs:58:9
++  --> $DIR/rename.rs:59:9
 +   |
 +LL | #![warn(clippy::option_map_unwrap_or)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 +
 +error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-   --> $DIR/rename.rs:59:9
++  --> $DIR/rename.rs:60:9
 +   |
 +LL | #![warn(clippy::option_map_unwrap_or_else)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 +
 +error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-   --> $DIR/rename.rs:60:9
++  --> $DIR/rename.rs:61:9
 +   |
 +LL | #![warn(clippy::option_unwrap_used)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 +
 +error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-   --> $DIR/rename.rs:61:9
++  --> $DIR/rename.rs:62:9
 +   |
 +LL | #![warn(clippy::ref_in_deref)]
 +   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 +
 +error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-   --> $DIR/rename.rs:62:9
++  --> $DIR/rename.rs:63:9
 +   |
 +LL | #![warn(clippy::result_expect_used)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 +
 +error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-   --> $DIR/rename.rs:63:9
++  --> $DIR/rename.rs:64:9
 +   |
 +LL | #![warn(clippy::result_map_unwrap_or_else)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 +
 +error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-   --> $DIR/rename.rs:64:9
++  --> $DIR/rename.rs:65:9
 +   |
 +LL | #![warn(clippy::result_unwrap_used)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 +
 +error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-   --> $DIR/rename.rs:65:9
++  --> $DIR/rename.rs:66:9
 +   |
 +LL | #![warn(clippy::single_char_push_str)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 +
 +error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-   --> $DIR/rename.rs:66:9
++  --> $DIR/rename.rs:67:9
 +   |
 +LL | #![warn(clippy::stutter)]
 +   |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 +
 +error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-   --> $DIR/rename.rs:67:9
++  --> $DIR/rename.rs:68:9
 +   |
 +LL | #![warn(clippy::to_string_in_display)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 +
 +error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-   --> $DIR/rename.rs:68:9
++  --> $DIR/rename.rs:69:9
 +   |
 +LL | #![warn(clippy::zero_width_space)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 +
 +error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-   --> $DIR/rename.rs:69:9
++  --> $DIR/rename.rs:70:9
 +   |
 +LL | #![warn(clippy::drop_bounds)]
 +   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 +
 +error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-   --> $DIR/rename.rs:70:9
++  --> $DIR/rename.rs:71:9
 +   |
 +LL | #![warn(clippy::for_loop_over_option)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 +
 +error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-   --> $DIR/rename.rs:71:9
++  --> $DIR/rename.rs:72:9
 +   |
 +LL | #![warn(clippy::for_loop_over_result)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 +
 +error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-   --> $DIR/rename.rs:72:9
++  --> $DIR/rename.rs:73:9
 +   |
 +LL | #![warn(clippy::for_loops_over_fallibles)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 +
 +error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-   --> $DIR/rename.rs:73:9
++  --> $DIR/rename.rs:74:9
 +   |
 +LL | #![warn(clippy::into_iter_on_array)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 +
 +error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-   --> $DIR/rename.rs:74:9
++  --> $DIR/rename.rs:75:9
 +   |
 +LL | #![warn(clippy::invalid_atomic_ordering)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 +
 +error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-   --> $DIR/rename.rs:75:9
++  --> $DIR/rename.rs:76:9
 +   |
 +LL | #![warn(clippy::invalid_ref)]
 +   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 +
 +error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-   --> $DIR/rename.rs:76:9
++  --> $DIR/rename.rs:77:9
 +   |
 +LL | #![warn(clippy::let_underscore_drop)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 +
 +error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-   --> $DIR/rename.rs:77:9
++  --> $DIR/rename.rs:78:9
 +   |
 +LL | #![warn(clippy::mem_discriminant_non_enum)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 +
 +error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-   --> $DIR/rename.rs:78:9
++  --> $DIR/rename.rs:79:9
 +   |
 +LL | #![warn(clippy::panic_params)]
 +   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 +
 +error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-   --> $DIR/rename.rs:79:9
++  --> $DIR/rename.rs:80:9
 +   |
 +LL | #![warn(clippy::positional_named_format_parameters)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 +
 +error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-   --> $DIR/rename.rs:80:9
++  --> $DIR/rename.rs:81:9
 +   |
 +LL | #![warn(clippy::temporary_cstring_as_ptr)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 +
 +error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-   --> $DIR/rename.rs:81:9
++  --> $DIR/rename.rs:82:9
 +   |
 +LL | #![warn(clippy::unknown_clippy_lints)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 +
 +error: lint `clippy::unused_label` has been renamed to `unused_labels`
- error: aborting due to 41 previous errors
++  --> $DIR/rename.rs:83:9
 +   |
 +LL | #![warn(clippy::unused_label)]
 +   |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 +
++error: aborting due to 42 previous errors
 +
index 63d31ff83f9b5c508f09fa556ba5ee2421bd0cc4,0000000000000000000000000000000000000000..a0dcc0172e8b0ba5cba4f7952aad8c521f9023aa
mode 100644,000000..100644
--- /dev/null
@@@ -1,36 -1,0 +1,63 @@@
 +// run-rustfix
 +// Tests from for_loop.rs that don't have suggestions
 +
 +#[warn(clippy::single_element_loop)]
 +fn main() {
 +    let item1 = 2;
 +    {
 +        let item = &item1;
 +        dbg!(item);
 +    }
 +
 +    {
 +        let item = &item1;
 +        dbg!(item);
 +    }
 +
 +    {
 +        let item = &(0..5);
 +        dbg!(item);
 +    }
 +
 +    {
 +        let item = &mut (0..5);
 +        dbg!(item);
 +    }
 +
 +    {
 +        let item = 0..5;
 +        dbg!(item);
 +    }
 +
 +    {
 +        let item = 0..5;
 +        dbg!(item);
 +    }
++
++    // should not lint (issue #10018)
++    for e in [42] {
++        if e > 0 {
++            continue;
++        }
++    }
++
++    // should not lint (issue #10018)
++    for e in [42] {
++        if e > 0 {
++            break;
++        }
++    }
++
++    // should lint (issue #10018)
++    {
++        let _ = 42;
++        let _f = |n: u32| {
++            for i in 0..n {
++                if i > 10 {
++                    dbg!(i);
++                    break;
++                }
++            }
++        };
++    }
 +}
index 2cda5a329d254fb496dec9dca41bfa899142ed4c,0000000000000000000000000000000000000000..bc014035c98a5671c8ccc59c9b96ebff077c646e
mode 100644,000000..100644
--- /dev/null
@@@ -1,30 -1,0 +1,56 @@@
 +// run-rustfix
 +// Tests from for_loop.rs that don't have suggestions
 +
 +#[warn(clippy::single_element_loop)]
 +fn main() {
 +    let item1 = 2;
 +    for item in &[item1] {
 +        dbg!(item);
 +    }
 +
 +    for item in [item1].iter() {
 +        dbg!(item);
 +    }
 +
 +    for item in &[0..5] {
 +        dbg!(item);
 +    }
 +
 +    for item in [0..5].iter_mut() {
 +        dbg!(item);
 +    }
 +
 +    for item in [0..5] {
 +        dbg!(item);
 +    }
 +
 +    for item in [0..5].into_iter() {
 +        dbg!(item);
 +    }
++
++    // should not lint (issue #10018)
++    for e in [42] {
++        if e > 0 {
++            continue;
++        }
++    }
++
++    // should not lint (issue #10018)
++    for e in [42] {
++        if e > 0 {
++            break;
++        }
++    }
++
++    // should lint (issue #10018)
++    for _ in [42] {
++        let _f = |n: u32| {
++            for i in 0..n {
++                if i > 10 {
++                    dbg!(i);
++                    break;
++                }
++            }
++        };
++    }
 +}
index 0aeb8da1a2e23e6dac4c85f1be745ede77c4c830,0000000000000000000000000000000000000000..14437a59745e04896bb17e386eefb04cb505f7a8
mode 100644,000000..100644
--- /dev/null
@@@ -1,99 -1,0 +1,126 @@@
- error: aborting due to 6 previous errors
 +error: for loop over a single element
 +  --> $DIR/single_element_loop.rs:7:5
 +   |
 +LL | /     for item in &[item1] {
 +LL | |         dbg!(item);
 +LL | |     }
 +   | |_____^
 +   |
 +   = note: `-D clippy::single-element-loop` implied by `-D warnings`
 +help: try
 +   |
 +LL ~     {
 +LL +         let item = &item1;
 +LL +         dbg!(item);
 +LL +     }
 +   |
 +
 +error: for loop over a single element
 +  --> $DIR/single_element_loop.rs:11:5
 +   |
 +LL | /     for item in [item1].iter() {
 +LL | |         dbg!(item);
 +LL | |     }
 +   | |_____^
 +   |
 +help: try
 +   |
 +LL ~     {
 +LL +         let item = &item1;
 +LL +         dbg!(item);
 +LL +     }
 +   |
 +
 +error: for loop over a single element
 +  --> $DIR/single_element_loop.rs:15:5
 +   |
 +LL | /     for item in &[0..5] {
 +LL | |         dbg!(item);
 +LL | |     }
 +   | |_____^
 +   |
 +help: try
 +   |
 +LL ~     {
 +LL +         let item = &(0..5);
 +LL +         dbg!(item);
 +LL +     }
 +   |
 +
 +error: for loop over a single element
 +  --> $DIR/single_element_loop.rs:19:5
 +   |
 +LL | /     for item in [0..5].iter_mut() {
 +LL | |         dbg!(item);
 +LL | |     }
 +   | |_____^
 +   |
 +help: try
 +   |
 +LL ~     {
 +LL +         let item = &mut (0..5);
 +LL +         dbg!(item);
 +LL +     }
 +   |
 +
 +error: for loop over a single element
 +  --> $DIR/single_element_loop.rs:23:5
 +   |
 +LL | /     for item in [0..5] {
 +LL | |         dbg!(item);
 +LL | |     }
 +   | |_____^
 +   |
 +help: try
 +   |
 +LL ~     {
 +LL +         let item = 0..5;
 +LL +         dbg!(item);
 +LL +     }
 +   |
 +
 +error: for loop over a single element
 +  --> $DIR/single_element_loop.rs:27:5
 +   |
 +LL | /     for item in [0..5].into_iter() {
 +LL | |         dbg!(item);
 +LL | |     }
 +   | |_____^
 +   |
 +help: try
 +   |
 +LL ~     {
 +LL +         let item = 0..5;
 +LL +         dbg!(item);
 +LL +     }
 +   |
 +
++error: for loop over a single element
++  --> $DIR/single_element_loop.rs:46:5
++   |
++LL | /     for _ in [42] {
++LL | |         let _f = |n: u32| {
++LL | |             for i in 0..n {
++LL | |                 if i > 10 {
++...  |
++LL | |         };
++LL | |     }
++   | |_____^
++   |
++help: try
++   |
++LL ~     {
++LL +         let _ = 42;
++LL +         let _f = |n: u32| {
++LL +             for i in 0..n {
++LL +                 if i > 10 {
++LL +                     dbg!(i);
++LL +                     break;
++LL +                 }
++LL +             }
++LL +         };
++LL +     }
++   |
++
++error: aborting due to 7 previous errors
 +
index ae1aec34d82e0b3ccb19e9d8a1050fb87c9336d4,0000000000000000000000000000000000000000..dec3f50d6f1b633fa85d3f2b61e180c2656884e2
mode 100644,000000..100644
--- /dev/null
@@@ -1,42 -1,0 +1,42 @@@
- error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
++error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
 +  --> $DIR/suspicious_to_owned.rs:16:13
 +   |
 +LL |     let _ = cow.to_owned();
 +   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
 +   |
 +   = note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
 +
- error: this `to_owned` call clones the std::borrow::Cow<'_, [char; 3]> itself and does not cause the std::borrow::Cow<'_, [char; 3]> contents to become owned
++error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
 +  --> $DIR/suspicious_to_owned.rs:26:13
 +   |
 +LL |     let _ = cow.to_owned();
 +   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
 +
- error: this `to_owned` call clones the std::borrow::Cow<'_, std::vec::Vec<char>> itself and does not cause the std::borrow::Cow<'_, std::vec::Vec<char>> contents to become owned
++error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
 +  --> $DIR/suspicious_to_owned.rs:36:13
 +   |
 +LL |     let _ = cow.to_owned();
 +   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
 +
- error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
++error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
 +  --> $DIR/suspicious_to_owned.rs:46:13
 +   |
 +LL |     let _ = cow.to_owned();
 +   |             ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
 +
 +error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
 +  --> $DIR/suspicious_to_owned.rs:60:13
 +   |
 +LL |     let _ = String::from(moo).to_owned();
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::from(moo).clone()`
 +   |
 +   = note: `-D clippy::implicit-clone` implied by `-D warnings`
 +
 +error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type
 +  --> $DIR/suspicious_to_owned.rs:61:13
 +   |
 +LL |     let _ = moos_vec.to_owned();
 +   |             ^^^^^^^^^^^^^^^^^^^ help: consider using: `moos_vec.clone()`
 +
 +error: aborting due to 6 previous errors
 +
index 94cc7777acacd787a8aff6f64f48f66d4c9eb0e2,0000000000000000000000000000000000000000..6022d9fa4c5c3e7d2493dc0cff56e1b305599c9e
mode 100644,000000..100644
--- /dev/null
@@@ -1,106 -1,0 +1,106 @@@
- error: using `clone` on type `std::option::Option<T>` which implements the `Copy` trait
 +error: using `.clone()` on a ref-counted pointer
 +  --> $DIR/unnecessary_clone.rs:23:5
 +   |
 +LL |     rc.clone();
 +   |     ^^^^^^^^^^ help: try this: `Rc::<bool>::clone(&rc)`
 +   |
 +   = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings`
 +
 +error: using `.clone()` on a ref-counted pointer
 +  --> $DIR/unnecessary_clone.rs:26:5
 +   |
 +LL |     arc.clone();
 +   |     ^^^^^^^^^^^ help: try this: `Arc::<bool>::clone(&arc)`
 +
 +error: using `.clone()` on a ref-counted pointer
 +  --> $DIR/unnecessary_clone.rs:29:5
 +   |
 +LL |     rcweak.clone();
 +   |     ^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&rcweak)`
 +
 +error: using `.clone()` on a ref-counted pointer
 +  --> $DIR/unnecessary_clone.rs:32:5
 +   |
 +LL |     arc_weak.clone();
 +   |     ^^^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&arc_weak)`
 +
 +error: using `.clone()` on a ref-counted pointer
 +  --> $DIR/unnecessary_clone.rs:36:33
 +   |
 +LL |     let _: Arc<dyn SomeTrait> = x.clone();
 +   |                                 ^^^^^^^^^ help: try this: `Arc::<SomeImpl>::clone(&x)`
 +
 +error: using `clone` on type `T` which implements the `Copy` trait
 +  --> $DIR/unnecessary_clone.rs:40:5
 +   |
 +LL |     t.clone();
 +   |     ^^^^^^^^^ help: try removing the `clone` call: `t`
 +   |
 +   = note: `-D clippy::clone-on-copy` implied by `-D warnings`
 +
- error: using `clone` on a double-reference; this will copy the reference of type `&std::vec::Vec<i32>` instead of cloning the inner type
++error: using `clone` on type `Option<T>` which implements the `Copy` trait
 +  --> $DIR/unnecessary_clone.rs:42:5
 +   |
 +LL |     Some(t).clone();
 +   |     ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
 +
- LL |     let z: &Vec<_> = <&std::vec::Vec<i32>>::clone(y);
-    |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++error: using `clone` on a double-reference; this will copy the reference of type `&Vec<i32>` instead of cloning the inner type
 +  --> $DIR/unnecessary_clone.rs:48:22
 +   |
 +LL |     let z: &Vec<_> = y.clone();
 +   |                      ^^^^^^^^^
 +   |
 +   = note: `#[deny(clippy::clone_double_ref)]` on by default
 +help: try dereferencing it
 +   |
 +LL |     let z: &Vec<_> = &(*y).clone();
 +   |                      ~~~~~~~~~~~~~
 +help: or try being explicit if you are sure, that you want to clone a reference
 +   |
- error: using `clone` on type `many_derefs::E` which implements the `Copy` trait
++LL |     let z: &Vec<_> = <&Vec<i32>>::clone(y);
++   |                      ~~~~~~~~~~~~~~~~~~~~~
 +
++error: using `clone` on type `E` which implements the `Copy` trait
 +  --> $DIR/unnecessary_clone.rs:84:20
 +   |
 +LL |         let _: E = a.clone();
 +   |                    ^^^^^^^^^ help: try dereferencing it: `*****a`
 +
 +error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type
 +  --> $DIR/unnecessary_clone.rs:89:22
 +   |
 +LL |         let _ = &mut encoded.clone();
 +   |                      ^^^^^^^^^^^^^^^
 +   |
 +help: try dereferencing it
 +   |
 +LL |         let _ = &mut &(*encoded).clone();
 +   |                      ~~~~~~~~~~~~~~~~~~~
 +help: or try being explicit if you are sure, that you want to clone a reference
 +   |
 +LL |         let _ = &mut <&[u8]>::clone(encoded);
 +   |                      ~~~~~~~~~~~~~~~~~~~~~~~
 +
 +error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type
 +  --> $DIR/unnecessary_clone.rs:90:18
 +   |
 +LL |         let _ = &encoded.clone();
 +   |                  ^^^^^^^^^^^^^^^
 +   |
 +help: try dereferencing it
 +   |
 +LL |         let _ = &&(*encoded).clone();
 +   |                  ~~~~~~~~~~~~~~~~~~~
 +help: or try being explicit if you are sure, that you want to clone a reference
 +   |
 +LL |         let _ = &<&[u8]>::clone(encoded);
 +   |                  ~~~~~~~~~~~~~~~~~~~~~~~
 +
 +error: using `.clone()` on a ref-counted pointer
 +  --> $DIR/unnecessary_clone.rs:108:14
 +   |
 +LL |         Some(try_opt!(Some(rc)).clone())
 +   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::<u8>::clone(&try_opt!(Some(rc)))`
 +
 +error: aborting due to 12 previous errors
 +
index 92e8e1dba69dd0a963f33439d9f134ec5cd7b1bc,0000000000000000000000000000000000000000..55bd5607185c67ec5f07eb9847f2e4ee4524c8b7
mode 100644,000000..100644
--- /dev/null
@@@ -1,149 -1,0 +1,159 @@@
 +#![warn(clippy::unused_self)]
 +#![allow(clippy::boxed_local, clippy::fn_params_excessive_bools)]
 +
 +mod unused_self {
 +    use std::pin::Pin;
 +    use std::sync::{Arc, Mutex};
 +
 +    struct A;
 +
 +    impl A {
 +        fn unused_self_move(self) {}
 +        fn unused_self_ref(&self) {}
 +        fn unused_self_mut_ref(&mut self) {}
 +        fn unused_self_pin_ref(self: Pin<&Self>) {}
 +        fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
 +        fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
 +        fn unused_self_box(self: Box<Self>) {}
 +        fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
 +            x + y
 +        }
 +        fn unused_self_class_method(&self) {
 +            Self::static_method();
 +        }
 +
 +        fn static_method() {}
 +    }
 +}
 +
 +mod unused_self_allow {
 +    struct A;
 +
 +    impl A {
 +        // shouldn't trigger
 +        #[allow(clippy::unused_self)]
 +        fn unused_self_move(self) {}
 +    }
 +
 +    struct B;
 +
 +    // shouldn't trigger
 +    #[allow(clippy::unused_self)]
 +    impl B {
 +        fn unused_self_move(self) {}
 +    }
 +
 +    struct C;
 +
 +    #[allow(clippy::unused_self)]
 +    impl C {
 +        #[warn(clippy::unused_self)]
 +        fn some_fn((): ()) {}
 +
 +        // shouldn't trigger
 +        fn unused_self_move(self) {}
 +    }
 +
 +    pub struct D;
 +
 +    impl D {
 +        // shouldn't trigger for public methods
 +        pub fn unused_self_move(self) {}
 +    }
++
++    pub struct E;
++
++    impl E {
++        // shouldn't trigger if body contains todo!()
++        pub fn unused_self_todo(self) {
++            let x = 42;
++            todo!()
++        }
++    }
 +}
 +
 +pub use unused_self_allow::D;
 +
 +mod used_self {
 +    use std::pin::Pin;
 +
 +    struct A {
 +        x: u8,
 +    }
 +
 +    impl A {
 +        fn used_self_move(self) -> u8 {
 +            self.x
 +        }
 +        fn used_self_ref(&self) -> u8 {
 +            self.x
 +        }
 +        fn used_self_mut_ref(&mut self) {
 +            self.x += 1
 +        }
 +        fn used_self_pin_ref(self: Pin<&Self>) -> u8 {
 +            self.x
 +        }
 +        fn used_self_box(self: Box<Self>) -> u8 {
 +            self.x
 +        }
 +        fn used_self_with_other_unused_args(&self, x: u8, y: u8) -> u8 {
 +            self.x
 +        }
 +        fn used_in_nested_closure(&self) -> u8 {
 +            let mut a = || -> u8 { self.x };
 +            a()
 +        }
 +
 +        #[allow(clippy::collapsible_if)]
 +        fn used_self_method_nested_conditions(&self, a: bool, b: bool, c: bool, d: bool) {
 +            if a {
 +                if b {
 +                    if c {
 +                        if d {
 +                            self.used_self_ref();
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +
 +        fn foo(&self) -> u32 {
 +            let mut sum = 0u32;
 +            for i in 0..self.x {
 +                sum += i as u32;
 +            }
 +            sum
 +        }
 +
 +        fn bar(&mut self, x: u8) -> u32 {
 +            let mut y = 0u32;
 +            for i in 0..x {
 +                y += self.foo()
 +            }
 +            y
 +        }
 +    }
 +}
 +
 +mod not_applicable {
 +    use std::fmt;
 +
 +    struct A;
 +
 +    impl fmt::Debug for A {
 +        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 +            write!(f, "A")
 +        }
 +    }
 +
 +    impl A {
 +        fn method(x: u8, y: u8) {}
 +    }
 +
 +    trait B {
 +        fn method(&self) {}
 +    }
 +}
 +
 +fn main() {}
index 23186122a9af7ef5dd4247c6df02e97438767aa8,0000000000000000000000000000000000000000..919f9b6efdab8cb9ebb6a3d9f47a26d49b7382f5
mode 100644,000000..100644
--- /dev/null
@@@ -1,75 -1,0 +1,75 @@@
-    = help: consider refactoring to a associated function
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:11:29
 +   |
 +LL |         fn unused_self_move(self) {}
 +   |                             ^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +   = note: `-D clippy::unused-self` implied by `-D warnings`
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:12:28
 +   |
 +LL |         fn unused_self_ref(&self) {}
 +   |                            ^^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:13:32
 +   |
 +LL |         fn unused_self_mut_ref(&mut self) {}
 +   |                                ^^^^^^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:14:32
 +   |
 +LL |         fn unused_self_pin_ref(self: Pin<&Self>) {}
 +   |                                ^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:15:36
 +   |
 +LL |         fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
 +   |                                    ^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:16:35
 +   |
 +LL |         fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
 +   |                                   ^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:17:28
 +   |
 +LL |         fn unused_self_box(self: Box<Self>) {}
 +   |                            ^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:18:40
 +   |
 +LL |         fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
 +   |                                        ^^^^^
 +   |
-    = help: consider refactoring to a associated function
++   = help: consider refactoring to an associated function
 +
 +error: unused `self` argument
 +  --> $DIR/unused_self.rs:21:37
 +   |
 +LL |         fn unused_self_class_method(&self) {
 +   |                                     ^^^^^
 +   |
++   = help: consider refactoring to an associated function
 +
 +error: aborting due to 9 previous errors
 +