]> git.lizzy.rs Git - rust.git/commitdiff
Merge commit '43a1777b89cf6791f9e20878b4e5e3ae907867a5' into clippyup
authorflip1995 <hello@philkrones.com>
Mon, 11 May 2020 18:23:47 +0000 (20:23 +0200)
committerflip1995 <hello@philkrones.com>
Mon, 11 May 2020 18:23:47 +0000 (20:23 +0200)
34 files changed:
1  2 
src/tools/clippy/CHANGELOG.md
src/tools/clippy/Cargo.toml
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/loops.rs
src/tools/clippy/clippy_lints/src/manual_async_fn.rs
src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
src/tools/clippy/clippy_lints/src/match_on_vec_items.rs
src/tools/clippy/clippy_lints/src/misc_early.rs
src/tools/clippy/clippy_lints/src/unwrap.rs
src/tools/clippy/clippy_lints/src/utils/conf.rs
src/tools/clippy/clippy_lints/src/utils/mod.rs
src/tools/clippy/clippy_lints/src/utils/paths.rs
src/tools/clippy/clippy_lints/src/wildcard_imports.rs
src/tools/clippy/src/lintlist/mod.rs
src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
src/tools/clippy/tests/ui/builtin-type-shadow.stderr
src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
src/tools/clippy/tests/ui/future_not_send.rs
src/tools/clippy/tests/ui/future_not_send.stderr
src/tools/clippy/tests/ui/manual_async_fn.fixed
src/tools/clippy/tests/ui/manual_async_fn.rs
src/tools/clippy/tests/ui/manual_async_fn.stderr
src/tools/clippy/tests/ui/manual_memcpy.rs
src/tools/clippy/tests/ui/manual_memcpy.stderr
src/tools/clippy/tests/ui/manual_non_exhaustive.rs
src/tools/clippy/tests/ui/manual_non_exhaustive.stderr
src/tools/clippy/tests/ui/match_on_vec_items.rs
src/tools/clippy/tests/ui/while_let_on_iterator.fixed
src/tools/clippy/tests/ui/while_let_on_iterator.rs
src/tools/clippy/tests/ui/while_let_on_iterator.stderr
src/tools/clippy/tests/ui/wildcard_imports.fixed
src/tools/clippy/tests/ui/wildcard_imports.rs
src/tools/clippy/tests/ui/wildcard_imports.stderr

index 575773580c0be25ee59792a3e2d2e9a3aa0ebc6b,0000000000000000000000000000000000000000..8457d6ad05cf9d876fe7739d364189234bb9980d
mode 100644,000000..100644
--- /dev/null
@@@ -1,1657 -1,0 +1,1659 @@@
 +# Change Log
 +
 +All notable changes to this project will be documented in this file.
 +See [Changelog Update](doc/changelog_update.md) if you want to update this
 +document.
 +
 +## Unreleased / In Rust Nightly
 +
 +[891e1a8...master](https://github.com/rust-lang/rust-clippy/compare/891e1a8...master)
 +
 +## Rust 1.44
 +
 +Current beta, release 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
 +
 +Current stable, 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 `{unnnecessary,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`],
 +  [`mem_discriminant_non_enum`], [`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/doc/adding_lints.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
 +[`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
 +[`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
 +[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants
 +[`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
 +[`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock
 +[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
 +[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name
 +[`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
 +[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
 +[`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_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
 +[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
 +[`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata
 +[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless
 +[`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
 +[`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
 +[`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_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
 +[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
 +[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
 +[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
 +[`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_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access
 +[`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
 +[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
 +[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
 +[`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_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref
 +[`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_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
 +[`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
 +[`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op
 +[`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
 +[`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
 +[`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy
 +[`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
 +[`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
 +[`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_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
 +[`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
 +[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons
 +[`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_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
 +[`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy
 +[`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref
 +[`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send
 +[`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
 +[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
 +[`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_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
 +[`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
 +[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always
 +[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
 +[`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_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
 +[`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_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
 +[`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_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
 +[`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_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
 +[`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_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_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
 +[`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_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
 +[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
 +[`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_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
 +[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten
 +[`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_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_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_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm
 +[`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
 +[`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_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_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
 +[`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
 +[`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
 +[`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_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_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_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
 +[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
 +[`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_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
 +[`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
 +[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect
 +[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
 +[`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
 +[`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref
 +[`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect
 +[`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_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
 +[`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
 +[`panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic
 +[`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
 +[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl
 +[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
 +[`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_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal
 +[`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_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
 +[`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
 +[`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_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_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
 +[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 +[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
 +[`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_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_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
 +[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop
 +[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition
 +[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
 +[`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
 +[`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
 +[`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern
 +[`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports
 +[`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
 +[`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
 +[`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_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
 +[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
 +[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
 +[`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_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
 +[`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
 +[`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
 +[`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_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
 +[`transmuting_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmuting_null
 +[`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
 +[`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
 +[`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
 +[`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_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
 +[`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_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
 +[`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
 +[`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_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
 +[`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_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
 +[`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_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
 +[`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_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 63ce2cd8cad776ccf14c5da2da075358fbaf4660,0000000000000000000000000000000000000000..6999b6bd74040746afb6ac394a436d65ac05d4e3
mode 100644,000000..100644
--- /dev/null
@@@ -1,59 -1,0 +1,58 @@@
- regex = "1"
 +[package]
 +name = "clippy"
 +version = "0.0.212"
 +authors = [
 +      "Manish Goregaokar <manishsmail@gmail.com>",
 +      "Andre Bogus <bogusandre@gmail.com>",
 +      "Georg Brandl <georg@python.org>",
 +      "Martin Carton <cartonmartin@gmail.com>",
 +      "Oliver Schneider <clippy-iethah7aipeen8neex1a@oli-obk.de>"
 +]
 +description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 +repository = "https://github.com/rust-lang/rust-clippy"
 +readme = "README.md"
 +license = "MIT OR Apache-2.0"
 +keywords = ["clippy", "lint", "plugin"]
 +categories = ["development-tools", "development-tools::cargo-plugins"]
 +build = "build.rs"
 +edition = "2018"
 +publish = false
 +
 +[[bin]]
 +name = "cargo-clippy"
 +test = false
 +path = "src/main.rs"
 +
 +[[bin]]
 +name = "clippy-driver"
 +path = "src/driver.rs"
 +
 +[dependencies]
 +# begin automatic update
 +clippy_lints = { version = "0.0.212", path = "clippy_lints" }
 +# end automatic update
 +semver = "0.9"
 +rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
 +tempfile = { version = "3.1.0", optional = true }
 +lazy_static = "1.0"
 +
 +[dev-dependencies]
 +cargo_metadata = "0.9.0"
 +compiletest_rs = { version = "0.5.0", features = ["tmp"] }
 +tester = "0.7"
 +lazy_static = "1.0"
 +clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
 +serde = { version = "1.0", features = ["derive"] }
 +derive-new = "0.5"
 +
 +# A noop dependency that changes in the Rust repository, it's a bit of a hack.
 +# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
 +# for more information.
 +rustc-workspace-hack = "1.0.0"
 +
 +[build-dependencies]
 +rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
 +
 +[features]
 +deny-warnings = []
 +integration = ["tempfile"]
index 1f135cba6e4ee97156715db034622b65f803f779,0000000000000000000000000000000000000000..51b5401da7d00e65ce96ccac97d70d34ebcd5f69
mode 100644,000000..100644
--- /dev/null
@@@ -1,1795 -1,0 +1,1805 @@@
-     store.register_late_pass(|| box wildcard_imports::WildcardImports);
 +// error-pattern:cargo-clippy
 +
 +#![feature(box_syntax)]
 +#![feature(box_patterns)]
 +#![feature(or_patterns)]
 +#![feature(rustc_private)]
 +#![feature(stmt_expr_attributes)]
 +#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)]
 +#![recursion_limit = "512"]
 +#![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)]
 +#![deny(rustc::internal)]
 +#![cfg_attr(feature = "deny-warnings", deny(warnings))]
 +#![feature(crate_visibility_modifier)]
 +#![feature(concat_idents)]
 +
 +// FIXME: switch to something more ergonomic here, once available.
 +// (Currently there is no way to opt into sysroot crates without `extern crate`.)
 +#[allow(unused_extern_crates)]
 +extern crate fmt_macros;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_ast;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_ast_pretty;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_attr;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_data_structures;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_driver;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_errors;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_hir;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_hir_pretty;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_index;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_infer;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_lexer;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_lint;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_middle;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_mir;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_parse;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_session;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_span;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_target;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_trait_selection;
 +#[allow(unused_extern_crates)]
 +extern crate rustc_typeck;
 +
 +use rustc_data_structures::fx::FxHashSet;
 +use rustc_lint::LintId;
 +use rustc_session::Session;
 +
 +/// Macro used to declare a Clippy lint.
 +///
 +/// Every lint declaration consists of 4 parts:
 +///
 +/// 1. The documentation, which is used for the website
 +/// 2. The `LINT_NAME`. See [lint naming][lint_naming] on lint naming conventions.
 +/// 3. The `lint_level`, which is a mapping from *one* of our lint groups to `Allow`, `Warn` or
 +///    `Deny`. The lint level here has nothing to do with what lint groups the lint is a part of.
 +/// 4. The `description` that contains a short explanation on what's wrong with code where the
 +///    lint is triggered.
 +///
 +/// Currently the categories `style`, `correctness`, `complexity` and `perf` are enabled by default.
 +/// As said in the README.md of this repository, if the lint level mapping changes, please update
 +/// README.md.
 +///
 +/// # Example
 +///
 +/// ```
 +/// # #![feature(rustc_private)]
 +/// # #[allow(unused_extern_crates)]
 +/// # extern crate rustc_middle;
 +/// # #[allow(unused_extern_crates)]
 +/// # extern crate rustc_session;
 +/// # #[macro_use]
 +/// # use clippy_lints::declare_clippy_lint;
 +/// use rustc_session::declare_tool_lint;
 +///
 +/// declare_clippy_lint! {
 +///     /// **What it does:** Checks for ... (describe what the lint matches).
 +///     ///
 +///     /// **Why is this bad?** Supply the reason for linting the code.
 +///     ///
 +///     /// **Known problems:** None. (Or describe where it could go wrong.)
 +///     ///
 +///     /// **Example:**
 +///     ///
 +///     /// ```rust
 +///     /// // Bad
 +///     /// Insert a short example of code that triggers the lint
 +///     ///
 +///     /// // Good
 +///     /// Insert a short example of improved code that doesn't trigger the lint
 +///     /// ```
 +///     pub LINT_NAME,
 +///     pedantic,
 +///     "description"
 +/// }
 +/// ```
 +/// [lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
 +#[macro_export]
 +macro_rules! declare_clippy_lint {
 +    { $(#[$attr:meta])* pub $name:tt, style, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, correctness, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Deny, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true
 +        }
 +    };
 +    { $(#[$attr:meta])* pub $name:tt, internal_warn, $description:tt } => {
 +        declare_tool_lint! {
 +            $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true
 +        }
 +    };
 +}
 +
 +mod consts;
 +#[macro_use]
 +mod utils;
 +
 +// begin lints modules, do not remove this comment, it’s used in `update_lints`
 +mod approx_const;
 +mod arithmetic;
 +mod as_conversions;
 +mod assertions_on_constants;
 +mod assign_ops;
 +mod atomic_ordering;
 +mod attrs;
 +mod await_holding_lock;
 +mod bit_mask;
 +mod blacklisted_name;
 +mod block_in_if_condition;
 +mod booleans;
 +mod bytecount;
 +mod cargo_common_metadata;
 +mod checked_conversions;
 +mod cognitive_complexity;
 +mod collapsible_if;
 +mod comparison_chain;
 +mod copies;
 +mod copy_iterator;
 +mod dbg_macro;
 +mod default_trait_access;
 +mod dereference;
 +mod derive;
 +mod doc;
 +mod double_comparison;
 +mod double_parens;
 +mod drop_bounds;
 +mod drop_forget_ref;
 +mod duration_subsec;
 +mod else_if_without_else;
 +mod empty_enum;
 +mod entry;
 +mod enum_clike;
 +mod enum_variants;
 +mod eq_op;
 +mod erasing_op;
 +mod escape;
 +mod eta_reduction;
 +mod eval_order_dependence;
 +mod excessive_bools;
 +mod exit;
 +mod explicit_write;
 +mod fallible_impl_from;
 +mod float_literal;
 +mod floating_point_arithmetic;
 +mod format;
 +mod formatting;
 +mod functions;
 +mod future_not_send;
 +mod get_last_with_len;
 +mod identity_conversion;
 +mod identity_op;
 +mod if_let_mutex;
 +mod if_let_some_result;
 +mod if_not_else;
 +mod implicit_return;
 +mod implicit_saturating_sub;
 +mod indexing_slicing;
 +mod infinite_iter;
 +mod inherent_impl;
 +mod inherent_to_string;
 +mod inline_fn_without_body;
 +mod int_plus_one;
 +mod integer_division;
 +mod items_after_statements;
 +mod large_const_arrays;
 +mod large_enum_variant;
 +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_async_fn;
++mod manual_non_exhaustive;
 +mod map_clone;
 +mod map_unit_fn;
 +mod match_on_vec_items;
 +mod matches;
 +mod mem_discriminant;
 +mod mem_forget;
 +mod mem_replace;
 +mod methods;
 +mod minmax;
 +mod misc;
 +mod misc_early;
 +mod missing_const_for_fn;
 +mod missing_doc;
 +mod missing_inline;
 +mod modulo_arithmetic;
 +mod multiple_crate_versions;
 +mod mut_key;
 +mod mut_mut;
 +mod mut_reference;
 +mod mutable_debug_assertion;
 +mod mutex_atomic;
 +mod needless_bool;
 +mod needless_borrow;
 +mod needless_borrowed_ref;
 +mod needless_continue;
 +mod needless_pass_by_value;
 +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 open_options;
 +mod option_env_unwrap;
 +mod overflow_check_conditional;
 +mod panic_unimplemented;
 +mod partialeq_ne_impl;
 +mod path_buf_push_overwrite;
 +mod precedence;
 +mod ptr;
 +mod ptr_offset_with_cast;
 +mod question_mark;
 +mod ranges;
 +mod redundant_clone;
 +mod redundant_field_names;
 +mod redundant_pattern_matching;
 +mod redundant_pub_crate;
 +mod redundant_static_lifetimes;
 +mod reference;
 +mod regex;
 +mod returns;
 +mod serde_api;
 +mod shadow;
 +mod single_component_path_imports;
 +mod slow_vector_initialization;
 +mod strings;
 +mod suspicious_trait_impl;
 +mod swap;
 +mod tabs_in_doc_comments;
 +mod temporary_assignment;
 +mod to_digit_is_some;
 +mod trait_bounds;
 +mod transmute;
 +mod transmuting_null;
 +mod trivially_copy_pass_by_ref;
 +mod try_err;
 +mod types;
 +mod unicode;
 +mod unnamed_address;
 +mod unsafe_removed_from_name;
 +mod unused_io_amount;
 +mod unused_self;
 +mod unwrap;
 +mod use_self;
 +mod vec;
 +mod verbose_file_reads;
 +mod wildcard_dependencies;
 +mod wildcard_imports;
 +mod write;
 +mod zero_div_zero;
 +// end lints modules, do not remove this comment, it’s used in `update_lints`
 +
 +pub use crate::utils::conf::Conf;
 +
 +mod reexport {
 +    pub use rustc_span::Symbol as Name;
 +}
 +
 +/// 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, conf: &Conf) {
 +    store.register_pre_expansion_pass(|| box write::Write::default());
 +    store.register_pre_expansion_pass(|| box redundant_field_names::RedundantFieldNames);
 +    let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
 +    store.register_pre_expansion_pass(move || box non_expressive_names::NonExpressiveNames {
 +        single_char_binding_names_threshold,
 +    });
 +    store.register_pre_expansion_pass(|| box attrs::EarlyAttributes);
 +    store.register_pre_expansion_pass(|| box dbg_macro::DbgMacro);
 +}
 +
 +#[doc(hidden)]
 +pub fn read_conf(args: &[rustc_ast::ast::NestedMetaItem], sess: &Session) -> Conf {
 +    use std::path::Path;
 +    match utils::conf::file_from_args(args) {
 +        Ok(file_name) => {
 +            // if the user specified a file, it must exist, otherwise default to `clippy.toml` but
 +            // do not require the file to exist
 +            let file_name = match file_name {
 +                Some(file_name) => file_name,
 +                None => match utils::conf::lookup_conf_file() {
 +                    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 file_name = if file_name.is_relative() {
 +                sess.local_crate_source_file
 +                    .as_deref()
 +                    .and_then(Path::parent)
 +                    .unwrap_or_else(|| Path::new(""))
 +                    .join(file_name)
 +            } else {
 +                file_name
 +            };
 +
 +            let (conf, errors) = 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.struct_err(&format!(
 +                    "error reading Clippy's configuration file `{}`: {}",
 +                    file_name.display(),
 +                    error
 +                ))
 +                .emit();
 +            }
 +
 +            conf
 +        },
 +        Err((err, span)) => {
 +            sess.struct_span_err(span, err)
 +                .span_note(span, "Clippy will use default configuration")
 +                .emit();
 +            Conf::default()
 +        },
 +    }
 +}
 +
 +/// Register all lints and lint groups with the rustc plugin registry
 +///
 +/// Used in `./src/driver.rs`.
 +#[allow(clippy::too_many_lines)]
 +#[rustfmt::skip]
 +pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
 +    register_removed_non_tool_lints(store);
 +
 +    // begin deprecated lints, do not remove this comment, it’s used in `update_lints`
 +    store.register_removed(
 +        "clippy::should_assert_eq",
 +        "`assert!()` will be more flexible with RFC 2011",
 +    );
 +    store.register_removed(
 +        "clippy::extend_from_slice",
 +        "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice",
 +    );
 +    store.register_removed(
 +        "clippy::range_step_by_zero",
 +        "`iterator.step_by(0)` panics nowadays",
 +    );
 +    store.register_removed(
 +        "clippy::unstable_as_slice",
 +        "`Vec::as_slice` has been stabilized in 1.7",
 +    );
 +    store.register_removed(
 +        "clippy::unstable_as_mut_slice",
 +        "`Vec::as_mut_slice` has been stabilized in 1.7",
 +    );
 +    store.register_removed(
 +        "clippy::str_to_string",
 +        "using `str::to_string` is common even today and specialization will likely happen soon",
 +    );
 +    store.register_removed(
 +        "clippy::string_to_string",
 +        "using `string::to_string` is common even today and specialization will likely happen soon",
 +    );
 +    store.register_removed(
 +        "clippy::misaligned_transmute",
 +        "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
 +    );
 +    store.register_removed(
 +        "clippy::assign_ops",
 +        "using compound assignment operators (e.g., `+=`) is harmless",
 +    );
 +    store.register_removed(
 +        "clippy::if_let_redundant_pattern_matching",
 +        "this lint has been changed to redundant_pattern_matching",
 +    );
 +    store.register_removed(
 +        "clippy::unsafe_vector_initialization",
 +        "the replacement suggested by this lint had substantially different behavior",
 +    );
 +    store.register_removed(
 +        "clippy::invalid_ref",
 +        "superseded by rustc lint `invalid_value`",
 +    );
 +    store.register_removed(
 +        "clippy::unused_collect",
 +        "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint",
 +    );
 +    store.register_removed(
 +        "clippy::into_iter_on_array",
 +        "this lint has been uplifted to rustc and is now called `array_into_iter`",
 +    );
 +    store.register_removed(
 +        "clippy::unused_label",
 +        "this lint has been uplifted to rustc and is now called `unused_labels`",
 +    );
 +    store.register_removed(
 +        "clippy::replace_consts",
 +        "associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants",
 +    );
 +    // end deprecated lints, do not remove this comment, it’s used in `update_lints`
 +
 +    // begin register lints, do not remove this comment, it’s used in `update_lints`
 +    store.register_lints(&[
 +        &approx_const::APPROX_CONSTANT,
 +        &arithmetic::FLOAT_ARITHMETIC,
 +        &arithmetic::INTEGER_ARITHMETIC,
 +        &as_conversions::AS_CONVERSIONS,
 +        &assertions_on_constants::ASSERTIONS_ON_CONSTANTS,
 +        &assign_ops::ASSIGN_OP_PATTERN,
 +        &assign_ops::MISREFACTORED_ASSIGN_OP,
 +        &atomic_ordering::INVALID_ATOMIC_ORDERING,
 +        &attrs::DEPRECATED_CFG_ATTR,
 +        &attrs::DEPRECATED_SEMVER,
 +        &attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
 +        &attrs::INLINE_ALWAYS,
 +        &attrs::MISMATCHED_TARGET_OS,
 +        &attrs::UNKNOWN_CLIPPY_LINTS,
 +        &attrs::USELESS_ATTRIBUTE,
 +        &await_holding_lock::AWAIT_HOLDING_LOCK,
 +        &bit_mask::BAD_BIT_MASK,
 +        &bit_mask::INEFFECTIVE_BIT_MASK,
 +        &bit_mask::VERBOSE_BIT_MASK,
 +        &blacklisted_name::BLACKLISTED_NAME,
 +        &block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR,
 +        &block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT,
 +        &booleans::LOGIC_BUG,
 +        &booleans::NONMINIMAL_BOOL,
 +        &bytecount::NAIVE_BYTECOUNT,
 +        &cargo_common_metadata::CARGO_COMMON_METADATA,
 +        &checked_conversions::CHECKED_CONVERSIONS,
 +        &cognitive_complexity::COGNITIVE_COMPLEXITY,
 +        &collapsible_if::COLLAPSIBLE_IF,
 +        &comparison_chain::COMPARISON_CHAIN,
 +        &copies::IFS_SAME_COND,
 +        &copies::IF_SAME_THEN_ELSE,
 +        &copies::MATCH_SAME_ARMS,
 +        &copies::SAME_FUNCTIONS_IN_IF_CONDITION,
 +        &copy_iterator::COPY_ITERATOR,
 +        &dbg_macro::DBG_MACRO,
 +        &default_trait_access::DEFAULT_TRAIT_ACCESS,
 +        &dereference::EXPLICIT_DEREF_METHODS,
 +        &derive::DERIVE_HASH_XOR_EQ,
 +        &derive::EXPL_IMPL_CLONE_ON_COPY,
 +        &derive::UNSAFE_DERIVE_DESERIALIZE,
 +        &doc::DOC_MARKDOWN,
 +        &doc::MISSING_ERRORS_DOC,
 +        &doc::MISSING_SAFETY_DOC,
 +        &doc::NEEDLESS_DOCTEST_MAIN,
 +        &double_comparison::DOUBLE_COMPARISONS,
 +        &double_parens::DOUBLE_PARENS,
 +        &drop_bounds::DROP_BOUNDS,
 +        &drop_forget_ref::DROP_COPY,
 +        &drop_forget_ref::DROP_REF,
 +        &drop_forget_ref::FORGET_COPY,
 +        &drop_forget_ref::FORGET_REF,
 +        &duration_subsec::DURATION_SUBSEC,
 +        &else_if_without_else::ELSE_IF_WITHOUT_ELSE,
 +        &empty_enum::EMPTY_ENUM,
 +        &entry::MAP_ENTRY,
 +        &enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT,
 +        &enum_variants::ENUM_VARIANT_NAMES,
 +        &enum_variants::MODULE_INCEPTION,
 +        &enum_variants::MODULE_NAME_REPETITIONS,
 +        &enum_variants::PUB_ENUM_VARIANT_NAMES,
 +        &eq_op::EQ_OP,
 +        &eq_op::OP_REF,
 +        &erasing_op::ERASING_OP,
 +        &escape::BOXED_LOCAL,
 +        &eta_reduction::REDUNDANT_CLOSURE,
 +        &eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
 +        &eval_order_dependence::DIVERGING_SUB_EXPRESSION,
 +        &eval_order_dependence::EVAL_ORDER_DEPENDENCE,
 +        &excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS,
 +        &excessive_bools::STRUCT_EXCESSIVE_BOOLS,
 +        &exit::EXIT,
 +        &explicit_write::EXPLICIT_WRITE,
 +        &fallible_impl_from::FALLIBLE_IMPL_FROM,
 +        &float_literal::EXCESSIVE_PRECISION,
 +        &float_literal::LOSSY_FLOAT_LITERAL,
 +        &floating_point_arithmetic::IMPRECISE_FLOPS,
 +        &floating_point_arithmetic::SUBOPTIMAL_FLOPS,
 +        &format::USELESS_FORMAT,
 +        &formatting::POSSIBLE_MISSING_COMMA,
 +        &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
 +        &formatting::SUSPICIOUS_ELSE_FORMATTING,
 +        &formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
 +        &functions::DOUBLE_MUST_USE,
 +        &functions::MUST_USE_CANDIDATE,
 +        &functions::MUST_USE_UNIT,
 +        &functions::NOT_UNSAFE_PTR_ARG_DEREF,
 +        &functions::TOO_MANY_ARGUMENTS,
 +        &functions::TOO_MANY_LINES,
 +        &future_not_send::FUTURE_NOT_SEND,
 +        &get_last_with_len::GET_LAST_WITH_LEN,
 +        &identity_conversion::IDENTITY_CONVERSION,
 +        &identity_op::IDENTITY_OP,
 +        &if_let_mutex::IF_LET_MUTEX,
 +        &if_let_some_result::IF_LET_SOME_RESULT,
 +        &if_not_else::IF_NOT_ELSE,
 +        &implicit_return::IMPLICIT_RETURN,
 +        &implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
 +        &indexing_slicing::INDEXING_SLICING,
 +        &indexing_slicing::OUT_OF_BOUNDS_INDEXING,
 +        &infinite_iter::INFINITE_ITER,
 +        &infinite_iter::MAYBE_INFINITE_ITER,
 +        &inherent_impl::MULTIPLE_INHERENT_IMPL,
 +        &inherent_to_string::INHERENT_TO_STRING,
 +        &inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY,
 +        &inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
 +        &int_plus_one::INT_PLUS_ONE,
 +        &integer_division::INTEGER_DIVISION,
 +        &items_after_statements::ITEMS_AFTER_STATEMENTS,
 +        &large_const_arrays::LARGE_CONST_ARRAYS,
 +        &large_enum_variant::LARGE_ENUM_VARIANT,
 +        &large_stack_arrays::LARGE_STACK_ARRAYS,
 +        &len_zero::LEN_WITHOUT_IS_EMPTY,
 +        &len_zero::LEN_ZERO,
 +        &let_if_seq::USELESS_LET_IF_SEQ,
 +        &let_underscore::LET_UNDERSCORE_LOCK,
 +        &let_underscore::LET_UNDERSCORE_MUST_USE,
 +        &lifetimes::EXTRA_UNUSED_LIFETIMES,
 +        &lifetimes::NEEDLESS_LIFETIMES,
 +        &literal_representation::DECIMAL_LITERAL_REPRESENTATION,
 +        &literal_representation::INCONSISTENT_DIGIT_GROUPING,
 +        &literal_representation::LARGE_DIGIT_GROUPS,
 +        &literal_representation::MISTYPED_LITERAL_SUFFIXES,
 +        &literal_representation::UNREADABLE_LITERAL,
 +        &loops::EMPTY_LOOP,
 +        &loops::EXPLICIT_COUNTER_LOOP,
 +        &loops::EXPLICIT_INTO_ITER_LOOP,
 +        &loops::EXPLICIT_ITER_LOOP,
 +        &loops::FOR_KV_MAP,
 +        &loops::FOR_LOOP_OVER_OPTION,
 +        &loops::FOR_LOOP_OVER_RESULT,
 +        &loops::ITER_NEXT_LOOP,
 +        &loops::MANUAL_MEMCPY,
 +        &loops::MUT_RANGE_BOUND,
 +        &loops::NEEDLESS_COLLECT,
 +        &loops::NEEDLESS_RANGE_LOOP,
 +        &loops::NEVER_LOOP,
 +        &loops::REVERSE_RANGE_LOOP,
 +        &loops::WHILE_IMMUTABLE_CONDITION,
 +        &loops::WHILE_LET_LOOP,
 +        &loops::WHILE_LET_ON_ITERATOR,
 +        &macro_use::MACRO_USE_IMPORTS,
 +        &main_recursion::MAIN_RECURSION,
++        &manual_async_fn::MANUAL_ASYNC_FN,
++        &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
 +        &map_clone::MAP_CLONE,
 +        &map_unit_fn::OPTION_MAP_UNIT_FN,
 +        &map_unit_fn::RESULT_MAP_UNIT_FN,
 +        &match_on_vec_items::MATCH_ON_VEC_ITEMS,
 +        &matches::INFALLIBLE_DESTRUCTURING_MATCH,
 +        &matches::MATCH_AS_REF,
 +        &matches::MATCH_BOOL,
 +        &matches::MATCH_OVERLAPPING_ARM,
 +        &matches::MATCH_REF_PATS,
 +        &matches::MATCH_SINGLE_BINDING,
 +        &matches::MATCH_WILD_ERR_ARM,
 +        &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
 +        &matches::SINGLE_MATCH,
 +        &matches::SINGLE_MATCH_ELSE,
 +        &matches::WILDCARD_ENUM_MATCH_ARM,
 +        &matches::WILDCARD_IN_OR_PATTERNS,
 +        &mem_discriminant::MEM_DISCRIMINANT_NON_ENUM,
 +        &mem_forget::MEM_FORGET,
 +        &mem_replace::MEM_REPLACE_OPTION_WITH_NONE,
 +        &mem_replace::MEM_REPLACE_WITH_DEFAULT,
 +        &mem_replace::MEM_REPLACE_WITH_UNINIT,
 +        &methods::CHARS_LAST_CMP,
 +        &methods::CHARS_NEXT_CMP,
 +        &methods::CLONE_DOUBLE_REF,
 +        &methods::CLONE_ON_COPY,
 +        &methods::CLONE_ON_REF_PTR,
 +        &methods::EXPECT_FUN_CALL,
 +        &methods::FILETYPE_IS_FILE,
 +        &methods::FILTER_MAP,
 +        &methods::FILTER_MAP_NEXT,
 +        &methods::FILTER_NEXT,
 +        &methods::FIND_MAP,
 +        &methods::FLAT_MAP_IDENTITY,
 +        &methods::GET_UNWRAP,
 +        &methods::INEFFICIENT_TO_STRING,
 +        &methods::INTO_ITER_ON_REF,
 +        &methods::ITERATOR_STEP_BY_ZERO,
 +        &methods::ITER_CLONED_COLLECT,
 +        &methods::ITER_NTH,
 +        &methods::ITER_NTH_ZERO,
 +        &methods::ITER_SKIP_NEXT,
 +        &methods::MANUAL_SATURATING_ARITHMETIC,
 +        &methods::MAP_FLATTEN,
 +        &methods::NEW_RET_NO_SELF,
 +        &methods::OK_EXPECT,
 +        &methods::OPTION_AND_THEN_SOME,
 +        &methods::OPTION_AS_REF_DEREF,
 +        &methods::OPTION_EXPECT_USED,
 +        &methods::OPTION_MAP_OR_NONE,
 +        &methods::OPTION_MAP_UNWRAP_OR,
 +        &methods::OPTION_MAP_UNWRAP_OR_ELSE,
 +        &methods::OPTION_UNWRAP_USED,
 +        &methods::OR_FUN_CALL,
 +        &methods::RESULT_EXPECT_USED,
 +        &methods::RESULT_MAP_OR_INTO_OPTION,
 +        &methods::RESULT_MAP_UNWRAP_OR_ELSE,
 +        &methods::RESULT_UNWRAP_USED,
 +        &methods::SEARCH_IS_SOME,
 +        &methods::SHOULD_IMPLEMENT_TRAIT,
 +        &methods::SINGLE_CHAR_PATTERN,
 +        &methods::SKIP_WHILE_NEXT,
 +        &methods::STRING_EXTEND_CHARS,
 +        &methods::SUSPICIOUS_MAP,
 +        &methods::TEMPORARY_CSTRING_AS_PTR,
 +        &methods::UNINIT_ASSUMED_INIT,
 +        &methods::UNNECESSARY_FILTER_MAP,
 +        &methods::UNNECESSARY_FOLD,
 +        &methods::USELESS_ASREF,
 +        &methods::WRONG_PUB_SELF_CONVENTION,
 +        &methods::WRONG_SELF_CONVENTION,
 +        &methods::ZST_OFFSET,
 +        &minmax::MIN_MAX,
 +        &misc::CMP_NAN,
 +        &misc::CMP_OWNED,
 +        &misc::FLOAT_CMP,
 +        &misc::FLOAT_CMP_CONST,
 +        &misc::MODULO_ONE,
 +        &misc::SHORT_CIRCUIT_STATEMENT,
 +        &misc::TOPLEVEL_REF_ARG,
 +        &misc::USED_UNDERSCORE_BINDING,
 +        &misc::ZERO_PTR,
 +        &misc_early::BUILTIN_TYPE_SHADOW,
 +        &misc_early::DOUBLE_NEG,
 +        &misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
 +        &misc_early::MIXED_CASE_HEX_LITERALS,
 +        &misc_early::REDUNDANT_CLOSURE_CALL,
 +        &misc_early::REDUNDANT_PATTERN,
 +        &misc_early::UNNEEDED_FIELD_PATTERN,
 +        &misc_early::UNNEEDED_WILDCARD_PATTERN,
 +        &misc_early::UNSEPARATED_LITERAL_SUFFIX,
 +        &misc_early::ZERO_PREFIXED_LITERAL,
 +        &missing_const_for_fn::MISSING_CONST_FOR_FN,
 +        &missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
 +        &missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
 +        &modulo_arithmetic::MODULO_ARITHMETIC,
 +        &multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
 +        &mut_key::MUTABLE_KEY_TYPE,
 +        &mut_mut::MUT_MUT,
 +        &mut_reference::UNNECESSARY_MUT_PASSED,
 +        &mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL,
 +        &mutex_atomic::MUTEX_ATOMIC,
 +        &mutex_atomic::MUTEX_INTEGER,
 +        &needless_bool::BOOL_COMPARISON,
 +        &needless_bool::NEEDLESS_BOOL,
 +        &needless_borrow::NEEDLESS_BORROW,
 +        &needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
 +        &needless_continue::NEEDLESS_CONTINUE,
 +        &needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
 +        &needless_update::NEEDLESS_UPDATE,
 +        &neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD,
 +        &neg_multiply::NEG_MULTIPLY,
 +        &new_without_default::NEW_WITHOUT_DEFAULT,
 +        &no_effect::NO_EFFECT,
 +        &no_effect::UNNECESSARY_OPERATION,
 +        &non_copy_const::BORROW_INTERIOR_MUTABLE_CONST,
 +        &non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST,
 +        &non_expressive_names::JUST_UNDERSCORES_AND_DIGITS,
 +        &non_expressive_names::MANY_SINGLE_CHAR_NAMES,
 +        &non_expressive_names::SIMILAR_NAMES,
 +        &open_options::NONSENSICAL_OPEN_OPTIONS,
 +        &option_env_unwrap::OPTION_ENV_UNWRAP,
 +        &overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,
 +        &panic_unimplemented::PANIC,
 +        &panic_unimplemented::PANIC_PARAMS,
 +        &panic_unimplemented::TODO,
 +        &panic_unimplemented::UNIMPLEMENTED,
 +        &panic_unimplemented::UNREACHABLE,
 +        &partialeq_ne_impl::PARTIALEQ_NE_IMPL,
 +        &path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE,
 +        &precedence::PRECEDENCE,
 +        &ptr::CMP_NULL,
 +        &ptr::MUT_FROM_REF,
 +        &ptr::PTR_ARG,
 +        &ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
 +        &question_mark::QUESTION_MARK,
 +        &ranges::RANGE_MINUS_ONE,
 +        &ranges::RANGE_PLUS_ONE,
 +        &ranges::RANGE_ZIP_WITH_LEN,
 +        &redundant_clone::REDUNDANT_CLONE,
 +        &redundant_field_names::REDUNDANT_FIELD_NAMES,
 +        &redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING,
 +        &redundant_pub_crate::REDUNDANT_PUB_CRATE,
 +        &redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
 +        &reference::DEREF_ADDROF,
 +        &reference::REF_IN_DEREF,
 +        &regex::INVALID_REGEX,
 +        &regex::REGEX_MACRO,
 +        &regex::TRIVIAL_REGEX,
 +        &returns::LET_AND_RETURN,
 +        &returns::NEEDLESS_RETURN,
 +        &returns::UNUSED_UNIT,
 +        &serde_api::SERDE_API_MISUSE,
 +        &shadow::SHADOW_REUSE,
 +        &shadow::SHADOW_SAME,
 +        &shadow::SHADOW_UNRELATED,
 +        &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
 +        &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
 +        &strings::STRING_ADD,
 +        &strings::STRING_ADD_ASSIGN,
 +        &strings::STRING_LIT_AS_BYTES,
 +        &suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
 +        &suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
 +        &swap::ALMOST_SWAPPED,
 +        &swap::MANUAL_SWAP,
 +        &tabs_in_doc_comments::TABS_IN_DOC_COMMENTS,
 +        &temporary_assignment::TEMPORARY_ASSIGNMENT,
 +        &to_digit_is_some::TO_DIGIT_IS_SOME,
 +        &trait_bounds::TYPE_REPETITION_IN_BOUNDS,
 +        &transmute::CROSSPOINTER_TRANSMUTE,
 +        &transmute::TRANSMUTE_BYTES_TO_STR,
 +        &transmute::TRANSMUTE_FLOAT_TO_INT,
 +        &transmute::TRANSMUTE_INT_TO_BOOL,
 +        &transmute::TRANSMUTE_INT_TO_CHAR,
 +        &transmute::TRANSMUTE_INT_TO_FLOAT,
 +        &transmute::TRANSMUTE_PTR_TO_PTR,
 +        &transmute::TRANSMUTE_PTR_TO_REF,
 +        &transmute::UNSOUND_COLLECTION_TRANSMUTE,
 +        &transmute::USELESS_TRANSMUTE,
 +        &transmute::WRONG_TRANSMUTE,
 +        &transmuting_null::TRANSMUTING_NULL,
 +        &trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF,
 +        &try_err::TRY_ERR,
 +        &types::ABSURD_EXTREME_COMPARISONS,
 +        &types::BORROWED_BOX,
 +        &types::BOX_VEC,
 +        &types::CAST_LOSSLESS,
 +        &types::CAST_POSSIBLE_TRUNCATION,
 +        &types::CAST_POSSIBLE_WRAP,
 +        &types::CAST_PRECISION_LOSS,
 +        &types::CAST_PTR_ALIGNMENT,
 +        &types::CAST_REF_TO_MUT,
 +        &types::CAST_SIGN_LOSS,
 +        &types::CHAR_LIT_AS_U8,
 +        &types::FN_TO_NUMERIC_CAST,
 +        &types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
 +        &types::IMPLICIT_HASHER,
 +        &types::INVALID_UPCAST_COMPARISONS,
 +        &types::LET_UNIT_VALUE,
 +        &types::LINKEDLIST,
 +        &types::OPTION_OPTION,
 +        &types::REDUNDANT_ALLOCATION,
 +        &types::TYPE_COMPLEXITY,
 +        &types::UNIT_ARG,
 +        &types::UNIT_CMP,
 +        &types::UNNECESSARY_CAST,
 +        &types::VEC_BOX,
 +        &unicode::NON_ASCII_LITERAL,
 +        &unicode::UNICODE_NOT_NFC,
 +        &unicode::ZERO_WIDTH_SPACE,
 +        &unnamed_address::FN_ADDRESS_COMPARISONS,
 +        &unnamed_address::VTABLE_ADDRESS_COMPARISONS,
 +        &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
 +        &unused_io_amount::UNUSED_IO_AMOUNT,
 +        &unused_self::UNUSED_SELF,
 +        &unwrap::PANICKING_UNWRAP,
 +        &unwrap::UNNECESSARY_UNWRAP,
 +        &use_self::USE_SELF,
 +        &utils::internal_lints::CLIPPY_LINTS_INTERNAL,
 +        &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
 +        &utils::internal_lints::COMPILER_LINT_FUNCTIONS,
 +        &utils::internal_lints::DEFAULT_LINT,
 +        &utils::internal_lints::LINT_WITHOUT_LINT_PASS,
 +        &utils::internal_lints::OUTER_EXPN_EXPN_DATA,
 +        &utils::internal_lints::PRODUCE_ICE,
 +        &vec::USELESS_VEC,
 +        &verbose_file_reads::VERBOSE_FILE_READS,
 +        &wildcard_dependencies::WILDCARD_DEPENDENCIES,
 +        &wildcard_imports::ENUM_GLOB_USE,
 +        &wildcard_imports::WILDCARD_IMPORTS,
 +        &write::PRINTLN_EMPTY_STRING,
 +        &write::PRINT_LITERAL,
 +        &write::PRINT_STDOUT,
 +        &write::PRINT_WITH_NEWLINE,
 +        &write::USE_DEBUG,
 +        &write::WRITELN_EMPTY_STRING,
 +        &write::WRITE_LITERAL,
 +        &write::WRITE_WITH_NEWLINE,
 +        &zero_div_zero::ZERO_DIVIDED_BY_ZERO,
 +    ]);
 +    // end register lints, do not remove this comment, it’s used in `update_lints`
 +
 +    store.register_late_pass(|| box await_holding_lock::AwaitHoldingLock);
 +    store.register_late_pass(|| box serde_api::SerdeAPI);
 +    store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
 +    store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
 +    store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
 +    store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
 +    store.register_late_pass(|| box utils::author::Author);
 +    let vec_box_size_threshold = conf.vec_box_size_threshold;
 +    store.register_late_pass(move || box types::Types::new(vec_box_size_threshold));
 +    store.register_late_pass(|| box booleans::NonminimalBool);
 +    store.register_late_pass(|| box eq_op::EqOp);
 +    store.register_late_pass(|| box enum_clike::UnportableVariant);
 +    store.register_late_pass(|| box float_literal::FloatLiteral);
 +    let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
 +    store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold));
 +    store.register_late_pass(|| box ptr::Ptr);
 +    store.register_late_pass(|| box needless_bool::NeedlessBool);
 +    store.register_late_pass(|| box needless_bool::BoolComparison);
 +    store.register_late_pass(|| box approx_const::ApproxConstant);
 +    store.register_late_pass(|| box misc::MiscLints);
 +    store.register_late_pass(|| box eta_reduction::EtaReduction);
 +    store.register_late_pass(|| box identity_op::IdentityOp);
 +    store.register_late_pass(|| box erasing_op::ErasingOp);
 +    store.register_late_pass(|| box mut_mut::MutMut);
 +    store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed);
 +    store.register_late_pass(|| box len_zero::LenZero);
 +    store.register_late_pass(|| box attrs::Attributes);
 +    store.register_late_pass(|| box block_in_if_condition::BlockInIfCondition);
 +    store.register_late_pass(|| box unicode::Unicode);
 +    store.register_late_pass(|| box strings::StringAdd);
 +    store.register_late_pass(|| box implicit_return::ImplicitReturn);
 +    store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
 +    store.register_late_pass(|| box methods::Methods);
 +    store.register_late_pass(|| box map_clone::MapClone);
 +    store.register_late_pass(|| box shadow::Shadow);
 +    store.register_late_pass(|| box types::LetUnitValue);
 +    store.register_late_pass(|| box types::UnitCmp);
 +    store.register_late_pass(|| box loops::Loops);
 +    store.register_late_pass(|| box main_recursion::MainRecursion::default());
 +    store.register_late_pass(|| box lifetimes::Lifetimes);
 +    store.register_late_pass(|| box entry::HashMapPass);
 +    store.register_late_pass(|| box ranges::Ranges);
 +    store.register_late_pass(|| box types::Casts);
 +    let type_complexity_threshold = conf.type_complexity_threshold;
 +    store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
 +    store.register_late_pass(|| box matches::Matches::default());
 +    store.register_late_pass(|| box minmax::MinMaxPass);
 +    store.register_late_pass(|| box open_options::OpenOptions);
 +    store.register_late_pass(|| box zero_div_zero::ZeroDiv);
 +    store.register_late_pass(|| box mutex_atomic::Mutex);
 +    store.register_late_pass(|| box needless_update::NeedlessUpdate);
 +    store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default());
 +    store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef);
 +    store.register_late_pass(|| box no_effect::NoEffect);
 +    store.register_late_pass(|| box temporary_assignment::TemporaryAssignment);
 +    store.register_late_pass(|| box transmute::Transmute);
 +    let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
 +    store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold));
 +    let too_large_for_stack = conf.too_large_for_stack;
 +    store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack});
 +    store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented);
 +    store.register_late_pass(|| box strings::StringLitAsBytes);
 +    store.register_late_pass(|| box derive::Derive);
 +    store.register_late_pass(|| box types::CharLitAsU8);
 +    store.register_late_pass(|| box vec::UselessVec);
 +    store.register_late_pass(|| box drop_bounds::DropBounds);
 +    store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
 +    store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
 +    store.register_late_pass(|| box empty_enum::EmptyEnum);
 +    store.register_late_pass(|| box types::AbsurdExtremeComparisons);
 +    store.register_late_pass(|| box types::InvalidUpcastComparisons);
 +    store.register_late_pass(|| box regex::Regex::default());
 +    store.register_late_pass(|| box copies::CopyAndPaste);
 +    store.register_late_pass(|| box copy_iterator::CopyIterator);
 +    store.register_late_pass(|| box format::UselessFormat);
 +    store.register_late_pass(|| box swap::Swap);
 +    store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional);
 +    store.register_late_pass(|| box new_without_default::NewWithoutDefault::default());
 +    let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>();
 +    store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone()));
 +    let too_many_arguments_threshold1 = conf.too_many_arguments_threshold;
 +    let too_many_lines_threshold2 = conf.too_many_lines_threshold;
 +    store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold1, too_many_lines_threshold2));
 +    let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
 +    store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone()));
 +    store.register_late_pass(|| box neg_multiply::NegMultiply);
 +    store.register_late_pass(|| box mem_discriminant::MemDiscriminant);
 +    store.register_late_pass(|| box mem_forget::MemForget);
 +    store.register_late_pass(|| box mem_replace::MemReplace);
 +    store.register_late_pass(|| box arithmetic::Arithmetic::default());
 +    store.register_late_pass(|| box assign_ops::AssignOps);
 +    store.register_late_pass(|| box let_if_seq::LetIfSeq);
 +    store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence);
 +    store.register_late_pass(|| box missing_doc::MissingDoc::new());
 +    store.register_late_pass(|| box missing_inline::MissingInline);
 +    store.register_late_pass(|| box if_let_some_result::OkIfLet);
 +    store.register_late_pass(|| box redundant_pattern_matching::RedundantPatternMatching);
 +    store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl);
 +    store.register_late_pass(|| box unused_io_amount::UnusedIoAmount);
 +    let enum_variant_size_threshold = conf.enum_variant_size_threshold;
 +    store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold));
 +    store.register_late_pass(|| box explicit_write::ExplicitWrite);
 +    store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue);
 +    let trivially_copy_pass_by_ref = trivially_copy_pass_by_ref::TriviallyCopyPassByRef::new(
 +        conf.trivial_copy_size_limit,
 +        &sess.target,
 +    );
 +    store.register_late_pass(move || box trivially_copy_pass_by_ref);
 +    store.register_late_pass(|| box try_err::TryErr);
 +    store.register_late_pass(|| box use_self::UseSelf);
 +    store.register_late_pass(|| box bytecount::ByteCount);
 +    store.register_late_pass(|| box infinite_iter::InfiniteIter);
 +    store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
 +    store.register_late_pass(|| box identity_conversion::IdentityConversion::default());
 +    store.register_late_pass(|| box types::ImplicitHasher);
 +    store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
 +    store.register_late_pass(|| box types::UnitArg);
 +    store.register_late_pass(|| box double_comparison::DoubleComparisons);
 +    store.register_late_pass(|| box question_mark::QuestionMark);
 +    store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl);
 +    store.register_late_pass(|| box map_unit_fn::MapUnit);
 +    store.register_late_pass(|| box inherent_impl::MultipleInherentImpl::default());
 +    store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
 +    store.register_late_pass(|| box unwrap::Unwrap);
 +    store.register_late_pass(|| box duration_subsec::DurationSubsec);
 +    store.register_late_pass(|| box default_trait_access::DefaultTraitAccess);
 +    store.register_late_pass(|| box indexing_slicing::IndexingSlicing);
 +    store.register_late_pass(|| box non_copy_const::NonCopyConst);
 +    store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast);
 +    store.register_late_pass(|| box redundant_clone::RedundantClone);
 +    store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
 +    store.register_late_pass(|| box types::RefToMut);
 +    store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
 +    store.register_late_pass(|| box missing_const_for_fn::MissingConstForFn);
 +    store.register_late_pass(|| box transmuting_null::TransmutingNull);
 +    store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
 +    store.register_late_pass(|| box checked_conversions::CheckedConversions);
 +    store.register_late_pass(|| box integer_division::IntegerDivision);
 +    store.register_late_pass(|| box inherent_to_string::InherentToString);
 +    store.register_late_pass(|| box trait_bounds::TraitBounds);
 +    store.register_late_pass(|| box comparison_chain::ComparisonChain);
 +    store.register_late_pass(|| box mut_key::MutableKeyType);
 +    store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
 +    store.register_early_pass(|| box reference::DerefAddrOf);
 +    store.register_early_pass(|| box reference::RefInDeref);
 +    store.register_early_pass(|| box double_parens::DoubleParens);
 +    store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval);
 +    store.register_early_pass(|| box if_not_else::IfNotElse);
 +    store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse);
 +    store.register_early_pass(|| box int_plus_one::IntPlusOne);
 +    store.register_early_pass(|| box formatting::Formatting);
 +    store.register_early_pass(|| box misc_early::MiscEarlyLints);
 +    store.register_early_pass(|| box returns::Return);
 +    store.register_early_pass(|| box collapsible_if::CollapsibleIf);
 +    store.register_early_pass(|| box items_after_statements::ItemsAfterStatements);
 +    store.register_early_pass(|| box precedence::Precedence);
 +    store.register_early_pass(|| box needless_continue::NeedlessContinue);
 +    store.register_early_pass(|| box redundant_static_lifetimes::RedundantStaticLifetimes);
 +    store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata);
 +    store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
 +    store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
 +    store.register_early_pass(|| box literal_representation::LiteralDigitGrouping);
 +    let literal_representation_threshold = conf.literal_representation_threshold;
 +    store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
 +    store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
 +    let enum_variant_name_threshold = conf.enum_variant_name_threshold;
 +    store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
 +    store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
 +    store.register_late_pass(|| box unused_self::UnusedSelf);
 +    store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
 +    store.register_late_pass(|| box exit::Exit);
 +    store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
 +    let array_size_threshold = conf.array_size_threshold;
 +    store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
 +    store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold));
 +    store.register_late_pass(move || box floating_point_arithmetic::FloatingPointArithmetic);
 +    store.register_early_pass(|| box as_conversions::AsConversions);
 +    store.register_early_pass(|| box utils::internal_lints::ProduceIce);
 +    store.register_late_pass(|| box let_underscore::LetUnderscore);
 +    store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
 +    store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
 +    let max_fn_params_bools = conf.max_fn_params_bools;
 +    let max_struct_bools = conf.max_struct_bools;
 +    store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools));
 +    store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap);
-         LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
++    let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
++    store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports));
 +    store.register_early_pass(|| box macro_use::MacroUseImports);
 +    store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
 +    store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
 +    store.register_late_pass(|| box unnamed_address::UnnamedAddress);
 +    store.register_late_pass(|| box dereference::Dereferencing);
 +    store.register_late_pass(|| box future_not_send::FutureNotSend);
 +    store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
 +    store.register_late_pass(|| box if_let_mutex::IfLetMutex);
 +    store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
++    store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
++    store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
 +
 +    store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
 +        LintId::of(&arithmetic::FLOAT_ARITHMETIC),
 +        LintId::of(&arithmetic::INTEGER_ARITHMETIC),
 +        LintId::of(&as_conversions::AS_CONVERSIONS),
 +        LintId::of(&dbg_macro::DBG_MACRO),
 +        LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE),
 +        LintId::of(&exit::EXIT),
 +        LintId::of(&float_literal::LOSSY_FLOAT_LITERAL),
 +        LintId::of(&implicit_return::IMPLICIT_RETURN),
 +        LintId::of(&indexing_slicing::INDEXING_SLICING),
 +        LintId::of(&inherent_impl::MULTIPLE_INHERENT_IMPL),
 +        LintId::of(&integer_division::INTEGER_DIVISION),
 +        LintId::of(&let_underscore::LET_UNDERSCORE_MUST_USE),
 +        LintId::of(&literal_representation::DECIMAL_LITERAL_REPRESENTATION),
 +        LintId::of(&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS),
 +        LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM),
 +        LintId::of(&mem_forget::MEM_FORGET),
 +        LintId::of(&methods::CLONE_ON_REF_PTR),
 +        LintId::of(&methods::FILETYPE_IS_FILE),
 +        LintId::of(&methods::GET_UNWRAP),
 +        LintId::of(&methods::OPTION_EXPECT_USED),
 +        LintId::of(&methods::OPTION_UNWRAP_USED),
 +        LintId::of(&methods::RESULT_EXPECT_USED),
 +        LintId::of(&methods::RESULT_UNWRAP_USED),
 +        LintId::of(&methods::WRONG_PUB_SELF_CONVENTION),
 +        LintId::of(&misc::FLOAT_CMP_CONST),
 +        LintId::of(&misc_early::UNNEEDED_FIELD_PATTERN),
 +        LintId::of(&missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
 +        LintId::of(&missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
 +        LintId::of(&modulo_arithmetic::MODULO_ARITHMETIC),
 +        LintId::of(&panic_unimplemented::PANIC),
 +        LintId::of(&panic_unimplemented::TODO),
 +        LintId::of(&panic_unimplemented::UNIMPLEMENTED),
 +        LintId::of(&panic_unimplemented::UNREACHABLE),
 +        LintId::of(&shadow::SHADOW_REUSE),
 +        LintId::of(&shadow::SHADOW_SAME),
 +        LintId::of(&strings::STRING_ADD),
 +        LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
 +        LintId::of(&write::PRINT_STDOUT),
 +        LintId::of(&write::USE_DEBUG),
 +    ]);
 +
 +    store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
 +        LintId::of(&attrs::INLINE_ALWAYS),
 +        LintId::of(&await_holding_lock::AWAIT_HOLDING_LOCK),
 +        LintId::of(&checked_conversions::CHECKED_CONVERSIONS),
 +        LintId::of(&copies::MATCH_SAME_ARMS),
 +        LintId::of(&copies::SAME_FUNCTIONS_IN_IF_CONDITION),
 +        LintId::of(&copy_iterator::COPY_ITERATOR),
 +        LintId::of(&default_trait_access::DEFAULT_TRAIT_ACCESS),
 +        LintId::of(&dereference::EXPLICIT_DEREF_METHODS),
 +        LintId::of(&derive::EXPL_IMPL_CLONE_ON_COPY),
 +        LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE),
 +        LintId::of(&doc::DOC_MARKDOWN),
 +        LintId::of(&doc::MISSING_ERRORS_DOC),
 +        LintId::of(&empty_enum::EMPTY_ENUM),
 +        LintId::of(&enum_variants::MODULE_NAME_REPETITIONS),
 +        LintId::of(&enum_variants::PUB_ENUM_VARIANT_NAMES),
 +        LintId::of(&eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
 +        LintId::of(&excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
 +        LintId::of(&excessive_bools::STRUCT_EXCESSIVE_BOOLS),
 +        LintId::of(&functions::MUST_USE_CANDIDATE),
 +        LintId::of(&functions::TOO_MANY_LINES),
 +        LintId::of(&if_not_else::IF_NOT_ELSE),
 +        LintId::of(&implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
 +        LintId::of(&infinite_iter::MAYBE_INFINITE_ITER),
 +        LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS),
 +        LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS),
 +        LintId::of(&literal_representation::LARGE_DIGIT_GROUPS),
 +        LintId::of(&literal_representation::UNREADABLE_LITERAL),
 +        LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP),
 +        LintId::of(&loops::EXPLICIT_ITER_LOOP),
 +        LintId::of(&macro_use::MACRO_USE_IMPORTS),
++        LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
 +        LintId::of(&matches::MATCH_BOOL),
 +        LintId::of(&matches::SINGLE_MATCH_ELSE),
 +        LintId::of(&methods::FILTER_MAP),
 +        LintId::of(&methods::FILTER_MAP_NEXT),
 +        LintId::of(&methods::FIND_MAP),
 +        LintId::of(&methods::INEFFICIENT_TO_STRING),
 +        LintId::of(&methods::MAP_FLATTEN),
 +        LintId::of(&methods::OPTION_MAP_UNWRAP_OR),
 +        LintId::of(&methods::OPTION_MAP_UNWRAP_OR_ELSE),
 +        LintId::of(&methods::RESULT_MAP_UNWRAP_OR_ELSE),
 +        LintId::of(&misc::USED_UNDERSCORE_BINDING),
 +        LintId::of(&misc_early::UNSEPARATED_LITERAL_SUFFIX),
 +        LintId::of(&mut_mut::MUT_MUT),
 +        LintId::of(&needless_continue::NEEDLESS_CONTINUE),
 +        LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
 +        LintId::of(&non_expressive_names::SIMILAR_NAMES),
 +        LintId::of(&ranges::RANGE_PLUS_ONE),
 +        LintId::of(&shadow::SHADOW_UNRELATED),
 +        LintId::of(&strings::STRING_ADD_ASSIGN),
 +        LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS),
 +        LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF),
 +        LintId::of(&types::CAST_LOSSLESS),
 +        LintId::of(&types::CAST_POSSIBLE_TRUNCATION),
 +        LintId::of(&types::CAST_POSSIBLE_WRAP),
 +        LintId::of(&types::CAST_PRECISION_LOSS),
 +        LintId::of(&types::CAST_SIGN_LOSS),
 +        LintId::of(&types::IMPLICIT_HASHER),
 +        LintId::of(&types::INVALID_UPCAST_COMPARISONS),
 +        LintId::of(&types::LET_UNIT_VALUE),
 +        LintId::of(&types::LINKEDLIST),
 +        LintId::of(&types::OPTION_OPTION),
 +        LintId::of(&unicode::NON_ASCII_LITERAL),
 +        LintId::of(&unicode::UNICODE_NOT_NFC),
 +        LintId::of(&unused_self::UNUSED_SELF),
 +        LintId::of(&wildcard_imports::ENUM_GLOB_USE),
 +        LintId::of(&wildcard_imports::WILDCARD_IMPORTS),
 +    ]);
 +
 +    store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
 +        LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL),
 +        LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
 +        LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS),
 +        LintId::of(&utils::internal_lints::DEFAULT_LINT),
 +        LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS),
 +        LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA),
 +        LintId::of(&utils::internal_lints::PRODUCE_ICE),
 +    ]);
 +
 +    store.register_group(true, "clippy::all", Some("clippy"), vec![
 +        LintId::of(&approx_const::APPROX_CONSTANT),
 +        LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
 +        LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
 +        LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
 +        LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
 +        LintId::of(&attrs::DEPRECATED_CFG_ATTR),
 +        LintId::of(&attrs::DEPRECATED_SEMVER),
 +        LintId::of(&attrs::MISMATCHED_TARGET_OS),
 +        LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
 +        LintId::of(&attrs::USELESS_ATTRIBUTE),
 +        LintId::of(&bit_mask::BAD_BIT_MASK),
 +        LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
 +        LintId::of(&bit_mask::VERBOSE_BIT_MASK),
 +        LintId::of(&blacklisted_name::BLACKLISTED_NAME),
 +        LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR),
 +        LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT),
 +        LintId::of(&booleans::LOGIC_BUG),
 +        LintId::of(&booleans::NONMINIMAL_BOOL),
 +        LintId::of(&bytecount::NAIVE_BYTECOUNT),
 +        LintId::of(&collapsible_if::COLLAPSIBLE_IF),
 +        LintId::of(&comparison_chain::COMPARISON_CHAIN),
 +        LintId::of(&copies::IFS_SAME_COND),
 +        LintId::of(&copies::IF_SAME_THEN_ELSE),
 +        LintId::of(&derive::DERIVE_HASH_XOR_EQ),
 +        LintId::of(&doc::MISSING_SAFETY_DOC),
 +        LintId::of(&doc::NEEDLESS_DOCTEST_MAIN),
 +        LintId::of(&double_comparison::DOUBLE_COMPARISONS),
 +        LintId::of(&double_parens::DOUBLE_PARENS),
 +        LintId::of(&drop_bounds::DROP_BOUNDS),
 +        LintId::of(&drop_forget_ref::DROP_COPY),
 +        LintId::of(&drop_forget_ref::DROP_REF),
 +        LintId::of(&drop_forget_ref::FORGET_COPY),
 +        LintId::of(&drop_forget_ref::FORGET_REF),
 +        LintId::of(&duration_subsec::DURATION_SUBSEC),
 +        LintId::of(&entry::MAP_ENTRY),
 +        LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
 +        LintId::of(&enum_variants::ENUM_VARIANT_NAMES),
 +        LintId::of(&enum_variants::MODULE_INCEPTION),
 +        LintId::of(&eq_op::EQ_OP),
 +        LintId::of(&eq_op::OP_REF),
 +        LintId::of(&erasing_op::ERASING_OP),
 +        LintId::of(&escape::BOXED_LOCAL),
 +        LintId::of(&eta_reduction::REDUNDANT_CLOSURE),
 +        LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION),
 +        LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
 +        LintId::of(&explicit_write::EXPLICIT_WRITE),
 +        LintId::of(&float_literal::EXCESSIVE_PRECISION),
 +        LintId::of(&format::USELESS_FORMAT),
 +        LintId::of(&formatting::POSSIBLE_MISSING_COMMA),
 +        LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
 +        LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
 +        LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
 +        LintId::of(&functions::DOUBLE_MUST_USE),
 +        LintId::of(&functions::MUST_USE_UNIT),
 +        LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF),
 +        LintId::of(&functions::TOO_MANY_ARGUMENTS),
 +        LintId::of(&get_last_with_len::GET_LAST_WITH_LEN),
 +        LintId::of(&identity_conversion::IDENTITY_CONVERSION),
 +        LintId::of(&identity_op::IDENTITY_OP),
 +        LintId::of(&if_let_mutex::IF_LET_MUTEX),
 +        LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
 +        LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING),
 +        LintId::of(&infinite_iter::INFINITE_ITER),
 +        LintId::of(&inherent_to_string::INHERENT_TO_STRING),
 +        LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
 +        LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
 +        LintId::of(&int_plus_one::INT_PLUS_ONE),
 +        LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
 +        LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
 +        LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
 +        LintId::of(&len_zero::LEN_ZERO),
 +        LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
 +        LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
 +        LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
 +        LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
 +        LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
 +        LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
 +        LintId::of(&loops::EMPTY_LOOP),
 +        LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
 +        LintId::of(&loops::FOR_KV_MAP),
 +        LintId::of(&loops::FOR_LOOP_OVER_OPTION),
 +        LintId::of(&loops::FOR_LOOP_OVER_RESULT),
 +        LintId::of(&loops::ITER_NEXT_LOOP),
 +        LintId::of(&loops::MANUAL_MEMCPY),
 +        LintId::of(&loops::MUT_RANGE_BOUND),
 +        LintId::of(&loops::NEEDLESS_COLLECT),
 +        LintId::of(&loops::NEEDLESS_RANGE_LOOP),
 +        LintId::of(&loops::NEVER_LOOP),
 +        LintId::of(&loops::REVERSE_RANGE_LOOP),
 +        LintId::of(&loops::WHILE_IMMUTABLE_CONDITION),
 +        LintId::of(&loops::WHILE_LET_LOOP),
 +        LintId::of(&loops::WHILE_LET_ON_ITERATOR),
 +        LintId::of(&main_recursion::MAIN_RECURSION),
++        LintId::of(&manual_async_fn::MANUAL_ASYNC_FN),
++        LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
 +        LintId::of(&map_clone::MAP_CLONE),
 +        LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
 +        LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
-         LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
 +        LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
 +        LintId::of(&matches::MATCH_AS_REF),
 +        LintId::of(&matches::MATCH_OVERLAPPING_ARM),
 +        LintId::of(&matches::MATCH_REF_PATS),
 +        LintId::of(&matches::MATCH_SINGLE_BINDING),
 +        LintId::of(&matches::MATCH_WILD_ERR_ARM),
 +        LintId::of(&matches::SINGLE_MATCH),
 +        LintId::of(&matches::WILDCARD_IN_OR_PATTERNS),
 +        LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
 +        LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
 +        LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
 +        LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT),
 +        LintId::of(&methods::CHARS_LAST_CMP),
 +        LintId::of(&methods::CHARS_NEXT_CMP),
 +        LintId::of(&methods::CLONE_DOUBLE_REF),
 +        LintId::of(&methods::CLONE_ON_COPY),
 +        LintId::of(&methods::EXPECT_FUN_CALL),
 +        LintId::of(&methods::FILTER_NEXT),
 +        LintId::of(&methods::FLAT_MAP_IDENTITY),
 +        LintId::of(&methods::INTO_ITER_ON_REF),
 +        LintId::of(&methods::ITERATOR_STEP_BY_ZERO),
 +        LintId::of(&methods::ITER_CLONED_COLLECT),
 +        LintId::of(&methods::ITER_NTH),
 +        LintId::of(&methods::ITER_NTH_ZERO),
 +        LintId::of(&methods::ITER_SKIP_NEXT),
 +        LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
 +        LintId::of(&methods::NEW_RET_NO_SELF),
 +        LintId::of(&methods::OK_EXPECT),
 +        LintId::of(&methods::OPTION_AND_THEN_SOME),
 +        LintId::of(&methods::OPTION_AS_REF_DEREF),
 +        LintId::of(&methods::OPTION_MAP_OR_NONE),
 +        LintId::of(&methods::OR_FUN_CALL),
 +        LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION),
 +        LintId::of(&methods::SEARCH_IS_SOME),
 +        LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
 +        LintId::of(&methods::SINGLE_CHAR_PATTERN),
 +        LintId::of(&methods::SKIP_WHILE_NEXT),
 +        LintId::of(&methods::STRING_EXTEND_CHARS),
 +        LintId::of(&methods::SUSPICIOUS_MAP),
 +        LintId::of(&methods::TEMPORARY_CSTRING_AS_PTR),
 +        LintId::of(&methods::UNINIT_ASSUMED_INIT),
 +        LintId::of(&methods::UNNECESSARY_FILTER_MAP),
 +        LintId::of(&methods::UNNECESSARY_FOLD),
 +        LintId::of(&methods::USELESS_ASREF),
 +        LintId::of(&methods::WRONG_SELF_CONVENTION),
 +        LintId::of(&methods::ZST_OFFSET),
 +        LintId::of(&minmax::MIN_MAX),
 +        LintId::of(&misc::CMP_NAN),
 +        LintId::of(&misc::CMP_OWNED),
 +        LintId::of(&misc::FLOAT_CMP),
 +        LintId::of(&misc::MODULO_ONE),
 +        LintId::of(&misc::SHORT_CIRCUIT_STATEMENT),
 +        LintId::of(&misc::TOPLEVEL_REF_ARG),
 +        LintId::of(&misc::ZERO_PTR),
 +        LintId::of(&misc_early::BUILTIN_TYPE_SHADOW),
 +        LintId::of(&misc_early::DOUBLE_NEG),
 +        LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
 +        LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS),
 +        LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL),
 +        LintId::of(&misc_early::REDUNDANT_PATTERN),
 +        LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN),
 +        LintId::of(&misc_early::ZERO_PREFIXED_LITERAL),
 +        LintId::of(&mut_key::MUTABLE_KEY_TYPE),
 +        LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED),
 +        LintId::of(&mutex_atomic::MUTEX_ATOMIC),
 +        LintId::of(&needless_bool::BOOL_COMPARISON),
 +        LintId::of(&needless_bool::NEEDLESS_BOOL),
 +        LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
 +        LintId::of(&needless_update::NEEDLESS_UPDATE),
 +        LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
 +        LintId::of(&neg_multiply::NEG_MULTIPLY),
 +        LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT),
 +        LintId::of(&no_effect::NO_EFFECT),
 +        LintId::of(&no_effect::UNNECESSARY_OPERATION),
 +        LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
 +        LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
 +        LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
 +        LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES),
 +        LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS),
 +        LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP),
 +        LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
 +        LintId::of(&panic_unimplemented::PANIC_PARAMS),
 +        LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
 +        LintId::of(&precedence::PRECEDENCE),
 +        LintId::of(&ptr::CMP_NULL),
 +        LintId::of(&ptr::MUT_FROM_REF),
 +        LintId::of(&ptr::PTR_ARG),
 +        LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
 +        LintId::of(&question_mark::QUESTION_MARK),
 +        LintId::of(&ranges::RANGE_MINUS_ONE),
 +        LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
 +        LintId::of(&redundant_clone::REDUNDANT_CLONE),
 +        LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
 +        LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING),
 +        LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
 +        LintId::of(&reference::DEREF_ADDROF),
 +        LintId::of(&reference::REF_IN_DEREF),
 +        LintId::of(&regex::INVALID_REGEX),
 +        LintId::of(&regex::REGEX_MACRO),
 +        LintId::of(&regex::TRIVIAL_REGEX),
 +        LintId::of(&returns::LET_AND_RETURN),
 +        LintId::of(&returns::NEEDLESS_RETURN),
 +        LintId::of(&returns::UNUSED_UNIT),
 +        LintId::of(&serde_api::SERDE_API_MISUSE),
 +        LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
 +        LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
 +        LintId::of(&strings::STRING_LIT_AS_BYTES),
 +        LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
 +        LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
 +        LintId::of(&swap::ALMOST_SWAPPED),
 +        LintId::of(&swap::MANUAL_SWAP),
 +        LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
 +        LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT),
 +        LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
 +        LintId::of(&transmute::CROSSPOINTER_TRANSMUTE),
 +        LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR),
 +        LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT),
 +        LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL),
 +        LintId::of(&transmute::TRANSMUTE_INT_TO_CHAR),
 +        LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT),
 +        LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR),
 +        LintId::of(&transmute::TRANSMUTE_PTR_TO_REF),
 +        LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE),
 +        LintId::of(&transmute::WRONG_TRANSMUTE),
 +        LintId::of(&transmuting_null::TRANSMUTING_NULL),
 +        LintId::of(&try_err::TRY_ERR),
 +        LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
 +        LintId::of(&types::BORROWED_BOX),
 +        LintId::of(&types::BOX_VEC),
 +        LintId::of(&types::CAST_PTR_ALIGNMENT),
 +        LintId::of(&types::CAST_REF_TO_MUT),
 +        LintId::of(&types::CHAR_LIT_AS_U8),
 +        LintId::of(&types::FN_TO_NUMERIC_CAST),
 +        LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
 +        LintId::of(&types::REDUNDANT_ALLOCATION),
 +        LintId::of(&types::TYPE_COMPLEXITY),
 +        LintId::of(&types::UNIT_ARG),
 +        LintId::of(&types::UNIT_CMP),
 +        LintId::of(&types::UNNECESSARY_CAST),
 +        LintId::of(&types::VEC_BOX),
 +        LintId::of(&unicode::ZERO_WIDTH_SPACE),
 +        LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
 +        LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
 +        LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
 +        LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
 +        LintId::of(&unwrap::PANICKING_UNWRAP),
 +        LintId::of(&unwrap::UNNECESSARY_UNWRAP),
 +        LintId::of(&vec::USELESS_VEC),
 +        LintId::of(&write::PRINTLN_EMPTY_STRING),
 +        LintId::of(&write::PRINT_LITERAL),
 +        LintId::of(&write::PRINT_WITH_NEWLINE),
 +        LintId::of(&write::WRITELN_EMPTY_STRING),
 +        LintId::of(&write::WRITE_LITERAL),
 +        LintId::of(&write::WRITE_WITH_NEWLINE),
 +        LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO),
 +    ]);
 +
 +    store.register_group(true, "clippy::style", Some("clippy_style"), vec![
 +        LintId::of(&assertions_on_constants::ASSERTIONS_ON_CONSTANTS),
 +        LintId::of(&assign_ops::ASSIGN_OP_PATTERN),
 +        LintId::of(&attrs::UNKNOWN_CLIPPY_LINTS),
 +        LintId::of(&bit_mask::VERBOSE_BIT_MASK),
 +        LintId::of(&blacklisted_name::BLACKLISTED_NAME),
 +        LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_EXPR),
 +        LintId::of(&block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT),
 +        LintId::of(&collapsible_if::COLLAPSIBLE_IF),
 +        LintId::of(&comparison_chain::COMPARISON_CHAIN),
 +        LintId::of(&doc::MISSING_SAFETY_DOC),
 +        LintId::of(&doc::NEEDLESS_DOCTEST_MAIN),
 +        LintId::of(&enum_variants::ENUM_VARIANT_NAMES),
 +        LintId::of(&enum_variants::MODULE_INCEPTION),
 +        LintId::of(&eq_op::OP_REF),
 +        LintId::of(&eta_reduction::REDUNDANT_CLOSURE),
 +        LintId::of(&float_literal::EXCESSIVE_PRECISION),
 +        LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
 +        LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
 +        LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
 +        LintId::of(&functions::DOUBLE_MUST_USE),
 +        LintId::of(&functions::MUST_USE_UNIT),
 +        LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
 +        LintId::of(&inherent_to_string::INHERENT_TO_STRING),
 +        LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
 +        LintId::of(&len_zero::LEN_ZERO),
 +        LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
 +        LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
 +        LintId::of(&loops::EMPTY_LOOP),
 +        LintId::of(&loops::FOR_KV_MAP),
 +        LintId::of(&loops::NEEDLESS_RANGE_LOOP),
 +        LintId::of(&loops::WHILE_LET_ON_ITERATOR),
 +        LintId::of(&main_recursion::MAIN_RECURSION),
++        LintId::of(&manual_async_fn::MANUAL_ASYNC_FN),
++        LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
 +        LintId::of(&map_clone::MAP_CLONE),
 +        LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH),
 +        LintId::of(&matches::MATCH_OVERLAPPING_ARM),
 +        LintId::of(&matches::MATCH_REF_PATS),
 +        LintId::of(&matches::MATCH_WILD_ERR_ARM),
 +        LintId::of(&matches::SINGLE_MATCH),
 +        LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
 +        LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
 +        LintId::of(&methods::CHARS_LAST_CMP),
 +        LintId::of(&methods::CHARS_NEXT_CMP),
 +        LintId::of(&methods::INTO_ITER_ON_REF),
 +        LintId::of(&methods::ITER_CLONED_COLLECT),
 +        LintId::of(&methods::ITER_NTH_ZERO),
 +        LintId::of(&methods::ITER_SKIP_NEXT),
 +        LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
 +        LintId::of(&methods::NEW_RET_NO_SELF),
 +        LintId::of(&methods::OK_EXPECT),
 +        LintId::of(&methods::OPTION_MAP_OR_NONE),
 +        LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION),
 +        LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT),
 +        LintId::of(&methods::STRING_EXTEND_CHARS),
 +        LintId::of(&methods::UNNECESSARY_FOLD),
 +        LintId::of(&methods::WRONG_SELF_CONVENTION),
 +        LintId::of(&misc::TOPLEVEL_REF_ARG),
 +        LintId::of(&misc::ZERO_PTR),
 +        LintId::of(&misc_early::BUILTIN_TYPE_SHADOW),
 +        LintId::of(&misc_early::DOUBLE_NEG),
 +        LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
 +        LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS),
 +        LintId::of(&misc_early::REDUNDANT_PATTERN),
 +        LintId::of(&mut_reference::UNNECESSARY_MUT_PASSED),
 +        LintId::of(&neg_multiply::NEG_MULTIPLY),
 +        LintId::of(&new_without_default::NEW_WITHOUT_DEFAULT),
 +        LintId::of(&non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
 +        LintId::of(&non_expressive_names::MANY_SINGLE_CHAR_NAMES),
 +        LintId::of(&panic_unimplemented::PANIC_PARAMS),
 +        LintId::of(&ptr::CMP_NULL),
 +        LintId::of(&ptr::PTR_ARG),
 +        LintId::of(&question_mark::QUESTION_MARK),
 +        LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
 +        LintId::of(&redundant_pattern_matching::REDUNDANT_PATTERN_MATCHING),
 +        LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
 +        LintId::of(&regex::REGEX_MACRO),
 +        LintId::of(&regex::TRIVIAL_REGEX),
 +        LintId::of(&returns::LET_AND_RETURN),
 +        LintId::of(&returns::NEEDLESS_RETURN),
 +        LintId::of(&returns::UNUSED_UNIT),
 +        LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
 +        LintId::of(&strings::STRING_LIT_AS_BYTES),
 +        LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
 +        LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
 +        LintId::of(&try_err::TRY_ERR),
 +        LintId::of(&types::FN_TO_NUMERIC_CAST),
 +        LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION),
 +        LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
 +        LintId::of(&write::PRINTLN_EMPTY_STRING),
 +        LintId::of(&write::PRINT_LITERAL),
 +        LintId::of(&write::PRINT_WITH_NEWLINE),
 +        LintId::of(&write::WRITELN_EMPTY_STRING),
 +        LintId::of(&write::WRITE_LITERAL),
 +        LintId::of(&write::WRITE_WITH_NEWLINE),
 +    ]);
 +
 +    store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![
 +        LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP),
 +        LintId::of(&attrs::DEPRECATED_CFG_ATTR),
 +        LintId::of(&booleans::NONMINIMAL_BOOL),
 +        LintId::of(&double_comparison::DOUBLE_COMPARISONS),
 +        LintId::of(&double_parens::DOUBLE_PARENS),
 +        LintId::of(&duration_subsec::DURATION_SUBSEC),
 +        LintId::of(&eval_order_dependence::DIVERGING_SUB_EXPRESSION),
 +        LintId::of(&eval_order_dependence::EVAL_ORDER_DEPENDENCE),
 +        LintId::of(&explicit_write::EXPLICIT_WRITE),
 +        LintId::of(&format::USELESS_FORMAT),
 +        LintId::of(&functions::TOO_MANY_ARGUMENTS),
 +        LintId::of(&get_last_with_len::GET_LAST_WITH_LEN),
 +        LintId::of(&identity_conversion::IDENTITY_CONVERSION),
 +        LintId::of(&identity_op::IDENTITY_OP),
 +        LintId::of(&int_plus_one::INT_PLUS_ONE),
 +        LintId::of(&lifetimes::EXTRA_UNUSED_LIFETIMES),
 +        LintId::of(&lifetimes::NEEDLESS_LIFETIMES),
 +        LintId::of(&loops::EXPLICIT_COUNTER_LOOP),
 +        LintId::of(&loops::MUT_RANGE_BOUND),
 +        LintId::of(&loops::WHILE_LET_LOOP),
 +        LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN),
 +        LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN),
 +        LintId::of(&matches::MATCH_AS_REF),
 +        LintId::of(&matches::MATCH_SINGLE_BINDING),
 +        LintId::of(&matches::WILDCARD_IN_OR_PATTERNS),
 +        LintId::of(&methods::CLONE_ON_COPY),
 +        LintId::of(&methods::FILTER_NEXT),
 +        LintId::of(&methods::FLAT_MAP_IDENTITY),
 +        LintId::of(&methods::OPTION_AND_THEN_SOME),
 +        LintId::of(&methods::OPTION_AS_REF_DEREF),
 +        LintId::of(&methods::SEARCH_IS_SOME),
 +        LintId::of(&methods::SKIP_WHILE_NEXT),
 +        LintId::of(&methods::SUSPICIOUS_MAP),
 +        LintId::of(&methods::UNNECESSARY_FILTER_MAP),
 +        LintId::of(&methods::USELESS_ASREF),
 +        LintId::of(&misc::SHORT_CIRCUIT_STATEMENT),
 +        LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL),
 +        LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN),
 +        LintId::of(&misc_early::ZERO_PREFIXED_LITERAL),
 +        LintId::of(&needless_bool::BOOL_COMPARISON),
 +        LintId::of(&needless_bool::NEEDLESS_BOOL),
 +        LintId::of(&needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
 +        LintId::of(&needless_update::NEEDLESS_UPDATE),
 +        LintId::of(&neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
 +        LintId::of(&no_effect::NO_EFFECT),
 +        LintId::of(&no_effect::UNNECESSARY_OPERATION),
 +        LintId::of(&overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
 +        LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
 +        LintId::of(&precedence::PRECEDENCE),
 +        LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
 +        LintId::of(&ranges::RANGE_MINUS_ONE),
 +        LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
 +        LintId::of(&reference::DEREF_ADDROF),
 +        LintId::of(&reference::REF_IN_DEREF),
 +        LintId::of(&swap::MANUAL_SWAP),
 +        LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT),
 +        LintId::of(&transmute::CROSSPOINTER_TRANSMUTE),
 +        LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR),
 +        LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT),
 +        LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL),
 +        LintId::of(&transmute::TRANSMUTE_INT_TO_CHAR),
 +        LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT),
 +        LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR),
 +        LintId::of(&transmute::TRANSMUTE_PTR_TO_REF),
 +        LintId::of(&types::BORROWED_BOX),
 +        LintId::of(&types::CHAR_LIT_AS_U8),
 +        LintId::of(&types::TYPE_COMPLEXITY),
 +        LintId::of(&types::UNIT_ARG),
 +        LintId::of(&types::UNNECESSARY_CAST),
 +        LintId::of(&types::VEC_BOX),
 +        LintId::of(&unwrap::UNNECESSARY_UNWRAP),
 +        LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO),
 +    ]);
 +
 +    store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![
 +        LintId::of(&approx_const::APPROX_CONSTANT),
 +        LintId::of(&atomic_ordering::INVALID_ATOMIC_ORDERING),
 +        LintId::of(&attrs::DEPRECATED_SEMVER),
 +        LintId::of(&attrs::MISMATCHED_TARGET_OS),
 +        LintId::of(&attrs::USELESS_ATTRIBUTE),
 +        LintId::of(&bit_mask::BAD_BIT_MASK),
 +        LintId::of(&bit_mask::INEFFECTIVE_BIT_MASK),
 +        LintId::of(&booleans::LOGIC_BUG),
 +        LintId::of(&copies::IFS_SAME_COND),
 +        LintId::of(&copies::IF_SAME_THEN_ELSE),
 +        LintId::of(&derive::DERIVE_HASH_XOR_EQ),
 +        LintId::of(&drop_bounds::DROP_BOUNDS),
 +        LintId::of(&drop_forget_ref::DROP_COPY),
 +        LintId::of(&drop_forget_ref::DROP_REF),
 +        LintId::of(&drop_forget_ref::FORGET_COPY),
 +        LintId::of(&drop_forget_ref::FORGET_REF),
 +        LintId::of(&enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
 +        LintId::of(&eq_op::EQ_OP),
 +        LintId::of(&erasing_op::ERASING_OP),
 +        LintId::of(&formatting::POSSIBLE_MISSING_COMMA),
 +        LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF),
 +        LintId::of(&if_let_mutex::IF_LET_MUTEX),
 +        LintId::of(&indexing_slicing::OUT_OF_BOUNDS_INDEXING),
 +        LintId::of(&infinite_iter::INFINITE_ITER),
 +        LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
 +        LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
 +        LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
 +        LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES),
 +        LintId::of(&loops::FOR_LOOP_OVER_OPTION),
 +        LintId::of(&loops::FOR_LOOP_OVER_RESULT),
 +        LintId::of(&loops::ITER_NEXT_LOOP),
 +        LintId::of(&loops::NEVER_LOOP),
 +        LintId::of(&loops::REVERSE_RANGE_LOOP),
 +        LintId::of(&loops::WHILE_IMMUTABLE_CONDITION),
 +        LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM),
 +        LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT),
 +        LintId::of(&methods::CLONE_DOUBLE_REF),
 +        LintId::of(&methods::ITERATOR_STEP_BY_ZERO),
 +        LintId::of(&methods::TEMPORARY_CSTRING_AS_PTR),
 +        LintId::of(&methods::UNINIT_ASSUMED_INIT),
 +        LintId::of(&methods::ZST_OFFSET),
 +        LintId::of(&minmax::MIN_MAX),
 +        LintId::of(&misc::CMP_NAN),
 +        LintId::of(&misc::FLOAT_CMP),
 +        LintId::of(&misc::MODULO_ONE),
 +        LintId::of(&mut_key::MUTABLE_KEY_TYPE),
 +        LintId::of(&non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
 +        LintId::of(&non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
 +        LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS),
 +        LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP),
 +        LintId::of(&ptr::MUT_FROM_REF),
 +        LintId::of(&regex::INVALID_REGEX),
 +        LintId::of(&serde_api::SERDE_API_MISUSE),
 +        LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
 +        LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
 +        LintId::of(&swap::ALMOST_SWAPPED),
 +        LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE),
 +        LintId::of(&transmute::WRONG_TRANSMUTE),
 +        LintId::of(&transmuting_null::TRANSMUTING_NULL),
 +        LintId::of(&types::ABSURD_EXTREME_COMPARISONS),
 +        LintId::of(&types::CAST_PTR_ALIGNMENT),
 +        LintId::of(&types::CAST_REF_TO_MUT),
 +        LintId::of(&types::UNIT_CMP),
 +        LintId::of(&unicode::ZERO_WIDTH_SPACE),
 +        LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
 +        LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
 +        LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
 +        LintId::of(&unwrap::PANICKING_UNWRAP),
 +    ]);
 +
 +    store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
 +        LintId::of(&bytecount::NAIVE_BYTECOUNT),
 +        LintId::of(&entry::MAP_ENTRY),
 +        LintId::of(&escape::BOXED_LOCAL),
 +        LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
 +        LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
 +        LintId::of(&loops::MANUAL_MEMCPY),
 +        LintId::of(&loops::NEEDLESS_COLLECT),
 +        LintId::of(&methods::EXPECT_FUN_CALL),
 +        LintId::of(&methods::ITER_NTH),
 +        LintId::of(&methods::OR_FUN_CALL),
 +        LintId::of(&methods::SINGLE_CHAR_PATTERN),
 +        LintId::of(&misc::CMP_OWNED),
 +        LintId::of(&mutex_atomic::MUTEX_ATOMIC),
 +        LintId::of(&redundant_clone::REDUNDANT_CLONE),
 +        LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
 +        LintId::of(&types::BOX_VEC),
 +        LintId::of(&types::REDUNDANT_ALLOCATION),
 +        LintId::of(&vec::USELESS_VEC),
 +    ]);
 +
 +    store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![
 +        LintId::of(&cargo_common_metadata::CARGO_COMMON_METADATA),
 +        LintId::of(&multiple_crate_versions::MULTIPLE_CRATE_VERSIONS),
 +        LintId::of(&wildcard_dependencies::WILDCARD_DEPENDENCIES),
 +    ]);
 +
 +    store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
 +        LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
 +        LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
 +        LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
 +        LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
 +        LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
 +        LintId::of(&future_not_send::FUTURE_NOT_SEND),
 +        LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN),
 +        LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
 +        LintId::of(&mutex_atomic::MUTEX_INTEGER),
 +        LintId::of(&needless_borrow::NEEDLESS_BORROW),
 +        LintId::of(&path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
 +        LintId::of(&redundant_pub_crate::REDUNDANT_PUB_CRATE),
 +        LintId::of(&transmute::USELESS_TRANSMUTE),
 +        LintId::of(&use_self::USE_SELF),
 +    ]);
 +}
 +
 +#[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(
 +        "str_to_string",
 +        "using `str::to_string` is common even today and specialization will likely happen soon",
 +    );
 +    store.register_removed(
 +        "string_to_string",
 +        "using `string::to_string` is common even today and specialization will likely happen soon",
 +    );
 +    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",
 +    );
 +}
 +
 +/// Register renamed lints.
 +///
 +/// Used in `./src/driver.rs`.
 +pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
 +    ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions");
 +    ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default");
 +    ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity");
 +    ls.register_renamed("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes");
 +}
 +
 +// 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 f7c7fd82d833b6c71a93c7b3b97fc854d93f9af7,0000000000000000000000000000000000000000..2bbf4dba614b41970f846d8175d995a06fca8ba6
mode 100644,000000..100644
--- /dev/null
@@@ -1,2550 -1,0 +1,2541 @@@
- use itertools::Itertools;
 +use crate::consts::{constant, Constant};
 +use crate::reexport::Name;
 +use crate::utils::paths;
 +use crate::utils::usage::{is_unused, mutated_variables};
 +use crate::utils::{
 +    get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
 +    is_integer_const, is_no_std_crate, is_refutable, last_path_segment, match_trait_method, match_type, match_var,
 +    multispan_sugg, snippet, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help,
 +    span_lint_and_sugg, span_lint_and_then, SpanlessEq,
 +};
 +use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg};
 +use if_chain::if_chain;
-         if let ExprKind::Path(ref qpath) = expr.kind;
-         if let QPath::Resolved(None, ref path) = *qpath;
 +use rustc_ast::ast;
 +use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 +use rustc_errors::Applicability;
 +use rustc_hir::def::{DefKind, Res};
 +use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
 +use rustc_hir::{
 +    def_id, BinOpKind, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, GenericArg, HirId, LoopSource,
 +    MatchSource, Mutability, Node, Pat, PatKind, QPath, Stmt, StmtKind,
 +};
 +use rustc_infer::infer::TyCtxtInferExt;
 +use rustc_lint::{LateContext, LateLintPass, LintContext};
 +use rustc_middle::hir::map::Map;
 +use rustc_middle::lint::in_external_macro;
 +use rustc_middle::middle::region;
 +use rustc_middle::ty::{self, Ty};
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::source_map::Span;
 +use rustc_span::BytePos;
 +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase};
 +use std::iter::{once, Iterator};
 +use std::mem;
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for for-loops that manually copy items between
 +    /// slices that could be optimized by having a memcpy.
 +    ///
 +    /// **Why is this bad?** It is not as fast as a memcpy.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let src = vec![1];
 +    /// # let mut dst = vec![0; 65];
 +    /// for i in 0..src.len() {
 +    ///     dst[i + 64] = src[i];
 +    /// }
 +    /// ```
 +    /// Could be written as:
 +    /// ```rust
 +    /// # let src = vec![1];
 +    /// # let mut dst = vec![0; 65];
 +    /// dst[64..(src.len() + 64)].clone_from_slice(&src[..]);
 +    /// ```
 +    pub MANUAL_MEMCPY,
 +    perf,
 +    "manually copying items between slices"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for looping over the range of `0..len` of some
 +    /// collection just to get the values by index.
 +    ///
 +    /// **Why is this bad?** Just iterating the collection itself makes the intent
 +    /// more clear and is probably faster.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// let vec = vec!['a', 'b', 'c'];
 +    /// for i in 0..vec.len() {
 +    ///     println!("{}", vec[i]);
 +    /// }
 +    /// ```
 +    /// Could be written as:
 +    /// ```rust
 +    /// let vec = vec!['a', 'b', 'c'];
 +    /// for i in vec {
 +    ///     println!("{}", i);
 +    /// }
 +    /// ```
 +    pub NEEDLESS_RANGE_LOOP,
 +    style,
 +    "for-looping over a range of indices where an iterator over items would do"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for loops on `x.iter()` where `&x` will do, and
 +    /// suggests the latter.
 +    ///
 +    /// **Why is this bad?** Readability.
 +    ///
 +    /// **Known problems:** False negatives. We currently only warn on some known
 +    /// types.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// // with `y` a `Vec` or slice:
 +    /// # let y = vec![1];
 +    /// for x in y.iter() {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    /// can be rewritten to
 +    /// ```rust
 +    /// # let y = vec![1];
 +    /// for x in &y {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    pub EXPLICIT_ITER_LOOP,
 +    pedantic,
 +    "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for loops on `y.into_iter()` where `y` will do, and
 +    /// suggests the latter.
 +    ///
 +    /// **Why is this bad?** Readability.
 +    ///
 +    /// **Known problems:** None
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let y = vec![1];
 +    /// // with `y` a `Vec` or slice:
 +    /// for x in y.into_iter() {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    /// can be rewritten to
 +    /// ```rust
 +    /// # let y = vec![1];
 +    /// for x in y {
 +    ///     // ..
 +    /// }
 +    /// ```
 +    pub EXPLICIT_INTO_ITER_LOOP,
 +    pedantic,
 +    "for-looping over `_.into_iter()` when `_` would do"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for loops on `x.next()`.
 +    ///
 +    /// **Why is this bad?** `next()` returns either `Some(value)` if there was a
 +    /// value, or `None` otherwise. The insidious thing is that `Option<_>`
 +    /// implements `IntoIterator`, so that possibly one value will be iterated,
 +    /// leading to some hard to find bugs. No one will want to write such code
 +    /// [except to win an Underhanded Rust
 +    /// Contest](https://www.reddit.com/r/rust/comments/3hb0wm/underhanded_rust_contest/cu5yuhr).
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```ignore
 +    /// for x in y.next() {
 +    ///     ..
 +    /// }
 +    /// ```
 +    pub ITER_NEXT_LOOP,
 +    correctness,
 +    "for-looping over `_.next()` which is probably not intended"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for `for` loops over `Option` values.
 +    ///
 +    /// **Why is this bad?** Readability. This is more clearly expressed as an `if
 +    /// let`.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```ignore
 +    /// for x in option {
 +    ///     ..
 +    /// }
 +    /// ```
 +    ///
 +    /// This should be
 +    /// ```ignore
 +    /// if let Some(x) = option {
 +    ///     ..
 +    /// }
 +    /// ```
 +    pub FOR_LOOP_OVER_OPTION,
 +    correctness,
 +    "for-looping over an `Option`, which is more clearly expressed as an `if let`"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for `for` loops over `Result` values.
 +    ///
 +    /// **Why is this bad?** Readability. This is more clearly expressed as an `if
 +    /// let`.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```ignore
 +    /// for x in result {
 +    ///     ..
 +    /// }
 +    /// ```
 +    ///
 +    /// This should be
 +    /// ```ignore
 +    /// if let Ok(x) = result {
 +    ///     ..
 +    /// }
 +    /// ```
 +    pub FOR_LOOP_OVER_RESULT,
 +    correctness,
 +    "for-looping over a `Result`, which is more clearly expressed as an `if let`"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Detects `loop + match` combinations that are easier
 +    /// written as a `while let` loop.
 +    ///
 +    /// **Why is this bad?** The `while let` loop is usually shorter and more
 +    /// readable.
 +    ///
 +    /// **Known problems:** Sometimes the wrong binding is displayed (#383).
 +    ///
 +    /// **Example:**
 +    /// ```rust,no_run
 +    /// # let y = Some(1);
 +    /// loop {
 +    ///     let x = match y {
 +    ///         Some(x) => x,
 +    ///         None => break,
 +    ///     };
 +    ///     // .. do something with x
 +    /// }
 +    /// // is easier written as
 +    /// while let Some(x) = y {
 +    ///     // .. do something with x
 +    /// };
 +    /// ```
 +    pub WHILE_LET_LOOP,
 +    complexity,
 +    "`loop { if let { ... } else break }`, which can be written as a `while let` loop"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for functions collecting an iterator when collect
 +    /// is not needed.
 +    ///
 +    /// **Why is this bad?** `collect` causes the allocation of a new data structure,
 +    /// when this allocation may not be needed.
 +    ///
 +    /// **Known problems:**
 +    /// None
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let iterator = vec![1].into_iter();
 +    /// let len = iterator.clone().collect::<Vec<_>>().len();
 +    /// // should be
 +    /// let len = iterator.count();
 +    /// ```
 +    pub NEEDLESS_COLLECT,
 +    perf,
 +    "collecting an iterator when collect is not needed"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for loops over ranges `x..y` where both `x` and `y`
 +    /// are constant and `x` is greater or equal to `y`, unless the range is
 +    /// reversed or has a negative `.step_by(_)`.
 +    ///
 +    /// **Why is it bad?** Such loops will either be skipped or loop until
 +    /// wrap-around (in debug code, this may `panic!()`). Both options are probably
 +    /// not intended.
 +    ///
 +    /// **Known problems:** The lint cannot catch loops over dynamically defined
 +    /// ranges. Doing this would require simulating all possible inputs and code
 +    /// paths through the program, which would be complex and error-prone.
 +    ///
 +    /// **Example:**
 +    /// ```ignore
 +    /// for x in 5..10 - 5 {
 +    ///     ..
 +    /// } // oops, stray `-`
 +    /// ```
 +    pub REVERSE_RANGE_LOOP,
 +    correctness,
 +    "iteration over an empty range, such as `10..0` or `5..5`"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks `for` loops over slices with an explicit counter
 +    /// and suggests the use of `.enumerate()`.
 +    ///
 +    /// **Why is it bad?** Using `.enumerate()` makes the intent more clear,
 +    /// declutters the code and may be faster in some instances.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let v = vec![1];
 +    /// # fn bar(bar: usize, baz: usize) {}
 +    /// let mut i = 0;
 +    /// for item in &v {
 +    ///     bar(i, *item);
 +    ///     i += 1;
 +    /// }
 +    /// ```
 +    /// Could be written as
 +    /// ```rust
 +    /// # let v = vec![1];
 +    /// # fn bar(bar: usize, baz: usize) {}
 +    /// for (i, item) in v.iter().enumerate() { bar(i, *item); }
 +    /// ```
 +    pub EXPLICIT_COUNTER_LOOP,
 +    complexity,
 +    "for-looping with an explicit counter when `_.enumerate()` would do"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for empty `loop` expressions.
 +    ///
 +    /// **Why is this bad?** Those busy loops burn CPU cycles without doing
 +    /// anything. Think of the environment and either block on something or at least
 +    /// make the thread sleep for some microseconds.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```no_run
 +    /// loop {}
 +    /// ```
 +    pub EMPTY_LOOP,
 +    style,
 +    "empty `loop {}`, which should block or sleep"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for `while let` expressions on iterators.
 +    ///
 +    /// **Why is this bad?** Readability. A simple `for` loop is shorter and conveys
 +    /// the intent better.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```ignore
 +    /// while let Some(val) = iter() {
 +    ///     ..
 +    /// }
 +    /// ```
 +    pub WHILE_LET_ON_ITERATOR,
 +    style,
 +    "using a while-let loop instead of a for loop on an iterator"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for iterating a map (`HashMap` or `BTreeMap`) and
 +    /// ignoring either the keys or values.
 +    ///
 +    /// **Why is this bad?** Readability. There are `keys` and `values` methods that
 +    /// can be used to express that don't need the values or keys.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```ignore
 +    /// for (k, _) in &map {
 +    ///     ..
 +    /// }
 +    /// ```
 +    ///
 +    /// could be replaced by
 +    ///
 +    /// ```ignore
 +    /// for k in map.keys() {
 +    ///     ..
 +    /// }
 +    /// ```
 +    pub FOR_KV_MAP,
 +    style,
 +    "looping on a map using `iter` when `keys` or `values` would do"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for loops that will always `break`, `return` or
 +    /// `continue` an outer loop.
 +    ///
 +    /// **Why is this bad?** This loop never loops, all it does is obfuscating the
 +    /// code.
 +    ///
 +    /// **Known problems:** None
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// loop {
 +    ///     ..;
 +    ///     break;
 +    /// }
 +    /// ```
 +    pub NEVER_LOOP,
 +    correctness,
 +    "any loop that will always `break` or `return`"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for loops which have a range bound that is a mutable variable
 +    ///
 +    /// **Why is this bad?** One might think that modifying the mutable variable changes the loop bounds
 +    ///
 +    /// **Known problems:** None
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// let mut foo = 42;
 +    /// for i in 0..foo {
 +    ///     foo -= 1;
 +    ///     println!("{}", i); // prints numbers from 0 to 42, not 0 to 21
 +    /// }
 +    /// ```
 +    pub MUT_RANGE_BOUND,
 +    complexity,
 +    "for loop over a range where one of the bounds is a mutable variable"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks whether variables used within while loop condition
 +    /// can be (and are) mutated in the body.
 +    ///
 +    /// **Why is this bad?** If the condition is unchanged, entering the body of the loop
 +    /// will lead to an infinite loop.
 +    ///
 +    /// **Known problems:** If the `while`-loop is in a closure, the check for mutation of the
 +    /// condition variables in the body can cause false negatives. For example when only `Upvar` `a` is
 +    /// in the condition and only `Upvar` `b` gets mutated in the body, the lint will not trigger.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// let i = 0;
 +    /// while i > 10 {
 +    ///     println!("let me loop forever!");
 +    /// }
 +    /// ```
 +    pub WHILE_IMMUTABLE_CONDITION,
 +    correctness,
 +    "variables used within while expression are not mutated in the body"
 +}
 +
 +declare_lint_pass!(Loops => [
 +    MANUAL_MEMCPY,
 +    NEEDLESS_RANGE_LOOP,
 +    EXPLICIT_ITER_LOOP,
 +    EXPLICIT_INTO_ITER_LOOP,
 +    ITER_NEXT_LOOP,
 +    FOR_LOOP_OVER_RESULT,
 +    FOR_LOOP_OVER_OPTION,
 +    WHILE_LET_LOOP,
 +    NEEDLESS_COLLECT,
 +    REVERSE_RANGE_LOOP,
 +    EXPLICIT_COUNTER_LOOP,
 +    EMPTY_LOOP,
 +    WHILE_LET_ON_ITERATOR,
 +    FOR_KV_MAP,
 +    NEVER_LOOP,
 +    MUT_RANGE_BOUND,
 +    WHILE_IMMUTABLE_CONDITION,
 +]);
 +
 +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
 +    #[allow(clippy::too_many_lines)]
 +    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
 +        if let Some((pat, arg, body)) = higher::for_loop(expr) {
 +            // we don't want to check expanded macros
 +            // this check is not at the top of the function
 +            // since higher::for_loop expressions are marked as expansions
 +            if body.span.from_expansion() {
 +                return;
 +            }
 +            check_for_loop(cx, pat, arg, body, expr);
 +        }
 +
 +        // we don't want to check expanded macros
 +        if expr.span.from_expansion() {
 +            return;
 +        }
 +
 +        // check for never_loop
 +        if let ExprKind::Loop(ref block, _, _) = expr.kind {
 +            match never_loop_block(block, expr.hir_id) {
 +                NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
 +                NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
 +            }
 +        }
 +
 +        // check for `loop { if let {} else break }` that could be `while let`
 +        // (also matches an explicit "match" instead of "if let")
 +        // (even if the "match" or "if let" is used for declaration)
 +        if let ExprKind::Loop(ref block, _, LoopSource::Loop) = expr.kind {
 +            // also check for empty `loop {}` statements
 +            if block.stmts.is_empty() && block.expr.is_none() && !is_no_std_crate(cx.tcx.hir().krate()) {
 +                span_lint(
 +                    cx,
 +                    EMPTY_LOOP,
 +                    expr.span,
 +                    "empty `loop {}` detected. You may want to either use `panic!()` or add \
 +                     `std::thread::sleep(..);` to the loop body.",
 +                );
 +            }
 +
 +            // extract the expression from the first statement (if any) in a block
 +            let inner_stmt_expr = extract_expr_from_first_stmt(block);
 +            // or extract the first expression (if any) from the block
 +            if let Some(inner) = inner_stmt_expr.or_else(|| extract_first_expr(block)) {
 +                if let ExprKind::Match(ref matchexpr, ref arms, ref source) = inner.kind {
 +                    // ensure "if let" compatible match structure
 +                    match *source {
 +                        MatchSource::Normal | MatchSource::IfLetDesugar { .. } => {
 +                            if arms.len() == 2
 +                                && arms[0].guard.is_none()
 +                                && arms[1].guard.is_none()
 +                                && is_simple_break_expr(&arms[1].body)
 +                            {
 +                                if in_external_macro(cx.sess(), expr.span) {
 +                                    return;
 +                                }
 +
 +                                // NOTE: we used to build a body here instead of using
 +                                // ellipsis, this was removed because:
 +                                // 1) it was ugly with big bodies;
 +                                // 2) it was not indented properly;
 +                                // 3) it wasn’t very smart (see #675).
 +                                let mut applicability = Applicability::HasPlaceholders;
 +                                span_lint_and_sugg(
 +                                    cx,
 +                                    WHILE_LET_LOOP,
 +                                    expr.span,
 +                                    "this loop could be written as a `while let` loop",
 +                                    "try",
 +                                    format!(
 +                                        "while let {} = {} {{ .. }}",
 +                                        snippet_with_applicability(cx, arms[0].pat.span, "..", &mut applicability),
 +                                        snippet_with_applicability(cx, matchexpr.span, "..", &mut applicability),
 +                                    ),
 +                                    applicability,
 +                                );
 +                            }
 +                        },
 +                        _ => (),
 +                    }
 +                }
 +            }
 +        }
 +        if let ExprKind::Match(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.kind {
 +            let pat = &arms[0].pat.kind;
 +            if let (
 +                &PatKind::TupleStruct(ref qpath, ref pat_args, _),
 +                &ExprKind::MethodCall(ref method_path, _, ref method_args),
 +            ) = (pat, &match_expr.kind)
 +            {
 +                let iter_expr = &method_args[0];
 +
 +                // Don't lint when the iterator is recreated on every iteration
 +                if_chain! {
 +                    if let ExprKind::MethodCall(..) | ExprKind::Call(..) = iter_expr.kind;
 +                    if let Some(iter_def_id) = get_trait_def_id(cx, &paths::ITERATOR);
 +                    if implements_trait(cx, cx.tables.expr_ty(iter_expr), iter_def_id, &[]);
 +                    then {
 +                        return;
 +                    }
 +                }
 +
 +                let lhs_constructor = last_path_segment(qpath);
 +                if method_path.ident.name == sym!(next)
 +                    && match_trait_method(cx, match_expr, &paths::ITERATOR)
 +                    && lhs_constructor.ident.name == sym!(Some)
 +                    && (pat_args.is_empty()
 +                        || !is_refutable(cx, &pat_args[0])
 +                            && !is_used_inside(cx, iter_expr, &arms[0].body)
 +                            && !is_iterator_used_after_while_let(cx, iter_expr)
 +                            && !is_nested(cx, expr, &method_args[0]))
 +                {
 +                    let mut applicability = Applicability::MachineApplicable;
 +                    let iterator = snippet_with_applicability(cx, method_args[0].span, "_", &mut applicability);
 +                    let loop_var = if pat_args.is_empty() {
 +                        "_".to_string()
 +                    } else {
 +                        snippet_with_applicability(cx, pat_args[0].span, "_", &mut applicability).into_owned()
 +                    };
 +                    span_lint_and_sugg(
 +                        cx,
 +                        WHILE_LET_ON_ITERATOR,
 +                        expr.span.with_hi(match_expr.span.hi()),
 +                        "this loop could be written as a `for` loop",
 +                        "try",
 +                        format!("for {} in {}", loop_var, iterator),
 +                        applicability,
 +                    );
 +                }
 +            }
 +        }
 +
 +        if let Some((cond, body)) = higher::while_loop(&expr) {
 +            check_infinite_loop(cx, cond, body);
 +        }
 +
 +        check_needless_collect(expr, cx);
 +    }
 +}
 +
 +enum NeverLoopResult {
 +    // A break/return always get triggered but not necessarily for the main loop.
 +    AlwaysBreak,
 +    // A continue may occur for the main loop.
 +    MayContinueMainLoop,
 +    Otherwise,
 +}
 +
 +#[must_use]
 +fn absorb_break(arg: &NeverLoopResult) -> NeverLoopResult {
 +    match *arg {
 +        NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
 +        NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
 +    }
 +}
 +
 +// Combine two results for parts that are called in order.
 +#[must_use]
 +fn combine_seq(first: NeverLoopResult, second: NeverLoopResult) -> NeverLoopResult {
 +    match first {
 +        NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop => first,
 +        NeverLoopResult::Otherwise => second,
 +    }
 +}
 +
 +// Combine two results where both parts are called but not necessarily in order.
 +#[must_use]
 +fn combine_both(left: NeverLoopResult, right: NeverLoopResult) -> NeverLoopResult {
 +    match (left, right) {
 +        (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
 +            NeverLoopResult::MayContinueMainLoop
 +        },
 +        (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
 +        (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
 +    }
 +}
 +
 +// Combine two results where only one of the part may have been executed.
 +#[must_use]
 +fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult {
 +    match (b1, b2) {
 +        (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
 +        (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
 +            NeverLoopResult::MayContinueMainLoop
 +        },
 +        (NeverLoopResult::Otherwise, _) | (_, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
 +    }
 +}
 +
 +fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
 +    let stmts = block.stmts.iter().map(stmt_to_expr);
 +    let expr = once(block.expr.as_deref());
 +    let mut iter = stmts.chain(expr).filter_map(|e| e);
 +    never_loop_expr_seq(&mut iter, main_loop_id)
 +}
 +
 +fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 +    match stmt.kind {
 +        StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e),
 +        StmtKind::Local(ref local) => local.init.as_deref(),
 +        _ => None,
 +    }
 +}
 +
 +fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
 +    match expr.kind {
 +        ExprKind::Box(ref e)
 +        | ExprKind::Unary(_, ref e)
 +        | ExprKind::Cast(ref e, _)
 +        | ExprKind::Type(ref e, _)
 +        | ExprKind::Field(ref e, _)
 +        | ExprKind::AddrOf(_, _, ref e)
 +        | ExprKind::Struct(_, _, Some(ref e))
 +        | ExprKind::Repeat(ref e, _)
 +        | ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id),
 +        ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => {
 +            never_loop_expr_all(&mut es.iter(), main_loop_id)
 +        },
 +        ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
 +        ExprKind::Binary(_, ref e1, ref e2)
 +        | ExprKind::Assign(ref e1, ref e2, _)
 +        | ExprKind::AssignOp(_, ref e1, ref e2)
 +        | ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
 +        ExprKind::Loop(ref b, _, _) => {
 +            // Break can come from the inner loop so remove them.
 +            absorb_break(&never_loop_block(b, main_loop_id))
 +        },
 +        ExprKind::Match(ref e, ref arms, _) => {
 +            let e = never_loop_expr(e, main_loop_id);
 +            if arms.is_empty() {
 +                e
 +            } else {
 +                let arms = never_loop_expr_branch(&mut arms.iter().map(|a| &*a.body), main_loop_id);
 +                combine_seq(e, arms)
 +            }
 +        },
 +        ExprKind::Block(ref b, _) => never_loop_block(b, main_loop_id),
 +        ExprKind::Continue(d) => {
 +            let id = d
 +                .target_id
 +                .expect("target ID can only be missing in the presence of compilation errors");
 +            if id == main_loop_id {
 +                NeverLoopResult::MayContinueMainLoop
 +            } else {
 +                NeverLoopResult::AlwaysBreak
 +            }
 +        },
 +        ExprKind::Break(_, ref e) | ExprKind::Ret(ref e) => {
 +            if let Some(ref e) = *e {
 +                combine_seq(never_loop_expr(e, main_loop_id), NeverLoopResult::AlwaysBreak)
 +            } else {
 +                NeverLoopResult::AlwaysBreak
 +            }
 +        },
 +        ExprKind::Struct(_, _, None)
 +        | ExprKind::Yield(_, _)
 +        | ExprKind::Closure(_, _, _, _, _)
 +        | ExprKind::LlvmInlineAsm(_)
 +        | ExprKind::Path(_)
 +        | ExprKind::Lit(_)
 +        | ExprKind::Err => NeverLoopResult::Otherwise,
 +    }
 +}
 +
 +fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_loop_id: HirId) -> NeverLoopResult {
 +    es.map(|e| never_loop_expr(e, main_loop_id))
 +        .fold(NeverLoopResult::Otherwise, combine_seq)
 +}
 +
 +fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_loop_id: HirId) -> NeverLoopResult {
 +    es.map(|e| never_loop_expr(e, main_loop_id))
 +        .fold(NeverLoopResult::Otherwise, combine_both)
 +}
 +
 +fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(e: &mut T, main_loop_id: HirId) -> NeverLoopResult {
 +    e.map(|e| never_loop_expr(e, main_loop_id))
 +        .fold(NeverLoopResult::AlwaysBreak, combine_branches)
 +}
 +
 +fn check_for_loop<'a, 'tcx>(
 +    cx: &LateContext<'a, 'tcx>,
 +    pat: &'tcx Pat<'_>,
 +    arg: &'tcx Expr<'_>,
 +    body: &'tcx Expr<'_>,
 +    expr: &'tcx Expr<'_>,
 +) {
 +    check_for_loop_range(cx, pat, arg, body, expr);
 +    check_for_loop_reverse_range(cx, arg, expr);
 +    check_for_loop_arg(cx, pat, arg, expr);
 +    check_for_loop_explicit_counter(cx, pat, arg, body, expr);
 +    check_for_loop_over_map_kv(cx, pat, arg, body, expr);
 +    check_for_mut_range_bound(cx, arg, body);
 +    detect_manual_memcpy(cx, pat, arg, body, expr);
 +}
 +
 +fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> bool {
 +    if_chain! {
-         // our variable!
-         if local_id == var;
++        if let ExprKind::Path(qpath) = &expr.kind;
++        if let QPath::Resolved(None, path) = qpath;
 +        if path.segments.len() == 1;
 +        if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id);
-             return true;
 +        then {
-     false
++            // our variable!
++            local_id == var
++        } else {
++            false
 +        }
 +    }
++}
 +
-     negate: bool,
++#[derive(Clone, Copy)]
++enum OffsetSign {
++    Positive,
++    Negative,
 +}
 +
 +struct Offset {
 +    value: String,
-     fn negative(s: String) -> Self {
-         Self { value: s, negate: true }
++    sign: OffsetSign,
 +}
 +
 +impl Offset {
-     fn positive(s: String) -> Self {
++    fn negative(value: String) -> Self {
++        Self {
++            value,
++            sign: OffsetSign::Negative,
++        }
 +    }
 +
-             value: s,
-             negate: false,
++    fn positive(value: String) -> Self {
 +        Self {
- struct FixedOffsetVar {
-     var_name: String,
++            value,
++            sign: OffsetSign::Positive,
 +        }
 +    }
 +}
 +
- fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> {
++struct FixedOffsetVar<'hir> {
++    var: &'hir Expr<'hir>,
 +    offset: Offset,
 +}
 +
 +fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
 +    let is_slice = match ty.kind {
 +        ty::Ref(_, subty, _) => is_slice_like(cx, subty),
 +        ty::Slice(..) | ty::Array(..) => true,
 +        _ => false,
 +    };
 +
 +    is_slice || is_type_diagnostic_item(cx, ty, sym!(vec_type)) || is_type_diagnostic_item(cx, ty, sym!(vecdeque_type))
 +}
 +
-         match e.kind {
-             ExprKind::Lit(ref l) => match l.node {
++fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
++    if_chain! {
++        if let ExprKind::MethodCall(method, _, args) = expr.kind;
++        if method.ident.name == sym!(clone);
++        if args.len() == 1;
++        if let Some(arg) = args.get(0);
++        then { arg } else { expr }
++    }
++}
++
++fn get_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, idx: &Expr<'_>, var: HirId) -> Option<Offset> {
 +    fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option<String> {
-     if let ExprKind::Index(ref seqexpr, ref idx) = expr.kind {
-         let ty = cx.tables.expr_ty(seqexpr);
-         if !is_slice_like(cx, ty) {
-             return None;
-         }
-         let offset = match idx.kind {
-             ExprKind::Binary(op, ref lhs, ref rhs) => match op.node {
-                 BinOpKind::Add => {
-                     let offset_opt = if same_var(cx, lhs, var) {
-                         extract_offset(cx, rhs, var)
-                     } else if same_var(cx, rhs, var) {
-                         extract_offset(cx, lhs, var)
-                     } else {
-                         None
-                     };
-                     offset_opt.map(Offset::positive)
-                 },
-                 BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative),
-                 _ => None,
-             },
-             ExprKind::Path(..) => {
-                 if same_var(cx, idx, var) {
-                     Some(Offset::positive("0".into()))
++        match &e.kind {
++            ExprKind::Lit(l) => match l.node {
 +                ast::LitKind::Int(x, _ty) => Some(x.to_string()),
 +                _ => None,
 +            },
 +            ExprKind::Path(..) if !same_var(cx, e, var) => Some(snippet_opt(cx, e.span).unwrap_or_else(|| "??".into())),
 +            _ => None,
 +        }
 +    }
 +
-                 }
++    match idx.kind {
++        ExprKind::Binary(op, lhs, rhs) => match op.node {
++            BinOpKind::Add => {
++                let offset_opt = if same_var(cx, lhs, var) {
++                    extract_offset(cx, rhs, var)
++                } else if same_var(cx, rhs, var) {
++                    extract_offset(cx, lhs, var)
 +                } else {
 +                    None
-         };
-         offset.map(|o| FixedOffsetVar {
-             var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()),
-             offset: o,
-         })
-     } else {
-         None
-     }
- }
- fn fetch_cloned_fixed_offset_var<'a, 'tcx>(
-     cx: &LateContext<'a, 'tcx>,
-     expr: &Expr<'_>,
-     var: HirId,
- ) -> Option<FixedOffsetVar> {
-     if_chain! {
-         if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind;
-         if method.ident.name == sym!(clone);
-         if args.len() == 1;
-         if let Some(arg) = args.get(0);
-         then {
-             return get_fixed_offset_var(cx, arg, var);
-         }
++                };
++
++                offset_opt.map(Offset::positive)
 +            },
++            BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative),
 +            _ => None,
-     get_fixed_offset_var(cx, expr, var)
++        },
++        ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())),
++        _ => None,
 +    }
- fn get_indexed_assignments<'a, 'tcx>(
-     cx: &LateContext<'a, 'tcx>,
-     body: &Expr<'_>,
-     var: HirId,
- ) -> Vec<(FixedOffsetVar, FixedOffsetVar)> {
-     fn get_assignment<'a, 'tcx>(
-         cx: &LateContext<'a, 'tcx>,
-         e: &Expr<'_>,
-         var: HirId,
-     ) -> Option<(FixedOffsetVar, FixedOffsetVar)> {
-         if let ExprKind::Assign(ref lhs, ref rhs, _) = e.kind {
-             match (
-                 get_fixed_offset_var(cx, lhs, var),
-                 fetch_cloned_fixed_offset_var(cx, rhs, var),
-             ) {
-                 (Some(offset_left), Some(offset_right)) => {
-                     // Source and destination must be different
-                     if offset_left.var_name == offset_right.var_name {
-                         None
-                     } else {
-                         Some((offset_left, offset_right))
-                     }
-                 },
-                 _ => None,
-             }
 +}
 +
-     if let ExprKind::Block(ref b, _) = body.kind {
-         let Block {
-             ref stmts, ref expr, ..
-         } = **b;
++fn get_assignments<'tcx>(body: &'tcx Expr<'tcx>) -> impl Iterator<Item = Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)>> {
++    fn get_assignment<'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> {
++        if let ExprKind::Assign(lhs, rhs, _) = e.kind {
++            Some((lhs, rhs))
 +        } else {
 +            None
 +        }
 +    }
 +
-         stmts
++    // This is one of few ways to return different iterators
++    // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434
++    let mut iter_a = None;
++    let mut iter_b = None;
++
++    if let ExprKind::Block(b, _) = body.kind {
++        let Block { stmts, expr, .. } = *b;
 +
-             .map(|stmt| match stmt.kind {
++        iter_a = stmts
 +            .iter()
-                 StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => Some(get_assignment(cx, e, var)),
++            .filter_map(|stmt| match stmt.kind {
 +                StmtKind::Local(..) | StmtKind::Item(..) => None,
-             .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var))))
-             .filter_map(|op| op)
-             .collect::<Option<Vec<_>>>()
-             .unwrap_or_default()
++                StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e),
 +            })
-         get_assignment(cx, body, var).into_iter().collect()
++            .chain(expr.into_iter())
++            .map(get_assignment)
++            .into()
 +    } else {
-         ref end,
++        iter_b = Some(get_assignment(body))
 +    }
++
++    iter_a.into_iter().flatten().chain(iter_b.into_iter())
 +}
 +
++fn build_manual_memcpy_suggestion<'a, 'tcx>(
++    cx: &LateContext<'a, 'tcx>,
++    start: &Expr<'_>,
++    end: &Expr<'_>,
++    limits: ast::RangeLimits,
++    dst_var: FixedOffsetVar<'_>,
++    src_var: FixedOffsetVar<'_>,
++) -> String {
++    fn print_sum(arg1: &str, arg2: &Offset) -> String {
++        match (arg1, &arg2.value[..], arg2.sign) {
++            ("0", "0", _) => "0".into(),
++            ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(),
++            ("0", x, OffsetSign::Negative) => format!("-{}", x),
++            (x, y, OffsetSign::Positive) => format!("({} + {})", x, y),
++            (x, y, OffsetSign::Negative) => {
++                if x == y {
++                    "0".into()
++                } else {
++                    format!("({} - {})", x, y)
++                }
++            },
++        }
++    }
++
++    fn print_offset(start_str: &str, inline_offset: &Offset) -> String {
++        let offset = print_sum(start_str, inline_offset);
++        if offset.as_str() == "0" {
++            "".into()
++        } else {
++            offset
++        }
++    }
++
++    let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| {
++        if_chain! {
++            if let ExprKind::MethodCall(method, _, len_args) = end.kind;
++            if method.ident.name == sym!(len);
++            if len_args.len() == 1;
++            if let Some(arg) = len_args.get(0);
++            if var_def_id(cx, arg) == var_def_id(cx, var);
++            then {
++                match offset.sign {
++                    OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value),
++                    OffsetSign::Positive => "".into(),
++                }
++            } else {
++                let end_str = match limits {
++                    ast::RangeLimits::Closed => {
++                        let end = sugg::Sugg::hir(cx, end, "<count>");
++                        format!("{}", end + sugg::ONE)
++                    },
++                    ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")),
++                };
++
++                print_sum(&end_str, &offset)
++            }
++        }
++    };
++
++    let start_str = snippet(cx, start.span, "").to_string();
++    let dst_offset = print_offset(&start_str, &dst_var.offset);
++    let dst_limit = print_limit(end, dst_var.offset, dst_var.var);
++    let src_offset = print_offset(&start_str, &src_var.offset);
++    let src_limit = print_limit(end, src_var.offset, src_var.var);
++
++    let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into());
++    let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into());
++
++    let dst = if dst_offset == "" && dst_limit == "" {
++        dst_var_name
++    } else {
++        format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit)
++    };
++
++    format!(
++        "{}.clone_from_slice(&{}[{}..{}])",
++        dst, src_var_name, src_offset, src_limit
++    )
++}
 +/// Checks for for loops that sequentially copy items from one slice-like
 +/// object to another.
 +fn detect_manual_memcpy<'a, 'tcx>(
 +    cx: &LateContext<'a, 'tcx>,
 +    pat: &'tcx Pat<'_>,
 +    arg: &'tcx Expr<'_>,
 +    body: &'tcx Expr<'_>,
 +    expr: &'tcx Expr<'_>,
 +) {
 +    if let Some(higher::Range {
 +        start: Some(start),
-             let print_sum = |arg1: &Offset, arg2: &Offset| -> String {
-                 match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) {
-                     ("0", _, "0", _) => "".into(),
-                     ("0", _, x, false) | (x, false, "0", false) => x.into(),
-                     ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x),
-                     (x, false, y, false) => format!("({} + {})", x, y),
-                     (x, false, y, true) => {
-                         if x == y {
-                             "0".into()
-                         } else {
-                             format!("({} - {})", x, y)
-                         }
-                     },
-                     (x, true, y, false) => {
-                         if x == y {
-                             "0".into()
-                         } else {
-                             format!("({} - {})", y, x)
-                         }
-                     },
-                     (x, true, y, true) => format!("-({} + {})", x, y),
-                 }
-             };
-             let print_limit = |end: &Option<&Expr<'_>>, offset: Offset, var_name: &str| {
-                 if let Some(end) = *end {
-                     if_chain! {
-                         if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind;
-                         if method.ident.name == sym!(len);
-                         if len_args.len() == 1;
-                         if let Some(arg) = len_args.get(0);
-                         if snippet(cx, arg.span, "??") == var_name;
-                         then {
-                             return if offset.negate {
-                                 format!("({} - {})", snippet(cx, end.span, "<src>.len()"), offset.value)
-                             } else {
-                                 String::new()
-                             };
-                         }
-                     }
-                     let end_str = match limits {
-                         ast::RangeLimits::Closed => {
-                             let end = sugg::Sugg::hir(cx, end, "<count>");
-                             format!("{}", end + sugg::ONE)
-                         },
-                         ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")),
-                     };
-                     print_sum(&Offset::positive(end_str), &offset)
-                 } else {
-                     "..".into()
-                 }
-             };
++        end: Some(end),
 +        limits,
 +    }) = higher::range(cx, arg)
 +    {
 +        // the var must be a single name
 +        if let PatKind::Binding(_, canonical_id, _, _) = pat.kind {
-             let manual_copies = get_indexed_assignments(cx, body, canonical_id);
-             let big_sugg = manual_copies
-                 .into_iter()
-                 .map(|(dst_var, src_var)| {
-                     let start_str = Offset::positive(snippet(cx, start.span, "").to_string());
-                     let dst_offset = print_sum(&start_str, &dst_var.offset);
-                     let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name);
-                     let src_offset = print_sum(&start_str, &src_var.offset);
-                     let src_limit = print_limit(end, src_var.offset, &src_var.var_name);
-                     let dst = if dst_offset == "" && dst_limit == "" {
-                         dst_var.var_name
-                     } else {
-                         format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit)
-                     };
-                     format!(
-                         "{}.clone_from_slice(&{}[{}..{}])",
-                         dst, src_var.var_name, src_offset, src_limit
-                     )
 +            // The only statements in the for loops can be indexed assignments from
 +            // indexed retrievals.
-                 .join("\n    ");
++            let big_sugg = get_assignments(body)
++                .map(|o| {
++                    o.and_then(|(lhs, rhs)| {
++                        let rhs = fetch_cloned_expr(rhs);
++                        if_chain! {
++                            if let ExprKind::Index(seqexpr_left, idx_left) = lhs.kind;
++                            if let ExprKind::Index(seqexpr_right, idx_right) = rhs.kind;
++                            if is_slice_like(cx, cx.tables.expr_ty(seqexpr_left))
++                                && is_slice_like(cx, cx.tables.expr_ty(seqexpr_right));
++                            if let Some(offset_left) = get_offset(cx, &idx_left, canonical_id);
++                            if let Some(offset_right) = get_offset(cx, &idx_right, canonical_id);
++
++                            // Source and destination must be different
++                            if var_def_id(cx, seqexpr_left) != var_def_id(cx, seqexpr_right);
++                            then {
++                                Some((FixedOffsetVar { var: seqexpr_left, offset: offset_left },
++                                    FixedOffsetVar { var: seqexpr_right, offset: offset_right }))
++                            } else {
++                                None
++                            }
++                        }
++                    })
 +                })
-             if !big_sugg.is_empty() {
++                .map(|o| o.map(|(dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, dst, src)))
++                .collect::<Option<Vec<_>>>()
++                .filter(|v| !v.is_empty())
++                .map(|v| v.join("\n    "));
 +
++            if let Some(big_sugg) = big_sugg {
 +                span_lint_and_sugg(
 +                    cx,
 +                    MANUAL_MEMCPY,
 +                    expr.span,
 +                    "it looks like you're manually copying between slices",
 +                    "try replacing the loop by",
 +                    big_sugg,
 +                    Applicability::Unspecified,
 +                );
 +            }
 +        }
 +    }
 +}
 +
 +/// Checks for looping over a range and then indexing a sequence with it.
 +/// The iteratee must be a range literal.
 +#[allow(clippy::too_many_lines)]
 +fn check_for_loop_range<'a, 'tcx>(
 +    cx: &LateContext<'a, '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(cx, 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_id = cx.tcx.hir().get_parent_item(expr.hir_id);
 +                    let parent_def_id = cx.tcx.hir().local_def_id(parent_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);
 +                    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 {
 +                    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, ref left, ref right) = end.kind {
 +                        if let BinOpKind::Add = op.node {
 +                            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 {
 +                        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,
 +                        expr.span,
 +                        &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed),
 +                        |diag| {
 +                            multispan_sugg(
 +                                diag,
 +                                "consider using an iterator".to_string(),
 +                                vec![
 +                                    (pat.span, format!("({}, <item>)", ident.name)),
 +                                    (
 +                                        arg.span,
 +                                        format!("{}.{}().enumerate(){}{}", indexed, method, 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,
 +                        expr.span,
 +                        &format!(
 +                            "the loop variable `{}` is only used to index `{}`.",
 +                            ident.name, indexed
 +                        ),
 +                        |diag| {
 +                            multispan_sugg(
 +                                diag,
 +                                "consider using an iterator".to_string(),
 +                                vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
 +                            );
 +                        },
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +fn is_len_call(expr: &Expr<'_>, var: Name) -> bool {
 +    if_chain! {
 +        if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.kind;
 +        if len_args.len() == 1;
 +        if method.ident.name == sym!(len);
 +        if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].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
 +}
 +
 +fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
 +    // if this for loop is iterating over a two-sided range...
 +    if let Some(higher::Range {
 +        start: Some(start),
 +        end: Some(end),
 +        limits,
 +    }) = higher::range(cx, arg)
 +    {
 +        // ...and both sides are compile-time constant integers...
 +        if let Some((start_idx, _)) = constant(cx, cx.tables, start) {
 +            if let Some((end_idx, _)) = constant(cx, cx.tables, end) {
 +                // ...and the start index is greater than the end index,
 +                // this loop will never run. This is often confusing for developers
 +                // who think that this will iterate from the larger value to the
 +                // smaller value.
 +                let ty = cx.tables.expr_ty(start);
 +                let (sup, eq) = match (start_idx, end_idx) {
 +                    (Constant::Int(start_idx), Constant::Int(end_idx)) => (
 +                        match ty.kind {
 +                            ty::Int(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity),
 +                            ty::Uint(_) => start_idx > end_idx,
 +                            _ => false,
 +                        },
 +                        start_idx == end_idx,
 +                    ),
 +                    _ => (false, false),
 +                };
 +
 +                if sup {
 +                    let start_snippet = snippet(cx, start.span, "_");
 +                    let end_snippet = snippet(cx, end.span, "_");
 +                    let dots = if limits == ast::RangeLimits::Closed {
 +                        "..="
 +                    } else {
 +                        ".."
 +                    };
 +
 +                    span_lint_and_then(
 +                        cx,
 +                        REVERSE_RANGE_LOOP,
 +                        expr.span,
 +                        "this range is empty so this for loop will never run",
 +                        |diag| {
 +                            diag.span_suggestion(
 +                                arg.span,
 +                                "consider using the following if you are attempting to iterate over this \
 +                                 range in reverse",
 +                                format!(
 +                                    "({end}{dots}{start}).rev()",
 +                                    end = end_snippet,
 +                                    dots = dots,
 +                                    start = start_snippet
 +                                ),
 +                                Applicability::MaybeIncorrect,
 +                            );
 +                        },
 +                    );
 +                } else if eq && limits != ast::RangeLimits::Closed {
 +                    // if they are equal, it's also problematic - this loop
 +                    // will never run.
 +                    span_lint(
 +                        cx,
 +                        REVERSE_RANGE_LOOP,
 +                        expr.span,
 +                        "this range is empty so this for loop will never run",
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>, method_name: &str) {
 +    let mut applicability = Applicability::MachineApplicable;
 +    let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
 +    let muta = if method_name == "iter_mut" { "mut " } else { "" };
 +    span_lint_and_sugg(
 +        cx,
 +        EXPLICIT_ITER_LOOP,
 +        arg.span,
 +        "it is more concise to loop over references to containers instead of using explicit \
 +         iteration methods",
 +        "to write this more concisely, try",
 +        format!("&{}{}", muta, object),
 +        applicability,
 +    )
 +}
 +
 +fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
 +    let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
 +    if let ExprKind::MethodCall(ref method, _, ref args) = arg.kind {
 +        // just the receiver, no arguments
 +        if args.len() == 1 {
 +            let method_name = &*method.ident.as_str();
 +            // check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
 +            if method_name == "iter" || method_name == "iter_mut" {
 +                if is_ref_iterable_type(cx, &args[0]) {
 +                    lint_iter_method(cx, args, arg, method_name);
 +                }
 +            } else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) {
 +                let receiver_ty = cx.tables.expr_ty(&args[0]);
 +                let receiver_ty_adjusted = cx.tables.expr_ty_adjusted(&args[0]);
 +                if same_tys(cx, receiver_ty, receiver_ty_adjusted) {
 +                    let mut applicability = Applicability::MachineApplicable;
 +                    let object = snippet_with_applicability(cx, args[0].span, "_", &mut applicability);
 +                    span_lint_and_sugg(
 +                        cx,
 +                        EXPLICIT_INTO_ITER_LOOP,
 +                        arg.span,
 +                        "it is more concise to loop over containers instead of using explicit \
 +                         iteration methods",
 +                        "to write this more concisely, try",
 +                        object.to_string(),
 +                        applicability,
 +                    );
 +                } else {
 +                    let ref_receiver_ty = cx.tcx.mk_ref(
 +                        cx.tcx.lifetimes.re_erased,
 +                        ty::TypeAndMut {
 +                            ty: receiver_ty,
 +                            mutbl: Mutability::Not,
 +                        },
 +                    );
 +                    if same_tys(cx, receiver_ty_adjusted, ref_receiver_ty) {
 +                        lint_iter_method(cx, args, arg, method_name)
 +                    }
 +                }
 +            } else if method_name == "next" && match_trait_method(cx, arg, &paths::ITERATOR) {
 +                span_lint(
 +                    cx,
 +                    ITER_NEXT_LOOP,
 +                    expr.span,
 +                    "you are iterating over `Iterator::next()` which is an Option; this will compile but is \
 +                     probably not what you want",
 +                );
 +                next_loop_linted = true;
 +            }
 +        }
 +    }
 +    if !next_loop_linted {
 +        check_arg_type(cx, pat, arg);
 +    }
 +}
 +
 +/// Checks for `for` loops over `Option`s and `Result`s.
 +fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
 +    let ty = cx.tables.expr_ty(arg);
 +    if is_type_diagnostic_item(cx, ty, sym!(option_type)) {
 +        span_lint_and_help(
 +            cx,
 +            FOR_LOOP_OVER_OPTION,
 +            arg.span,
 +            &format!(
 +                "for loop over `{0}`, which is an `Option`. This is more readably written as an \
 +                 `if let` statement.",
 +                snippet(cx, arg.span, "_")
 +            ),
 +            None,
 +            &format!(
 +                "consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`",
 +                snippet(cx, pat.span, "_"),
 +                snippet(cx, arg.span, "_")
 +            ),
 +        );
 +    } else if is_type_diagnostic_item(cx, ty, sym!(result_type)) {
 +        span_lint_and_help(
 +            cx,
 +            FOR_LOOP_OVER_RESULT,
 +            arg.span,
 +            &format!(
 +                "for loop over `{0}`, which is a `Result`. This is more readably written as an \
 +                 `if let` statement.",
 +                snippet(cx, arg.span, "_")
 +            ),
 +            None,
 +            &format!(
 +                "consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`",
 +                snippet(cx, pat.span, "_"),
 +                snippet(cx, arg.span, "_")
 +            ),
 +        );
 +    }
 +}
 +
 +fn check_for_loop_explicit_counter<'a, 'tcx>(
 +    cx: &LateContext<'a, 'tcx>,
 +    pat: &'tcx Pat<'_>,
 +    arg: &'tcx Expr<'_>,
 +    body: &'tcx Expr<'_>,
 +    expr: &'tcx Expr<'_>,
 +) {
 +    // Look for variables that are incremented once per loop iteration.
 +    let mut visitor = IncrementVisitor {
 +        cx,
 +        states: FxHashMap::default(),
 +        depth: 0,
 +        done: false,
 +    };
 +    walk_expr(&mut visitor, body);
 +
 +    // For each candidate, check the parent block to see if
 +    // it's initialized to zero at the start of the loop.
 +    if let Some(block) = get_enclosing_block(&cx, expr.hir_id) {
 +        for (id, _) in visitor.states.iter().filter(|&(_, v)| *v == VarState::IncrOnce) {
 +            let mut visitor2 = InitializeVisitor {
 +                cx,
 +                end_expr: expr,
 +                var_id: *id,
 +                state: VarState::IncrOnce,
 +                name: None,
 +                depth: 0,
 +                past_loop: false,
 +            };
 +            walk_block(&mut visitor2, block);
 +
 +            if visitor2.state == VarState::Warn {
 +                if let Some(name) = visitor2.name {
 +                    let mut applicability = Applicability::MachineApplicable;
 +
 +                    // for some reason this is the only way to get the `Span`
 +                    // of the entire `for` loop
 +                    let for_span = if let ExprKind::Match(_, arms, _) = &expr.kind {
 +                        arms[0].body.span
 +                    } else {
 +                        unreachable!()
 +                    };
 +
 +                    span_lint_and_sugg(
 +                        cx,
 +                        EXPLICIT_COUNTER_LOOP,
 +                        for_span.with_hi(arg.span.hi()),
 +                        &format!("the variable `{}` is used as a loop counter.", name),
 +                        "consider using",
 +                        format!(
 +                            "for ({}, {}) in {}.enumerate()",
 +                            name,
 +                            snippet_with_applicability(cx, pat.span, "item", &mut applicability),
 +                            make_iterator_snippet(cx, arg, &mut applicability),
 +                        ),
 +                        applicability,
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +/// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
 +/// actual `Iterator` that the loop uses.
 +fn make_iterator_snippet(cx: &LateContext<'_, '_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String {
 +    let impls_iterator = get_trait_def_id(cx, &paths::ITERATOR)
 +        .map_or(false, |id| implements_trait(cx, cx.tables.expr_ty(arg), id, &[]));
 +    if impls_iterator {
 +        format!(
 +            "{}",
 +            sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
 +        )
 +    } else {
 +        // (&x).into_iter() ==> x.iter()
 +        // (&mut x).into_iter() ==> x.iter_mut()
 +        match &arg.kind {
 +            ExprKind::AddrOf(BorrowKind::Ref, mutability, arg_inner)
 +                if has_iter_method(cx, cx.tables.expr_ty(&arg_inner)).is_some() =>
 +            {
 +                let meth_name = match mutability {
 +                    Mutability::Mut => "iter_mut",
 +                    Mutability::Not => "iter",
 +                };
 +                format!(
 +                    "{}.{}()",
 +                    sugg::Sugg::hir_with_applicability(cx, &arg_inner, "_", applic_ref).maybe_par(),
 +                    meth_name,
 +                )
 +            }
 +            _ => format!(
 +                "{}.into_iter()",
 +                sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
 +            ),
 +        }
 +    }
 +}
 +
 +/// Checks for the `FOR_KV_MAP` lint.
 +fn check_for_loop_over_map_kv<'a, 'tcx>(
 +    cx: &LateContext<'a, 'tcx>,
 +    pat: &'tcx Pat<'_>,
 +    arg: &'tcx Expr<'_>,
 +    body: &'tcx Expr<'_>,
 +    expr: &'tcx Expr<'_>,
 +) {
 +    let pat_span = pat.span;
 +
 +    if let PatKind::Tuple(ref pat, _) = pat.kind {
 +        if pat.len() == 2 {
 +            let arg_span = arg.span;
 +            let (new_pat_span, kind, ty, mutbl) = match cx.tables.expr_ty(arg).kind {
 +                ty::Ref(_, ty, mutbl) => match (&pat[0].kind, &pat[1].kind) {
 +                    (key, _) if pat_is_wild(key, body) => (pat[1].span, "value", ty, mutbl),
 +                    (_, value) if pat_is_wild(value, body) => (pat[0].span, "key", ty, Mutability::Not),
 +                    _ => return,
 +                },
 +                _ => return,
 +            };
 +            let mutbl = match mutbl {
 +                Mutability::Not => "",
 +                Mutability::Mut => "_mut",
 +            };
 +            let arg = match arg.kind {
 +                ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) => &**expr,
 +                _ => arg,
 +            };
 +
 +            if is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) || match_type(cx, ty, &paths::BTREEMAP) {
 +                span_lint_and_then(
 +                    cx,
 +                    FOR_KV_MAP,
 +                    expr.span,
 +                    &format!("you seem to want to iterate on a map's {}s", kind),
 +                    |diag| {
 +                        let map = sugg::Sugg::hir(cx, arg, "map");
 +                        multispan_sugg(
 +                            diag,
 +                            "use the corresponding method".into(),
 +                            vec![
 +                                (pat_span, snippet(cx, new_pat_span, kind).into_owned()),
 +                                (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl)),
 +                            ],
 +                        );
 +                    },
 +                );
 +            }
 +        }
 +    }
 +}
 +
 +struct MutatePairDelegate {
 +    hir_id_low: Option<HirId>,
 +    hir_id_high: Option<HirId>,
 +    span_low: Option<Span>,
 +    span_high: Option<Span>,
 +}
 +
 +impl<'tcx> Delegate<'tcx> for MutatePairDelegate {
 +    fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {}
 +
 +    fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) {
 +        if let ty::BorrowKind::MutBorrow = bk {
 +            if let PlaceBase::Local(id) = cmt.base {
 +                if Some(id) == self.hir_id_low {
 +                    self.span_low = Some(cmt.span)
 +                }
 +                if Some(id) == self.hir_id_high {
 +                    self.span_high = Some(cmt.span)
 +                }
 +            }
 +        }
 +    }
 +
 +    fn mutate(&mut self, cmt: &Place<'tcx>) {
 +        if let PlaceBase::Local(id) = cmt.base {
 +            if Some(id) == self.hir_id_low {
 +                self.span_low = Some(cmt.span)
 +            }
 +            if Some(id) == self.hir_id_high {
 +                self.span_high = Some(cmt.span)
 +            }
 +        }
 +    }
 +}
 +
 +impl<'tcx> MutatePairDelegate {
 +    fn mutation_span(&self) -> (Option<Span>, Option<Span>) {
 +        (self.span_low, self.span_high)
 +    }
 +}
 +
 +fn check_for_mut_range_bound(cx: &LateContext<'_, '_>, arg: &Expr<'_>, body: &Expr<'_>) {
 +    if let Some(higher::Range {
 +        start: Some(start),
 +        end: Some(end),
 +        ..
 +    }) = higher::range(cx, arg)
 +    {
 +        let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)];
 +        if mut_ids[0].is_some() || mut_ids[1].is_some() {
 +            let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids);
 +            mut_warn_with_span(cx, span_low);
 +            mut_warn_with_span(cx, span_high);
 +        }
 +    }
 +}
 +
 +fn mut_warn_with_span(cx: &LateContext<'_, '_>, span: Option<Span>) {
 +    if let Some(sp) = span {
 +        span_lint(
 +            cx,
 +            MUT_RANGE_BOUND,
 +            sp,
 +            "attempt to mutate range bound within loop; note that the range of the loop is unchanged",
 +        );
 +    }
 +}
 +
 +fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option<HirId> {
 +    if_chain! {
 +        if let ExprKind::Path(ref qpath) = bound.kind;
 +        if let QPath::Resolved(None, _) = *qpath;
 +        then {
 +            let res = qpath_res(cx, qpath, bound.hir_id);
 +            if let Res::Local(hir_id) = res {
 +                let node_str = cx.tcx.hir().get(hir_id);
 +                if_chain! {
 +                    if let Node::Binding(pat) = node_str;
 +                    if let PatKind::Binding(bind_ann, ..) = pat.kind;
 +                    if let BindingAnnotation::Mutable = bind_ann;
 +                    then {
 +                        return Some(hir_id);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +    None
 +}
 +
 +fn check_for_mutation(
 +    cx: &LateContext<'_, '_>,
 +    body: &Expr<'_>,
 +    bound_ids: &[Option<HirId>],
 +) -> (Option<Span>, Option<Span>) {
 +    let mut delegate = MutatePairDelegate {
 +        hir_id_low: bound_ids[0],
 +        hir_id_high: bound_ids[1],
 +        span_low: None,
 +        span_high: None,
 +    };
 +    let def_id = body.hir_id.owner.to_def_id();
 +    cx.tcx.infer_ctxt().enter(|infcx| {
 +        ExprUseVisitor::new(&mut delegate, &infcx, def_id.expect_local(), cx.param_env, cx.tables).walk_expr(body);
 +    });
 +    delegate.mutation_span()
 +}
 +
 +/// Returns `true` if the pattern is a `PatWild` or an ident prefixed with `_`.
 +fn pat_is_wild<'tcx>(pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
 +    match *pat {
 +        PatKind::Wild => true,
 +        PatKind::Binding(.., ident, None) if ident.as_str().starts_with('_') => is_unused(&ident, body),
 +        _ => false,
 +    }
 +}
 +
 +struct LocalUsedVisitor<'a, 'tcx> {
 +    cx: &'a LateContext<'a, 'tcx>,
 +    local: HirId,
 +    used: bool,
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if same_var(self.cx, expr, self.local) {
 +            self.used = true;
 +        } else {
 +            walk_expr(self, expr);
 +        }
 +    }
 +
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +struct VarVisitor<'a, 'tcx> {
 +    /// context reference
 +    cx: &'a LateContext<'a, 'tcx>,
 +    /// var name to look for as index
 +    var: HirId,
 +    /// indexed variables that are used mutably
 +    indexed_mut: FxHashSet<Name>,
 +    /// indirectly indexed variables (`v[(i + 4) % N]`), the extend is `None` for global
 +    indexed_indirectly: FxHashMap<Name, 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<Name, (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<Name>,
 +    /// 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, ref seqvar) = *seqpath;
 +            if seqvar.segments.len() == 1;
 +            then {
 +                let index_used_directly = same_var(self.cx, idx, self.var);
 +                let indexed_indirectly = {
 +                    let mut used_visitor = LocalUsedVisitor {
 +                        cx: self.cx,
 +                        local: self.var,
 +                        used: false,
 +                    };
 +                    walk_expr(&mut used_visitor, idx);
 +                    used_visitor.used
 +                };
 +
 +                if indexed_indirectly || index_used_directly {
 +                    if self.prefer_mutable {
 +                        self.indexed_mut.insert(seqvar.segments[0].ident.name);
 +                    }
 +                    let res = qpath_res(self.cx, seqpath, seqexpr.hir_id);
 +                    match res {
 +                        Res::Local(hir_id) => {
 +                            let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
 +                            let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id);
 +                            let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
 +                            if indexed_indirectly {
 +                                self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent));
 +                            }
 +                            if index_used_directly {
 +                                self.indexed_directly.insert(
 +                                    seqvar.segments[0].ident.name,
 +                                    (Some(extent), self.cx.tables.node_type(seqexpr.hir_id)),
 +                                );
 +                            }
 +                            return false;  // no need to walk further *on the variable*
 +                        }
 +                        Res::Def(DefKind::Static | DefKind::Const, ..) => {
 +                            if indexed_indirectly {
 +                                self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
 +                            }
 +                            if index_used_directly {
 +                                self.indexed_directly.insert(
 +                                    seqvar.segments[0].ident.name,
 +                                    (None, self.cx.tables.node_type(seqexpr.hir_id)),
 +                                );
 +                            }
 +                            return false;  // no need to walk further *on the variable*
 +                        }
 +                        _ => (),
 +                    }
 +                }
 +            }
 +        }
 +        true
 +    }
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if_chain! {
 +            // a range index op
 +            if let ExprKind::MethodCall(ref meth, _, ref args) = expr.kind;
 +            if (meth.ident.name == sym!(index) && match_trait_method(self.cx, expr, &paths::INDEX))
 +                || (meth.ident.name == sym!(index_mut) && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
 +            if !self.check(&args[1], &args[0], expr);
 +            then { return }
 +        }
 +
 +        if_chain! {
 +            // an index op
 +            if let ExprKind::Index(ref seqexpr, ref idx) = expr.kind;
 +            if !self.check(idx, seqexpr, expr);
 +            then { return }
 +        }
 +
 +        if_chain! {
 +            // directly using a variable
 +            if let ExprKind::Path(ref qpath) = expr.kind;
 +            if let QPath::Resolved(None, ref path) = *qpath;
 +            if path.segments.len() == 1;
 +            then {
 +                if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id) {
 +                    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(_, ref lhs, ref rhs) | ExprKind::Assign(ref lhs, ref rhs, _) => {
 +                self.prefer_mutable = true;
 +                self.visit_expr(lhs);
 +                self.prefer_mutable = false;
 +                self.visit_expr(rhs);
 +            },
 +            ExprKind::AddrOf(BorrowKind::Ref, mutbl, ref expr) => {
 +                if mutbl == Mutability::Mut {
 +                    self.prefer_mutable = true;
 +                }
 +                self.visit_expr(expr);
 +            },
 +            ExprKind::Call(ref f, args) => {
 +                self.visit_expr(f);
 +                for expr in args {
 +                    let ty = self.cx.tables.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(_, _, args) => {
 +                let def_id = self.cx.tables.type_dependent_def_id(expr.hir_id).unwrap();
 +                for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
 +                    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(_, _, body_id, ..) => {
 +                let body = self.cx.tcx.hir().body(body_id);
 +                self.visit_expr(&body.value);
 +            },
 +            _ => walk_expr(self, expr),
 +        }
 +        self.prefer_mutable = old;
 +    }
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +fn is_used_inside<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, container: &'tcx Expr<'_>) -> bool {
 +    let def_id = match var_def_id(cx, expr) {
 +        Some(id) => id,
 +        None => return false,
 +    };
 +    if let Some(used_mutably) = mutated_variables(container, cx) {
 +        if used_mutably.contains(&def_id) {
 +            return true;
 +        }
 +    }
 +    false
 +}
 +
 +fn is_iterator_used_after_while_let<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, iter_expr: &'tcx Expr<'_>) -> bool {
 +    let def_id = match var_def_id(cx, iter_expr) {
 +        Some(id) => id,
 +        None => return false,
 +    };
 +    let mut visitor = VarUsedAfterLoopVisitor {
 +        cx,
 +        def_id,
 +        iter_expr_id: iter_expr.hir_id,
 +        past_while_let: false,
 +        var_used_after_while_let: false,
 +    };
 +    if let Some(enclosing_block) = get_enclosing_block(cx, def_id) {
 +        walk_block(&mut visitor, enclosing_block);
 +    }
 +    visitor.var_used_after_while_let
 +}
 +
 +struct VarUsedAfterLoopVisitor<'a, 'tcx> {
 +    cx: &'a LateContext<'a, 'tcx>,
 +    def_id: HirId,
 +    iter_expr_id: HirId,
 +    past_while_let: bool,
 +    var_used_after_while_let: bool,
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if self.past_while_let {
 +            if Some(self.def_id) == var_def_id(self.cx, expr) {
 +                self.var_used_after_while_let = true;
 +            }
 +        } else if self.iter_expr_id == expr.hir_id {
 +            self.past_while_let = true;
 +        }
 +        walk_expr(self, expr);
 +    }
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +/// Returns `true` if the type of expr is one that provides `IntoIterator` impls
 +/// for `&T` and `&mut T`, such as `Vec`.
 +#[rustfmt::skip]
 +fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool {
 +    // no walk_ptrs_ty: calling iter() on a reference can make sense because it
 +    // will allow further borrows afterwards
 +    let ty = cx.tables.expr_ty(e);
 +    is_iterable_array(ty, cx) ||
 +    is_type_diagnostic_item(cx, ty, sym!(vec_type)) ||
 +    match_type(cx, ty, &paths::LINKED_LIST) ||
 +    is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) ||
 +    is_type_diagnostic_item(cx, ty, sym!(hashset_type)) ||
 +    is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) ||
 +    match_type(cx, ty, &paths::BINARY_HEAP) ||
 +    match_type(cx, ty, &paths::BTREEMAP) ||
 +    match_type(cx, ty, &paths::BTREESET)
 +}
 +
 +fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'_, 'tcx>) -> bool {
 +    // IntoIterator is currently only implemented for array sizes <= 32 in rustc
 +    match ty.kind {
 +        ty::Array(_, n) => {
 +            if let Some(val) = n.try_eval_usize(cx.tcx, cx.param_env) {
 +                (0..=32).contains(&val)
 +            } else {
 +                false
 +            }
 +        },
 +        _ => false,
 +    }
 +}
 +
 +/// If a block begins with a statement (possibly a `let` binding) and has an
 +/// expression, return it.
 +fn extract_expr_from_first_stmt<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 +    if block.stmts.is_empty() {
 +        return None;
 +    }
 +    if let StmtKind::Local(ref local) = block.stmts[0].kind {
 +        if let Some(expr) = local.init {
 +            Some(expr)
 +        } else {
 +            None
 +        }
 +    } else {
 +        None
 +    }
 +}
 +
 +/// If a block begins with an expression (with or without semicolon), return it.
 +fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 +    match block.expr {
 +        Some(ref expr) if block.stmts.is_empty() => Some(expr),
 +        None if !block.stmts.is_empty() => match block.stmts[0].kind {
 +            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => Some(expr),
 +            StmtKind::Local(..) | StmtKind::Item(..) => None,
 +        },
 +        _ => None,
 +    }
 +}
 +
 +/// Returns `true` if expr contains a single break expr without destination label
 +/// and
 +/// passed expression. The expression may be within a block.
 +fn is_simple_break_expr(expr: &Expr<'_>) -> bool {
 +    match expr.kind {
 +        ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true,
 +        ExprKind::Block(ref b, _) => extract_first_expr(b).map_or(false, |subexpr| is_simple_break_expr(subexpr)),
 +        _ => false,
 +    }
 +}
 +
 +// To trigger the EXPLICIT_COUNTER_LOOP lint, a variable must be
 +// incremented exactly once in the loop body, and initialized to zero
 +// at the start of the loop.
 +#[derive(Debug, PartialEq)]
 +enum VarState {
 +    Initial,  // Not examined yet
 +    IncrOnce, // Incremented exactly once, may be a loop counter
 +    Declared, // Declared but not (yet) initialized to zero
 +    Warn,
 +    DontWarn,
 +}
 +
 +/// Scan a for loop for variables that are incremented exactly once.
 +struct IncrementVisitor<'a, 'tcx> {
 +    cx: &'a LateContext<'a, 'tcx>,      // context reference
 +    states: FxHashMap<HirId, VarState>, // incremented variables
 +    depth: u32,                         // depth of conditional expressions
 +    done: bool,
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if self.done {
 +            return;
 +        }
 +
 +        // If node is a variable
 +        if let Some(def_id) = var_def_id(self.cx, expr) {
 +            if let Some(parent) = get_parent_expr(self.cx, expr) {
 +                let state = self.states.entry(def_id).or_insert(VarState::Initial);
 +
 +                match parent.kind {
 +                    ExprKind::AssignOp(op, ref lhs, ref rhs) => {
 +                        if lhs.hir_id == expr.hir_id {
 +                            if op.node == BinOpKind::Add && is_integer_const(self.cx, rhs, 1) {
 +                                *state = match *state {
 +                                    VarState::Initial if self.depth == 0 => VarState::IncrOnce,
 +                                    _ => VarState::DontWarn,
 +                                };
 +                            } else {
 +                                // Assigned some other value
 +                                *state = VarState::DontWarn;
 +                            }
 +                        }
 +                    },
 +                    ExprKind::Assign(ref lhs, _, _) if lhs.hir_id == expr.hir_id => *state = VarState::DontWarn,
 +                    ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
 +                        *state = VarState::DontWarn
 +                    },
 +                    _ => (),
 +                }
 +            }
 +        } else if is_loop(expr) || is_conditional(expr) {
 +            self.depth += 1;
 +            walk_expr(self, expr);
 +            self.depth -= 1;
 +            return;
 +        } else if let ExprKind::Continue(_) = expr.kind {
 +            self.done = true;
 +            return;
 +        }
 +        walk_expr(self, expr);
 +    }
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +/// Checks whether a variable is initialized to zero at the start of a loop.
 +struct InitializeVisitor<'a, 'tcx> {
 +    cx: &'a LateContext<'a, 'tcx>, // context reference
 +    end_expr: &'tcx Expr<'tcx>,    // the for loop. Stop scanning here.
 +    var_id: HirId,
 +    state: VarState,
 +    name: Option<Name>,
 +    depth: u32, // depth of conditional expressions
 +    past_loop: bool,
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
 +        // Look for declarations of the variable
 +        if let StmtKind::Local(ref local) = stmt.kind {
 +            if local.pat.hir_id == self.var_id {
 +                if let PatKind::Binding(.., ident, _) = local.pat.kind {
 +                    self.name = Some(ident.name);
 +
 +                    self.state = if let Some(ref init) = local.init {
 +                        if is_integer_const(&self.cx, init, 0) {
 +                            VarState::Warn
 +                        } else {
 +                            VarState::Declared
 +                        }
 +                    } else {
 +                        VarState::Declared
 +                    }
 +                }
 +            }
 +        }
 +        walk_stmt(self, stmt);
 +    }
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if self.state == VarState::DontWarn {
 +            return;
 +        }
 +        if SpanlessEq::new(self.cx).eq_expr(&expr, self.end_expr) {
 +            self.past_loop = true;
 +            return;
 +        }
 +        // No need to visit expressions before the variable is
 +        // declared
 +        if self.state == VarState::IncrOnce {
 +            return;
 +        }
 +
 +        // If node is the desired variable, see how it's used
 +        if var_def_id(self.cx, expr) == Some(self.var_id) {
 +            if let Some(parent) = get_parent_expr(self.cx, expr) {
 +                match parent.kind {
 +                    ExprKind::AssignOp(_, ref lhs, _) if lhs.hir_id == expr.hir_id => {
 +                        self.state = VarState::DontWarn;
 +                    },
 +                    ExprKind::Assign(ref lhs, ref rhs, _) if lhs.hir_id == expr.hir_id => {
 +                        self.state = if is_integer_const(&self.cx, rhs, 0) && self.depth == 0 {
 +                            VarState::Warn
 +                        } else {
 +                            VarState::DontWarn
 +                        }
 +                    },
 +                    ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
 +                        self.state = VarState::DontWarn
 +                    },
 +                    _ => (),
 +                }
 +            }
 +
 +            if self.past_loop {
 +                self.state = VarState::DontWarn;
 +                return;
 +            }
 +        } else if !self.past_loop && is_loop(expr) {
 +            self.state = VarState::DontWarn;
 +            return;
 +        } else if is_conditional(expr) {
 +            self.depth += 1;
 +            walk_expr(self, expr);
 +            self.depth -= 1;
 +            return;
 +        }
 +        walk_expr(self, expr);
 +    }
 +
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
 +    }
 +}
 +
 +fn var_def_id(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<HirId> {
 +    if let ExprKind::Path(ref qpath) = expr.kind {
 +        let path_res = qpath_res(cx, qpath, expr.hir_id);
 +        if let Res::Local(hir_id) = path_res {
 +            return Some(hir_id);
 +        }
 +    }
 +    None
 +}
 +
 +fn is_loop(expr: &Expr<'_>) -> bool {
 +    match expr.kind {
 +        ExprKind::Loop(..) => true,
 +        _ => false,
 +    }
 +}
 +
 +fn is_conditional(expr: &Expr<'_>) -> bool {
 +    match expr.kind {
 +        ExprKind::Match(..) => true,
 +        _ => false,
 +    }
 +}
 +
 +fn is_nested(cx: &LateContext<'_, '_>, match_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool {
 +    if_chain! {
 +        if let Some(loop_block) = get_enclosing_block(cx, match_expr.hir_id);
 +        let parent_node = cx.tcx.hir().get_parent_node(loop_block.hir_id);
 +        if let Some(Node::Expr(loop_expr)) = cx.tcx.hir().find(parent_node);
 +        then {
 +            return is_loop_nested(cx, loop_expr, iter_expr)
 +        }
 +    }
 +    false
 +}
 +
 +fn is_loop_nested(cx: &LateContext<'_, '_>, loop_expr: &Expr<'_>, iter_expr: &Expr<'_>) -> bool {
 +    let mut id = loop_expr.hir_id;
 +    let iter_name = if let Some(name) = path_name(iter_expr) {
 +        name
 +    } else {
 +        return true;
 +    };
 +    loop {
 +        let parent = cx.tcx.hir().get_parent_node(id);
 +        if parent == id {
 +            return false;
 +        }
 +        match cx.tcx.hir().find(parent) {
 +            Some(Node::Expr(expr)) => {
 +                if let ExprKind::Loop(..) = expr.kind {
 +                    return true;
 +                };
 +            },
 +            Some(Node::Block(block)) => {
 +                let mut block_visitor = LoopNestVisitor {
 +                    hir_id: id,
 +                    iterator: iter_name,
 +                    nesting: Unknown,
 +                };
 +                walk_block(&mut block_visitor, block);
 +                if block_visitor.nesting == RuledOut {
 +                    return false;
 +                }
 +            },
 +            Some(Node::Stmt(_)) => (),
 +            _ => {
 +                return false;
 +            },
 +        }
 +        id = parent;
 +    }
 +}
 +
 +#[derive(PartialEq, Eq)]
 +enum Nesting {
 +    Unknown,     // no nesting detected yet
 +    RuledOut,    // the iterator is initialized or assigned within scope
 +    LookFurther, // no nesting detected, no further walk required
 +}
 +
 +use self::Nesting::{LookFurther, RuledOut, Unknown};
 +
 +struct LoopNestVisitor {
 +    hir_id: HirId,
 +    iterator: Name,
 +    nesting: Nesting,
 +}
 +
 +impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
 +        if stmt.hir_id == self.hir_id {
 +            self.nesting = LookFurther;
 +        } else if self.nesting == Unknown {
 +            walk_stmt(self, stmt);
 +        }
 +    }
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if self.nesting != Unknown {
 +            return;
 +        }
 +        if expr.hir_id == self.hir_id {
 +            self.nesting = LookFurther;
 +            return;
 +        }
 +        match expr.kind {
 +            ExprKind::Assign(ref path, _, _) | ExprKind::AssignOp(_, ref path, _) => {
 +                if match_var(path, self.iterator) {
 +                    self.nesting = RuledOut;
 +                }
 +            },
 +            _ => walk_expr(self, expr),
 +        }
 +    }
 +
 +    fn visit_pat(&mut self, pat: &'tcx Pat<'_>) {
 +        if self.nesting != Unknown {
 +            return;
 +        }
 +        if let PatKind::Binding(.., span_name, _) = pat.kind {
 +            if self.iterator == span_name.name {
 +                self.nesting = RuledOut;
 +                return;
 +            }
 +        }
 +        walk_pat(self, pat)
 +    }
 +
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +fn path_name(e: &Expr<'_>) -> Option<Name> {
 +    if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.kind {
 +        let segments = &path.segments;
 +        if segments.len() == 1 {
 +            return Some(segments[0].ident.name);
 +        }
 +    };
 +    None
 +}
 +
 +fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
 +    if constant(cx, cx.tables, cond).is_some() {
 +        // A pure constant condition (e.g., `while false`) is not linted.
 +        return;
 +    }
 +
 +    let mut var_visitor = VarCollectorVisitor {
 +        cx,
 +        ids: FxHashSet::default(),
 +        def_ids: FxHashMap::default(),
 +        skip: false,
 +    };
 +    var_visitor.visit_expr(cond);
 +    if var_visitor.skip {
 +        return;
 +    }
 +    let used_in_condition = &var_visitor.ids;
 +    let no_cond_variable_mutated = if let Some(used_mutably) = mutated_variables(expr, cx) {
 +        used_in_condition.is_disjoint(&used_mutably)
 +    } else {
 +        return;
 +    };
 +    let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
 +
 +    let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
 +        has_break_or_return: false,
 +    };
 +    has_break_or_return_visitor.visit_expr(expr);
 +    let has_break_or_return = has_break_or_return_visitor.has_break_or_return;
 +
 +    if no_cond_variable_mutated && !mutable_static_in_cond {
 +        span_lint_and_then(
 +            cx,
 +            WHILE_IMMUTABLE_CONDITION,
 +            cond.span,
 +            "variables in the condition are not mutated in the loop body",
 +            |diag| {
 +                diag.note("this may lead to an infinite or to a never running loop");
 +
 +                if has_break_or_return {
 +                    diag.note("this loop contains `return`s or `break`s");
 +                    diag.help("rewrite it as `if cond { loop { } }`");
 +                }
 +            },
 +        );
 +    }
 +}
 +
 +struct HasBreakOrReturnVisitor {
 +    has_break_or_return: bool,
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        if self.has_break_or_return {
 +            return;
 +        }
 +
 +        match expr.kind {
 +            ExprKind::Ret(_) | ExprKind::Break(_, _) => {
 +                self.has_break_or_return = true;
 +                return;
 +            },
 +            _ => {},
 +        }
 +
 +        walk_expr(self, expr);
 +    }
 +
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +/// Collects the set of variables in an expression
 +/// Stops analysis if a function call is found
 +/// Note: In some cases such as `self`, there are no mutable annotation,
 +/// All variables definition IDs are collected
 +struct VarCollectorVisitor<'a, 'tcx> {
 +    cx: &'a LateContext<'a, 'tcx>,
 +    ids: FxHashSet<HirId>,
 +    def_ids: FxHashMap<def_id::DefId, bool>,
 +    skip: bool,
 +}
 +
 +impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
 +    fn insert_def_id(&mut self, ex: &'tcx Expr<'_>) {
 +        if_chain! {
 +            if let ExprKind::Path(ref qpath) = ex.kind;
 +            if let QPath::Resolved(None, _) = *qpath;
 +            let res = qpath_res(self.cx, qpath, ex.hir_id);
 +            then {
 +                match res {
 +                    Res::Local(hir_id) => {
 +                        self.ids.insert(hir_id);
 +                    },
 +                    Res::Def(DefKind::Static, def_id) => {
 +                        let mutable = self.cx.tcx.is_mutable_static(def_id);
 +                        self.def_ids.insert(def_id, mutable);
 +                    },
 +                    _ => {},
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
 +        match ex.kind {
 +            ExprKind::Path(_) => self.insert_def_id(ex),
 +            // If there is any function/method call… we just stop analysis
 +            ExprKind::Call(..) | ExprKind::MethodCall(..) => self.skip = true,
 +
 +            _ => walk_expr(self, ex),
 +        }
 +    }
 +
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
 +
 +fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) {
 +    if_chain! {
 +        if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind;
 +        if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].kind;
 +        if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR);
 +        if let Some(ref generic_args) = chain_method.args;
 +        if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
 +        then {
 +            let ty = cx.tables.node_type(ty.hir_id);
 +            if is_type_diagnostic_item(cx, ty, sym!(vec_type)) ||
 +                is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) ||
 +                match_type(cx, ty, &paths::BTREEMAP) ||
 +                is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) {
 +                if method.ident.name == sym!(len) {
 +                    let span = shorten_needless_collect_span(expr);
 +                    span_lint_and_sugg(
 +                        cx,
 +                        NEEDLESS_COLLECT,
 +                        span,
 +                        NEEDLESS_COLLECT_MSG,
 +                        "replace with",
 +                        ".count()".to_string(),
 +                        Applicability::MachineApplicable,
 +                    );
 +                }
 +                if method.ident.name == sym!(is_empty) {
 +                    let span = shorten_needless_collect_span(expr);
 +                    span_lint_and_sugg(
 +                        cx,
 +                        NEEDLESS_COLLECT,
 +                        span,
 +                        NEEDLESS_COLLECT_MSG,
 +                        "replace with",
 +                        ".next().is_none()".to_string(),
 +                        Applicability::MachineApplicable,
 +                    );
 +                }
 +                if method.ident.name == sym!(contains) {
 +                    let contains_arg = snippet(cx, args[1].span, "??");
 +                    let span = shorten_needless_collect_span(expr);
 +                    span_lint_and_then(
 +                        cx,
 +                        NEEDLESS_COLLECT,
 +                        span,
 +                        NEEDLESS_COLLECT_MSG,
 +                        |diag| {
 +                            let (arg, pred) = if contains_arg.starts_with('&') {
 +                                ("x", &contains_arg[1..])
 +                            } else {
 +                                ("&x", &*contains_arg)
 +                            };
 +                            diag.span_suggestion(
 +                                span,
 +                                "replace with",
 +                                format!(
 +                                    ".any(|{}| x == {})",
 +                                    arg, pred
 +                                ),
 +                                Applicability::MachineApplicable,
 +                            );
 +                        }
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +fn shorten_needless_collect_span(expr: &Expr<'_>) -> Span {
 +    if_chain! {
 +        if let ExprKind::MethodCall(_, _, ref args) = expr.kind;
 +        if let ExprKind::MethodCall(_, ref span, _) = args[0].kind;
 +        then {
 +            return expr.span.with_lo(span.lo() - BytePos(1));
 +        }
 +    }
 +    unreachable!()
 +}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cb72a24058234dcafce74496cc8431f2391f67db
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,159 @@@
++use crate::utils::paths::FUTURE_FROM_GENERATOR;
++use crate::utils::{match_function_call, snippet_block, snippet_opt, span_lint_and_then};
++use if_chain::if_chain;
++use rustc_errors::Applicability;
++use rustc_hir::intravisit::FnKind;
++use rustc_hir::{
++    AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericBound, HirId, IsAsync,
++    ItemKind, TraitRef, Ty, TyKind, TypeBindingKind,
++};
++use rustc_lint::{LateContext, LateLintPass};
++use rustc_session::{declare_lint_pass, declare_tool_lint};
++use rustc_span::Span;
++
++declare_clippy_lint! {
++    /// **What it does:** It checks for manual implementations of `async` functions.
++    ///
++    /// **Why is this bad?** It's more idiomatic to use the dedicated syntax.
++    ///
++    /// **Known problems:** None.
++    ///
++    /// **Example:**
++    ///
++    /// ```rust
++    /// use std::future::Future;
++    ///
++    /// fn foo() -> impl Future<Output = i32> { async { 42 } }
++    /// ```
++    /// Use instead:
++    /// ```rust
++    /// use std::future::Future;
++    ///
++    /// async fn foo() -> i32 { 42 }
++    /// ```
++    pub MANUAL_ASYNC_FN,
++    style,
++    "manual implementations of `async` functions can be simplified using the dedicated syntax"
++}
++
++declare_lint_pass!(ManualAsyncFn => [MANUAL_ASYNC_FN]);
++
++impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn {
++    fn check_fn(
++        &mut self,
++        cx: &LateContext<'a, 'tcx>,
++        kind: FnKind<'tcx>,
++        decl: &'tcx FnDecl<'_>,
++        body: &'tcx Body<'_>,
++        span: Span,
++        _: HirId,
++    ) {
++        if_chain! {
++            if let Some(header) = kind.header();
++            if let IsAsync::NotAsync = header.asyncness;
++            // Check that this function returns `impl Future`
++            if let FnRetTy::Return(ret_ty) = decl.output;
++            if let Some(trait_ref) = future_trait_ref(cx, ret_ty);
++            if let Some(output) = future_output_ty(trait_ref);
++            // Check that the body of the function consists of one async block
++            if let ExprKind::Block(block, _) = body.value.kind;
++            if block.stmts.is_empty();
++            if let Some(closure_body) = desugared_async_block(cx, block);
++            then {
++                let header_span = span.with_hi(ret_ty.span.hi());
++
++                span_lint_and_then(
++                    cx,
++                    MANUAL_ASYNC_FN,
++                    header_span,
++                    "this function can be simplified using the `async fn` syntax",
++                    |diag| {
++                        if_chain! {
++                            if let Some(header_snip) = snippet_opt(cx, header_span);
++                            if let Some(ret_pos) = header_snip.rfind("->");
++                            if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
++                            then {
++                                let help = format!("make the function `async` and {}", ret_sugg);
++                                diag.span_suggestion(
++                                    header_span,
++                                    &help,
++                                    format!("async {}{}", &header_snip[..ret_pos], ret_snip),
++                                    Applicability::MachineApplicable
++                                );
++
++                                let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span));
++                                diag.span_suggestion(
++                                    block.span,
++                                    "move the body of the async block to the enclosing function",
++                                    body_snip.to_string(),
++                                    Applicability::MachineApplicable
++                                );
++                            }
++                        }
++                    },
++                );
++            }
++        }
++    }
++}
++
++fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
++    if_chain! {
++        if let TyKind::Def(item_id, _) = ty.kind;
++        let item = cx.tcx.hir().item(item_id.id);
++        if let ItemKind::OpaqueTy(opaque) = &item.kind;
++        if opaque.bounds.len() == 1;
++        if let GenericBound::Trait(poly, _) = &opaque.bounds[0];
++        if poly.trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait();
++        then {
++            return Some(&poly.trait_ref);
++        }
++    }
++
++    None
++}
++
++fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> {
++    if_chain! {
++        if let Some(segment) = trait_ref.path.segments.last();
++        if let Some(args) = segment.args;
++        if args.bindings.len() == 1;
++        let binding = &args.bindings[0];
++        if binding.ident.as_str() == "Output";
++        if let TypeBindingKind::Equality{ty: output} = binding.kind;
++        then {
++            return Some(output)
++        }
++    }
++
++    None
++}
++
++fn desugared_async_block<'tcx>(cx: &LateContext<'_, 'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
++    if_chain! {
++        if let Some(block_expr) = block.expr;
++        if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR);
++        if args.len() == 1;
++        if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0];
++        let closure_body = cx.tcx.hir().body(body_id);
++        if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind;
++        then {
++            return Some(closure_body);
++        }
++    }
++
++    None
++}
++
++fn suggested_ret(cx: &LateContext<'_, '_>, output: &Ty<'_>) -> Option<(&'static str, String)> {
++    match output.kind {
++        TyKind::Tup(tys) if tys.is_empty() => {
++            let sugg = "remove the return type";
++            Some((sugg, "".into()))
++        },
++        _ => {
++            let sugg = "return the output of the future directly";
++            snippet_opt(cx, output.span).map(|snip| (sugg, format!("-> {}", snip)))
++        },
++    }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f3b8902e26f672f4df92b63f07da040c67734b44
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,173 @@@
++use crate::utils::{snippet_opt, span_lint_and_then};
++use if_chain::if_chain;
++use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
++use rustc_attr as attr;
++use rustc_errors::Applicability;
++use rustc_lint::{EarlyContext, EarlyLintPass};
++use rustc_session::{declare_lint_pass, declare_tool_lint};
++use rustc_span::Span;
++
++declare_clippy_lint! {
++    /// **What it does:** Checks for manual implementations of the non-exhaustive pattern.
++    ///
++    /// **Why is this bad?** Using the #[non_exhaustive] attribute expresses better the intent
++    /// and allows possible optimizations when applied to enums.
++    ///
++    /// **Known problems:** None.
++    ///
++    /// **Example:**
++    ///
++    /// ```rust
++    /// struct S {
++    ///     pub a: i32,
++    ///     pub b: i32,
++    ///     _c: (),
++    /// }
++    ///
++    /// enum E {
++    ///     A,
++    ///     B,
++    ///     #[doc(hidden)]
++    ///     _C,
++    /// }
++    ///
++    /// struct T(pub i32, pub i32, ());
++    /// ```
++    /// Use instead:
++    /// ```rust
++    /// #[non_exhaustive]
++    /// struct S {
++    ///     pub a: i32,
++    ///     pub b: i32,
++    /// }
++    ///
++    /// #[non_exhaustive]
++    /// enum E {
++    ///     A,
++    ///     B,
++    /// }
++    ///
++    /// #[non_exhaustive]
++    /// struct T(pub i32, pub i32);
++    /// ```
++    pub MANUAL_NON_EXHAUSTIVE,
++    style,
++    "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
++}
++
++declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
++
++impl EarlyLintPass for ManualNonExhaustive {
++    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
++        match &item.kind {
++            ItemKind::Enum(def, _) => {
++                check_manual_non_exhaustive_enum(cx, item, &def.variants);
++            },
++            ItemKind::Struct(variant_data, _) => {
++                if let VariantData::Unit(..) = variant_data {
++                    return;
++                }
++
++                check_manual_non_exhaustive_struct(cx, item, variant_data);
++            },
++            _ => {},
++        }
++    }
++}
++
++fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
++    fn is_non_exhaustive_marker(variant: &Variant) -> bool {
++        matches!(variant.data, VariantData::Unit(_))
++            && variant.ident.as_str().starts_with('_')
++            && variant.attrs.iter().any(|a| is_doc_hidden(a))
++    }
++
++    fn is_doc_hidden(attr: &Attribute) -> bool {
++        attr.check_name(sym!(doc))
++            && match attr.meta_item_list() {
++                Some(l) => attr::list_contains_name(&l, sym!(hidden)),
++                None => false,
++            }
++    }
++
++    if_chain! {
++        let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v));
++        if let Some(marker) = markers.next();
++        if markers.count() == 0 && variants.len() > 1;
++        then {
++            span_lint_and_then(
++                cx,
++                MANUAL_NON_EXHAUSTIVE,
++                item.span,
++                "this seems like a manual implementation of the non-exhaustive pattern",
++                |diag| {
++                    if_chain! {
++                        if !attr::contains_name(&item.attrs, sym!(non_exhaustive));
++                        let header_span = cx.sess.source_map().span_until_char(item.span, '{');
++                        if let Some(snippet) = snippet_opt(cx, header_span);
++                        then {
++                            diag.span_suggestion(
++                                header_span,
++                                "add the attribute",
++                                format!("#[non_exhaustive] {}", snippet),
++                                Applicability::Unspecified,
++                            );
++                        }
++                    }
++                    diag.span_help(marker.span, "remove this variant");
++                });
++        }
++    }
++}
++
++fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) {
++    fn is_private(field: &StructField) -> bool {
++        matches!(field.vis.node, VisibilityKind::Inherited)
++    }
++
++    fn is_non_exhaustive_marker(field: &StructField) -> bool {
++        is_private(field) && field.ty.kind.is_unit() && field.ident.map_or(true, |n| n.as_str().starts_with('_'))
++    }
++
++    fn find_header_span(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) -> Span {
++        let delimiter = match data {
++            VariantData::Struct(..) => '{',
++            VariantData::Tuple(..) => '(',
++            VariantData::Unit(_) => unreachable!("`VariantData::Unit` is already handled above"),
++        };
++
++        cx.sess.source_map().span_until_char(item.span, delimiter)
++    }
++
++    let fields = data.fields();
++    let private_fields = fields.iter().filter(|f| is_private(f)).count();
++    let public_fields = fields.iter().filter(|f| f.vis.node.is_pub()).count();
++
++    if_chain! {
++        if private_fields == 1 && public_fields >= 1 && public_fields == fields.len() - 1;
++        if let Some(marker) = fields.iter().find(|f| is_non_exhaustive_marker(f));
++        then {
++            span_lint_and_then(
++                cx,
++                MANUAL_NON_EXHAUSTIVE,
++                item.span,
++                "this seems like a manual implementation of the non-exhaustive pattern",
++                |diag| {
++                    if_chain! {
++                        if !attr::contains_name(&item.attrs, sym!(non_exhaustive));
++                        let header_span = find_header_span(cx, item, data);
++                        if let Some(snippet) = snippet_opt(cx, header_span);
++                        then {
++                            diag.span_suggestion(
++                                header_span,
++                                "add the attribute",
++                                format!("#[non_exhaustive] {}", snippet),
++                                Applicability::Unspecified,
++                            );
++                        }
++                    }
++                    diag.span_help(marker.span, "remove this field");
++                });
++        }
++    }
++}
index 4071406cc84c3366cd29e94d6e0012038ebe0cf1,0000000000000000000000000000000000000000..ee69628e9f05224953a8e9d3680f83c263efe6ef
mode 100644,000000..100644
--- /dev/null
@@@ -1,89 -1,0 +1,100 @@@
- use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_sugg, walk_ptrs_ty};
++use crate::utils::{self, is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty};
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir::{Expr, ExprKind, MatchSource};
 +use rustc_lint::{LateContext, LateLintPass, LintContext};
 +use rustc_middle::lint::in_external_macro;
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for `match vec[idx]` or `match vec[n..m]`.
 +    ///
 +    /// **Why is this bad?** This can panic at runtime.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust, no_run
 +    /// let arr = vec![0, 1, 2, 3];
 +    /// let idx = 1;
 +    ///
 +    /// // Bad
 +    /// match arr[idx] {
 +    ///     0 => println!("{}", 0),
 +    ///     1 => println!("{}", 3),
 +    ///     _ => {},
 +    /// }
 +    /// ```
 +    /// Use instead:
 +    /// ```rust, no_run
 +    /// let arr = vec![0, 1, 2, 3];
 +    /// let idx = 1;
 +    ///
 +    /// // Good
 +    /// match arr.get(idx) {
 +    ///     Some(0) => println!("{}", 0),
 +    ///     Some(1) => println!("{}", 3),
 +    ///     _ => {},
 +    /// }
 +    /// ```
 +    pub MATCH_ON_VEC_ITEMS,
-     correctness,
++    pedantic,
 +    "matching on vector elements can panic"
 +}
 +
 +declare_lint_pass!(MatchOnVecItems => [MATCH_ON_VEC_ITEMS]);
 +
 +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchOnVecItems {
 +    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) {
 +        if_chain! {
 +            if !in_external_macro(cx.sess(), expr.span);
 +            if let ExprKind::Match(ref match_expr, _, MatchSource::Normal) = expr.kind;
 +            if let Some(idx_expr) = is_vec_indexing(cx, match_expr);
 +            if let ExprKind::Index(vec, idx) = idx_expr.kind;
 +
 +            then {
 +                // FIXME: could be improved to suggest surrounding every pattern with Some(_),
 +                // but only when `or_patterns` are stabilized.
 +                span_lint_and_sugg(
 +                    cx,
 +                    MATCH_ON_VEC_ITEMS,
 +                    match_expr.span,
 +                    "indexing into a vector may panic",
 +                    "try this",
 +                    format!(
 +                        "{}.get({})",
 +                        snippet(cx, vec.span, ".."),
 +                        snippet(cx, idx.span, "..")
 +                    ),
 +                    Applicability::MaybeIncorrect
 +                );
 +            }
 +        }
 +    }
 +}
 +
 +fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 +    if_chain! {
-         if let ExprKind::Index(ref array, _) = expr.kind;
-         let ty = cx.tables.expr_ty(array);
-         let ty = walk_ptrs_ty(ty);
-         if is_type_diagnostic_item(cx, ty, sym!(vec_type));
++        if let ExprKind::Index(ref array, ref index) = expr.kind;
++        if is_vector(cx, array);
++        if !is_full_range(cx, index);
 +
 +        then {
 +            return Some(expr);
 +        }
 +    }
 +
 +    None
 +}
++
++fn is_vector(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
++    let ty = cx.tables.expr_ty(expr);
++    let ty = walk_ptrs_ty(ty);
++    is_type_diagnostic_item(cx, ty, sym!(vec_type))
++}
++
++fn is_full_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
++    let ty = cx.tables.expr_ty(expr);
++    let ty = walk_ptrs_ty(ty);
++    match_type(cx, ty, &utils::paths::RANGE_FULL)
++}
index adfd8dfb1c18af5abcdb6d4eca6414e9803ed86f,0000000000000000000000000000000000000000..62ee051624b488afe3411b463204516acf408169
mode 100644,000000..100644
--- /dev/null
@@@ -1,638 -1,0 +1,655 @@@
-     /// ```ignore
-     /// let { a: _, b: ref b, c: _ } = ..
 +use crate::utils::{
 +    constants, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg,
 +    span_lint_and_then,
 +};
 +use if_chain::if_chain;
 +use rustc_ast::ast::{
 +    BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability,
 +    NodeId, Pat, PatKind, StmtKind, UnOp,
 +};
 +use rustc_ast::visit::{walk_expr, FnKind, Visitor};
 +use rustc_data_structures::fx::FxHashMap;
 +use rustc_errors::Applicability;
 +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 +use rustc_middle::lint::in_external_macro;
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::source_map::Span;
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for structure field patterns bound to wildcards.
 +    ///
 +    /// **Why is this bad?** Using `..` instead is shorter and leaves the focus on
 +    /// the fields that are actually bound.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
++    /// ```rust
++    /// # struct Foo {
++    /// #     a: i32,
++    /// #     b: i32,
++    /// #     c: i32,
++    /// # }
++    /// let f = Foo { a: 0, b: 0, c: 0 };
++    ///
++    /// // Bad
++    /// match f {
++    ///     Foo { a: _, b: 0, .. } => {},
++    ///     Foo { a: _, b: _, c: _ } => {},
++    /// }
++    ///
++    /// // Good
++    /// match f {
++    ///     Foo { b: 0, .. } => {},
++    ///     Foo { .. } => {},
++    /// }
 +    /// ```
 +    pub UNNEEDED_FIELD_PATTERN,
 +    restriction,
 +    "struct fields bound to a wildcard instead of using `..`"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for function arguments having the similar names
 +    /// differing by an underscore.
 +    ///
 +    /// **Why is this bad?** It affects code readability.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// fn foo(a: i32, _a: i32) {}
 +    /// ```
 +    pub DUPLICATE_UNDERSCORE_ARGUMENT,
 +    style,
 +    "function arguments having names which only differ by an underscore"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Detects closures called in the same expression where they
 +    /// are defined.
 +    ///
 +    /// **Why is this bad?** It is unnecessarily adding to the expression's
 +    /// complexity.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust,ignore
 +    /// (|| 42)()
 +    /// ```
 +    pub REDUNDANT_CLOSURE_CALL,
 +    complexity,
 +    "throwaway closures called in the expression they are defined"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Detects expressions of the form `--x`.
 +    ///
 +    /// **Why is this bad?** It can mislead C/C++ programmers to think `x` was
 +    /// decremented.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// let mut x = 3;
 +    /// --x;
 +    /// ```
 +    pub DOUBLE_NEG,
 +    style,
 +    "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Warns on hexadecimal literals with mixed-case letter
 +    /// digits.
 +    ///
 +    /// **Why is this bad?** It looks confusing.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// let y = 0x1a9BAcD;
 +    /// ```
 +    pub MIXED_CASE_HEX_LITERALS,
 +    style,
 +    "hex literals whose letter digits are not consistently upper- or lowercased"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Warns if literal suffixes are not separated by an
 +    /// underscore.
 +    ///
 +    /// **Why is this bad?** It is much less readable.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// let y = 123832i32;
 +    /// ```
 +    pub UNSEPARATED_LITERAL_SUFFIX,
 +    pedantic,
 +    "literals whose suffix is not separated by an underscore"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Warns if an integral constant literal starts with `0`.
 +    ///
 +    /// **Why is this bad?** In some languages (including the infamous C language
 +    /// and most of its
 +    /// family), this marks an octal constant. In Rust however, this is a decimal
 +    /// constant. This could
 +    /// be confusing for both the writer and a reader of the constant.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    ///
 +    /// In Rust:
 +    /// ```rust
 +    /// fn main() {
 +    ///     let a = 0123;
 +    ///     println!("{}", a);
 +    /// }
 +    /// ```
 +    ///
 +    /// prints `123`, while in C:
 +    ///
 +    /// ```c
 +    /// #include <stdio.h>
 +    ///
 +    /// int main() {
 +    ///     int a = 0123;
 +    ///     printf("%d\n", a);
 +    /// }
 +    /// ```
 +    ///
 +    /// prints `83` (as `83 == 0o123` while `123 == 0o173`).
 +    pub ZERO_PREFIXED_LITERAL,
 +    complexity,
 +    "integer literals starting with `0`"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Warns if a generic shadows a built-in type.
 +    ///
 +    /// **Why is this bad?** This gives surprising type errors.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    ///
 +    /// ```ignore
 +    /// impl<u32> Foo<u32> {
 +    ///     fn impl_func(&self) -> u32 {
 +    ///         42
 +    ///     }
 +    /// }
 +    /// ```
 +    pub BUILTIN_TYPE_SHADOW,
 +    style,
 +    "shadowing a builtin type"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for patterns in the form `name @ _`.
 +    ///
 +    /// **Why is this bad?** It's almost always more readable to just use direct
 +    /// bindings.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let v = Some("abc");
 +    ///
 +    /// match v {
 +    ///     Some(x) => (),
 +    ///     y @ _ => (), // easier written as `y`,
 +    /// }
 +    /// ```
 +    pub REDUNDANT_PATTERN,
 +    style,
 +    "using `name @ _` in a pattern"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for tuple patterns with a wildcard
 +    /// pattern (`_`) is next to a rest pattern (`..`).
 +    ///
 +    /// _NOTE_: While `_, ..` means there is at least one element left, `..`
 +    /// means there are 0 or more elements left. This can make a difference
 +    /// when refactoring, but shouldn't result in errors in the refactored code,
 +    /// since the wildcard pattern isn't used anyway.
 +    /// **Why is this bad?** The wildcard pattern is unneeded as the rest pattern
 +    /// can match that element as well.
 +    ///
 +    /// **Known problems:** None.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # struct TupleStruct(u32, u32, u32);
 +    /// # let t = TupleStruct(1, 2, 3);
 +    ///
 +    /// match t {
 +    ///     TupleStruct(0, .., _) => (),
 +    ///     _ => (),
 +    /// }
 +    /// ```
 +    /// can be written as
 +    /// ```rust
 +    /// # struct TupleStruct(u32, u32, u32);
 +    /// # let t = TupleStruct(1, 2, 3);
 +    ///
 +    /// match t {
 +    ///     TupleStruct(0, ..) => (),
 +    ///     _ => (),
 +    /// }
 +    /// ```
 +    pub UNNEEDED_WILDCARD_PATTERN,
 +    complexity,
 +    "tuple patterns with a wildcard pattern (`_`) is next to a rest pattern (`..`)"
 +}
 +
 +declare_lint_pass!(MiscEarlyLints => [
 +    UNNEEDED_FIELD_PATTERN,
 +    DUPLICATE_UNDERSCORE_ARGUMENT,
 +    REDUNDANT_CLOSURE_CALL,
 +    DOUBLE_NEG,
 +    MIXED_CASE_HEX_LITERALS,
 +    UNSEPARATED_LITERAL_SUFFIX,
 +    ZERO_PREFIXED_LITERAL,
 +    BUILTIN_TYPE_SHADOW,
 +    REDUNDANT_PATTERN,
 +    UNNEEDED_WILDCARD_PATTERN,
 +]);
 +
 +// Used to find `return` statements or equivalents e.g., `?`
 +struct ReturnVisitor {
 +    found_return: bool,
 +}
 +
 +impl ReturnVisitor {
 +    #[must_use]
 +    fn new() -> Self {
 +        Self { found_return: false }
 +    }
 +}
 +
 +impl<'ast> Visitor<'ast> for ReturnVisitor {
 +    fn visit_expr(&mut self, ex: &'ast Expr) {
 +        if let ExprKind::Ret(_) = ex.kind {
 +            self.found_return = true;
 +        } else if let ExprKind::Try(_) = ex.kind {
 +            self.found_return = true;
 +        }
 +
 +        walk_expr(self, ex)
 +    }
 +}
 +
 +impl EarlyLintPass for MiscEarlyLints {
 +    fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) {
 +        for param in &gen.params {
 +            if let GenericParamKind::Type { .. } = param.kind {
 +                let name = param.ident.as_str();
 +                if constants::BUILTIN_TYPES.contains(&&*name) {
 +                    span_lint(
 +                        cx,
 +                        BUILTIN_TYPE_SHADOW,
 +                        param.ident.span,
 +                        &format!("This generic shadows the built-in type `{}`", name),
 +                    );
 +                }
 +            }
 +        }
 +    }
 +
 +    fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
 +        if let PatKind::Struct(ref npat, ref pfields, _) = pat.kind {
 +            let mut wilds = 0;
 +            let type_name = npat
 +                .segments
 +                .last()
 +                .expect("A path must have at least one segment")
 +                .ident
 +                .name;
 +
 +            for field in pfields {
 +                if let PatKind::Wild = field.pat.kind {
 +                    wilds += 1;
 +                }
 +            }
 +            if !pfields.is_empty() && wilds == pfields.len() {
 +                span_lint_and_help(
 +                    cx,
 +                    UNNEEDED_FIELD_PATTERN,
 +                    pat.span,
 +                    "All the struct fields are matched to a wildcard pattern, consider using `..`.",
 +                    None,
 +                    &format!("Try with `{} {{ .. }}` instead", type_name),
 +                );
 +                return;
 +            }
 +            if wilds > 0 {
 +                for field in pfields {
 +                    if let PatKind::Wild = field.pat.kind {
 +                        wilds -= 1;
 +                        if wilds > 0 {
 +                            span_lint(
 +                                cx,
 +                                UNNEEDED_FIELD_PATTERN,
 +                                field.span,
 +                                "You matched a field with a wildcard pattern. Consider using `..` instead",
 +                            );
 +                        } else {
 +                            let mut normal = vec![];
 +
 +                            for field in pfields {
 +                                match field.pat.kind {
 +                                    PatKind::Wild => {},
 +                                    _ => {
 +                                        if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
 +                                            normal.push(n);
 +                                        }
 +                                    },
 +                                }
 +                            }
 +
 +                            span_lint_and_help(
 +                                cx,
 +                                UNNEEDED_FIELD_PATTERN,
 +                                field.span,
 +                                "You matched a field with a wildcard pattern. Consider using `..` \
 +                                 instead",
 +                                None,
 +                                &format!("Try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")),
 +                            );
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +
 +        if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind {
 +            let left_binding = match left {
 +                BindingMode::ByRef(Mutability::Mut) => "ref mut ",
 +                BindingMode::ByRef(Mutability::Not) => "ref ",
 +                _ => "",
 +            };
 +
 +            if let PatKind::Wild = right.kind {
 +                span_lint_and_sugg(
 +                    cx,
 +                    REDUNDANT_PATTERN,
 +                    pat.span,
 +                    &format!(
 +                        "the `{} @ _` pattern can be written as just `{}`",
 +                        ident.name, ident.name,
 +                    ),
 +                    "try",
 +                    format!("{}{}", left_binding, ident.name),
 +                    Applicability::MachineApplicable,
 +                );
 +            }
 +        }
 +
 +        check_unneeded_wildcard_pattern(cx, pat);
 +    }
 +
 +    fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) {
 +        let mut registered_names: FxHashMap<String, Span> = FxHashMap::default();
 +
 +        for arg in &fn_kind.decl().inputs {
 +            if let PatKind::Ident(_, ident, None) = arg.pat.kind {
 +                let arg_name = ident.to_string();
 +
 +                if arg_name.starts_with('_') {
 +                    if let Some(correspondence) = registered_names.get(&arg_name[1..]) {
 +                        span_lint(
 +                            cx,
 +                            DUPLICATE_UNDERSCORE_ARGUMENT,
 +                            *correspondence,
 +                            &format!(
 +                                "`{}` already exists, having another argument having almost the same \
 +                                 name makes code comprehension and documentation more difficult",
 +                                arg_name[1..].to_owned()
 +                            ),
 +                        );
 +                    }
 +                } else {
 +                    registered_names.insert(arg_name, arg.pat.span);
 +                }
 +            }
 +        }
 +    }
 +
 +    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
 +        if in_external_macro(cx.sess(), expr.span) {
 +            return;
 +        }
 +        match expr.kind {
 +            ExprKind::Call(ref paren, _) => {
 +                if let ExprKind::Paren(ref closure) = paren.kind {
 +                    if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind {
 +                        let mut visitor = ReturnVisitor::new();
 +                        visitor.visit_expr(block);
 +                        if !visitor.found_return {
 +                            span_lint_and_then(
 +                                cx,
 +                                REDUNDANT_CLOSURE_CALL,
 +                                expr.span,
 +                                "Try not to call a closure in the expression where it is declared.",
 +                                |diag| {
 +                                    if decl.inputs.is_empty() {
 +                                        let mut app = Applicability::MachineApplicable;
 +                                        let hint =
 +                                            snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
 +                                        diag.span_suggestion(expr.span, "Try doing something like: ", hint, app);
 +                                    }
 +                                },
 +                            );
 +                        }
 +                    }
 +                }
 +            },
 +            ExprKind::Unary(UnOp::Neg, ref inner) => {
 +                if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
 +                    span_lint(
 +                        cx,
 +                        DOUBLE_NEG,
 +                        expr.span,
 +                        "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
 +                    );
 +                }
 +            },
 +            ExprKind::Lit(ref lit) => Self::check_lit(cx, lit),
 +            _ => (),
 +        }
 +    }
 +
 +    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
 +        for w in block.stmts.windows(2) {
 +            if_chain! {
 +                if let StmtKind::Local(ref local) = w[0].kind;
 +                if let Option::Some(ref t) = local.init;
 +                if let ExprKind::Closure(..) = t.kind;
 +                if let PatKind::Ident(_, ident, _) = local.pat.kind;
 +                if let StmtKind::Semi(ref second) = w[1].kind;
 +                if let ExprKind::Assign(_, ref call, _) = second.kind;
 +                if let ExprKind::Call(ref closure, _) = call.kind;
 +                if let ExprKind::Path(_, ref path) = closure.kind;
 +                then {
 +                    if ident == path.segments[0].ident {
 +                        span_lint(
 +                            cx,
 +                            REDUNDANT_CLOSURE_CALL,
 +                            second.span,
 +                            "Closure called just once immediately after it was declared",
 +                        );
 +                    }
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +impl MiscEarlyLints {
 +    fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
 +        // We test if first character in snippet is a number, because the snippet could be an expansion
 +        // from a built-in macro like `line!()` or a proc-macro like `#[wasm_bindgen]`.
 +        // Note that this check also covers special case that `line!()` is eagerly expanded by compiler.
 +        // See <https://github.com/rust-lang/rust-clippy/issues/4507> for a regression.
 +        // FIXME: Find a better way to detect those cases.
 +        let lit_snip = match snippet_opt(cx, lit.span) {
 +            Some(snip) if snip.chars().next().map_or(false, |c| c.is_digit(10)) => snip,
 +            _ => return,
 +        };
 +
 +        if let LitKind::Int(value, lit_int_type) = lit.kind {
 +            let suffix = match lit_int_type {
 +                LitIntType::Signed(ty) => ty.name_str(),
 +                LitIntType::Unsigned(ty) => ty.name_str(),
 +                LitIntType::Unsuffixed => "",
 +            };
 +
 +            let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
 +                val
 +            } else {
 +                return; // It's useless so shouldn't lint.
 +            };
 +            // Do not lint when literal is unsuffixed.
 +            if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
 +                span_lint_and_sugg(
 +                    cx,
 +                    UNSEPARATED_LITERAL_SUFFIX,
 +                    lit.span,
 +                    "integer type suffix should be separated by an underscore",
 +                    "add an underscore",
 +                    format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
 +                    Applicability::MachineApplicable,
 +                );
 +            }
 +
 +            if lit_snip.starts_with("0x") {
 +                if maybe_last_sep_idx <= 2 {
 +                    // It's meaningless or causes range error.
 +                    return;
 +                }
 +                let mut seen = (false, false);
 +                for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() {
 +                    match ch {
 +                        b'a'..=b'f' => seen.0 = true,
 +                        b'A'..=b'F' => seen.1 = true,
 +                        _ => {},
 +                    }
 +                    if seen.0 && seen.1 {
 +                        span_lint(
 +                            cx,
 +                            MIXED_CASE_HEX_LITERALS,
 +                            lit.span,
 +                            "inconsistent casing in hexadecimal literal",
 +                        );
 +                        break;
 +                    }
 +                }
 +            } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
 +                /* nothing to do */
 +            } else if value != 0 && lit_snip.starts_with('0') {
 +                span_lint_and_then(
 +                    cx,
 +                    ZERO_PREFIXED_LITERAL,
 +                    lit.span,
 +                    "this is a decimal constant",
 +                    |diag| {
 +                        diag.span_suggestion(
 +                            lit.span,
 +                            "if you mean to use a decimal constant, remove the `0` to avoid confusion",
 +                            lit_snip.trim_start_matches(|c| c == '_' || c == '0').to_string(),
 +                            Applicability::MaybeIncorrect,
 +                        );
 +                        diag.span_suggestion(
 +                            lit.span,
 +                            "if you mean to use an octal constant, use `0o`",
 +                            format!("0o{}", lit_snip.trim_start_matches(|c| c == '_' || c == '0')),
 +                            Applicability::MaybeIncorrect,
 +                        );
 +                    },
 +                );
 +            }
 +        } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
 +            let suffix = float_ty.name_str();
 +            let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
 +                val
 +            } else {
 +                return; // It's useless so shouldn't lint.
 +            };
 +            if lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
 +                span_lint_and_sugg(
 +                    cx,
 +                    UNSEPARATED_LITERAL_SUFFIX,
 +                    lit.span,
 +                    "float type suffix should be separated by an underscore",
 +                    "add an underscore",
 +                    format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
 +                    Applicability::MachineApplicable,
 +                );
 +            }
 +        }
 +    }
 +}
 +
 +fn check_unneeded_wildcard_pattern(cx: &EarlyContext<'_>, pat: &Pat) {
 +    if let PatKind::TupleStruct(_, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind {
 +        fn span_lint(cx: &EarlyContext<'_>, span: Span, only_one: bool) {
 +            span_lint_and_sugg(
 +                cx,
 +                UNNEEDED_WILDCARD_PATTERN,
 +                span,
 +                if only_one {
 +                    "this pattern is unneeded as the `..` pattern can match that element"
 +                } else {
 +                    "these patterns are unneeded as the `..` pattern can match those elements"
 +                },
 +                if only_one { "remove it" } else { "remove them" },
 +                "".to_string(),
 +                Applicability::MachineApplicable,
 +            );
 +        }
 +
 +        #[allow(clippy::trivially_copy_pass_by_ref)]
 +        fn is_wild<P: std::ops::Deref<Target = Pat>>(pat: &&P) -> bool {
 +            if let PatKind::Wild = pat.kind {
 +                true
 +            } else {
 +                false
 +            }
 +        }
 +
 +        if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) {
 +            if let Some((left_index, left_pat)) = patterns[..rest_index]
 +                .iter()
 +                .rev()
 +                .take_while(is_wild)
 +                .enumerate()
 +                .last()
 +            {
 +                span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0);
 +            }
 +
 +            if let Some((right_index, right_pat)) =
 +                patterns[rest_index + 1..].iter().take_while(is_wild).enumerate().last()
 +            {
 +                span_lint(
 +                    cx,
 +                    patterns[rest_index].span.shrink_to_hi().to(right_pat.span),
 +                    right_index == 0,
 +                );
 +            }
 +        }
 +    }
 +}
index 5235c98efab13d1fa40884bb513ba02f35064fe6,0000000000000000000000000000000000000000..f3844c7d3b68f4f7e37449a3640c879a2691990e
mode 100644,000000..100644
--- /dev/null
@@@ -1,216 -1,0 +1,225 @@@
- use crate::utils::{higher::if_block, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated};
++use crate::utils::{
++    differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then,
++    usage::is_potentially_mutated,
++};
 +use if_chain::if_chain;
 +use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
 +use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp};
 +use rustc_lint::{LateContext, LateLintPass};
 +use rustc_middle::hir::map::Map;
 +use rustc_middle::lint::in_external_macro;
 +use rustc_session::{declare_lint_pass, declare_tool_lint};
 +use rustc_span::source_map::Span;
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for calls of `unwrap[_err]()` that cannot fail.
 +    ///
 +    /// **Why is this bad?** Using `if let` or `match` is more idiomatic.
 +    ///
 +    /// **Known problems:** None
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let option = Some(0);
 +    /// # fn do_something_with(_x: usize) {}
 +    /// if option.is_some() {
 +    ///     do_something_with(option.unwrap())
 +    /// }
 +    /// ```
 +    ///
 +    /// Could be written:
 +    ///
 +    /// ```rust
 +    /// # let option = Some(0);
 +    /// # fn do_something_with(_x: usize) {}
 +    /// if let Some(value) = option {
 +    ///     do_something_with(value)
 +    /// }
 +    /// ```
 +    pub UNNECESSARY_UNWRAP,
 +    complexity,
 +    "checks for calls of `unwrap[_err]()` that cannot fail"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for calls of `unwrap[_err]()` that will always fail.
 +    ///
 +    /// **Why is this bad?** If panicking is desired, an explicit `panic!()` should be used.
 +    ///
 +    /// **Known problems:** This lint only checks `if` conditions not assignments.
 +    /// So something like `let x: Option<()> = None; x.unwrap();` will not be recognized.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// # let option = Some(0);
 +    /// # fn do_something_with(_x: usize) {}
 +    /// if option.is_none() {
 +    ///     do_something_with(option.unwrap())
 +    /// }
 +    /// ```
 +    ///
 +    /// This code will always panic. The if condition should probably be inverted.
 +    pub PANICKING_UNWRAP,
 +    correctness,
 +    "checks for calls of `unwrap[_err]()` that will always fail"
 +}
 +
 +/// Visitor that keeps track of which variables are unwrappable.
 +struct UnwrappableVariablesVisitor<'a, 'tcx> {
 +    unwrappables: Vec<UnwrapInfo<'tcx>>,
 +    cx: &'a LateContext<'a, 'tcx>,
 +}
 +/// Contains information about whether a variable can be unwrapped.
 +#[derive(Copy, Clone, Debug)]
 +struct UnwrapInfo<'tcx> {
 +    /// The variable that is checked
 +    ident: &'tcx Path<'tcx>,
 +    /// The check, like `x.is_ok()`
 +    check: &'tcx Expr<'tcx>,
++    /// The branch where the check takes place, like `if x.is_ok() { .. }`
++    branch: &'tcx Expr<'tcx>,
 +    /// Whether `is_some()` or `is_ok()` was called (as opposed to `is_err()` or `is_none()`).
 +    safe_to_unwrap: bool,
 +}
 +
 +/// Collects the information about unwrappable variables from an if condition
 +/// The `invert` argument tells us whether the condition is negated.
 +fn collect_unwrap_info<'a, 'tcx>(
 +    cx: &'a LateContext<'a, 'tcx>,
 +    expr: &'tcx Expr<'_>,
++    branch: &'tcx Expr<'_>,
 +    invert: bool,
 +) -> Vec<UnwrapInfo<'tcx>> {
 +    if let ExprKind::Binary(op, left, right) = &expr.kind {
 +        match (invert, op.node) {
 +            (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => {
-                 let mut unwrap_info = collect_unwrap_info(cx, left, invert);
-                 unwrap_info.append(&mut collect_unwrap_info(cx, right, invert));
++                let mut unwrap_info = collect_unwrap_info(cx, left, branch, invert);
++                unwrap_info.append(&mut collect_unwrap_info(cx, right, branch, invert));
 +                return unwrap_info;
 +            },
 +            _ => (),
 +        }
 +    } else if let ExprKind::Unary(UnOp::UnNot, expr) = &expr.kind {
-         return collect_unwrap_info(cx, expr, !invert);
++        return collect_unwrap_info(cx, expr, branch, !invert);
 +    } else {
 +        if_chain! {
 +            if let ExprKind::MethodCall(method_name, _, args) = &expr.kind;
 +            if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind;
 +            let ty = cx.tables.expr_ty(&args[0]);
 +            if is_type_diagnostic_item(cx, ty, sym!(option_type)) || is_type_diagnostic_item(cx, ty, sym!(result_type));
 +            let name = method_name.ident.as_str();
 +            if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name);
 +            then {
 +                assert!(args.len() == 1);
 +                let unwrappable = match name.as_ref() {
 +                    "is_some" | "is_ok" => true,
 +                    "is_err" | "is_none" => false,
 +                    _ => unreachable!(),
 +                };
 +                let safe_to_unwrap = unwrappable != invert;
-                 return vec![UnwrapInfo { ident: path, check: expr, safe_to_unwrap }];
++                return vec![UnwrapInfo { ident: path, check: expr, branch, safe_to_unwrap }];
 +            }
 +        }
 +    }
 +    Vec::new()
 +}
 +
 +impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
 +    fn visit_branch(&mut self, cond: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, else_branch: bool) {
 +        let prev_len = self.unwrappables.len();
-         for unwrap_info in collect_unwrap_info(self.cx, cond, else_branch) {
++        for unwrap_info in collect_unwrap_info(self.cx, cond, branch, else_branch) {
 +            if is_potentially_mutated(unwrap_info.ident, cond, self.cx)
 +                || is_potentially_mutated(unwrap_info.ident, branch, self.cx)
 +            {
 +                // if the variable is mutated, we don't know whether it can be unwrapped:
 +                continue;
 +            }
 +            self.unwrappables.push(unwrap_info);
 +        }
 +        walk_expr(self, branch);
 +        self.unwrappables.truncate(prev_len);
 +    }
 +}
 +
 +impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 +        // Shouldn't lint when `expr` is in macro.
 +        if in_external_macro(self.cx.tcx.sess, expr.span) {
 +            return;
 +        }
 +        if let Some((cond, then, els)) = if_block(&expr) {
 +            walk_expr(self, cond);
 +            self.visit_branch(cond, then, false);
 +            if let Some(els) = els {
 +                self.visit_branch(cond, els, true);
 +            }
 +        } else {
 +            // find `unwrap[_err]()` calls:
 +            if_chain! {
 +                if let ExprKind::MethodCall(ref method_name, _, ref args) = expr.kind;
 +                if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].kind;
 +                if [sym!(unwrap), sym!(unwrap_err)].contains(&method_name.ident.name);
 +                let call_to_unwrap = method_name.ident.name == sym!(unwrap);
 +                if let Some(unwrappable) = self.unwrappables.iter()
 +                    .find(|u| u.ident.res == path.res);
++                // Span contexts should not differ with the conditional branch
++                if !differing_macro_contexts(unwrappable.branch.span, expr.span);
++                if !differing_macro_contexts(unwrappable.branch.span, unwrappable.check.span);
 +                then {
 +                    if call_to_unwrap == unwrappable.safe_to_unwrap {
 +                        span_lint_and_then(
 +                            self.cx,
 +                            UNNECESSARY_UNWRAP,
 +                            expr.span,
 +                            &format!("You checked before that `{}()` cannot fail. \
 +                            Instead of checking and unwrapping, it's better to use `if let` or `match`.",
 +                            method_name.ident.name),
 +                            |diag| { diag.span_label(unwrappable.check.span, "the check is happening here"); },
 +                        );
 +                    } else {
 +                        span_lint_and_then(
 +                            self.cx,
 +                            PANICKING_UNWRAP,
 +                            expr.span,
 +                            &format!("This call to `{}()` will always panic.",
 +                            method_name.ident.name),
 +                            |diag| { diag.span_label(unwrappable.check.span, "because of this check"); },
 +                        );
 +                    }
 +                }
 +            }
 +            walk_expr(self, expr);
 +        }
 +    }
 +
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
 +    }
 +}
 +
 +declare_lint_pass!(Unwrap => [PANICKING_UNWRAP, UNNECESSARY_UNWRAP]);
 +
 +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Unwrap {
 +    fn check_fn(
 +        &mut self,
 +        cx: &LateContext<'a, 'tcx>,
 +        kind: FnKind<'tcx>,
 +        decl: &'tcx FnDecl<'_>,
 +        body: &'tcx Body<'_>,
 +        span: Span,
 +        fn_id: HirId,
 +    ) {
 +        if span.from_expansion() {
 +            return;
 +        }
 +
 +        let mut v = UnwrappableVariablesVisitor {
 +            cx,
 +            unwrappables: Vec::new(),
 +        };
 +
 +        walk_fn(&mut v, kind, decl, body.id(), span, fn_id);
 +    }
 +}
index 4b81ff33495c7c089c0ad55ffc96f5336958aa8a,0000000000000000000000000000000000000000..57b9eafd14dbd4a8760998f0a1662a486765b2b7
mode 100644,000000..100644
--- /dev/null
@@@ -1,240 -1,0 +1,242 @@@
 +//! Read configurations files.
 +
 +#![deny(clippy::missing_docs_in_private_items)]
 +
 +use lazy_static::lazy_static;
 +use rustc_ast::ast::{LitKind, MetaItemKind, NestedMetaItem};
 +use rustc_span::source_map;
 +use source_map::Span;
 +use std::path::{Path, PathBuf};
 +use std::sync::Mutex;
 +use std::{env, fmt, fs, io};
 +
 +/// Gets the configuration file from arguments.
 +pub fn file_from_args(args: &[NestedMetaItem]) -> Result<Option<PathBuf>, (&'static str, Span)> {
 +    for arg in args.iter().filter_map(NestedMetaItem::meta_item) {
 +        if arg.check_name(sym!(conf_file)) {
 +            return match arg.kind {
 +                MetaItemKind::Word | MetaItemKind::List(_) => Err(("`conf_file` must be a named value", arg.span)),
 +                MetaItemKind::NameValue(ref value) => {
 +                    if let LitKind::Str(ref file, _) = value.kind {
 +                        Ok(Some(file.to_string().into()))
 +                    } else {
 +                        Err(("`conf_file` value must be a string", value.span))
 +                    }
 +                },
 +            };
 +        }
 +    }
 +
 +    Ok(None)
 +}
 +
 +/// Error from reading a configuration file.
 +#[derive(Debug)]
 +pub enum Error {
 +    /// An I/O error.
 +    Io(io::Error),
 +    /// Not valid toml or doesn't fit the expected config format
 +    Toml(String),
 +}
 +
 +impl fmt::Display for Error {
 +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 +        match self {
 +            Self::Io(err) => err.fmt(f),
 +            Self::Toml(err) => err.fmt(f),
 +        }
 +    }
 +}
 +
 +impl From<io::Error> for Error {
 +    fn from(e: io::Error) -> Self {
 +        Self::Io(e)
 +    }
 +}
 +
 +lazy_static! {
 +    static ref ERRORS: Mutex<Vec<Error>> = Mutex::new(Vec::new());
 +}
 +
 +macro_rules! define_Conf {
 +    ($(#[$doc:meta] ($config:ident, $config_str:literal: $Ty:ty, $default:expr),)+) => {
 +        mod helpers {
 +            use serde::Deserialize;
 +            /// Type used to store lint configuration.
 +            #[derive(Deserialize)]
 +            #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 +            pub struct Conf {
 +                $(
 +                    #[$doc]
 +                    #[serde(default = $config_str)]
 +                    #[serde(with = $config_str)]
 +                    pub $config: $Ty,
 +                )+
 +                #[allow(dead_code)]
 +                #[serde(default)]
 +                third_party: Option<::toml::Value>,
 +            }
 +
 +            $(
 +                mod $config {
 +                    use serde::Deserialize;
 +                    pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<$Ty, D::Error> {
 +                        use super::super::{ERRORS, Error};
 +                        Ok(
 +                            <$Ty>::deserialize(deserializer).unwrap_or_else(|e| {
 +                                ERRORS
 +                                    .lock()
 +                                    .expect("no threading here")
 +                                    .push(Error::Toml(e.to_string()));
 +                                super::$config()
 +                            })
 +                        )
 +                    }
 +                }
 +
 +                #[must_use]
 +                fn $config() -> $Ty {
 +                    let x = $default;
 +                    x
 +                }
 +            )+
 +        }
 +    };
 +}
 +
 +pub use self::helpers::Conf;
 +define_Conf! {
 +    /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about
 +    (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "bar", "baz", "quux"].iter().map(ToString::to_string).collect()),
 +    /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
 +    (cognitive_complexity_threshold, "cognitive_complexity_threshold": u64, 25),
 +    /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead.
 +    (cyclomatic_complexity_threshold, "cyclomatic_complexity_threshold": Option<u64>, None),
 +    /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks
 +    (doc_valid_idents, "doc_valid_idents": Vec<String>, [
 +        "KiB", "MiB", "GiB", "TiB", "PiB", "EiB",
 +        "DirectX",
 +        "ECMAScript",
 +        "GPLv2", "GPLv3",
 +        "GitHub", "GitLab",
 +        "IPv4", "IPv6",
 +        "JavaScript",
 +        "NaN", "NaNs",
 +        "OAuth",
 +        "OpenGL", "OpenSSH", "OpenSSL", "OpenStreetMap",
 +        "TrueType",
 +        "iOS", "macOS",
 +        "TeX", "LaTeX", "BibTeX", "BibLaTeX",
 +        "MinGW",
 +        "CamelCase",
 +    ].iter().map(ToString::to_string).collect()),
 +    /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have
 +    (too_many_arguments_threshold, "too_many_arguments_threshold": u64, 7),
 +    /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have
 +    (type_complexity_threshold, "type_complexity_threshold": u64, 250),
 +    /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have
 +    (single_char_binding_names_threshold, "single_char_binding_names_threshold": u64, 4),
 +    /// Lint: BOXED_LOCAL. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
 +    (too_large_for_stack, "too_large_for_stack": u64, 200),
 +    /// Lint: ENUM_VARIANT_NAMES. The minimum number of enum variants for the lints about variant names to trigger
 +    (enum_variant_name_threshold, "enum_variant_name_threshold": u64, 3),
 +    /// Lint: LARGE_ENUM_VARIANT. The maximum size of a enum's variant to avoid box suggestion
 +    (enum_variant_size_threshold, "enum_variant_size_threshold": u64, 200),
 +    /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
 +    (verbose_bit_mask_threshold, "verbose_bit_mask_threshold": u64, 1),
 +    /// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals
 +    (literal_representation_threshold, "literal_representation_threshold": u64, 16384),
 +    /// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
 +    (trivial_copy_size_limit, "trivial_copy_size_limit": Option<u64>, None),
 +    /// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have
 +    (too_many_lines_threshold, "too_many_lines_threshold": u64, 100),
 +    /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS. The maximum allowed size for arrays on the stack
 +    (array_size_threshold, "array_size_threshold": u64, 512_000),
 +    /// Lint: VEC_BOX. The size of the boxed type in bytes, where boxing in a `Vec` is allowed
 +    (vec_box_size_threshold, "vec_box_size_threshold": u64, 4096),
 +    /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bools a struct can have
 +    (max_struct_bools, "max_struct_bools": u64, 3),
 +    /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bools function parameters can have
 +    (max_fn_params_bools, "max_fn_params_bools": u64, 3),
++    /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
++    (warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false),
 +}
 +
 +impl Default for Conf {
 +    #[must_use]
 +    fn default() -> Self {
 +        toml::from_str("").expect("we never error on empty config files")
 +    }
 +}
 +
 +/// Search for the configuration file.
 +pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
 +    /// Possible filename to search for.
 +    const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"];
 +
 +    // Start looking for a config file in CLIPPY_CONF_DIR, or failing that, CARGO_MANIFEST_DIR.
 +    // If neither of those exist, use ".".
 +    let mut current = env::var_os("CLIPPY_CONF_DIR")
 +        .or_else(|| env::var_os("CARGO_MANIFEST_DIR"))
 +        .map_or_else(|| PathBuf::from("."), PathBuf::from);
 +    loop {
 +        for config_file_name in &CONFIG_FILE_NAMES {
 +            let config_file = current.join(config_file_name);
 +            match fs::metadata(&config_file) {
 +                // Only return if it's a file to handle the unlikely situation of a directory named
 +                // `clippy.toml`.
 +                Ok(ref md) if !md.is_dir() => return Ok(Some(config_file)),
 +                // Return the error if it's something other than `NotFound`; otherwise we didn't
 +                // find the project file yet, and continue searching.
 +                Err(e) if e.kind() != io::ErrorKind::NotFound => return Err(e),
 +                _ => {},
 +            }
 +        }
 +
 +        // If the current directory has no parent, we're done searching.
 +        if !current.pop() {
 +            return Ok(None);
 +        }
 +    }
 +}
 +
 +/// Produces a `Conf` filled with the default values and forwards the errors
 +///
 +/// Used internally for convenience
 +fn default(errors: Vec<Error>) -> (Conf, Vec<Error>) {
 +    (Conf::default(), errors)
 +}
 +
 +/// Read the `toml` configuration file.
 +///
 +/// In case of error, the function tries to continue as much as possible.
 +pub fn read(path: &Path) -> (Conf, Vec<Error>) {
 +    let content = match fs::read_to_string(path) {
 +        Ok(content) => content,
 +        Err(err) => return default(vec![err.into()]),
 +    };
 +
 +    assert!(ERRORS.lock().expect("no threading -> mutex always safe").is_empty());
 +    match toml::from_str(&content) {
 +        Ok(toml) => {
 +            let mut errors = ERRORS.lock().expect("no threading -> mutex always safe").split_off(0);
 +
 +            let toml_ref: &Conf = &toml;
 +
 +            let cyc_field: Option<u64> = toml_ref.cyclomatic_complexity_threshold;
 +
 +            if cyc_field.is_some() {
 +                let cyc_err = "found deprecated field `cyclomatic-complexity-threshold`. Please use `cognitive-complexity-threshold` instead.".to_string();
 +                errors.push(Error::Toml(cyc_err));
 +            }
 +
 +            (toml, errors)
 +        },
 +        Err(e) => {
 +            let mut errors = ERRORS.lock().expect("no threading -> mutex always safe").split_off(0);
 +            errors.push(Error::Toml(e.to_string()));
 +
 +            default(errors)
 +        },
 +    }
 +}
index 2fd080e9ef0f848b67f6e00427f5149e83cee0d9,0000000000000000000000000000000000000000..3b8ef18bfab8672a3dd4405655956d5002779ee8
mode 100644,000000..100644
--- /dev/null
@@@ -1,1491 -1,0 +1,1499 @@@
-         PatKind::Binding(..) | PatKind::Wild => false,
 +#[macro_use]
 +pub mod sym;
 +
 +pub mod attrs;
 +pub mod author;
 +pub mod camel_case;
 +pub mod comparisons;
 +pub mod conf;
 +pub mod constants;
 +mod diagnostics;
 +pub mod higher;
 +mod hir_utils;
 +pub mod inspector;
 +pub mod internal_lints;
 +pub mod numeric_literal;
 +pub mod paths;
 +pub mod ptr;
 +pub mod sugg;
 +pub mod usage;
 +pub use self::attrs::*;
 +pub use self::diagnostics::*;
 +pub use self::hir_utils::{SpanlessEq, SpanlessHash};
 +
 +use std::borrow::Cow;
 +use std::mem;
 +
 +use if_chain::if_chain;
 +use rustc_ast::ast::{self, Attribute, LitKind};
 +use rustc_attr as attr;
 +use rustc_errors::Applicability;
 +use rustc_hir as hir;
 +use rustc_hir::def::{DefKind, Res};
 +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 +use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 +use rustc_hir::Node;
 +use rustc_hir::{
 +    def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind,
 +    MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety,
 +};
 +use rustc_infer::infer::TyCtxtInferExt;
 +use rustc_lint::{LateContext, Level, Lint, LintContext};
 +use rustc_middle::hir::map::Map;
 +use rustc_middle::traits;
 +use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Binder, Ty, TyCtxt, TypeFoldable};
 +use rustc_span::hygiene::{ExpnKind, MacroKind};
 +use rustc_span::source_map::original_sp;
 +use rustc_span::symbol::{self, kw, Symbol};
 +use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
 +use rustc_target::abi::Integer;
 +use rustc_trait_selection::traits::predicate_for_trait_def;
 +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 +use rustc_trait_selection::traits::query::normalize::AtExt;
 +use smallvec::SmallVec;
 +
 +use crate::consts::{constant, Constant};
 +use crate::reexport::Name;
 +
 +/// Returns `true` if the two spans come from differing expansions (i.e., one is
 +/// from a macro and one isn't).
 +#[must_use]
 +pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
 +    rhs.ctxt() != lhs.ctxt()
 +}
 +
 +/// 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);
 +    match cx.tcx.hir().get(parent_id) {
 +        Node::Item(&Item {
 +            kind: ItemKind::Const(..),
 +            ..
 +        })
 +        | Node::TraitItem(&TraitItem {
 +            kind: TraitItemKind::Const(..),
 +            ..
 +        })
 +        | Node::ImplItem(&ImplItem {
 +            kind: ImplItemKind::Const(..),
 +            ..
 +        })
 +        | Node::AnonConst(_)
 +        | Node::Item(&Item {
 +            kind: ItemKind::Static(..),
 +            ..
 +        }) => true,
 +        Node::Item(&Item {
 +            kind: ItemKind::Fn(ref sig, ..),
 +            ..
 +        })
 +        | Node::ImplItem(&ImplItem {
 +            kind: ImplItemKind::Fn(ref sig, _),
 +            ..
 +        }) => sig.header.constness == Constness::Const,
 +        _ => false,
 +    }
 +}
 +
 +/// Returns `true` if this `span` was expanded by any macro.
 +#[must_use]
 +pub fn in_macro(span: Span) -> bool {
 +    if span.from_expansion() {
 +        if let ExpnKind::Desugaring(..) = span.ctxt().outer_expn_data().kind {
 +            false
 +        } else {
 +            true
 +        }
 +    } else {
 +        false
 +    }
 +}
 +// If the snippet is empty, it's an attribute that was inserted during macro
 +// expansion and we want to ignore those, because they could come from external
 +// sources that the user has no control over.
 +// For some reason these attributes don't have any expansion info on them, so
 +// we have to check it this way until there is a better way.
 +pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
 +    if let Some(snippet) = snippet_opt(cx, span) {
 +        if snippet.is_empty() {
 +            return false;
 +        }
 +    }
 +    true
 +}
 +
 +/// Checks if given pattern is a wildcard (`_`)
 +pub fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool {
 +    match pat.kind {
 +        PatKind::Wild => true,
 +        _ => false,
 +    }
 +}
 +
 +/// Checks if type is struct, enum or union type with the given def path.
 +pub fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool {
 +    match ty.kind {
 +        ty::Adt(adt, _) => match_def_path(cx, adt.did, path),
 +        _ => false,
 +    }
 +}
 +
 +/// Checks if the type is equal to a diagnostic item
 +pub fn is_type_diagnostic_item(cx: &LateContext<'_, '_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
 +    match ty.kind {
 +        ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),
 +        _ => false,
 +    }
 +}
 +
 +/// Checks if the method call given in `expr` belongs to the given trait.
 +pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr<'_>, path: &[&str]) -> bool {
 +    let def_id = cx.tables.type_dependent_def_id(expr.hir_id).unwrap();
 +    let trt_id = cx.tcx.trait_of_item(def_id);
 +    if let Some(trt_id) = trt_id {
 +        match_def_path(cx, trt_id, path)
 +    } else {
 +        false
 +    }
 +}
 +
 +/// Checks if an expression references a variable of the given name.
 +pub fn match_var(expr: &Expr<'_>, var: Name) -> bool {
 +    if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
 +        if path.segments.len() == 1 && path.segments[0].ident.name == var {
 +            return true;
 +        }
 +    }
 +    false
 +}
 +
 +pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
 +    match *path {
 +        QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"),
 +        QPath::TypeRelative(_, ref seg) => seg,
 +    }
 +}
 +
 +pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
 +    match *path {
 +        QPath::Resolved(_, ref path) if path.segments.len() == 1 => Some(&path.segments[0]),
 +        QPath::Resolved(..) => None,
 +        QPath::TypeRelative(_, ref seg) => Some(seg),
 +    }
 +}
 +
 +/// 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(_, ref path) => match_path(path, segments),
 +        QPath::TypeRelative(ref ty, ref segment) => match ty.kind {
 +            TyKind::Path(ref inner_path) => {
 +                !segments.is_empty()
 +                    && match_qpath(inner_path, &segments[..(segments.len() - 1)])
 +                    && segment.ident.name.as_str() == segments[segments.len() - 1]
 +            },
 +            _ => false,
 +        },
 +    }
 +}
 +
 +/// 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)
 +}
 +
 +/// Matches a `Path` against a slice of segment string literals, e.g.
 +///
 +/// # Examples
 +/// ```rust,ignore
 +/// match_path_ast(path, &["std", "rt", "begin_unwind"])
 +/// ```
 +pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
 +    path.segments
 +        .iter()
 +        .rev()
 +        .zip(segments.iter().rev())
 +        .all(|(a, b)| a.ident.name.as_str() == *b)
 +}
 +
 +/// Gets the definition associated to a path.
 +pub fn path_to_res(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<def::Res> {
 +    let crates = cx.tcx.crates();
 +    let krate = crates
 +        .iter()
 +        .find(|&&krate| cx.tcx.crate_name(krate).as_str() == path[0]);
 +    if let Some(krate) = krate {
 +        let krate = DefId {
 +            krate: *krate,
 +            index: CRATE_DEF_INDEX,
 +        };
 +        let mut items = cx.tcx.item_children(krate);
 +        let mut path_it = path.iter().skip(1).peekable();
 +
 +        loop {
 +            let segment = match path_it.next() {
 +                Some(segment) => segment,
 +                None => return None,
 +            };
 +
 +            let result = SmallVec::<[_; 8]>::new();
 +            for item in mem::replace(&mut items, cx.tcx.arena.alloc_slice(&result)).iter() {
 +                if item.ident.name.as_str() == *segment {
 +                    if path_it.peek().is_none() {
 +                        return Some(item.res);
 +                    }
 +
 +                    items = cx.tcx.item_children(item.res.def_id());
 +                    break;
 +                }
 +            }
 +        }
 +    } else {
 +        None
 +    }
 +}
 +
 +pub fn qpath_res(cx: &LateContext<'_, '_>, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
 +    match qpath {
 +        hir::QPath::Resolved(_, path) => path.res,
 +        hir::QPath::TypeRelative(..) => {
 +            if cx.tcx.has_typeck_tables(id.owner.to_def_id()) {
 +                cx.tcx
 +                    .typeck_tables_of(id.owner.to_def_id().expect_local())
 +                    .qpath_res(qpath, id)
 +            } else {
 +                Res::Err
 +            }
 +        },
 +    }
 +}
 +
 +/// Convenience function to get the `DefId` of a trait by path.
 +/// It could be a trait or trait alias.
 +pub fn get_trait_def_id(cx: &LateContext<'_, '_>, path: &[&str]) -> Option<DefId> {
 +    let res = match path_to_res(cx, path) {
 +        Some(res) => res,
 +        None => return None,
 +    };
 +
 +    match res {
 +        Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
 +        Res::Err => unreachable!("this trait resolution is impossible: {:?}", &path),
 +        _ => None,
 +    }
 +}
 +
 +/// Checks whether a type implements a trait.
 +/// See also `get_trait_def_id`.
 +pub fn implements_trait<'a, 'tcx>(
 +    cx: &LateContext<'a, 'tcx>,
 +    ty: Ty<'tcx>,
 +    trait_id: DefId,
 +    ty_params: &[GenericArg<'tcx>],
 +) -> bool {
 +    let ty = cx.tcx.erase_regions(&ty);
 +    let obligation = predicate_for_trait_def(
 +        cx.tcx,
 +        cx.param_env,
 +        traits::ObligationCause::dummy(),
 +        trait_id,
 +        0,
 +        ty,
 +        ty_params,
 +    );
 +    cx.tcx
 +        .infer_ctxt()
 +        .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
 +}
 +
 +/// 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>, hir_id: HirId) -> Option<&'tcx TraitRef<'tcx>> {
 +    // Get the implemented trait for the current function
 +    let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
 +    if_chain! {
 +        if parent_impl != hir::CRATE_HIR_ID;
 +        if let hir::Node::Item(item) = cx.tcx.hir().get(parent_impl);
 +        if let hir::ItemKind::Impl{ of_trait: trait_ref, .. } = &item.kind;
 +        then { return trait_ref.as_ref(); }
 +    }
 +    None
 +}
 +
 +/// Checks whether this type implements `Drop`.
 +pub fn has_drop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
 +    match ty.ty_adt_def() {
 +        Some(def) => def.has_dtor(cx.tcx),
 +        _ => false,
 +    }
 +}
 +
 +/// 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>, Vec<&'tcx [Expr<'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, span, args) = &current.kind {
 +            if args.iter().any(|e| e.span.from_expansion()) {
 +                break;
 +            }
 +            method_names.push(path.ident.name);
 +            arg_lists.push(&**args);
 +            spans.push(*span);
 +            current = &args[0];
 +        } 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()`,
 +/// `matched_method_chain(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>]>> {
 +    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(ref path, _, ref args) = current.kind {
 +            if path.ident.name.as_str() == *method_name {
 +                if args.iter().any(|e| e.span.from_expansion()) {
 +                    return None;
 +                }
 +                matched.push(&**args); // build up `matched` backwards
 +                current = &args[0] // 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(LOCAL_CRATE)
 +        .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id.to_def_id())
 +}
 +
 +/// Gets the name of the item the expression is in, if available.
 +pub fn get_item_name(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<Name> {
 +    let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
 +    match cx.tcx.hir().find(parent_id) {
 +        Some(
 +            Node::Item(Item { ident, .. })
 +            | Node::TraitItem(TraitItem { ident, .. })
 +            | Node::ImplItem(ImplItem { ident, .. }),
 +        ) => Some(ident.name),
 +        _ => None,
 +    }
 +}
 +
 +/// Gets the name of a `Pat`, if any.
 +pub fn get_pat_name(pat: &Pat<'_>) -> Option<Name> {
 +    match pat.kind {
 +        PatKind::Binding(.., ref spname, _) => Some(spname.name),
 +        PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
 +        PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p),
 +        _ => None,
 +    }
 +}
 +
 +struct ContainsName {
 +    name: Name,
 +    result: bool,
 +}
 +
 +impl<'tcx> Visitor<'tcx> for ContainsName {
 +    type Map = Map<'tcx>;
 +
 +    fn visit_name(&mut self, _: Span, name: Name) {
 +        if self.name == name {
 +            self.result = true;
 +        }
 +    }
 +    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
 +        NestedVisitorMap::None
 +    }
 +}
 +
 +/// Checks if an `Expr` contains a certain name.
 +pub fn contains_name(name: Name, expr: &Expr<'_>) -> bool {
 +    let mut cn = ContainsName { name, result: false };
 +    cn.visit_expr(expr);
 +    cn.result
 +}
 +
 +/// Converts a span to a code snippet if available, otherwise use default.
 +///
 +/// This is useful if you want to provide suggestions for your lint or more generally, if you want
 +/// to convert a given `Span` to a `str`.
 +///
 +/// # Example
 +/// ```rust,ignore
 +/// snippet(cx, expr.span, "..")
 +/// ```
 +pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
 +    snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
 +}
 +
 +/// Same as `snippet`, but it adapts the applicability level by following rules:
 +///
 +/// - Applicability level `Unspecified` will never be changed.
 +/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
 +/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
 +/// `HasPlaceholders`
 +pub fn snippet_with_applicability<'a, T: LintContext>(
 +    cx: &T,
 +    span: Span,
 +    default: &'a str,
 +    applicability: &mut Applicability,
 +) -> Cow<'a, str> {
 +    if *applicability != Applicability::Unspecified && span.from_expansion() {
 +        *applicability = Applicability::MaybeIncorrect;
 +    }
 +    snippet_opt(cx, span).map_or_else(
 +        || {
 +            if *applicability == Applicability::MachineApplicable {
 +                *applicability = Applicability::HasPlaceholders;
 +            }
 +            Cow::Borrowed(default)
 +        },
 +        From::from,
 +    )
 +}
 +
 +/// Same as `snippet`, but should only be used when it's clear that the input span is
 +/// not a macro argument.
 +pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
 +    snippet(cx, span.source_callsite(), default)
 +}
 +
 +/// Converts a span to a code snippet. Returns `None` if not available.
 +pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
 +    cx.sess().source_map().span_to_snippet(span).ok()
 +}
 +
 +/// Converts a span (from a block) to a code snippet if available, otherwise use default.
 +///
 +/// This trims the code of indentation, except for the first line. Use it for blocks or block-like
 +/// things which need to be printed as such.
 +///
 +/// The `indent_relative_to` arg can be used, to provide a span, where the indentation of the
 +/// resulting snippet of the given span.
 +///
 +/// # Example
 +///
 +/// ```rust,ignore
 +/// snippet_block(cx, block.span, "..", None)
 +/// // where, `block` is the block of the if expr
 +///     if x {
 +///         y;
 +///     }
 +/// // will return the snippet
 +/// {
 +///     y;
 +/// }
 +/// ```
 +///
 +/// ```rust,ignore
 +/// snippet_block(cx, block.span, "..", Some(if_expr.span))
 +/// // where, `block` is the block of the if expr
 +///     if x {
 +///         y;
 +///     }
 +/// // will return the snippet
 +/// {
 +///         y;
 +///     } // aligned with `if`
 +/// ```
 +/// Note that the first line of the snippet always has 0 indentation.
 +pub fn snippet_block<'a, T: LintContext>(
 +    cx: &T,
 +    span: Span,
 +    default: &'a str,
 +    indent_relative_to: Option<Span>,
 +) -> Cow<'a, str> {
 +    let snip = snippet(cx, span, default);
 +    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
 +    trim_multiline(snip, true, indent)
 +}
 +
 +/// Same as `snippet_block`, but adapts the applicability level by the rules of
 +/// `snippet_with_applicabiliy`.
 +pub fn snippet_block_with_applicability<'a, T: LintContext>(
 +    cx: &T,
 +    span: Span,
 +    default: &'a str,
 +    indent_relative_to: Option<Span>,
 +    applicability: &mut Applicability,
 +) -> Cow<'a, str> {
 +    let snip = snippet_with_applicability(cx, span, default, applicability);
 +    let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
 +    trim_multiline(snip, true, indent)
 +}
 +
 +/// Returns a new Span that extends the original Span to the first non-whitespace char of the first
 +/// line.
 +///
 +/// ```rust,ignore
 +///     let x = ();
 +/// //          ^^
 +/// // will be converted to
 +///     let x = ();
 +/// //  ^^^^^^^^^^
 +/// ```
 +pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
 +    if let Some(first_char_pos) = first_char_in_first_line(cx, span) {
 +        span.with_lo(first_char_pos)
 +    } else {
 +        span
 +    }
 +}
 +
 +fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
 +    let line_span = line_span(cx, span);
 +    if let Some(snip) = snippet_opt(cx, line_span) {
 +        snip.find(|c: char| !c.is_whitespace())
 +            .map(|pos| line_span.lo() + BytePos::from_usize(pos))
 +    } else {
 +        None
 +    }
 +}
 +
 +/// Returns the indentation of the line of a span
 +///
 +/// ```rust,ignore
 +/// let x = ();
 +/// //      ^^ -- will return 0
 +///     let x = ();
 +/// //          ^^ -- will return 4
 +/// ```
 +pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
 +    if let Some(snip) = snippet_opt(cx, line_span(cx, span)) {
 +        snip.find(|c: char| !c.is_whitespace())
 +    } else {
 +        None
 +    }
 +}
 +
 +/// Extends the span to the beginning of the spans line, incl. whitespaces.
 +///
 +/// ```rust,ignore
 +///        let x = ();
 +/// //             ^^
 +/// // will be converted to
 +///        let x = ();
 +/// // ^^^^^^^^^^^^^^
 +/// ```
 +fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
 +    let span = original_sp(span, DUMMY_SP);
 +    let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
 +    let line_no = source_map_and_line.line;
 +    let line_start = source_map_and_line.sf.lines[line_no];
 +    Span::new(line_start, span.hi(), span.ctxt())
 +}
 +
 +/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
 +/// Also takes an `Option<String>` which can be put inside the braces.
 +pub fn expr_block<'a, T: LintContext>(
 +    cx: &T,
 +    expr: &Expr<'_>,
 +    option: Option<String>,
 +    default: &'a str,
 +    indent_relative_to: Option<Span>,
 +) -> Cow<'a, str> {
 +    let code = snippet_block(cx, expr.span, default, indent_relative_to);
 +    let string = option.unwrap_or_default();
 +    if expr.span.from_expansion() {
 +        Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
 +    } else if let ExprKind::Block(_, _) = expr.kind {
 +        Cow::Owned(format!("{}{}", code, string))
 +    } else if string.is_empty() {
 +        Cow::Owned(format!("{{ {} }}", code))
 +    } else {
 +        Cow::Owned(format!("{{\n{};\n{}\n}}", code, string))
 +    }
 +}
 +
 +/// Trim indentation from a multiline string with possibility of ignoring the
 +/// first line.
 +fn trim_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> {
 +    let s_space = trim_multiline_inner(s, ignore_first, indent, ' ');
 +    let s_tab = trim_multiline_inner(s_space, ignore_first, indent, '\t');
 +    trim_multiline_inner(s_tab, ignore_first, indent, ' ')
 +}
 +
 +fn trim_multiline_inner(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>, ch: char) -> Cow<'_, str> {
 +    let mut x = s
 +        .lines()
 +        .skip(ignore_first as usize)
 +        .filter_map(|l| {
 +            if l.is_empty() {
 +                None
 +            } else {
 +                // ignore empty lines
 +                Some(l.char_indices().find(|&(_, x)| x != ch).unwrap_or((l.len(), ch)).0)
 +            }
 +        })
 +        .min()
 +        .unwrap_or(0);
 +    if let Some(indent) = indent {
 +        x = x.saturating_sub(indent);
 +    }
 +    if x > 0 {
 +        Cow::Owned(
 +            s.lines()
 +                .enumerate()
 +                .map(|(i, l)| {
 +                    if (ignore_first && i == 0) || l.is_empty() {
 +                        l
 +                    } else {
 +                        l.split_at(x).1
 +                    }
 +                })
 +                .collect::<Vec<_>>()
 +                .join("\n"),
 +        )
 +    } else {
 +        s
 +    }
 +}
 +
 +/// Gets the parent expression, if any –- this is useful to constrain a lint.
 +pub fn get_parent_expr<'c>(cx: &'c LateContext<'_, '_>, e: &Expr<'_>) -> Option<&'c Expr<'c>> {
 +    let map = &cx.tcx.hir();
 +    let hir_id = e.hir_id;
 +    let parent_id = map.get_parent_node(hir_id);
 +    if hir_id == parent_id {
 +        return None;
 +    }
 +    map.find(parent_id).and_then(|node| {
 +        if let Node::Expr(parent) = node {
 +            Some(parent)
 +        } else {
 +            None
 +        }
 +    })
 +}
 +
 +pub fn get_enclosing_block<'a, 'tcx>(cx: &LateContext<'a, '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));
 +    if let Some(node) = enclosing_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(ref block, _) => Some(block),
 +                _ => None,
 +            },
 +            _ => None,
 +        }
 +    } else {
 +        None
 +    }
 +}
 +
 +/// Returns the base type for HIR references and pointers.
 +pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
 +    match ty.kind {
 +        TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty),
 +        _ => ty,
 +    }
 +}
 +
 +/// Returns the base type for references and raw pointers.
 +pub fn walk_ptrs_ty(ty: Ty<'_>) -> Ty<'_> {
 +    match ty.kind {
 +        ty::Ref(_, ty, _) => walk_ptrs_ty(ty),
 +        _ => ty,
 +    }
 +}
 +
 +/// Returns the base type for references and raw pointers, and count reference
 +/// depth.
 +pub fn walk_ptrs_ty_depth(ty: Ty<'_>) -> (Ty<'_>, usize) {
 +    fn inner(ty: Ty<'_>, depth: usize) -> (Ty<'_>, usize) {
 +        match ty.kind {
 +            ty::Ref(_, ty, _) => inner(ty, depth + 1),
 +            _ => (ty, depth),
 +        }
 +    }
 +    inner(ty, 0)
 +}
 +
 +/// 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 map = cx.tcx.hir();
 +    let parent_item = map.get_parent_item(e.hir_id);
 +    if let Some((Constant::Int(v), _)) = map
 +        .maybe_body_owned_by(parent_item)
 +        .and_then(|body_id| constant(cx, cx.tcx.body_tables(body_id), e))
 +    {
 +        value == v
 +    } else {
 +        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_typeck::check::coercion` for more
 +/// information on adjustments and coercions.
 +pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool {
 +    cx.tables.adjustments().get(e.hir_id).is_some()
 +}
 +
 +/// Returns the pre-expansion span if is 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,ignore
 +/// foo!(bar!(42));
 +/// ```
 +/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only
 +/// `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<'a, 'tcx>(cx: &LateContext<'a, '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)
 +}
 +
 +/// Checks if two types are the same.
 +///
 +/// This discards any lifetime annotations, too.
 +//
 +// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` ==
 +// `for <'b> Foo<'b>`, but not for type parameters).
 +pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
 +    let a = cx.tcx.erase_late_bound_regions(&Binder::bind(a));
 +    let b = cx.tcx.erase_late_bound_regions(&Binder::bind(b));
 +    cx.tcx
 +        .infer_ctxt()
 +        .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok())
 +}
 +
 +/// Returns `true` if the given type is an `unsafe` function.
 +pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
 +    match ty.kind {
 +        ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe,
 +        _ => false,
 +    }
 +}
 +
 +pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
 +    ty.is_copy_modulo_regions(cx.tcx, cx.param_env, DUMMY_SP)
 +}
 +
 +/// 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(ref fun, _) = expr.kind {
 +        if let ExprKind::Path(ref qp) = fun.kind {
 +            let res = cx.tables.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/hair machinery
 +pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool {
 +    fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, id: HirId) -> bool {
 +        matches!(
 +            cx.tables.qpath_res(qpath, id),
 +            def::Res::Def(DefKind::Variant, ..) | Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), _)
 +        )
 +    }
 +
 +    fn are_refutable<'a, I: Iterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_, '_>, mut i: I) -> bool {
 +        i.any(|pat| is_refutable(cx, pat))
 +    }
 +
 +    match pat.kind {
-         PatKind::Or(ref pats) | PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
++        PatKind::Wild => false,
++        PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
 +        PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat),
 +        PatKind::Lit(..) | PatKind::Range(..) => true,
 +        PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
-             if is_enum_variant(cx, qpath, pat.hir_id) {
-                 true
-             } else {
-                 are_refutable(cx, fields.iter().map(|field| &*field.pat))
-             }
++        PatKind::Or(ref pats) => {
++            // TODO: should be the honest check, that pats is exhaustive set
++            are_refutable(cx, pats.iter().map(|pat| &**pat))
++        },
++        PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
 +        PatKind::Struct(ref qpath, ref fields, _) => {
-             if is_enum_variant(cx, qpath, pat.hir_id) {
-                 true
-             } else {
-                 are_refutable(cx, pats.iter().map(|pat| &**pat))
-             }
++            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
 +        },
 +        PatKind::TupleStruct(ref qpath, ref pats, _) => {
-             are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat))
++            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat))
 +        },
 +        PatKind::Slice(ref head, ref middle, ref tail) => {
++            match &cx.tables.node_type(pat.hir_id).kind {
++                ty::Slice(..) => {
++                    // [..] is the only irrefutable slice pattern.
++                    !head.is_empty() || middle.is_none() || !tail.is_empty()
++                },
++                ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)),
++                _ => {
++                    // unreachable!()
++                    true
++                },
++            }
 +        },
 +    }
 +}
 +
 +/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d
 +/// implementations have.
 +pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
 +    attr::contains_name(attrs, sym!(automatically_derived))
 +}
 +
 +/// Remove blocks around an expression.
 +///
 +/// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return
 +/// themselves.
 +pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
 +    while let ExprKind::Block(ref block, ..) = expr.kind {
 +        match (block.stmts.is_empty(), block.expr.as_ref()) {
 +            (true, Some(e)) => expr = e,
 +            _ => break,
 +        }
 +    }
 +    expr
 +}
 +
 +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_chain! {
 +        if let TyKind::Path(ref qp) = slf.kind;
 +        if let QPath::Resolved(None, ref path) = *qp;
 +        if let Res::SelfTy(..) = path.res;
 +        then {
 +            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>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
 +    fn is_ok(arm: &Arm<'_>) -> bool {
 +        if_chain! {
 +            if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pat.kind;
 +            if match_qpath(path, &paths::RESULT_OK[1..]);
 +            if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
 +            if let ExprKind::Path(QPath::Resolved(None, ref path)) = arm.body.kind;
 +            if let Res::Local(lid) = path.res;
 +            if lid == hir_id;
 +            then {
 +                return true;
 +            }
 +        }
 +        false
 +    }
 +
 +    fn is_err(arm: &Arm<'_>) -> bool {
 +        if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
 +            match_qpath(path, &paths::RESULT_ERR[1..])
 +        } else {
 +            false
 +        }
 +    }
 +
 +    if let ExprKind::Match(_, ref arms, ref source) = expr.kind {
 +        // desugared from a `?` operator
 +        if let MatchSource::TryDesugar = *source {
 +            return Some(expr);
 +        }
 +
 +        if_chain! {
 +            if arms.len() == 2;
 +            if arms[0].guard.is_none();
 +            if arms[1].guard.is_none();
 +            if (is_ok(&arms[0]) && is_err(&arms[1])) ||
 +                (is_ok(&arms[1]) && is_err(&arms[0]));
 +            then {
 +                return Some(expr);
 +            }
 +        }
 +    }
 +
 +    None
 +}
 +
 +/// Returns `true` if the lint is allowed in the current context
 +///
 +/// Useful for skipping long running code when it's unnecessary
 +pub fn is_allowed(cx: &LateContext<'_, '_>, lint: &'static Lint, id: HirId) -> bool {
 +    cx.tcx.lint_level_at_node(lint, id).0 == Level::Allow
 +}
 +
 +pub fn get_arg_name(pat: &Pat<'_>) -> Option<Name> {
 +    match pat.kind {
 +        PatKind::Binding(.., ident, None) => Some(ident.name),
 +        PatKind::Ref(ref subpat, _) => get_arg_name(subpat),
 +        _ => None,
 +    }
 +}
 +
 +pub fn int_bits(tcx: TyCtxt<'_>, ity: ast::IntTy) -> u64 {
 +    Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)).size().bits()
 +}
 +
 +#[allow(clippy::cast_possible_wrap)]
 +/// Turn a constant int byte representation into an i128
 +pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: ast::IntTy) -> i128 {
 +    let amt = 128 - int_bits(tcx, ity);
 +    ((u as i128) << amt) >> amt
 +}
 +
 +#[allow(clippy::cast_sign_loss)]
 +/// clip unused bytes
 +pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ast::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: ast::UintTy) -> u128 {
 +    let bits = Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)).size().bits();
 +    let amt = 128 - bits;
 +    (u << amt) >> amt
 +}
 +
 +/// Removes block comments from the given `Vec` of lines.
 +///
 +/// # Examples
 +///
 +/// ```rust,ignore
 +/// without_block_comments(vec!["/*", "foo", "*/"]);
 +/// // => vec![]
 +///
 +/// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
 +/// // => vec!["bar"]
 +/// ```
 +pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
 +    let mut without = vec![];
 +
 +    let mut nest_level = 0;
 +
 +    for line in lines {
 +        if line.contains("/*") {
 +            nest_level += 1;
 +            continue;
 +        } else if line.contains("*/") {
 +            nest_level -= 1;
 +            continue;
 +        }
 +
 +        if nest_level == 0 {
 +            without.push(line);
 +        }
 +    }
 +
 +    without
 +}
 +
 +pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
 +    let map = &tcx.hir();
 +    let mut prev_enclosing_node = None;
 +    let mut enclosing_node = node;
 +    while Some(enclosing_node) != prev_enclosing_node {
 +        if is_automatically_derived(map.attrs(enclosing_node)) {
 +            return true;
 +        }
 +        prev_enclosing_node = Some(enclosing_node);
 +        enclosing_node = map.get_parent_item(enclosing_node);
 +    }
 +    false
 +}
 +
 +/// Returns true if ty has `iter` or `iter_mut` methods
 +pub fn has_iter_method(cx: &LateContext<'_, '_>, probably_ref_ty: Ty<'_>) -> Option<&'static str> {
 +    // FIXME: instead of this hard-coded list, we should check if `<adt>::iter`
 +    // exists and has the desired signature. Unfortunately FnCtxt is not exported
 +    // so we can't use its `lookup_method` method.
 +    let into_iter_collections: [&[&str]; 13] = [
 +        &paths::VEC,
 +        &paths::OPTION,
 +        &paths::RESULT,
 +        &paths::BTREESET,
 +        &paths::BTREEMAP,
 +        &paths::VEC_DEQUE,
 +        &paths::LINKED_LIST,
 +        &paths::BINARY_HEAP,
 +        &paths::HASHSET,
 +        &paths::HASHMAP,
 +        &paths::PATH_BUF,
 +        &paths::PATH,
 +        &paths::RECEIVER,
 +    ];
 +
 +    let ty_to_check = match probably_ref_ty.kind {
 +        ty::Ref(_, ty_to_check, _) => ty_to_check,
 +        _ => probably_ref_ty,
 +    };
 +
 +    let def_id = match ty_to_check.kind {
 +        ty::Array(..) => return Some("array"),
 +        ty::Slice(..) => return Some("slice"),
 +        ty::Adt(adt, _) => adt.did,
 +        _ => return None,
 +    };
 +
 +    for path in &into_iter_collections {
 +        if match_def_path(cx, def_id, path) {
 +            return Some(*path.last().unwrap());
 +        }
 +    }
 +    None
 +}
 +
 +/// Matches a function call with the given path and returns the arguments.
 +///
 +/// Usage:
 +///
 +/// ```rust,ignore
 +/// if let Some(args) = match_function_call(cx, begin_panic_call, &paths::BEGIN_PANIC);
 +/// ```
 +pub fn match_function_call<'a, 'tcx>(
 +    cx: &LateContext<'a, 'tcx>,
 +    expr: &'tcx Expr<'_>,
 +    path: &[&str],
 +) -> Option<&'tcx [Expr<'tcx>]> {
 +    if_chain! {
 +        if let ExprKind::Call(ref fun, ref args) = expr.kind;
 +        if let ExprKind::Path(ref qpath) = fun.kind;
 +        if let Some(fun_def_id) = cx.tables.qpath_res(qpath, fun.hir_id).opt_def_id();
 +        if match_def_path(cx, fun_def_id, path);
 +        then {
 +            return Some(&args)
 +        }
 +    };
 +    None
 +}
 +
 +/// Checks if `Ty` is normalizable. This function is useful
 +/// to avoid crashes on `layout_of`.
 +pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
 +    cx.tcx.infer_ctxt().enter(|infcx| {
 +        let cause = rustc_middle::traits::ObligationCause::dummy();
 +        infcx.at(&cause, param_env).normalize(&ty).is_ok()
 +    })
 +}
 +
 +pub fn match_def_path<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, did: DefId, syms: &[&str]) -> bool {
 +    // We have to convert `syms` to `&[Symbol]` here because rustc's `match_def_path`
 +    // accepts only that. We should probably move to Symbols in Clippy as well.
 +    let syms = syms.iter().map(|p| Symbol::intern(p)).collect::<Vec<Symbol>>();
 +    cx.match_def_path(did, &syms)
 +}
 +
 +/// 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>,
 +) -> (SmallVec<[&'tcx Expr<'tcx>; 1]>, SmallVec<[&'tcx Block<'tcx>; 1]>) {
 +    let mut conds = SmallVec::new();
 +    let mut blocks: SmallVec<[&Block<'_>; 1]> = SmallVec::new();
 +
 +    while let Some((ref cond, ref then_expr, ref else_expr)) = higher::if_block(&expr) {
 +        conds.push(&**cond);
 +        if let ExprKind::Block(ref block, _) = then_expr.kind {
 +            blocks.push(block);
 +        } else {
 +            panic!("ExprKind::If node is not an ExprKind::Block");
 +        }
 +
 +        if let Some(ref else_expr) = *else_expr {
 +            expr = else_expr;
 +        } else {
 +            break;
 +        }
 +    }
 +
 +    // final `else {..}`
 +    if !blocks.is_empty() {
 +        if let ExprKind::Block(ref block, _) = expr.kind {
 +            blocks.push(&**block);
 +        }
 +    }
 +
 +    (conds, blocks)
 +}
 +
 +pub fn parent_node_is_if_expr<'a, 'b>(expr: &Expr<'_>, cx: &LateContext<'a, 'b>) -> bool {
 +    let map = cx.tcx.hir();
 +    let parent_id = map.get_parent_node(expr.hir_id);
 +    let parent_node = map.get(parent_id);
 +
 +    match parent_node {
 +        Node::Expr(e) => higher::if_block(&e).is_some(),
 +        Node::Arm(e) => higher::if_block(&e.body).is_some(),
 +        _ => false,
 +    }
 +}
 +
 +// Finds the attribute with the given name, if any
 +pub fn attr_by_name<'a>(attrs: &'a [Attribute], name: &'_ str) -> Option<&'a Attribute> {
 +    attrs
 +        .iter()
 +        .find(|attr| attr.ident().map_or(false, |ident| ident.as_str() == name))
 +}
 +
 +// Finds the `#[must_use]` attribute, if any
 +pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
 +    attr_by_name(attrs, "must_use")
 +}
 +
 +// Returns whether the type has #[must_use] attribute
 +pub fn is_must_use_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
 +    match ty.kind {
 +        ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(),
 +        ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(),
 +        ty::Slice(ref ty)
 +        | ty::Array(ref ty, _)
 +        | ty::RawPtr(ty::TypeAndMut { ref ty, .. })
 +        | ty::Ref(_, ref ty, _) => {
 +            // for the Array case we don't need to care for the len == 0 case
 +            // because we don't want to lint functions returning empty arrays
 +            is_must_use_ty(cx, *ty)
 +        },
 +        ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
 +        ty::Opaque(ref def_id, _) => {
 +            for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates {
 +                if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
 +                    if must_use_attr(&cx.tcx.get_attrs(poly_trait_predicate.skip_binder().trait_ref.def_id)).is_some() {
 +                        return true;
 +                    }
 +                }
 +            }
 +            false
 +        },
 +        ty::Dynamic(binder, _) => {
 +            for predicate in binder.skip_binder().iter() {
 +                if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
 +                    if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
 +                        return true;
 +                    }
 +                }
 +            }
 +            false
 +        },
 +        _ => false,
 +    }
 +}
 +
 +// check if expr is calling method or function with #[must_use] attribyte
 +pub fn is_must_use_func_call(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
 +    let did = match expr.kind {
 +        ExprKind::Call(ref path, _) => if_chain! {
 +            if let ExprKind::Path(ref qpath) = path.kind;
 +            if let def::Res::Def(_, did) = cx.tables.qpath_res(qpath, path.hir_id);
 +            then {
 +                Some(did)
 +            } else {
 +                None
 +            }
 +        },
 +        ExprKind::MethodCall(_, _, _) => cx.tables.type_dependent_def_id(expr.hir_id),
 +        _ => None,
 +    };
 +
 +    if let Some(did) = did {
 +        must_use_attr(&cx.tcx.get_attrs(did)).is_some()
 +    } else {
 +        false
 +    }
 +}
 +
 +pub fn is_no_std_crate(krate: &Crate<'_>) -> bool {
 +    krate.item.attrs.iter().any(|attr| {
 +        if let ast::AttrKind::Normal(ref attr) = attr.kind {
 +            attr.path == symbol::sym::no_std
 +        } else {
 +            false
 +        }
 +    })
 +}
 +
 +/// Check if parent of a hir node is a trait implementation block.
 +/// For example, `f` in
 +/// ```rust,ignore
 +/// 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(cx.tcx.hir().get_parent_node(hir_id)) {
 +        matches!(item.kind, ItemKind::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::normalize_and_test_predicates(
 +        cx.tcx,
 +        traits::elaborate_predicates(cx.tcx, predicates)
 +            .map(|o| o.predicate)
 +            .collect::<Vec<_>>(),
 +    )
 +}
 +
 +pub fn run_lints(cx: &LateContext<'_, '_>, lints: &[&'static Lint], id: HirId) -> bool {
 +    lints.iter().any(|lint| {
 +        matches!(
 +            cx.tcx.lint_level_at_node(lint, id),
 +            (Level::Forbid | Level::Deny | Level::Warn, _)
 +        )
 +    })
 +}
 +
 +#[cfg(test)]
 +mod test {
 +    use super::{trim_multiline, without_block_comments};
 +
 +    #[test]
 +    fn test_trim_multiline_single_line() {
 +        assert_eq!("", trim_multiline("".into(), false, None));
 +        assert_eq!("...", trim_multiline("...".into(), false, None));
 +        assert_eq!("...", trim_multiline("    ...".into(), false, None));
 +        assert_eq!("...", trim_multiline("\t...".into(), false, None));
 +        assert_eq!("...", trim_multiline("\t\t...".into(), false, None));
 +    }
 +
 +    #[test]
 +    #[rustfmt::skip]
 +    fn test_trim_multiline_block() {
 +        assert_eq!("\
 +    if x {
 +        y
 +    } else {
 +        z
 +    }", trim_multiline("    if x {
 +            y
 +        } else {
 +            z
 +        }".into(), false, None));
 +        assert_eq!("\
 +    if x {
 +    \ty
 +    } else {
 +    \tz
 +    }", trim_multiline("    if x {
 +        \ty
 +        } else {
 +        \tz
 +        }".into(), false, None));
 +    }
 +
 +    #[test]
 +    #[rustfmt::skip]
 +    fn test_trim_multiline_empty_line() {
 +        assert_eq!("\
 +    if x {
 +        y
 +
 +    } else {
 +        z
 +    }", trim_multiline("    if x {
 +            y
 +
 +        } else {
 +            z
 +        }".into(), false, None));
 +    }
 +
 +    #[test]
 +    fn test_without_block_comments_lines_without_block_comments() {
 +        let result = without_block_comments(vec!["/*", "", "*/"]);
 +        println!("result: {:?}", result);
 +        assert!(result.is_empty());
 +
 +        let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
 +        assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
 +
 +        let result = without_block_comments(vec!["/* rust", "", "*/"]);
 +        assert!(result.is_empty());
 +
 +        let result = without_block_comments(vec!["/* one-line comment */"]);
 +        assert!(result.is_empty());
 +
 +        let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
 +        assert!(result.is_empty());
 +
 +        let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
 +        assert!(result.is_empty());
 +
 +        let result = without_block_comments(vec!["foo", "bar", "baz"]);
 +        assert_eq!(result, vec!["foo", "bar", "baz"]);
 +    }
 +}
index ca2c4ade15565bc0d45c1e3c607fb0c883a4b788,0000000000000000000000000000000000000000..b3ad2ad9d9987e73205b42299003e146a7c80bd6
mode 100644,000000..100644
--- /dev/null
@@@ -1,139 -1,0 +1,140 @@@
- pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"];
 +//! 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.
 +
 +pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"];
 +pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"];
 +pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"];
 +pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"];
 +pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"];
 +pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"];
 +pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"];
 +pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"];
 +pub const BOX: [&str; 3] = ["alloc", "boxed", "Box"];
 +pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"];
 +pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"];
 +pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"];
 +pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"];
 +pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
 +pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
 +pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
 +pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
 +pub const CSTRING: [&str; 4] = ["std", "ffi", "c_str", "CString"];
 +pub const CSTRING_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"];
 +pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
 +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"];
 +pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
 +pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
 +pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"];
 +pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
 +pub const DROP: [&str; 3] = ["core", "mem", "drop"];
 +pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"];
 +pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
 +pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"];
 +pub const EXIT: [&str; 3] = ["std", "process", "exit"];
 +pub const FILE: [&str; 3] = ["std", "fs", "File"];
 +pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"];
 +pub const FMT_ARGUMENTS_NEW_V1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"];
 +pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
 +pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"];
 +pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
 +pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"];
++pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"];
 +pub const HASH: [&str; 2] = ["hash", "Hash"];
 +pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"];
 +pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"];
 +pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"];
 +pub const INDEX: [&str; 3] = ["core", "ops", "Index"];
 +pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"];
 +pub const INTO: [&str; 3] = ["core", "convert", "Into"];
 +pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"];
 +pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
 +pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
 +pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"];
 +pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"];
 +pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
 +pub const LINT: [&str; 3] = ["rustc_session", "lint", "Lint"];
 +pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
 +pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
 +pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"];
 +pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"];
 +pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
 +pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
 +pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
 +pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
 +pub const OPTION: [&str; 3] = ["core", "option", "Option"];
 +pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"];
 +pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"];
 +pub const ORD: [&str; 3] = ["core", "cmp", "Ord"];
 +pub const OS_STRING: [&str; 4] = ["std", "ffi", "os_str", "OsString"];
 +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; 2] = ["parking_lot", "MutexGuard"];
 +pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 2] = ["parking_lot", "RwLockReadGuard"];
 +pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 2] = ["parking_lot", "RwLockWriteGuard"];
 +pub const PATH: [&str; 3] = ["std", "path", "Path"];
 +pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"];
 +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 PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
 +pub const PTR_NULL: [&str; 2] = ["ptr", "null"];
 +pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"];
 +pub const RANGE: [&str; 3] = ["core", "ops", "Range"];
 +pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
 +pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"];
 +pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"];
++pub const RANGE_FULL: [&str; 4] = ["core", "ops", "range", "RangeFull"];
 +pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"];
 +pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"];
 +pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"];
 +pub const RANGE_STD: [&str; 3] = ["std", "ops", "Range"];
 +pub const RANGE_TO: [&str; 3] = ["core", "ops", "RangeTo"];
 +pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"];
 +pub const RANGE_TO_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeToInclusive"];
 +pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"];
 +pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
 +pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
 +pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"];
 +pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"];
 +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 REPEAT: [&str; 3] = ["core", "iter", "repeat"];
 +pub const RESULT: [&str; 3] = ["core", "result", "Result"];
 +pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];
 +pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"];
 +pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGuard"];
 +pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
 +pub const SERDE_DESERIALIZE: [&str; 2] = ["_serde", "Deserialize"];
 +pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 +pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 +pub const SLICE_ITER: [&str; 3] = ["core", "slice", "Iter"];
 +pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
 +pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
 +pub const STD_CONVERT_IDENTITY: [&str; 3] = ["std", "convert", "identity"];
 +pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
 +pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
 +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 SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
 +pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"];
 +pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
 +pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];
 +pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
 +pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
 +pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"];
 +pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
 +pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
 +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: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"];
 +pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
 +pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 +pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
 +pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
index f3038861cee2431c41795dd5db020f0fcedc16fd,0000000000000000000000000000000000000000..32d9a45c37d78fea94190d3273cbf3844cab6b73
mode 100644,000000..100644
--- /dev/null
@@@ -1,156 -1,0 +1,208 @@@
-     Item, ItemKind, UseKind,
 +use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_sugg};
 +use if_chain::if_chain;
 +use rustc_errors::Applicability;
 +use rustc_hir::{
 +    def::{DefKind, Res},
- use rustc_session::{declare_lint_pass, declare_tool_lint};
++    Item, ItemKind, PathSegment, UseKind,
 +};
 +use rustc_lint::{LateContext, LateLintPass};
-     /// Note that this will not warn about wildcard imports from modules named `prelude`; many
-     /// crates (including the standard library) provide modules named "prelude" specifically
-     /// designed for wildcard import.
++use rustc_session::{declare_tool_lint, impl_lint_pass};
 +use rustc_span::BytePos;
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for `use Enum::*`.
 +    ///
 +    /// **Why is this bad?** It is usually better style to use the prefixed name of
 +    /// an enumeration variant, rather than importing variants.
 +    ///
 +    /// **Known problems:** Old-style enumerations that prefix the variants are
 +    /// still around.
 +    ///
 +    /// **Example:**
 +    /// ```rust
 +    /// use std::cmp::Ordering::*;
 +    /// ```
 +    pub ENUM_GLOB_USE,
 +    pedantic,
 +    "use items that import all variants of an enum"
 +}
 +
 +declare_clippy_lint! {
 +    /// **What it does:** Checks for wildcard imports `use _::*`.
 +    ///
 +    /// **Why is this bad?** wildcard imports can polute the namespace. This is especially bad if
 +    /// you try to import something through a wildcard, that already has been imported by name from
 +    /// a different source:
 +    ///
 +    /// ```rust,ignore
 +    /// use crate1::foo; // Imports a function named foo
 +    /// use crate2::*; // Has a function named foo
 +    ///
 +    /// foo(); // Calls crate1::foo
 +    /// ```
 +    ///
 +    /// This can lead to confusing error messages at best and to unexpected behavior at worst.
 +    ///
- declare_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
++    /// **Exceptions:**
++    ///
++    /// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library)
++    /// provide modules named "prelude" specifically designed for wildcard import.
++    ///
++    /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name.
++    ///
++    /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag.
 +    ///
 +    /// **Known problems:** If macros are imported through the wildcard, this macro is not included
 +    /// by the suggestion and has to be added by hand.
 +    ///
 +    /// Applying the suggestion when explicit imports of the things imported with a glob import
 +    /// exist, may result in `unused_imports` warnings.
 +    ///
 +    /// **Example:**
 +    ///
 +    /// Bad:
 +    /// ```rust,ignore
 +    /// use crate1::*;
 +    ///
 +    /// foo();
 +    /// ```
 +    ///
 +    /// Good:
 +    /// ```rust,ignore
 +    /// use crate1::foo;
 +    ///
 +    /// foo();
 +    /// ```
 +    pub WILDCARD_IMPORTS,
 +    pedantic,
 +    "lint `use _::*` statements"
 +}
 +
-             if !in_macro(item.span);
++#[derive(Default)]
++pub struct WildcardImports {
++    warn_on_all: bool,
++    test_modules_deep: u32,
++}
++
++impl WildcardImports {
++    pub fn new(warn_on_all: bool) -> Self {
++        Self {
++            warn_on_all,
++            test_modules_deep: 0,
++        }
++    }
++}
++
++impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
 +
 +impl LateLintPass<'_, '_> for WildcardImports {
 +    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) {
++        if is_test_module_or_function(item) {
++            self.test_modules_deep = self.test_modules_deep.saturating_add(1);
++        }
 +        if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
 +            return;
 +        }
 +        if_chain! {
-             // don't lint prelude glob imports
-             if !use_path.segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude");
 +            if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind;
-                         span,
-                         false,
++            if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
 +            let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner);
 +            if !used_imports.is_empty(); // Already handled by `unused_imports`
 +            then {
 +                let mut applicability = Applicability::MachineApplicable;
 +                let import_source_snippet = snippet_with_applicability(cx, use_path.span, "..", &mut applicability);
 +                let (span, braced_glob) = if import_source_snippet.is_empty() {
 +                    // This is a `_::{_, *}` import
 +                    // In this case `use_path.span` is empty and ends directly in front of the `*`,
 +                    // so we need to extend it by one byte.
 +                    (
 +                        use_path.span.with_hi(use_path.span.hi() + BytePos(1)),
 +                        true,
 +                    )
 +                } else {
 +                    // In this case, the `use_path.span` ends right before the `::*`, so we need to
 +                    // extend it up to the `*`. Since it is hard to find the `*` in weird
 +                    // formattings like `use _ ::  *;`, we extend it up to, but not including the
 +                    // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
 +                    // can just use the end of the item span
 +                    let mut span = use_path.span.with_hi(item.span.hi());
 +                    if snippet(cx, span, "").ends_with(';') {
 +                        span = use_path.span.with_hi(item.span.hi() - BytePos(1));
 +                    }
 +                    (
++                        span, false,
 +                    )
 +                };
 +
 +                let imports_string = if used_imports.len() == 1 {
 +                    used_imports.iter().next().unwrap().to_string()
 +                } else {
 +                    let mut imports = used_imports
 +                        .iter()
 +                        .map(ToString::to_string)
 +                        .collect::<Vec<_>>();
 +                    imports.sort();
 +                    if braced_glob {
 +                        imports.join(", ")
 +                    } else {
 +                        format!("{{{}}}", imports.join(", "))
 +                    }
 +                };
 +
 +                let sugg = if braced_glob {
 +                    imports_string
 +                } else {
 +                    format!("{}::{}", import_source_snippet, imports_string)
 +                };
 +
 +                let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res {
 +                    (ENUM_GLOB_USE, "usage of wildcard import for enum variants")
 +                } else {
 +                    (WILDCARD_IMPORTS, "usage of wildcard import")
 +                };
 +
 +                span_lint_and_sugg(
 +                    cx,
 +                    lint,
 +                    span,
 +                    message,
 +                    "try",
 +                    sugg,
 +                    applicability,
 +                );
 +            }
 +        }
 +    }
++
++    fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) {
++        if is_test_module_or_function(item) {
++            self.test_modules_deep = self.test_modules_deep.saturating_sub(1);
++        }
++    }
++}
++
++impl WildcardImports {
++    fn check_exceptions(&self, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool {
++        in_macro(item.span)
++            || is_prelude_import(segments)
++            || (is_super_only_import(segments) && self.test_modules_deep > 0)
++    }
++}
++
++// Allow "...prelude::*" imports.
++// Many crates have a prelude, and it is imported as a glob by design.
++fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool {
++    segments
++        .iter()
++        .last()
++        .map_or(false, |ps| ps.ident.as_str() == "prelude")
++}
++
++// Allow "super::*" imports in tests.
++fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool {
++    segments.len() == 1 && segments[0].ident.as_str() == "super"
++}
++
++fn is_test_module_or_function(item: &Item<'_>) -> bool {
++    matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test")
 +}
index 72675c25175c98fdb421d25a79ed457ce795344e,0000000000000000000000000000000000000000..51d1cb2216a954c55e5907abc8c5885af1ea1a10
mode 100644,000000..100644
--- /dev/null
@@@ -1,2633 -1,0 +1,2647 @@@
-         group: "correctness",
 +//! This file is managed by `cargo dev update_lints`. Do not edit.
 +
 +use lazy_static::lazy_static;
 +
 +pub mod lint;
 +pub use lint::Level;
 +pub use lint::Lint;
 +pub use lint::LINT_LEVELS;
 +
 +lazy_static! {
 +// begin lint list, do not remove this comment, it’s used in `update_lints`
 +pub static ref ALL_LINTS: Vec<Lint> = vec![
 +    Lint {
 +        name: "absurd_extreme_comparisons",
 +        group: "correctness",
 +        desc: "a comparison with a maximum or minimum value that is always true or false",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "almost_swapped",
 +        group: "correctness",
 +        desc: "`foo = bar; bar = foo` sequence",
 +        deprecation: None,
 +        module: "swap",
 +    },
 +    Lint {
 +        name: "approx_constant",
 +        group: "correctness",
 +        desc: "the approximate of a known float constant (in `std::fXX::consts`)",
 +        deprecation: None,
 +        module: "approx_const",
 +    },
 +    Lint {
 +        name: "as_conversions",
 +        group: "restriction",
 +        desc: "using a potentially dangerous silent `as` conversion",
 +        deprecation: None,
 +        module: "as_conversions",
 +    },
 +    Lint {
 +        name: "assertions_on_constants",
 +        group: "style",
 +        desc: "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`",
 +        deprecation: None,
 +        module: "assertions_on_constants",
 +    },
 +    Lint {
 +        name: "assign_op_pattern",
 +        group: "style",
 +        desc: "assigning the result of an operation on a variable to that same variable",
 +        deprecation: None,
 +        module: "assign_ops",
 +    },
 +    Lint {
 +        name: "await_holding_lock",
 +        group: "pedantic",
 +        desc: "Inside an async function, holding a MutexGuard while calling await",
 +        deprecation: None,
 +        module: "await_holding_lock",
 +    },
 +    Lint {
 +        name: "bad_bit_mask",
 +        group: "correctness",
 +        desc: "expressions of the form `_ & mask == select` that will only ever return `true` or `false`",
 +        deprecation: None,
 +        module: "bit_mask",
 +    },
 +    Lint {
 +        name: "blacklisted_name",
 +        group: "style",
 +        desc: "usage of a blacklisted/placeholder name",
 +        deprecation: None,
 +        module: "blacklisted_name",
 +    },
 +    Lint {
 +        name: "block_in_if_condition_expr",
 +        group: "style",
 +        desc: "braces that can be eliminated in conditions, e.g., `if { true } ...`",
 +        deprecation: None,
 +        module: "block_in_if_condition",
 +    },
 +    Lint {
 +        name: "block_in_if_condition_stmt",
 +        group: "style",
 +        desc: "complex blocks in conditions, e.g., `if { let x = true; x } ...`",
 +        deprecation: None,
 +        module: "block_in_if_condition",
 +    },
 +    Lint {
 +        name: "bool_comparison",
 +        group: "complexity",
 +        desc: "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`",
 +        deprecation: None,
 +        module: "needless_bool",
 +    },
 +    Lint {
 +        name: "borrow_interior_mutable_const",
 +        group: "correctness",
 +        desc: "referencing `const` with interior mutability",
 +        deprecation: None,
 +        module: "non_copy_const",
 +    },
 +    Lint {
 +        name: "borrowed_box",
 +        group: "complexity",
 +        desc: "a borrow of a boxed type",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "box_vec",
 +        group: "perf",
 +        desc: "usage of `Box<Vec<T>>`, vector elements are already on the heap",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "boxed_local",
 +        group: "perf",
 +        desc: "using `Box<T>` where unnecessary",
 +        deprecation: None,
 +        module: "escape",
 +    },
 +    Lint {
 +        name: "builtin_type_shadow",
 +        group: "style",
 +        desc: "shadowing a builtin type",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "cargo_common_metadata",
 +        group: "cargo",
 +        desc: "common metadata is defined in `Cargo.toml`",
 +        deprecation: None,
 +        module: "cargo_common_metadata",
 +    },
 +    Lint {
 +        name: "cast_lossless",
 +        group: "pedantic",
 +        desc: "casts using `as` that are known to be lossless, e.g., `x as u64` where `x: u8`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "cast_possible_truncation",
 +        group: "pedantic",
 +        desc: "casts that may cause truncation of the value, e.g., `x as u8` where `x: u32`, or `x as i32` where `x: f32`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "cast_possible_wrap",
 +        group: "pedantic",
 +        desc: "casts that may cause wrapping around the value, e.g., `x as i32` where `x: u32` and `x > i32::MAX`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "cast_precision_loss",
 +        group: "pedantic",
 +        desc: "casts that cause loss of precision, e.g., `x as f32` where `x: u64`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "cast_ptr_alignment",
 +        group: "correctness",
 +        desc: "cast from a pointer to a more-strictly-aligned pointer",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "cast_ref_to_mut",
 +        group: "correctness",
 +        desc: "a cast of reference to a mutable pointer",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "cast_sign_loss",
 +        group: "pedantic",
 +        desc: "casts from signed types to unsigned types, e.g., `x as u32` where `x: i32`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "char_lit_as_u8",
 +        group: "complexity",
 +        desc: "casting a character literal to `u8` truncates",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "chars_last_cmp",
 +        group: "style",
 +        desc: "using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "chars_next_cmp",
 +        group: "style",
 +        desc: "using `.chars().next()` to check if a string starts with a char",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "checked_conversions",
 +        group: "pedantic",
 +        desc: "`try_from` could replace manual bounds checking when casting",
 +        deprecation: None,
 +        module: "checked_conversions",
 +    },
 +    Lint {
 +        name: "clone_double_ref",
 +        group: "correctness",
 +        desc: "using `clone` on `&&T`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "clone_on_copy",
 +        group: "complexity",
 +        desc: "using `clone` on a `Copy` type",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "clone_on_ref_ptr",
 +        group: "restriction",
 +        desc: "using \'clone\' on a ref-counted pointer",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "cmp_nan",
 +        group: "correctness",
 +        desc: "comparisons to `NAN`, which will always return false, probably not intended",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "cmp_null",
 +        group: "style",
 +        desc: "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead.",
 +        deprecation: None,
 +        module: "ptr",
 +    },
 +    Lint {
 +        name: "cmp_owned",
 +        group: "perf",
 +        desc: "creating owned instances for comparing with others, e.g., `x == \"foo\".to_string()`",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "cognitive_complexity",
 +        group: "nursery",
 +        desc: "functions that should be split up into multiple functions",
 +        deprecation: None,
 +        module: "cognitive_complexity",
 +    },
 +    Lint {
 +        name: "collapsible_if",
 +        group: "style",
 +        desc: "`if`s that can be collapsed (e.g., `if x { if y { ... } }` and `else { if x { ... } }`)",
 +        deprecation: None,
 +        module: "collapsible_if",
 +    },
 +    Lint {
 +        name: "comparison_chain",
 +        group: "style",
 +        desc: "`if`s that can be rewritten with `match` and `cmp`",
 +        deprecation: None,
 +        module: "comparison_chain",
 +    },
 +    Lint {
 +        name: "copy_iterator",
 +        group: "pedantic",
 +        desc: "implementing `Iterator` on a `Copy` type",
 +        deprecation: None,
 +        module: "copy_iterator",
 +    },
 +    Lint {
 +        name: "crosspointer_transmute",
 +        group: "complexity",
 +        desc: "transmutes that have to or from types that are a pointer to the other",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "dbg_macro",
 +        group: "restriction",
 +        desc: "`dbg!` macro is intended as a debugging tool",
 +        deprecation: None,
 +        module: "dbg_macro",
 +    },
 +    Lint {
 +        name: "debug_assert_with_mut_call",
 +        group: "nursery",
 +        desc: "mutable arguments in `debug_assert{,_ne,_eq}!`",
 +        deprecation: None,
 +        module: "mutable_debug_assertion",
 +    },
 +    Lint {
 +        name: "decimal_literal_representation",
 +        group: "restriction",
 +        desc: "using decimal representation when hexadecimal would be better",
 +        deprecation: None,
 +        module: "literal_representation",
 +    },
 +    Lint {
 +        name: "declare_interior_mutable_const",
 +        group: "correctness",
 +        desc: "declaring `const` with interior mutability",
 +        deprecation: None,
 +        module: "non_copy_const",
 +    },
 +    Lint {
 +        name: "default_trait_access",
 +        group: "pedantic",
 +        desc: "checks for literal calls to `Default::default()`",
 +        deprecation: None,
 +        module: "default_trait_access",
 +    },
 +    Lint {
 +        name: "deprecated_cfg_attr",
 +        group: "complexity",
 +        desc: "usage of `cfg_attr(rustfmt)` instead of tool attributes",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "deprecated_semver",
 +        group: "correctness",
 +        desc: "use of `#[deprecated(since = \"x\")]` where x is not semver",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "deref_addrof",
 +        group: "complexity",
 +        desc: "use of `*&` or `*&mut` in an expression",
 +        deprecation: None,
 +        module: "reference",
 +    },
 +    Lint {
 +        name: "derive_hash_xor_eq",
 +        group: "correctness",
 +        desc: "deriving `Hash` but implementing `PartialEq` explicitly",
 +        deprecation: None,
 +        module: "derive",
 +    },
 +    Lint {
 +        name: "diverging_sub_expression",
 +        group: "complexity",
 +        desc: "whether an expression contains a diverging sub expression",
 +        deprecation: None,
 +        module: "eval_order_dependence",
 +    },
 +    Lint {
 +        name: "doc_markdown",
 +        group: "pedantic",
 +        desc: "presence of `_`, `::` or camel-case outside backticks in documentation",
 +        deprecation: None,
 +        module: "doc",
 +    },
 +    Lint {
 +        name: "double_comparisons",
 +        group: "complexity",
 +        desc: "unnecessary double comparisons that can be simplified",
 +        deprecation: None,
 +        module: "double_comparison",
 +    },
 +    Lint {
 +        name: "double_must_use",
 +        group: "style",
 +        desc: "`#[must_use]` attribute on a `#[must_use]`-returning function / method",
 +        deprecation: None,
 +        module: "functions",
 +    },
 +    Lint {
 +        name: "double_neg",
 +        group: "style",
 +        desc: "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "double_parens",
 +        group: "complexity",
 +        desc: "Warn on unnecessary double parentheses",
 +        deprecation: None,
 +        module: "double_parens",
 +    },
 +    Lint {
 +        name: "drop_bounds",
 +        group: "correctness",
 +        desc: "Bounds of the form `T: Drop` are useless",
 +        deprecation: None,
 +        module: "drop_bounds",
 +    },
 +    Lint {
 +        name: "drop_copy",
 +        group: "correctness",
 +        desc: "calls to `std::mem::drop` with a value that implements Copy",
 +        deprecation: None,
 +        module: "drop_forget_ref",
 +    },
 +    Lint {
 +        name: "drop_ref",
 +        group: "correctness",
 +        desc: "calls to `std::mem::drop` with a reference instead of an owned value",
 +        deprecation: None,
 +        module: "drop_forget_ref",
 +    },
 +    Lint {
 +        name: "duplicate_underscore_argument",
 +        group: "style",
 +        desc: "function arguments having names which only differ by an underscore",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "duration_subsec",
 +        group: "complexity",
 +        desc: "checks for calculation of subsecond microseconds or milliseconds",
 +        deprecation: None,
 +        module: "duration_subsec",
 +    },
 +    Lint {
 +        name: "else_if_without_else",
 +        group: "restriction",
 +        desc: "`if` expression with an `else if`, but without a final `else` branch",
 +        deprecation: None,
 +        module: "else_if_without_else",
 +    },
 +    Lint {
 +        name: "empty_enum",
 +        group: "pedantic",
 +        desc: "enum with no variants",
 +        deprecation: None,
 +        module: "empty_enum",
 +    },
 +    Lint {
 +        name: "empty_line_after_outer_attr",
 +        group: "nursery",
 +        desc: "empty line after outer attribute",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "empty_loop",
 +        group: "style",
 +        desc: "empty `loop {}`, which should block or sleep",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "enum_clike_unportable_variant",
 +        group: "correctness",
 +        desc: "C-like enums that are `repr(isize/usize)` and have values that don\'t fit into an `i32`",
 +        deprecation: None,
 +        module: "enum_clike",
 +    },
 +    Lint {
 +        name: "enum_glob_use",
 +        group: "pedantic",
 +        desc: "use items that import all variants of an enum",
 +        deprecation: None,
 +        module: "wildcard_imports",
 +    },
 +    Lint {
 +        name: "enum_variant_names",
 +        group: "style",
 +        desc: "enums where all variants share a prefix/postfix",
 +        deprecation: None,
 +        module: "enum_variants",
 +    },
 +    Lint {
 +        name: "eq_op",
 +        group: "correctness",
 +        desc: "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)",
 +        deprecation: None,
 +        module: "eq_op",
 +    },
 +    Lint {
 +        name: "erasing_op",
 +        group: "correctness",
 +        desc: "using erasing operations, e.g., `x * 0` or `y & 0`",
 +        deprecation: None,
 +        module: "erasing_op",
 +    },
 +    Lint {
 +        name: "eval_order_dependence",
 +        group: "complexity",
 +        desc: "whether a variable read occurs before a write depends on sub-expression evaluation order",
 +        deprecation: None,
 +        module: "eval_order_dependence",
 +    },
 +    Lint {
 +        name: "excessive_precision",
 +        group: "style",
 +        desc: "excessive precision for float literal",
 +        deprecation: None,
 +        module: "float_literal",
 +    },
 +    Lint {
 +        name: "exit",
 +        group: "restriction",
 +        desc: "`std::process::exit` is called, terminating the program",
 +        deprecation: None,
 +        module: "exit",
 +    },
 +    Lint {
 +        name: "expect_fun_call",
 +        group: "perf",
 +        desc: "using any `expect` method with a function call",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "expl_impl_clone_on_copy",
 +        group: "pedantic",
 +        desc: "implementing `Clone` explicitly on `Copy` types",
 +        deprecation: None,
 +        module: "derive",
 +    },
 +    Lint {
 +        name: "explicit_counter_loop",
 +        group: "complexity",
 +        desc: "for-looping with an explicit counter when `_.enumerate()` would do",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "explicit_deref_methods",
 +        group: "pedantic",
 +        desc: "Explicit use of deref or deref_mut method while not in a method chain.",
 +        deprecation: None,
 +        module: "dereference",
 +    },
 +    Lint {
 +        name: "explicit_into_iter_loop",
 +        group: "pedantic",
 +        desc: "for-looping over `_.into_iter()` when `_` would do",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "explicit_iter_loop",
 +        group: "pedantic",
 +        desc: "for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "explicit_write",
 +        group: "complexity",
 +        desc: "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work",
 +        deprecation: None,
 +        module: "explicit_write",
 +    },
 +    Lint {
 +        name: "extra_unused_lifetimes",
 +        group: "complexity",
 +        desc: "unused lifetimes in function definitions",
 +        deprecation: None,
 +        module: "lifetimes",
 +    },
 +    Lint {
 +        name: "fallible_impl_from",
 +        group: "nursery",
 +        desc: "Warn on impls of `From<..>` that contain `panic!()` or `unwrap()`",
 +        deprecation: None,
 +        module: "fallible_impl_from",
 +    },
 +    Lint {
 +        name: "filetype_is_file",
 +        group: "restriction",
 +        desc: "`FileType::is_file` is not recommended to test for readable file type",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "filter_map",
 +        group: "pedantic",
 +        desc: "using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "filter_map_next",
 +        group: "pedantic",
 +        desc: "using combination of `filter_map` and `next` which can usually be written as a single method call",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "filter_next",
 +        group: "complexity",
 +        desc: "using `filter(p).next()`, which is more succinctly expressed as `.find(p)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "find_map",
 +        group: "pedantic",
 +        desc: "using a combination of `find` and `map` can usually be written as a single method call",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "flat_map_identity",
 +        group: "complexity",
 +        desc: "call to `flat_map` where `flatten` is sufficient",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "float_arithmetic",
 +        group: "restriction",
 +        desc: "any floating-point arithmetic statement",
 +        deprecation: None,
 +        module: "arithmetic",
 +    },
 +    Lint {
 +        name: "float_cmp",
 +        group: "correctness",
 +        desc: "using `==` or `!=` on float values instead of comparing difference with an epsilon",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "float_cmp_const",
 +        group: "restriction",
 +        desc: "using `==` or `!=` on float constants instead of comparing difference with an epsilon",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "fn_address_comparisons",
 +        group: "correctness",
 +        desc: "comparison with an address of a function item",
 +        deprecation: None,
 +        module: "unnamed_address",
 +    },
 +    Lint {
 +        name: "fn_params_excessive_bools",
 +        group: "pedantic",
 +        desc: "using too many bools in function parameters",
 +        deprecation: None,
 +        module: "excessive_bools",
 +    },
 +    Lint {
 +        name: "fn_to_numeric_cast",
 +        group: "style",
 +        desc: "casting a function pointer to a numeric type other than usize",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "fn_to_numeric_cast_with_truncation",
 +        group: "style",
 +        desc: "casting a function pointer to a numeric type not wide enough to store the address",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "for_kv_map",
 +        group: "style",
 +        desc: "looping on a map using `iter` when `keys` or `values` would do",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "for_loop_over_option",
 +        group: "correctness",
 +        desc: "for-looping over an `Option`, which is more clearly expressed as an `if let`",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "for_loop_over_result",
 +        group: "correctness",
 +        desc: "for-looping over a `Result`, which is more clearly expressed as an `if let`",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "forget_copy",
 +        group: "correctness",
 +        desc: "calls to `std::mem::forget` with a value that implements Copy",
 +        deprecation: None,
 +        module: "drop_forget_ref",
 +    },
 +    Lint {
 +        name: "forget_ref",
 +        group: "correctness",
 +        desc: "calls to `std::mem::forget` with a reference instead of an owned value",
 +        deprecation: None,
 +        module: "drop_forget_ref",
 +    },
 +    Lint {
 +        name: "future_not_send",
 +        group: "nursery",
 +        desc: "public Futures must be Send",
 +        deprecation: None,
 +        module: "future_not_send",
 +    },
 +    Lint {
 +        name: "get_last_with_len",
 +        group: "complexity",
 +        desc: "Using `x.get(x.len() - 1)` when `x.last()` is correct and simpler",
 +        deprecation: None,
 +        module: "get_last_with_len",
 +    },
 +    Lint {
 +        name: "get_unwrap",
 +        group: "restriction",
 +        desc: "using `.get().unwrap()` or `.get_mut().unwrap()` when using `[]` would work instead",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "identity_conversion",
 +        group: "complexity",
 +        desc: "using always-identical `Into`/`From`/`IntoIter` conversions",
 +        deprecation: None,
 +        module: "identity_conversion",
 +    },
 +    Lint {
 +        name: "identity_op",
 +        group: "complexity",
 +        desc: "using identity operations, e.g., `x + 0` or `y / 1`",
 +        deprecation: None,
 +        module: "identity_op",
 +    },
 +    Lint {
 +        name: "if_let_mutex",
 +        group: "correctness",
 +        desc: "locking a `Mutex` in an `if let` block can cause deadlocks",
 +        deprecation: None,
 +        module: "if_let_mutex",
 +    },
 +    Lint {
 +        name: "if_let_some_result",
 +        group: "style",
 +        desc: "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead",
 +        deprecation: None,
 +        module: "if_let_some_result",
 +    },
 +    Lint {
 +        name: "if_not_else",
 +        group: "pedantic",
 +        desc: "`if` branches that could be swapped so no negation operation is necessary on the condition",
 +        deprecation: None,
 +        module: "if_not_else",
 +    },
 +    Lint {
 +        name: "if_same_then_else",
 +        group: "correctness",
 +        desc: "`if` with the same `then` and `else` blocks",
 +        deprecation: None,
 +        module: "copies",
 +    },
 +    Lint {
 +        name: "ifs_same_cond",
 +        group: "correctness",
 +        desc: "consecutive `if`s with the same condition",
 +        deprecation: None,
 +        module: "copies",
 +    },
 +    Lint {
 +        name: "implicit_hasher",
 +        group: "pedantic",
 +        desc: "missing generalization over different hashers",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "implicit_return",
 +        group: "restriction",
 +        desc: "use a return statement like `return expr` instead of an expression",
 +        deprecation: None,
 +        module: "implicit_return",
 +    },
 +    Lint {
 +        name: "implicit_saturating_sub",
 +        group: "pedantic",
 +        desc: "Perform saturating subtraction instead of implicitly checking lower bound of data type",
 +        deprecation: None,
 +        module: "implicit_saturating_sub",
 +    },
 +    Lint {
 +        name: "imprecise_flops",
 +        group: "nursery",
 +        desc: "usage of imprecise floating point operations",
 +        deprecation: None,
 +        module: "floating_point_arithmetic",
 +    },
 +    Lint {
 +        name: "inconsistent_digit_grouping",
 +        group: "style",
 +        desc: "integer literals with digits grouped inconsistently",
 +        deprecation: None,
 +        module: "literal_representation",
 +    },
 +    Lint {
 +        name: "indexing_slicing",
 +        group: "restriction",
 +        desc: "indexing/slicing usage",
 +        deprecation: None,
 +        module: "indexing_slicing",
 +    },
 +    Lint {
 +        name: "ineffective_bit_mask",
 +        group: "correctness",
 +        desc: "expressions where a bit mask will be rendered useless by a comparison, e.g., `(x | 1) > 2`",
 +        deprecation: None,
 +        module: "bit_mask",
 +    },
 +    Lint {
 +        name: "inefficient_to_string",
 +        group: "pedantic",
 +        desc: "using `to_string` on `&&T` where `T: ToString`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "infallible_destructuring_match",
 +        group: "style",
 +        desc: "a `match` statement with a single infallible arm instead of a `let`",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "infinite_iter",
 +        group: "correctness",
 +        desc: "infinite iteration",
 +        deprecation: None,
 +        module: "infinite_iter",
 +    },
 +    Lint {
 +        name: "inherent_to_string",
 +        group: "style",
 +        desc: "type implements inherent method `to_string()`, but should instead implement the `Display` trait",
 +        deprecation: None,
 +        module: "inherent_to_string",
 +    },
 +    Lint {
 +        name: "inherent_to_string_shadow_display",
 +        group: "correctness",
 +        desc: "type implements inherent method `to_string()`, which gets shadowed by the implementation of the `Display` trait",
 +        deprecation: None,
 +        module: "inherent_to_string",
 +    },
 +    Lint {
 +        name: "inline_always",
 +        group: "pedantic",
 +        desc: "use of `#[inline(always)]`",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "inline_fn_without_body",
 +        group: "correctness",
 +        desc: "use of `#[inline]` on trait methods without bodies",
 +        deprecation: None,
 +        module: "inline_fn_without_body",
 +    },
 +    Lint {
 +        name: "int_plus_one",
 +        group: "complexity",
 +        desc: "instead of using `x >= y + 1`, use `x > y`",
 +        deprecation: None,
 +        module: "int_plus_one",
 +    },
 +    Lint {
 +        name: "integer_arithmetic",
 +        group: "restriction",
 +        desc: "any integer arithmetic expression which could overflow or panic",
 +        deprecation: None,
 +        module: "arithmetic",
 +    },
 +    Lint {
 +        name: "integer_division",
 +        group: "restriction",
 +        desc: "integer division may cause loss of precision",
 +        deprecation: None,
 +        module: "integer_division",
 +    },
 +    Lint {
 +        name: "into_iter_on_ref",
 +        group: "style",
 +        desc: "using `.into_iter()` on a reference",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "invalid_atomic_ordering",
 +        group: "correctness",
 +        desc: "usage of invalid atomic ordering in atomic loads/stores and memory fences",
 +        deprecation: None,
 +        module: "atomic_ordering",
 +    },
 +    Lint {
 +        name: "invalid_regex",
 +        group: "correctness",
 +        desc: "invalid regular expressions",
 +        deprecation: None,
 +        module: "regex",
 +    },
 +    Lint {
 +        name: "invalid_upcast_comparisons",
 +        group: "pedantic",
 +        desc: "a comparison involving an upcast which is always true or false",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "items_after_statements",
 +        group: "pedantic",
 +        desc: "blocks where an item comes after a statement",
 +        deprecation: None,
 +        module: "items_after_statements",
 +    },
 +    Lint {
 +        name: "iter_cloned_collect",
 +        group: "style",
 +        desc: "using `.cloned().collect()` on slice to create a `Vec`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "iter_next_loop",
 +        group: "correctness",
 +        desc: "for-looping over `_.next()` which is probably not intended",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "iter_nth",
 +        group: "perf",
 +        desc: "using `.iter().nth()` on a standard library type with O(1) element access",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "iter_nth_zero",
 +        group: "style",
 +        desc: "replace `iter.nth(0)` with `iter.next()`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "iter_skip_next",
 +        group: "style",
 +        desc: "using `.skip(x).next()` on an iterator",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "iterator_step_by_zero",
 +        group: "correctness",
 +        desc: "using `Iterator::step_by(0)`, which will panic at runtime",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "just_underscores_and_digits",
 +        group: "style",
 +        desc: "unclear name",
 +        deprecation: None,
 +        module: "non_expressive_names",
 +    },
 +    Lint {
 +        name: "large_const_arrays",
 +        group: "perf",
 +        desc: "large non-scalar const array may cause performance overhead",
 +        deprecation: None,
 +        module: "large_const_arrays",
 +    },
 +    Lint {
 +        name: "large_digit_groups",
 +        group: "pedantic",
 +        desc: "grouping digits into groups that are too large",
 +        deprecation: None,
 +        module: "literal_representation",
 +    },
 +    Lint {
 +        name: "large_enum_variant",
 +        group: "perf",
 +        desc: "large size difference between variants on an enum",
 +        deprecation: None,
 +        module: "large_enum_variant",
 +    },
 +    Lint {
 +        name: "large_stack_arrays",
 +        group: "pedantic",
 +        desc: "allocating large arrays on stack may cause stack overflow",
 +        deprecation: None,
 +        module: "large_stack_arrays",
 +    },
 +    Lint {
 +        name: "len_without_is_empty",
 +        group: "style",
 +        desc: "traits or impls with a public `len` method but no corresponding `is_empty` method",
 +        deprecation: None,
 +        module: "len_zero",
 +    },
 +    Lint {
 +        name: "len_zero",
 +        group: "style",
 +        desc: "checking `.len() == 0` or `.len() > 0` (or similar) when `.is_empty()` could be used instead",
 +        deprecation: None,
 +        module: "len_zero",
 +    },
 +    Lint {
 +        name: "let_and_return",
 +        group: "style",
 +        desc: "creating a let-binding and then immediately returning it like `let x = expr; x` at the end of a block",
 +        deprecation: None,
 +        module: "returns",
 +    },
 +    Lint {
 +        name: "let_underscore_lock",
 +        group: "correctness",
 +        desc: "non-binding let on a synchronization lock",
 +        deprecation: None,
 +        module: "let_underscore",
 +    },
 +    Lint {
 +        name: "let_underscore_must_use",
 +        group: "restriction",
 +        desc: "non-binding let on a `#[must_use]` expression",
 +        deprecation: None,
 +        module: "let_underscore",
 +    },
 +    Lint {
 +        name: "let_unit_value",
 +        group: "pedantic",
 +        desc: "creating a `let` binding to a value of unit type, which usually can\'t be used afterwards",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "linkedlist",
 +        group: "pedantic",
 +        desc: "usage of LinkedList, usually a vector is faster, or a more specialized data structure like a `VecDeque`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "logic_bug",
 +        group: "correctness",
 +        desc: "boolean expressions that contain terminals which can be eliminated",
 +        deprecation: None,
 +        module: "booleans",
 +    },
 +    Lint {
 +        name: "lossy_float_literal",
 +        group: "restriction",
 +        desc: "lossy whole number float literals",
 +        deprecation: None,
 +        module: "float_literal",
 +    },
 +    Lint {
 +        name: "macro_use_imports",
 +        group: "pedantic",
 +        desc: "#[macro_use] is no longer needed",
 +        deprecation: None,
 +        module: "macro_use",
 +    },
 +    Lint {
 +        name: "main_recursion",
 +        group: "style",
 +        desc: "recursion using the entrypoint",
 +        deprecation: None,
 +        module: "main_recursion",
 +    },
++    Lint {
++        name: "manual_async_fn",
++        group: "style",
++        desc: "manual implementations of `async` functions can be simplified using the dedicated syntax",
++        deprecation: None,
++        module: "manual_async_fn",
++    },
 +    Lint {
 +        name: "manual_memcpy",
 +        group: "perf",
 +        desc: "manually copying items between slices",
 +        deprecation: None,
 +        module: "loops",
 +    },
++    Lint {
++        name: "manual_non_exhaustive",
++        group: "style",
++        desc: "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]",
++        deprecation: None,
++        module: "manual_non_exhaustive",
++    },
 +    Lint {
 +        name: "manual_saturating_arithmetic",
 +        group: "style",
 +        desc: "`.chcked_add/sub(x).unwrap_or(MAX/MIN)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "manual_swap",
 +        group: "complexity",
 +        desc: "manual swap of two variables",
 +        deprecation: None,
 +        module: "swap",
 +    },
 +    Lint {
 +        name: "many_single_char_names",
 +        group: "style",
 +        desc: "too many single character bindings",
 +        deprecation: None,
 +        module: "non_expressive_names",
 +    },
 +    Lint {
 +        name: "map_clone",
 +        group: "style",
 +        desc: "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types",
 +        deprecation: None,
 +        module: "map_clone",
 +    },
 +    Lint {
 +        name: "map_entry",
 +        group: "perf",
 +        desc: "use of `contains_key` followed by `insert` on a `HashMap` or `BTreeMap`",
 +        deprecation: None,
 +        module: "entry",
 +    },
 +    Lint {
 +        name: "map_flatten",
 +        group: "pedantic",
 +        desc: "using combinations of `flatten` and `map` which can usually be written as a single method call",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "match_as_ref",
 +        group: "complexity",
 +        desc: "a `match` on an Option value instead of using `as_ref()` or `as_mut`",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "match_bool",
 +        group: "pedantic",
 +        desc: "a `match` on a boolean expression instead of an `if..else` block",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "match_on_vec_items",
++        group: "pedantic",
 +        desc: "matching on vector elements can panic",
 +        deprecation: None,
 +        module: "match_on_vec_items",
 +    },
 +    Lint {
 +        name: "match_overlapping_arm",
 +        group: "style",
 +        desc: "a `match` with overlapping arms",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "match_ref_pats",
 +        group: "style",
 +        desc: "a `match` or `if let` with all arms prefixed with `&` instead of deref-ing the match expression",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "match_same_arms",
 +        group: "pedantic",
 +        desc: "`match` with identical arm bodies",
 +        deprecation: None,
 +        module: "copies",
 +    },
 +    Lint {
 +        name: "match_single_binding",
 +        group: "complexity",
 +        desc: "a match with a single binding instead of using `let` statement",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "match_wild_err_arm",
 +        group: "style",
 +        desc: "a `match` with `Err(_)` arm and take drastic actions",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "maybe_infinite_iter",
 +        group: "pedantic",
 +        desc: "possible infinite iteration",
 +        deprecation: None,
 +        module: "infinite_iter",
 +    },
 +    Lint {
 +        name: "mem_discriminant_non_enum",
 +        group: "correctness",
 +        desc: "calling `mem::descriminant` on non-enum type",
 +        deprecation: None,
 +        module: "mem_discriminant",
 +    },
 +    Lint {
 +        name: "mem_forget",
 +        group: "restriction",
 +        desc: "`mem::forget` usage on `Drop` types, likely to cause memory leaks",
 +        deprecation: None,
 +        module: "mem_forget",
 +    },
 +    Lint {
 +        name: "mem_replace_option_with_none",
 +        group: "style",
 +        desc: "replacing an `Option` with `None` instead of `take()`",
 +        deprecation: None,
 +        module: "mem_replace",
 +    },
 +    Lint {
 +        name: "mem_replace_with_default",
 +        group: "style",
 +        desc: "replacing a value of type `T` with `T::default()` instead of using `std::mem::take`",
 +        deprecation: None,
 +        module: "mem_replace",
 +    },
 +    Lint {
 +        name: "mem_replace_with_uninit",
 +        group: "correctness",
 +        desc: "`mem::replace(&mut _, mem::uninitialized())` or `mem::replace(&mut _, mem::zeroed())`",
 +        deprecation: None,
 +        module: "mem_replace",
 +    },
 +    Lint {
 +        name: "min_max",
 +        group: "correctness",
 +        desc: "`min(_, max(_, _))` (or vice versa) with bounds clamping the result to a constant",
 +        deprecation: None,
 +        module: "minmax",
 +    },
 +    Lint {
 +        name: "mismatched_target_os",
 +        group: "correctness",
 +        desc: "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "misrefactored_assign_op",
 +        group: "complexity",
 +        desc: "having a variable on both sides of an assign op",
 +        deprecation: None,
 +        module: "assign_ops",
 +    },
 +    Lint {
 +        name: "missing_const_for_fn",
 +        group: "nursery",
 +        desc: "Lint functions definitions that could be made `const fn`",
 +        deprecation: None,
 +        module: "missing_const_for_fn",
 +    },
 +    Lint {
 +        name: "missing_docs_in_private_items",
 +        group: "restriction",
 +        desc: "detects missing documentation for public and private members",
 +        deprecation: None,
 +        module: "missing_doc",
 +    },
 +    Lint {
 +        name: "missing_errors_doc",
 +        group: "pedantic",
 +        desc: "`pub fn` returns `Result` without `# Errors` in doc comment",
 +        deprecation: None,
 +        module: "doc",
 +    },
 +    Lint {
 +        name: "missing_inline_in_public_items",
 +        group: "restriction",
 +        desc: "detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)",
 +        deprecation: None,
 +        module: "missing_inline",
 +    },
 +    Lint {
 +        name: "missing_safety_doc",
 +        group: "style",
 +        desc: "`pub unsafe fn` without `# Safety` docs",
 +        deprecation: None,
 +        module: "doc",
 +    },
 +    Lint {
 +        name: "mistyped_literal_suffixes",
 +        group: "correctness",
 +        desc: "mistyped literal suffix",
 +        deprecation: None,
 +        module: "literal_representation",
 +    },
 +    Lint {
 +        name: "mixed_case_hex_literals",
 +        group: "style",
 +        desc: "hex literals whose letter digits are not consistently upper- or lowercased",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "module_inception",
 +        group: "style",
 +        desc: "modules that have the same name as their parent module",
 +        deprecation: None,
 +        module: "enum_variants",
 +    },
 +    Lint {
 +        name: "module_name_repetitions",
 +        group: "pedantic",
 +        desc: "type names prefixed/postfixed with their containing module\'s name",
 +        deprecation: None,
 +        module: "enum_variants",
 +    },
 +    Lint {
 +        name: "modulo_arithmetic",
 +        group: "restriction",
 +        desc: "any modulo arithmetic statement",
 +        deprecation: None,
 +        module: "modulo_arithmetic",
 +    },
 +    Lint {
 +        name: "modulo_one",
 +        group: "correctness",
 +        desc: "taking a number modulo 1, which always returns 0",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "multiple_crate_versions",
 +        group: "cargo",
 +        desc: "multiple versions of the same crate being used",
 +        deprecation: None,
 +        module: "multiple_crate_versions",
 +    },
 +    Lint {
 +        name: "multiple_inherent_impl",
 +        group: "restriction",
 +        desc: "Multiple inherent impl that could be grouped",
 +        deprecation: None,
 +        module: "inherent_impl",
 +    },
 +    Lint {
 +        name: "must_use_candidate",
 +        group: "pedantic",
 +        desc: "function or method that could take a `#[must_use]` attribute",
 +        deprecation: None,
 +        module: "functions",
 +    },
 +    Lint {
 +        name: "must_use_unit",
 +        group: "style",
 +        desc: "`#[must_use]` attribute on a unit-returning function / method",
 +        deprecation: None,
 +        module: "functions",
 +    },
 +    Lint {
 +        name: "mut_from_ref",
 +        group: "correctness",
 +        desc: "fns that create mutable refs from immutable ref args",
 +        deprecation: None,
 +        module: "ptr",
 +    },
 +    Lint {
 +        name: "mut_mut",
 +        group: "pedantic",
 +        desc: "usage of double-mut refs, e.g., `&mut &mut ...`",
 +        deprecation: None,
 +        module: "mut_mut",
 +    },
 +    Lint {
 +        name: "mut_range_bound",
 +        group: "complexity",
 +        desc: "for loop over a range where one of the bounds is a mutable variable",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "mutable_key_type",
 +        group: "correctness",
 +        desc: "Check for mutable `Map`/`Set` key type",
 +        deprecation: None,
 +        module: "mut_key",
 +    },
 +    Lint {
 +        name: "mutex_atomic",
 +        group: "perf",
 +        desc: "using a mutex where an atomic value could be used instead",
 +        deprecation: None,
 +        module: "mutex_atomic",
 +    },
 +    Lint {
 +        name: "mutex_integer",
 +        group: "nursery",
 +        desc: "using a mutex for an integer type",
 +        deprecation: None,
 +        module: "mutex_atomic",
 +    },
 +    Lint {
 +        name: "naive_bytecount",
 +        group: "perf",
 +        desc: "use of naive `<slice>.filter(|&x| x == y).count()` to count byte values",
 +        deprecation: None,
 +        module: "bytecount",
 +    },
 +    Lint {
 +        name: "needless_bool",
 +        group: "complexity",
 +        desc: "if-statements with plain booleans in the then- and else-clause, e.g., `if p { true } else { false }`",
 +        deprecation: None,
 +        module: "needless_bool",
 +    },
 +    Lint {
 +        name: "needless_borrow",
 +        group: "nursery",
 +        desc: "taking a reference that is going to be automatically dereferenced",
 +        deprecation: None,
 +        module: "needless_borrow",
 +    },
 +    Lint {
 +        name: "needless_borrowed_reference",
 +        group: "complexity",
 +        desc: "taking a needless borrowed reference",
 +        deprecation: None,
 +        module: "needless_borrowed_ref",
 +    },
 +    Lint {
 +        name: "needless_collect",
 +        group: "perf",
 +        desc: "collecting an iterator when collect is not needed",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "needless_continue",
 +        group: "pedantic",
 +        desc: "`continue` statements that can be replaced by a rearrangement of code",
 +        deprecation: None,
 +        module: "needless_continue",
 +    },
 +    Lint {
 +        name: "needless_doctest_main",
 +        group: "style",
 +        desc: "presence of `fn main() {` in code examples",
 +        deprecation: None,
 +        module: "doc",
 +    },
 +    Lint {
 +        name: "needless_lifetimes",
 +        group: "complexity",
 +        desc: "using explicit lifetimes for references in function arguments when elision rules would allow omitting them",
 +        deprecation: None,
 +        module: "lifetimes",
 +    },
 +    Lint {
 +        name: "needless_pass_by_value",
 +        group: "pedantic",
 +        desc: "functions taking arguments by value, but not consuming them in its body",
 +        deprecation: None,
 +        module: "needless_pass_by_value",
 +    },
 +    Lint {
 +        name: "needless_range_loop",
 +        group: "style",
 +        desc: "for-looping over a range of indices where an iterator over items would do",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "needless_return",
 +        group: "style",
 +        desc: "using a return statement like `return expr;` where an expression would suffice",
 +        deprecation: None,
 +        module: "returns",
 +    },
 +    Lint {
 +        name: "needless_update",
 +        group: "complexity",
 +        desc: "using `Foo { ..base }` when there are no missing fields",
 +        deprecation: None,
 +        module: "needless_update",
 +    },
 +    Lint {
 +        name: "neg_cmp_op_on_partial_ord",
 +        group: "complexity",
 +        desc: "The use of negated comparison operators on partially ordered types may produce confusing code.",
 +        deprecation: None,
 +        module: "neg_cmp_op_on_partial_ord",
 +    },
 +    Lint {
 +        name: "neg_multiply",
 +        group: "style",
 +        desc: "multiplying integers with `-1`",
 +        deprecation: None,
 +        module: "neg_multiply",
 +    },
 +    Lint {
 +        name: "never_loop",
 +        group: "correctness",
 +        desc: "any loop that will always `break` or `return`",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "new_ret_no_self",
 +        group: "style",
 +        desc: "not returning type containing `Self` in a `new` method",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "new_without_default",
 +        group: "style",
 +        desc: "`fn new() -> Self` method without `Default` implementation",
 +        deprecation: None,
 +        module: "new_without_default",
 +    },
 +    Lint {
 +        name: "no_effect",
 +        group: "complexity",
 +        desc: "statements with no effect",
 +        deprecation: None,
 +        module: "no_effect",
 +    },
 +    Lint {
 +        name: "non_ascii_literal",
 +        group: "pedantic",
 +        desc: "using any literal non-ASCII chars in a string literal instead of using the `\\\\u` escape",
 +        deprecation: None,
 +        module: "unicode",
 +    },
 +    Lint {
 +        name: "nonminimal_bool",
 +        group: "complexity",
 +        desc: "boolean expressions that can be written more concisely",
 +        deprecation: None,
 +        module: "booleans",
 +    },
 +    Lint {
 +        name: "nonsensical_open_options",
 +        group: "correctness",
 +        desc: "nonsensical combination of options for opening a file",
 +        deprecation: None,
 +        module: "open_options",
 +    },
 +    Lint {
 +        name: "not_unsafe_ptr_arg_deref",
 +        group: "correctness",
 +        desc: "public functions dereferencing raw pointer arguments but not marked `unsafe`",
 +        deprecation: None,
 +        module: "functions",
 +    },
 +    Lint {
 +        name: "ok_expect",
 +        group: "style",
 +        desc: "using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "op_ref",
 +        group: "style",
 +        desc: "taking a reference to satisfy the type constraints on `==`",
 +        deprecation: None,
 +        module: "eq_op",
 +    },
 +    Lint {
 +        name: "option_and_then_some",
 +        group: "complexity",
 +        desc: "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "option_as_ref_deref",
 +        group: "complexity",
 +        desc: "using `as_ref().map(Deref::deref)`, which is more succinctly expressed as `as_deref()`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "option_env_unwrap",
 +        group: "correctness",
 +        desc: "using `option_env!(...).unwrap()` to get environment variable",
 +        deprecation: None,
 +        module: "option_env_unwrap",
 +    },
 +    Lint {
 +        name: "option_expect_used",
 +        group: "restriction",
 +        desc: "using `Option.expect()`, which might be better handled",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "option_map_or_none",
 +        group: "style",
 +        desc: "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "option_map_unit_fn",
 +        group: "complexity",
 +        desc: "using `option.map(f)`, where `f` is a function or closure that returns `()`",
 +        deprecation: None,
 +        module: "map_unit_fn",
 +    },
 +    Lint {
 +        name: "option_map_unwrap_or",
 +        group: "pedantic",
 +        desc: "using `Option.map(f).unwrap_or(a)`, which is more succinctly expressed as `map_or(a, f)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "option_map_unwrap_or_else",
 +        group: "pedantic",
 +        desc: "using `Option.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `map_or_else(g, f)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "option_option",
 +        group: "pedantic",
 +        desc: "usage of `Option<Option<T>>`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "option_unwrap_used",
 +        group: "restriction",
 +        desc: "using `Option.unwrap()`, which should at least get a better message using `expect()`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "or_fun_call",
 +        group: "perf",
 +        desc: "using any `*or` method with a function call, which suggests `*or_else`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "out_of_bounds_indexing",
 +        group: "correctness",
 +        desc: "out of bounds constant indexing",
 +        deprecation: None,
 +        module: "indexing_slicing",
 +    },
 +    Lint {
 +        name: "overflow_check_conditional",
 +        group: "complexity",
 +        desc: "overflow checks inspired by C which are likely to panic",
 +        deprecation: None,
 +        module: "overflow_check_conditional",
 +    },
 +    Lint {
 +        name: "panic",
 +        group: "restriction",
 +        desc: "usage of the `panic!` macro",
 +        deprecation: None,
 +        module: "panic_unimplemented",
 +    },
 +    Lint {
 +        name: "panic_params",
 +        group: "style",
 +        desc: "missing parameters in `panic!` calls",
 +        deprecation: None,
 +        module: "panic_unimplemented",
 +    },
 +    Lint {
 +        name: "panicking_unwrap",
 +        group: "correctness",
 +        desc: "checks for calls of `unwrap[_err]()` that will always fail",
 +        deprecation: None,
 +        module: "unwrap",
 +    },
 +    Lint {
 +        name: "partialeq_ne_impl",
 +        group: "complexity",
 +        desc: "re-implementing `PartialEq::ne`",
 +        deprecation: None,
 +        module: "partialeq_ne_impl",
 +    },
 +    Lint {
 +        name: "path_buf_push_overwrite",
 +        group: "nursery",
 +        desc: "calling `push` with file system root on `PathBuf` can overwrite it",
 +        deprecation: None,
 +        module: "path_buf_push_overwrite",
 +    },
 +    Lint {
 +        name: "possible_missing_comma",
 +        group: "correctness",
 +        desc: "possible missing comma in array",
 +        deprecation: None,
 +        module: "formatting",
 +    },
 +    Lint {
 +        name: "precedence",
 +        group: "complexity",
 +        desc: "operations where precedence may be unclear",
 +        deprecation: None,
 +        module: "precedence",
 +    },
 +    Lint {
 +        name: "print_literal",
 +        group: "style",
 +        desc: "printing a literal with a format string",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "print_stdout",
 +        group: "restriction",
 +        desc: "printing on stdout",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "print_with_newline",
 +        group: "style",
 +        desc: "using `print!()` with a format string that ends in a single newline",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "println_empty_string",
 +        group: "style",
 +        desc: "using `println!(\"\")` with an empty string",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "ptr_arg",
 +        group: "style",
 +        desc: "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively",
 +        deprecation: None,
 +        module: "ptr",
 +    },
 +    Lint {
 +        name: "ptr_offset_with_cast",
 +        group: "complexity",
 +        desc: "unneeded pointer offset cast",
 +        deprecation: None,
 +        module: "ptr_offset_with_cast",
 +    },
 +    Lint {
 +        name: "pub_enum_variant_names",
 +        group: "pedantic",
 +        desc: "enums where all variants share a prefix/postfix",
 +        deprecation: None,
 +        module: "enum_variants",
 +    },
 +    Lint {
 +        name: "question_mark",
 +        group: "style",
 +        desc: "checks for expressions that could be replaced by the question mark operator",
 +        deprecation: None,
 +        module: "question_mark",
 +    },
 +    Lint {
 +        name: "range_minus_one",
 +        group: "complexity",
 +        desc: "`x..=(y-1)` reads better as `x..y`",
 +        deprecation: None,
 +        module: "ranges",
 +    },
 +    Lint {
 +        name: "range_plus_one",
 +        group: "pedantic",
 +        desc: "`x..(y+1)` reads better as `x..=y`",
 +        deprecation: None,
 +        module: "ranges",
 +    },
 +    Lint {
 +        name: "range_zip_with_len",
 +        group: "complexity",
 +        desc: "zipping iterator with a range when `enumerate()` would do",
 +        deprecation: None,
 +        module: "ranges",
 +    },
 +    Lint {
 +        name: "redundant_allocation",
 +        group: "perf",
 +        desc: "redundant allocation",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "redundant_clone",
 +        group: "perf",
 +        desc: "`clone()` of an owned value that is going to be dropped immediately",
 +        deprecation: None,
 +        module: "redundant_clone",
 +    },
 +    Lint {
 +        name: "redundant_closure",
 +        group: "style",
 +        desc: "redundant closures, i.e., `|a| foo(a)` (which can be written as just `foo`)",
 +        deprecation: None,
 +        module: "eta_reduction",
 +    },
 +    Lint {
 +        name: "redundant_closure_call",
 +        group: "complexity",
 +        desc: "throwaway closures called in the expression they are defined",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "redundant_closure_for_method_calls",
 +        group: "pedantic",
 +        desc: "redundant closures for method calls",
 +        deprecation: None,
 +        module: "eta_reduction",
 +    },
 +    Lint {
 +        name: "redundant_field_names",
 +        group: "style",
 +        desc: "checks for fields in struct literals where shorthands could be used",
 +        deprecation: None,
 +        module: "redundant_field_names",
 +    },
 +    Lint {
 +        name: "redundant_pattern",
 +        group: "style",
 +        desc: "using `name @ _` in a pattern",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "redundant_pattern_matching",
 +        group: "style",
 +        desc: "use the proper utility function avoiding an `if let`",
 +        deprecation: None,
 +        module: "redundant_pattern_matching",
 +    },
 +    Lint {
 +        name: "redundant_pub_crate",
 +        group: "nursery",
 +        desc: "Using `pub(crate)` visibility on items that are not crate visible due to the visibility of the module that contains them.",
 +        deprecation: None,
 +        module: "redundant_pub_crate",
 +    },
 +    Lint {
 +        name: "redundant_static_lifetimes",
 +        group: "style",
 +        desc: "Using explicit `\'static` lifetime for constants or statics when elision rules would allow omitting them.",
 +        deprecation: None,
 +        module: "redundant_static_lifetimes",
 +    },
 +    Lint {
 +        name: "ref_in_deref",
 +        group: "complexity",
 +        desc: "Use of reference in auto dereference expression.",
 +        deprecation: None,
 +        module: "reference",
 +    },
 +    Lint {
 +        name: "regex_macro",
 +        group: "style",
 +        desc: "use of `regex!(_)` instead of `Regex::new(_)`",
 +        deprecation: None,
 +        module: "regex",
 +    },
 +    Lint {
 +        name: "rest_pat_in_fully_bound_structs",
 +        group: "restriction",
 +        desc: "a match on a struct that binds all fields but still uses the wildcard pattern",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "result_expect_used",
 +        group: "restriction",
 +        desc: "using `Result.expect()`, which might be better handled",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "result_map_or_into_option",
 +        group: "style",
 +        desc: "using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "result_map_unit_fn",
 +        group: "complexity",
 +        desc: "using `result.map(f)`, where `f` is a function or closure that returns `()`",
 +        deprecation: None,
 +        module: "map_unit_fn",
 +    },
 +    Lint {
 +        name: "result_map_unwrap_or_else",
 +        group: "pedantic",
 +        desc: "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "result_unwrap_used",
 +        group: "restriction",
 +        desc: "using `Result.unwrap()`, which might be better handled",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "reverse_range_loop",
 +        group: "correctness",
 +        desc: "iteration over an empty range, such as `10..0` or `5..5`",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "same_functions_in_if_condition",
 +        group: "pedantic",
 +        desc: "consecutive `if`s with the same function call",
 +        deprecation: None,
 +        module: "copies",
 +    },
 +    Lint {
 +        name: "search_is_some",
 +        group: "complexity",
 +        desc: "using an iterator search followed by `is_some()`, which is more succinctly expressed as a call to `any()`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "serde_api_misuse",
 +        group: "correctness",
 +        desc: "various things that will negatively affect your serde experience",
 +        deprecation: None,
 +        module: "serde_api",
 +    },
 +    Lint {
 +        name: "shadow_reuse",
 +        group: "restriction",
 +        desc: "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`",
 +        deprecation: None,
 +        module: "shadow",
 +    },
 +    Lint {
 +        name: "shadow_same",
 +        group: "restriction",
 +        desc: "rebinding a name to itself, e.g., `let mut x = &mut x`",
 +        deprecation: None,
 +        module: "shadow",
 +    },
 +    Lint {
 +        name: "shadow_unrelated",
 +        group: "pedantic",
 +        desc: "rebinding a name without even using the original value",
 +        deprecation: None,
 +        module: "shadow",
 +    },
 +    Lint {
 +        name: "short_circuit_statement",
 +        group: "complexity",
 +        desc: "using a short circuit boolean condition as a statement",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "should_implement_trait",
 +        group: "style",
 +        desc: "defining a method that should be implementing a std trait",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "similar_names",
 +        group: "pedantic",
 +        desc: "similarly named items and bindings",
 +        deprecation: None,
 +        module: "non_expressive_names",
 +    },
 +    Lint {
 +        name: "single_char_pattern",
 +        group: "perf",
 +        desc: "using a single-character str where a char could be used, e.g., `_.split(\"x\")`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "single_component_path_imports",
 +        group: "style",
 +        desc: "imports with single component path are redundant",
 +        deprecation: None,
 +        module: "single_component_path_imports",
 +    },
 +    Lint {
 +        name: "single_match",
 +        group: "style",
 +        desc: "a `match` statement with a single nontrivial arm (i.e., where the other arm is `_ => {}`) instead of `if let`",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "single_match_else",
 +        group: "pedantic",
 +        desc: "a `match` statement with two arms where the second arm\'s pattern is a placeholder instead of a specific match pattern",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "skip_while_next",
 +        group: "complexity",
 +        desc: "using `skip_while(p).next()`, which is more succinctly expressed as `.find(!p)`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "slow_vector_initialization",
 +        group: "perf",
 +        desc: "slow vector initialization",
 +        deprecation: None,
 +        module: "slow_vector_initialization",
 +    },
 +    Lint {
 +        name: "string_add",
 +        group: "restriction",
 +        desc: "using `x + ..` where x is a `String` instead of `push_str()`",
 +        deprecation: None,
 +        module: "strings",
 +    },
 +    Lint {
 +        name: "string_add_assign",
 +        group: "pedantic",
 +        desc: "using `x = x + ..` where x is a `String` instead of `push_str()`",
 +        deprecation: None,
 +        module: "strings",
 +    },
 +    Lint {
 +        name: "string_extend_chars",
 +        group: "style",
 +        desc: "using `x.extend(s.chars())` where s is a `&str` or `String`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "string_lit_as_bytes",
 +        group: "style",
 +        desc: "calling `as_bytes` on a string literal instead of using a byte string literal",
 +        deprecation: None,
 +        module: "strings",
 +    },
 +    Lint {
 +        name: "struct_excessive_bools",
 +        group: "pedantic",
 +        desc: "using too many bools in a struct",
 +        deprecation: None,
 +        module: "excessive_bools",
 +    },
 +    Lint {
 +        name: "suboptimal_flops",
 +        group: "nursery",
 +        desc: "usage of sub-optimal floating point operations",
 +        deprecation: None,
 +        module: "floating_point_arithmetic",
 +    },
 +    Lint {
 +        name: "suspicious_arithmetic_impl",
 +        group: "correctness",
 +        desc: "suspicious use of operators in impl of arithmetic trait",
 +        deprecation: None,
 +        module: "suspicious_trait_impl",
 +    },
 +    Lint {
 +        name: "suspicious_assignment_formatting",
 +        group: "style",
 +        desc: "suspicious formatting of `*=`, `-=` or `!=`",
 +        deprecation: None,
 +        module: "formatting",
 +    },
 +    Lint {
 +        name: "suspicious_else_formatting",
 +        group: "style",
 +        desc: "suspicious formatting of `else`",
 +        deprecation: None,
 +        module: "formatting",
 +    },
 +    Lint {
 +        name: "suspicious_map",
 +        group: "complexity",
 +        desc: "suspicious usage of map",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "suspicious_op_assign_impl",
 +        group: "correctness",
 +        desc: "suspicious use of operators in impl of OpAssign trait",
 +        deprecation: None,
 +        module: "suspicious_trait_impl",
 +    },
 +    Lint {
 +        name: "suspicious_unary_op_formatting",
 +        group: "style",
 +        desc: "suspicious formatting of unary `-` or `!` on the RHS of a BinOp",
 +        deprecation: None,
 +        module: "formatting",
 +    },
 +    Lint {
 +        name: "tabs_in_doc_comments",
 +        group: "style",
 +        desc: "using tabs in doc comments is not recommended",
 +        deprecation: None,
 +        module: "tabs_in_doc_comments",
 +    },
 +    Lint {
 +        name: "temporary_assignment",
 +        group: "complexity",
 +        desc: "assignments to temporaries",
 +        deprecation: None,
 +        module: "temporary_assignment",
 +    },
 +    Lint {
 +        name: "temporary_cstring_as_ptr",
 +        group: "correctness",
 +        desc: "getting the inner pointer of a temporary `CString`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "to_digit_is_some",
 +        group: "style",
 +        desc: "`char.is_digit()` is clearer",
 +        deprecation: None,
 +        module: "to_digit_is_some",
 +    },
 +    Lint {
 +        name: "todo",
 +        group: "restriction",
 +        desc: "`todo!` should not be present in production code",
 +        deprecation: None,
 +        module: "panic_unimplemented",
 +    },
 +    Lint {
 +        name: "too_many_arguments",
 +        group: "complexity",
 +        desc: "functions with too many arguments",
 +        deprecation: None,
 +        module: "functions",
 +    },
 +    Lint {
 +        name: "too_many_lines",
 +        group: "pedantic",
 +        desc: "functions with too many lines",
 +        deprecation: None,
 +        module: "functions",
 +    },
 +    Lint {
 +        name: "toplevel_ref_arg",
 +        group: "style",
 +        desc: "an entire binding declared as `ref`, in a function argument or a `let` statement",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "transmute_bytes_to_str",
 +        group: "complexity",
 +        desc: "transmutes from a `&[u8]` to a `&str`",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmute_float_to_int",
 +        group: "complexity",
 +        desc: "transmutes from a float to an integer",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmute_int_to_bool",
 +        group: "complexity",
 +        desc: "transmutes from an integer to a `bool`",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmute_int_to_char",
 +        group: "complexity",
 +        desc: "transmutes from an integer to a `char`",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmute_int_to_float",
 +        group: "complexity",
 +        desc: "transmutes from an integer to a float",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmute_ptr_to_ptr",
 +        group: "complexity",
 +        desc: "transmutes from a pointer to a pointer / a reference to a reference",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmute_ptr_to_ref",
 +        group: "complexity",
 +        desc: "transmutes from a pointer to a reference type",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "transmuting_null",
 +        group: "correctness",
 +        desc: "transmutes from a null pointer to a reference, which is undefined behavior",
 +        deprecation: None,
 +        module: "transmuting_null",
 +    },
 +    Lint {
 +        name: "trivial_regex",
 +        group: "style",
 +        desc: "trivial regular expressions",
 +        deprecation: None,
 +        module: "regex",
 +    },
 +    Lint {
 +        name: "trivially_copy_pass_by_ref",
 +        group: "pedantic",
 +        desc: "functions taking small copyable arguments by reference",
 +        deprecation: None,
 +        module: "trivially_copy_pass_by_ref",
 +    },
 +    Lint {
 +        name: "try_err",
 +        group: "style",
 +        desc: "return errors explicitly rather than hiding them behind a `?`",
 +        deprecation: None,
 +        module: "try_err",
 +    },
 +    Lint {
 +        name: "type_complexity",
 +        group: "complexity",
 +        desc: "usage of very complex types that might be better factored into `type` definitions",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "type_repetition_in_bounds",
 +        group: "pedantic",
 +        desc: "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`",
 +        deprecation: None,
 +        module: "trait_bounds",
 +    },
 +    Lint {
 +        name: "unicode_not_nfc",
 +        group: "pedantic",
 +        desc: "using a Unicode literal not in NFC normal form (see [Unicode tr15](http://www.unicode.org/reports/tr15/) for further information)",
 +        deprecation: None,
 +        module: "unicode",
 +    },
 +    Lint {
 +        name: "unimplemented",
 +        group: "restriction",
 +        desc: "`unimplemented!` should not be present in production code",
 +        deprecation: None,
 +        module: "panic_unimplemented",
 +    },
 +    Lint {
 +        name: "uninit_assumed_init",
 +        group: "correctness",
 +        desc: "`MaybeUninit::uninit().assume_init()`",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "unit_arg",
 +        group: "complexity",
 +        desc: "passing unit to a function",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "unit_cmp",
 +        group: "correctness",
 +        desc: "comparing unit values",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "unknown_clippy_lints",
 +        group: "style",
 +        desc: "unknown_lints for scoped Clippy lints",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "unnecessary_cast",
 +        group: "complexity",
 +        desc: "cast to the same type, e.g., `x as i32` where `x: i32`",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "unnecessary_filter_map",
 +        group: "complexity",
 +        desc: "using `filter_map` when a more succinct alternative exists",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "unnecessary_fold",
 +        group: "style",
 +        desc: "using `fold` when a more succinct alternative exists",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "unnecessary_mut_passed",
 +        group: "style",
 +        desc: "an argument passed as a mutable reference although the callee only demands an immutable reference",
 +        deprecation: None,
 +        module: "mut_reference",
 +    },
 +    Lint {
 +        name: "unnecessary_operation",
 +        group: "complexity",
 +        desc: "outer expressions with no effect",
 +        deprecation: None,
 +        module: "no_effect",
 +    },
 +    Lint {
 +        name: "unnecessary_unwrap",
 +        group: "complexity",
 +        desc: "checks for calls of `unwrap[_err]()` that cannot fail",
 +        deprecation: None,
 +        module: "unwrap",
 +    },
 +    Lint {
 +        name: "unneeded_field_pattern",
 +        group: "restriction",
 +        desc: "struct fields bound to a wildcard instead of using `..`",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "unneeded_wildcard_pattern",
 +        group: "complexity",
 +        desc: "tuple patterns with a wildcard pattern (`_`) is next to a rest pattern (`..`)",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "unreachable",
 +        group: "restriction",
 +        desc: "`unreachable!` should not be present in production code",
 +        deprecation: None,
 +        module: "panic_unimplemented",
 +    },
 +    Lint {
 +        name: "unreadable_literal",
 +        group: "pedantic",
 +        desc: "long integer literal without underscores",
 +        deprecation: None,
 +        module: "literal_representation",
 +    },
 +    Lint {
 +        name: "unsafe_derive_deserialize",
 +        group: "pedantic",
 +        desc: "deriving `serde::Deserialize` on a type that has methods using `unsafe`",
 +        deprecation: None,
 +        module: "derive",
 +    },
 +    Lint {
 +        name: "unsafe_removed_from_name",
 +        group: "style",
 +        desc: "`unsafe` removed from API names on import",
 +        deprecation: None,
 +        module: "unsafe_removed_from_name",
 +    },
 +    Lint {
 +        name: "unseparated_literal_suffix",
 +        group: "pedantic",
 +        desc: "literals whose suffix is not separated by an underscore",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "unsound_collection_transmute",
 +        group: "correctness",
 +        desc: "transmute between collections of layout-incompatible types",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "unused_io_amount",
 +        group: "correctness",
 +        desc: "unused written/read amount",
 +        deprecation: None,
 +        module: "unused_io_amount",
 +    },
 +    Lint {
 +        name: "unused_self",
 +        group: "pedantic",
 +        desc: "methods that contain a `self` argument but don\'t use it",
 +        deprecation: None,
 +        module: "unused_self",
 +    },
 +    Lint {
 +        name: "unused_unit",
 +        group: "style",
 +        desc: "needless unit expression",
 +        deprecation: None,
 +        module: "returns",
 +    },
 +    Lint {
 +        name: "use_debug",
 +        group: "restriction",
 +        desc: "use of `Debug`-based formatting",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "use_self",
 +        group: "nursery",
 +        desc: "Unnecessary structure name repetition whereas `Self` is applicable",
 +        deprecation: None,
 +        module: "use_self",
 +    },
 +    Lint {
 +        name: "used_underscore_binding",
 +        group: "pedantic",
 +        desc: "using a binding which is prefixed with an underscore",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "useless_asref",
 +        group: "complexity",
 +        desc: "using `as_ref` where the types before and after the call are the same",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "useless_attribute",
 +        group: "correctness",
 +        desc: "use of lint attributes on `extern crate` items",
 +        deprecation: None,
 +        module: "attrs",
 +    },
 +    Lint {
 +        name: "useless_format",
 +        group: "complexity",
 +        desc: "useless use of `format!`",
 +        deprecation: None,
 +        module: "format",
 +    },
 +    Lint {
 +        name: "useless_let_if_seq",
 +        group: "style",
 +        desc: "unidiomatic `let mut` declaration followed by initialization in `if`",
 +        deprecation: None,
 +        module: "let_if_seq",
 +    },
 +    Lint {
 +        name: "useless_transmute",
 +        group: "nursery",
 +        desc: "transmutes that have the same to and from types or could be a cast/coercion",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "useless_vec",
 +        group: "perf",
 +        desc: "useless `vec!`",
 +        deprecation: None,
 +        module: "vec",
 +    },
 +    Lint {
 +        name: "vec_box",
 +        group: "complexity",
 +        desc: "usage of `Vec<Box<T>>` where T: Sized, vector elements are already on the heap",
 +        deprecation: None,
 +        module: "types",
 +    },
 +    Lint {
 +        name: "verbose_bit_mask",
 +        group: "style",
 +        desc: "expressions where a bit mask is less readable than the corresponding method call",
 +        deprecation: None,
 +        module: "bit_mask",
 +    },
 +    Lint {
 +        name: "verbose_file_reads",
 +        group: "restriction",
 +        desc: "use of `File::read_to_end` or `File::read_to_string`",
 +        deprecation: None,
 +        module: "verbose_file_reads",
 +    },
 +    Lint {
 +        name: "vtable_address_comparisons",
 +        group: "correctness",
 +        desc: "comparison with an address of a trait vtable",
 +        deprecation: None,
 +        module: "unnamed_address",
 +    },
 +    Lint {
 +        name: "while_immutable_condition",
 +        group: "correctness",
 +        desc: "variables used within while expression are not mutated in the body",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "while_let_loop",
 +        group: "complexity",
 +        desc: "`loop { if let { ... } else break }`, which can be written as a `while let` loop",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "while_let_on_iterator",
 +        group: "style",
 +        desc: "using a while-let loop instead of a for loop on an iterator",
 +        deprecation: None,
 +        module: "loops",
 +    },
 +    Lint {
 +        name: "wildcard_dependencies",
 +        group: "cargo",
 +        desc: "wildcard dependencies being used",
 +        deprecation: None,
 +        module: "wildcard_dependencies",
 +    },
 +    Lint {
 +        name: "wildcard_enum_match_arm",
 +        group: "restriction",
 +        desc: "a wildcard enum match arm using `_`",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "wildcard_imports",
 +        group: "pedantic",
 +        desc: "lint `use _::*` statements",
 +        deprecation: None,
 +        module: "wildcard_imports",
 +    },
 +    Lint {
 +        name: "wildcard_in_or_patterns",
 +        group: "complexity",
 +        desc: "a wildcard pattern used with others patterns in same match arm",
 +        deprecation: None,
 +        module: "matches",
 +    },
 +    Lint {
 +        name: "write_literal",
 +        group: "style",
 +        desc: "writing a literal with a format string",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "write_with_newline",
 +        group: "style",
 +        desc: "using `write!()` with a format string that ends in a single newline",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "writeln_empty_string",
 +        group: "style",
 +        desc: "using `writeln!(buf, \"\")` with an empty string",
 +        deprecation: None,
 +        module: "write",
 +    },
 +    Lint {
 +        name: "wrong_pub_self_convention",
 +        group: "restriction",
 +        desc: "defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "wrong_self_convention",
 +        group: "style",
 +        desc: "defining a method named with an established prefix (like \"into_\") that takes `self` with the wrong convention",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +    Lint {
 +        name: "wrong_transmute",
 +        group: "correctness",
 +        desc: "transmutes that are confusing at best, undefined behaviour at worst and always useless",
 +        deprecation: None,
 +        module: "transmute",
 +    },
 +    Lint {
 +        name: "zero_divided_by_zero",
 +        group: "complexity",
 +        desc: "usage of `0.0 / 0.0` to obtain NaN instead of `f32::NAN` or `f64::NAN`",
 +        deprecation: None,
 +        module: "zero_div_zero",
 +    },
 +    Lint {
 +        name: "zero_prefixed_literal",
 +        group: "complexity",
 +        desc: "integer literals starting with `0`",
 +        deprecation: None,
 +        module: "misc_early",
 +    },
 +    Lint {
 +        name: "zero_ptr",
 +        group: "style",
 +        desc: "using `0 as *{const, mut} T`",
 +        deprecation: None,
 +        module: "misc",
 +    },
 +    Lint {
 +        name: "zero_width_space",
 +        group: "correctness",
 +        desc: "using a zero-width space in a string literal, which is confusing",
 +        deprecation: None,
 +        module: "unicode",
 +    },
 +    Lint {
 +        name: "zst_offset",
 +        group: "correctness",
 +        desc: "Check for offset calculations on raw pointers to zero-sized types",
 +        deprecation: None,
 +        module: "methods",
 +    },
 +];
 +// end lint list, do not remove this comment, it’s used in `update_lints`
 +}
index 18f5d994ba8aaf1df45a039a5275c14c6264f49f,0000000000000000000000000000000000000000..53970af41079d5a952038fb4911e19bca40c4bc5
mode 100644,000000..100644
--- /dev/null
@@@ -1,4 -1,0 +1,4 @@@
- error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `third-party` at line 5 column 1
++error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `third-party` at line 5 column 1
 +
 +error: aborting due to previous error
 +
index b6a4adde8488403c24eebbaa81681463ad59f14f,0000000000000000000000000000000000000000..bc785b075e0282641b3f095be8e6c4665398f198
mode 100644,000000..100644
--- /dev/null
@@@ -1,26 -1,0 +1,24 @@@
-    = help: type parameters must be constrained to match other types
-    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 +error: This generic shadows the built-in type `u32`
 +  --> $DIR/builtin-type-shadow.rs:4:8
 +   |
 +LL | fn foo<u32>(a: u32) -> u32 {
 +   |        ^^^
 +   |
 +   = note: `-D clippy::builtin-type-shadow` implied by `-D warnings`
 +
 +error[E0308]: mismatched types
 +  --> $DIR/builtin-type-shadow.rs:5:5
 +   |
 +LL | fn foo<u32>(a: u32) -> u32 {
 +   |        ---             --- expected `u32` because of return type
 +   |        |
 +   |        this type parameter
 +LL |     42
 +   |     ^^ expected type parameter `u32`, found integer
 +   |
 +   = note: expected type parameter `u32`
 +                        found type `{integer}`
 +
 +error: aborting due to 2 previous errors
 +
 +For more information about this error, try `rustc --explain E0308`.
index b0fc26ff76de559b36b13ee2170f1607d93f1bf8,0000000000000000000000000000000000000000..3e7b4b390bad48581244b7f66c666968af5db293
mode 100644,000000..100644
--- /dev/null
@@@ -1,53 -1,0 +1,80 @@@
 +#![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
 +#![allow(clippy::if_same_then_else)]
 +
 +macro_rules! m {
 +    ($a:expr) => {
 +        if $a.is_some() {
 +            $a.unwrap(); // unnecessary
 +        }
 +    };
 +}
 +
++macro_rules! checks_in_param {
++    ($a:expr, $b:expr) => {
++        if $a {
++            $b;
++        }
++    };
++}
++
++macro_rules! checks_unwrap {
++    ($a:expr, $b:expr) => {
++        if $a.is_some() {
++            $b;
++        }
++    };
++}
++
++macro_rules! checks_some {
++    ($a:expr, $b:expr) => {
++        if $a {
++            $b.unwrap();
++        }
++    };
++}
++
 +fn main() {
 +    let x = Some(());
 +    if x.is_some() {
 +        x.unwrap(); // unnecessary
 +    } else {
 +        x.unwrap(); // will panic
 +    }
 +    if x.is_none() {
 +        x.unwrap(); // will panic
 +    } else {
 +        x.unwrap(); // unnecessary
 +    }
 +    m!(x);
++    checks_in_param!(x.is_some(), x.unwrap()); // ok
++    checks_unwrap!(x, x.unwrap()); // ok
++    checks_some!(x.is_some(), x); // ok
 +    let mut x: Result<(), ()> = Ok(());
 +    if x.is_ok() {
 +        x.unwrap(); // unnecessary
 +        x.unwrap_err(); // will panic
 +    } else {
 +        x.unwrap(); // will panic
 +        x.unwrap_err(); // unnecessary
 +    }
 +    if x.is_err() {
 +        x.unwrap(); // will panic
 +        x.unwrap_err(); // unnecessary
 +    } else {
 +        x.unwrap(); // unnecessary
 +        x.unwrap_err(); // will panic
 +    }
 +    if x.is_ok() {
 +        x = Err(());
 +        x.unwrap(); // not unnecessary because of mutation of x
 +                    // it will always panic but the lint is not smart enough to see this (it only
 +                    // checks if conditions).
 +    } else {
 +        x = Ok(());
 +        x.unwrap_err(); // not unnecessary because of mutation of x
 +                        // it will always panic but the lint is not smart enough to see this (it
 +                        // only checks if conditions).
 +    }
 +
 +    assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern
 +}
index e40542e2e4f90ba47fd1bc788a97801941f86d1f,0000000000000000000000000000000000000000..4013d1ed667f16470d8abe497bfeff6562bb9ac2
mode 100644,000000..100644
--- /dev/null
@@@ -1,131 -1,0 +1,131 @@@
-   --> $DIR/simple_conditionals.rs:15:9
 +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
-   --> $DIR/simple_conditionals.rs:17:9
++  --> $DIR/simple_conditionals.rs:39:9
 +   |
 +LL |     if x.is_some() {
 +   |        ----------- the check is happening here
 +LL |         x.unwrap(); // unnecessary
 +   |         ^^^^^^^^^^
 +   |
 +note: the lint level is defined here
 +  --> $DIR/simple_conditionals.rs:1:35
 +   |
 +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
 +   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 +
 +error: This call to `unwrap()` will always panic.
-   --> $DIR/simple_conditionals.rs:20:9
++  --> $DIR/simple_conditionals.rs:41:9
 +   |
 +LL |     if x.is_some() {
 +   |        ----------- because of this check
 +...
 +LL |         x.unwrap(); // will panic
 +   |         ^^^^^^^^^^
 +   |
 +note: the lint level is defined here
 +  --> $DIR/simple_conditionals.rs:1:9
 +   |
 +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^
 +
 +error: This call to `unwrap()` will always panic.
-   --> $DIR/simple_conditionals.rs:22:9
++  --> $DIR/simple_conditionals.rs:44:9
 +   |
 +LL |     if x.is_none() {
 +   |        ----------- because of this check
 +LL |         x.unwrap(); // will panic
 +   |         ^^^^^^^^^^
 +
 +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
-   --> $DIR/simple_conditionals.rs:27:9
++  --> $DIR/simple_conditionals.rs:46:9
 +   |
 +LL |     if x.is_none() {
 +   |        ----------- the check is happening here
 +...
 +LL |         x.unwrap(); // unnecessary
 +   |         ^^^^^^^^^^
 +
 +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
 +  --> $DIR/simple_conditionals.rs:7:13
 +   |
 +LL |         if $a.is_some() {
 +   |            ------------ the check is happening here
 +LL |             $a.unwrap(); // unnecessary
 +   |             ^^^^^^^^^^^
 +...
 +LL |     m!(x);
 +   |     ------ in this macro invocation
 +   |
 +   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 +
 +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
-   --> $DIR/simple_conditionals.rs:28:9
++  --> $DIR/simple_conditionals.rs:54:9
 +   |
 +LL |     if x.is_ok() {
 +   |        --------- the check is happening here
 +LL |         x.unwrap(); // unnecessary
 +   |         ^^^^^^^^^^
 +
 +error: This call to `unwrap_err()` will always panic.
-   --> $DIR/simple_conditionals.rs:30:9
++  --> $DIR/simple_conditionals.rs:55:9
 +   |
 +LL |     if x.is_ok() {
 +   |        --------- because of this check
 +LL |         x.unwrap(); // unnecessary
 +LL |         x.unwrap_err(); // will panic
 +   |         ^^^^^^^^^^^^^^
 +
 +error: This call to `unwrap()` will always panic.
-   --> $DIR/simple_conditionals.rs:31:9
++  --> $DIR/simple_conditionals.rs:57:9
 +   |
 +LL |     if x.is_ok() {
 +   |        --------- because of this check
 +...
 +LL |         x.unwrap(); // will panic
 +   |         ^^^^^^^^^^
 +
 +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
-   --> $DIR/simple_conditionals.rs:34:9
++  --> $DIR/simple_conditionals.rs:58:9
 +   |
 +LL |     if x.is_ok() {
 +   |        --------- the check is happening here
 +...
 +LL |         x.unwrap_err(); // unnecessary
 +   |         ^^^^^^^^^^^^^^
 +
 +error: This call to `unwrap()` will always panic.
-   --> $DIR/simple_conditionals.rs:35:9
++  --> $DIR/simple_conditionals.rs:61:9
 +   |
 +LL |     if x.is_err() {
 +   |        ---------- because of this check
 +LL |         x.unwrap(); // will panic
 +   |         ^^^^^^^^^^
 +
 +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
-   --> $DIR/simple_conditionals.rs:37:9
++  --> $DIR/simple_conditionals.rs:62:9
 +   |
 +LL |     if x.is_err() {
 +   |        ---------- the check is happening here
 +LL |         x.unwrap(); // will panic
 +LL |         x.unwrap_err(); // unnecessary
 +   |         ^^^^^^^^^^^^^^
 +
 +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
-   --> $DIR/simple_conditionals.rs:38:9
++  --> $DIR/simple_conditionals.rs:64:9
 +   |
 +LL |     if x.is_err() {
 +   |        ---------- the check is happening here
 +...
 +LL |         x.unwrap(); // unnecessary
 +   |         ^^^^^^^^^^
 +
 +error: This call to `unwrap_err()` will always panic.
++  --> $DIR/simple_conditionals.rs:65:9
 +   |
 +LL |     if x.is_err() {
 +   |        ---------- because of this check
 +...
 +LL |         x.unwrap_err(); // will panic
 +   |         ^^^^^^^^^^^^^^
 +
 +error: aborting due to 13 previous errors
 +
index 6d09d71a630a28b6e85b089b6b74cf94a9558f45,0000000000000000000000000000000000000000..d3a920de4b6ad8a685f3c04096a3afd414826998
mode 100644,000000..100644
--- /dev/null
@@@ -1,79 -1,0 +1,80 @@@
 +// edition:2018
 +#![warn(clippy::future_not_send)]
 +
 +use std::cell::Cell;
 +use std::rc::Rc;
 +use std::sync::Arc;
 +
 +async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 +    async { true }.await
 +}
 +
 +pub async fn public_future(rc: Rc<[u8]>) {
 +    async { true }.await;
 +}
 +
 +pub async fn public_send(arc: Arc<[u8]>) -> bool {
 +    async { false }.await
 +}
 +
 +async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 +    true
 +}
 +
 +pub async fn public_future2(rc: Rc<[u8]>) {}
 +
 +pub async fn public_send2(arc: Arc<[u8]>) -> bool {
 +    false
 +}
 +
 +struct Dummy {
 +    rc: Rc<[u8]>,
 +}
 +
 +impl Dummy {
 +    async fn private_future(&self) -> usize {
 +        async { true }.await;
 +        self.rc.len()
 +    }
 +
 +    pub async fn public_future(&self) {
 +        self.private_future().await;
 +    }
 +
++    #[allow(clippy::manual_async_fn)]
 +    pub fn public_send(&self) -> impl std::future::Future<Output = bool> {
 +        async { false }
 +    }
 +}
 +
 +async fn generic_future<T>(t: T) -> T
 +where
 +    T: Send,
 +{
 +    let rt = &t;
 +    async { true }.await;
 +    t
 +}
 +
 +async fn generic_future_send<T>(t: T)
 +where
 +    T: Send,
 +{
 +    async { true }.await;
 +}
 +
 +async fn unclear_future<T>(t: T) {}
 +
 +fn main() {
 +    let rc = Rc::new([1, 2, 3]);
 +    private_future(rc.clone(), &Cell::new(42));
 +    public_future(rc.clone());
 +    let arc = Arc::new([4, 5, 6]);
 +    public_send(arc);
 +    generic_future(42);
 +    generic_future_send(42);
 +
 +    let dummy = Dummy { rc };
 +    dummy.public_future();
 +    dummy.public_send();
 +}
index 3b4968ef0a63c528c8060966465c349c55dc6b94,0000000000000000000000000000000000000000..d1863701bfe7c14dd0cd0a161d3b224530b4343e
mode 100644,000000..100644
--- /dev/null
@@@ -1,125 -1,0 +1,125 @@@
-   --> $DIR/future_not_send.rs:49:37
 +error: future cannot be sent between threads safely
 +  --> $DIR/future_not_send.rs:8:62
 +   |
 +LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 +   |                                                              ^^^^ future returned by `private_future` is not `Send`
 +   |
 +   = note: `-D clippy::future-not-send` implied by `-D warnings`
 +note: future is not `Send` as this value is used across an await
 +  --> $DIR/future_not_send.rs:9:5
 +   |
 +LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 +   |                         -- has type `std::rc::Rc<[u8]>` which is not `Send`
 +LL |     async { true }.await
 +   |     ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `rc` maybe used later
 +LL | }
 +   | - `rc` is later dropped here
 +   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 +note: future is not `Send` as this value is used across an await
 +  --> $DIR/future_not_send.rs:9:5
 +   |
 +LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 +   |                                       ---- has type `&std::cell::Cell<usize>` which is not `Send`
 +LL |     async { true }.await
 +   |     ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `cell` maybe used later
 +LL | }
 +   | - `cell` is later dropped here
 +   = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 +
 +error: future cannot be sent between threads safely
 +  --> $DIR/future_not_send.rs:12:42
 +   |
 +LL | pub async fn public_future(rc: Rc<[u8]>) {
 +   |                                          ^ future returned by `public_future` is not `Send`
 +   |
 +note: future is not `Send` as this value is used across an await
 +  --> $DIR/future_not_send.rs:13:5
 +   |
 +LL | pub async fn public_future(rc: Rc<[u8]>) {
 +   |                            -- has type `std::rc::Rc<[u8]>` which is not `Send`
 +LL |     async { true }.await;
 +   |     ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `rc` maybe used later
 +LL | }
 +   | - `rc` is later dropped here
 +   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 +
 +error: future cannot be sent between threads safely
 +  --> $DIR/future_not_send.rs:20:63
 +   |
 +LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
 +   |                                                               ^^^^
 +   |
 +   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 +   = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
 +
 +error: future cannot be sent between threads safely
 +  --> $DIR/future_not_send.rs:24:43
 +   |
 +LL | pub async fn public_future2(rc: Rc<[u8]>) {}
 +   |                                           ^
 +   |
 +   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
 +
 +error: future cannot be sent between threads safely
 +  --> $DIR/future_not_send.rs:35:39
 +   |
 +LL |     async fn private_future(&self) -> usize {
 +   |                                       ^^^^^ future returned by `private_future` is not `Send`
 +   |
 +note: future is not `Send` as this value is used across an await
 +  --> $DIR/future_not_send.rs:36:9
 +   |
 +LL |     async fn private_future(&self) -> usize {
 +   |                             ----- has type `&Dummy` which is not `Send`
 +LL |         async { true }.await;
 +   |         ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `&self` maybe used later
 +LL |         self.rc.len()
 +LL |     }
 +   |     - `&self` is later dropped here
 +   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 +
 +error: future cannot be sent between threads safely
 +  --> $DIR/future_not_send.rs:40:39
 +   |
 +LL |     pub async fn public_future(&self) {
 +   |                                       ^ future returned by `public_future` is not `Send`
 +   |
 +note: future is not `Send` as this value is used across an await
 +  --> $DIR/future_not_send.rs:41:9
 +   |
 +LL |     pub async fn public_future(&self) {
 +   |                                ----- has type `&Dummy` which is not `Send`
 +LL |         self.private_future().await;
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `&self` maybe used later
 +LL |     }
 +   |     - `&self` is later dropped here
 +   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
 +
 +error: future cannot be sent between threads safely
-   --> $DIR/future_not_send.rs:54:5
++  --> $DIR/future_not_send.rs:50:37
 +   |
 +LL | async fn generic_future<T>(t: T) -> T
 +   |                                     ^ future returned by `generic_future` is not `Send`
 +   |
 +note: future is not `Send` as this value is used across an await
-   --> $DIR/future_not_send.rs:65:34
++  --> $DIR/future_not_send.rs:55:5
 +   |
 +LL |     let rt = &t;
 +   |         -- has type `&T` which is not `Send`
 +LL |     async { true }.await;
 +   |     ^^^^^^^^^^^^^^^^^^^^ await occurs here, with `rt` maybe used later
 +LL |     t
 +LL | }
 +   | - `rt` is later dropped here
 +   = note: `T` doesn't implement `std::marker::Sync`
 +
 +error: future cannot be sent between threads safely
++  --> $DIR/future_not_send.rs:66:34
 +   |
 +LL | async fn unclear_future<T>(t: T) {}
 +   |                                  ^
 +   |
 +   = note: `T` doesn't implement `std::marker::Send`
 +
 +error: aborting due to 8 previous errors
 +
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6bb1032a17299108a9a2603662e5b25531e7114f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,67 @@@
++// run-rustfix
++// edition:2018
++#![warn(clippy::manual_async_fn)]
++#![allow(unused)]
++
++use std::future::Future;
++
++async fn fut() -> i32 { 42 }
++
++async fn empty_fut()  {}
++
++async fn core_fut() -> i32 { 42 }
++
++// should be ignored
++fn has_other_stmts() -> impl core::future::Future<Output = i32> {
++    let _ = 42;
++    async move { 42 }
++}
++
++// should be ignored
++fn not_fut() -> i32 {
++    42
++}
++
++// should be ignored
++async fn already_async() -> impl Future<Output = i32> {
++    async { 42 }
++}
++
++struct S {}
++impl S {
++    async fn inh_fut() -> i32 {
++        // NOTE: this code is here just to check that the identation is correct in the suggested fix
++        let a = 42;
++        let b = 21;
++        if a < b {
++            let c = 21;
++            let d = 42;
++            if c < d {
++                let _ = 42;
++            }
++        }
++        42
++    }
++
++    async fn meth_fut(&self) -> i32 { 42 }
++
++    async fn empty_fut(&self)  {}
++
++    // should be ignored
++    fn not_fut(&self) -> i32 {
++        42
++    }
++
++    // should be ignored
++    fn has_other_stmts() -> impl core::future::Future<Output = i32> {
++        let _ = 42;
++        async move { 42 }
++    }
++
++    // should be ignored
++    async fn already_async(&self) -> impl Future<Output = i32> {
++        async { 42 }
++    }
++}
++
++fn main() {}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d50c919188be13c4ff4111fa17e604771453da13
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,79 @@@
++// run-rustfix
++// edition:2018
++#![warn(clippy::manual_async_fn)]
++#![allow(unused)]
++
++use std::future::Future;
++
++fn fut() -> impl Future<Output = i32> {
++    async { 42 }
++}
++
++fn empty_fut() -> impl Future<Output = ()> {
++    async {}
++}
++
++fn core_fut() -> impl core::future::Future<Output = i32> {
++    async move { 42 }
++}
++
++// should be ignored
++fn has_other_stmts() -> impl core::future::Future<Output = i32> {
++    let _ = 42;
++    async move { 42 }
++}
++
++// should be ignored
++fn not_fut() -> i32 {
++    42
++}
++
++// should be ignored
++async fn already_async() -> impl Future<Output = i32> {
++    async { 42 }
++}
++
++struct S {}
++impl S {
++    fn inh_fut() -> impl Future<Output = i32> {
++        async {
++            // NOTE: this code is here just to check that the identation is correct in the suggested fix
++            let a = 42;
++            let b = 21;
++            if a < b {
++                let c = 21;
++                let d = 42;
++                if c < d {
++                    let _ = 42;
++                }
++            }
++            42
++        }
++    }
++
++    fn meth_fut(&self) -> impl Future<Output = i32> {
++        async { 42 }
++    }
++
++    fn empty_fut(&self) -> impl Future<Output = ()> {
++        async {}
++    }
++
++    // should be ignored
++    fn not_fut(&self) -> i32 {
++        42
++    }
++
++    // should be ignored
++    fn has_other_stmts() -> impl core::future::Future<Output = i32> {
++        let _ = 42;
++        async move { 42 }
++    }
++
++    // should be ignored
++    async fn already_async(&self) -> impl Future<Output = i32> {
++        async { 42 }
++    }
++}
++
++fn main() {}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f278ee41aa335607a9f26dd265ddb16bcc9206d7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,98 @@@
++error: this function can be simplified using the `async fn` syntax
++  --> $DIR/manual_async_fn.rs:8:1
++   |
++LL | fn fut() -> impl Future<Output = i32> {
++   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++   = note: `-D clippy::manual-async-fn` implied by `-D warnings`
++help: make the function `async` and return the output of the future directly
++   |
++LL | async fn fut() -> i32 {
++   | ^^^^^^^^^^^^^^^^^^^^^
++help: move the body of the async block to the enclosing function
++   |
++LL | fn fut() -> impl Future<Output = i32> { 42 }
++   |                                       ^^^^^^
++
++error: this function can be simplified using the `async fn` syntax
++  --> $DIR/manual_async_fn.rs:12:1
++   |
++LL | fn empty_fut() -> impl Future<Output = ()> {
++   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++help: make the function `async` and remove the return type
++   |
++LL | async fn empty_fut()  {
++   | ^^^^^^^^^^^^^^^^^^^^
++help: move the body of the async block to the enclosing function
++   |
++LL | fn empty_fut() -> impl Future<Output = ()> {}
++   |                                            ^^
++
++error: this function can be simplified using the `async fn` syntax
++  --> $DIR/manual_async_fn.rs:16:1
++   |
++LL | fn core_fut() -> impl core::future::Future<Output = i32> {
++   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++help: make the function `async` and return the output of the future directly
++   |
++LL | async fn core_fut() -> i32 {
++   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
++help: move the body of the async block to the enclosing function
++   |
++LL | fn core_fut() -> impl core::future::Future<Output = i32> { 42 }
++   |                                                          ^^^^^^
++
++error: this function can be simplified using the `async fn` syntax
++  --> $DIR/manual_async_fn.rs:38:5
++   |
++LL |     fn inh_fut() -> impl Future<Output = i32> {
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++help: make the function `async` and return the output of the future directly
++   |
++LL |     async fn inh_fut() -> i32 {
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
++help: move the body of the async block to the enclosing function
++   |
++LL |     fn inh_fut() -> impl Future<Output = i32> {
++LL |         // NOTE: this code is here just to check that the identation is correct in the suggested fix
++LL |         let a = 42;
++LL |         let b = 21;
++LL |         if a < b {
++LL |             let c = 21;
++ ...
++
++error: this function can be simplified using the `async fn` syntax
++  --> $DIR/manual_async_fn.rs:54:5
++   |
++LL |     fn meth_fut(&self) -> impl Future<Output = i32> {
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++help: make the function `async` and return the output of the future directly
++   |
++LL |     async fn meth_fut(&self) -> i32 {
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++help: move the body of the async block to the enclosing function
++   |
++LL |     fn meth_fut(&self) -> impl Future<Output = i32> { 42 }
++   |                                                     ^^^^^^
++
++error: this function can be simplified using the `async fn` syntax
++  --> $DIR/manual_async_fn.rs:58:5
++   |
++LL |     fn empty_fut(&self) -> impl Future<Output = ()> {
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++help: make the function `async` and remove the return type
++   |
++LL |     async fn empty_fut(&self)  {
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
++help: move the body of the async block to the enclosing function
++   |
++LL |     fn empty_fut(&self) -> impl Future<Output = ()> {}
++   |                                                     ^^
++
++error: aborting due to 6 previous errors
++
index aa347288875d5cc5f89058de21964be3230e3f55,0000000000000000000000000000000000000000..9c24d6d4db1f257de14382cdd58ad2d58c11ff21
mode 100644,000000..100644
--- /dev/null
@@@ -1,110 -1,0 +1,125 @@@
 +#![warn(clippy::needless_range_loop, clippy::manual_memcpy)]
 +
 +const LOOP_OFFSET: usize = 5000;
 +
 +pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) {
 +    // plain manual memcpy
 +    for i in 0..src.len() {
 +        dst[i] = src[i];
 +    }
 +
 +    // dst offset memcpy
 +    for i in 0..src.len() {
 +        dst[i + 10] = src[i];
 +    }
 +
 +    // src offset memcpy
 +    for i in 0..src.len() {
 +        dst[i] = src[i + 10];
 +    }
 +
 +    // src offset memcpy
 +    for i in 11..src.len() {
 +        dst[i] = src[i - 10];
 +    }
 +
 +    // overwrite entire dst
 +    for i in 0..dst.len() {
 +        dst[i] = src[i];
 +    }
 +
 +    // manual copy with branch - can't easily convert to memcpy!
 +    for i in 0..src.len() {
 +        dst[i] = src[i];
 +        if dst[i] > 5 {
 +            break;
 +        }
 +    }
 +
 +    // multiple copies - suggest two memcpy statements
 +    for i in 10..256 {
 +        dst[i] = src[i - 5];
 +        dst2[i + 500] = src[i]
 +    }
 +
 +    // this is a reversal - the copy lint shouldn't be triggered
 +    for i in 10..LOOP_OFFSET {
 +        dst[i + LOOP_OFFSET] = src[LOOP_OFFSET - i];
 +    }
 +
 +    let some_var = 5;
 +    // Offset in variable
 +    for i in 10..LOOP_OFFSET {
 +        dst[i + LOOP_OFFSET] = src[i - some_var];
 +    }
 +
 +    // Non continuous copy - don't trigger lint
 +    for i in 0..10 {
 +        dst[i + i] = src[i];
 +    }
 +
 +    let src_vec = vec![1, 2, 3, 4, 5];
 +    let mut dst_vec = vec![0, 0, 0, 0, 0];
 +
 +    // make sure vectors are supported
 +    for i in 0..src_vec.len() {
 +        dst_vec[i] = src_vec[i];
 +    }
 +
 +    // lint should not trigger when either
 +    // source or destination type is not
 +    // slice-like, like DummyStruct
 +    struct DummyStruct(i32);
 +
 +    impl ::std::ops::Index<usize> for DummyStruct {
 +        type Output = i32;
 +
 +        fn index(&self, _: usize) -> &i32 {
 +            &self.0
 +        }
 +    }
 +
 +    let src = DummyStruct(5);
 +    let mut dst_vec = vec![0; 10];
 +
 +    for i in 0..10 {
 +        dst_vec[i] = src[i];
 +    }
 +
 +    // Simplify suggestion (issue #3004)
 +    let src = [0, 1, 2, 3, 4];
 +    let mut dst = [0, 0, 0, 0, 0, 0];
 +    let from = 1;
 +
 +    for i in from..from + src.len() {
 +        dst[i] = src[i - from];
 +    }
 +
 +    for i in from..from + 3 {
 +        dst[i] = src[i - from];
 +    }
++
++    #[allow(clippy::identity_op)]
++    for i in 0..5 {
++        dst[i - 0] = src[i];
++    }
++
++    #[allow(clippy::reverse_range_loop)]
++    for i in 0..0 {
++        dst[i] = src[i];
++    }
++
++    // `RangeTo` `for` loop - don't trigger lint
++    for i in 0.. {
++        dst[i] = src[i];
++    }
 +}
 +
 +#[warn(clippy::needless_range_loop, clippy::manual_memcpy)]
 +pub fn manual_clone(src: &[String], dst: &mut [String]) {
 +    for i in 0..src.len() {
 +        dst[i] = src[i].clone();
 +    }
 +}
 +
 +fn main() {}
index 3dbb2155d4de7e52effaabfcebbeaa5929806f0a,0000000000000000000000000000000000000000..bad84a589008180df702444d2e57b4a9042b9d82
mode 100644,000000..100644
--- /dev/null
@@@ -1,76 -1,0 +1,88 @@@
-    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])`
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:7:14
 +   |
 +LL |     for i in 0..src.len() {
 +   |              ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])`
 +   |
 +   = note: `-D clippy::manual-memcpy` implied by `-D warnings`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:12:14
 +   |
 +LL |     for i in 0..src.len() {
 +   |              ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:17:14
 +   |
 +LL |     for i in 0..src.len() {
 +   |              ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:22:14
 +   |
 +LL |     for i in 11..src.len() {
 +   |              ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:27:14
 +   |
 +LL |     for i in 0..dst.len() {
 +   |              ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:40:14
 +   |
 +LL |     for i in 10..256 {
 +   |              ^^^^^^^
 +   |
 +help: try replacing the loop by
 +   |
 +LL |     for i in dst[10..256].clone_from_slice(&src[(10 - 5)..(256 - 5)])
 +LL |     dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) {
 +   |
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:52:14
 +   |
 +LL |     for i in 10..LOOP_OFFSET {
 +   |              ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:65:14
 +   |
 +LL |     for i in 0..src_vec.len() {
 +   |              ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:94:14
 +   |
 +LL |     for i in from..from + src.len() {
-    |              ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])`
++   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[..(from + src.len() - from)])`
 +
 +error: it looks like you're manually copying between slices
 +  --> $DIR/manual_memcpy.rs:98:14
 +   |
 +LL |     for i in from..from + 3 {
-   --> $DIR/manual_memcpy.rs:105:14
++   |              ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])`
 +
 +error: it looks like you're manually copying between slices
- error: aborting due to 11 previous errors
++  --> $DIR/manual_memcpy.rs:103:14
++   |
++LL |     for i in 0..5 {
++   |              ^^^^ help: try replacing the loop by: `dst[..5].clone_from_slice(&src[..5])`
++
++error: it looks like you're manually copying between slices
++  --> $DIR/manual_memcpy.rs:108:14
++   |
++LL |     for i in 0..0 {
++   |              ^^^^ help: try replacing the loop by: `dst[..0].clone_from_slice(&src[..0])`
++
++error: it looks like you're manually copying between slices
++  --> $DIR/manual_memcpy.rs:120:14
 +   |
 +LL |     for i in 0..src.len() {
 +   |              ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])`
 +
++error: aborting due to 13 previous errors
 +
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7a788f4852072022b393541e63edae6bf0d474da
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,137 @@@
++#![warn(clippy::manual_non_exhaustive)]
++#![allow(unused)]
++
++mod enums {
++    enum E {
++        A,
++        B,
++        #[doc(hidden)]
++        _C,
++    }
++
++    // user forgot to remove the marker
++    #[non_exhaustive]
++    enum Ep {
++        A,
++        B,
++        #[doc(hidden)]
++        _C,
++    }
++
++    // marker variant does not have doc hidden attribute, should be ignored
++    enum NoDocHidden {
++        A,
++        B,
++        _C,
++    }
++
++    // name of variant with doc hidden does not start with underscore, should be ignored
++    enum NoUnderscore {
++        A,
++        B,
++        #[doc(hidden)]
++        C,
++    }
++
++    // variant with doc hidden is not unit, should be ignored
++    enum NotUnit {
++        A,
++        B,
++        #[doc(hidden)]
++        _C(bool),
++    }
++
++    // variant with doc hidden is the only one, should be ignored
++    enum OnlyMarker {
++        #[doc(hidden)]
++        _A,
++    }
++
++    // variant with multiple markers, should be ignored
++    enum MultipleMarkers {
++        A,
++        #[doc(hidden)]
++        _B,
++        #[doc(hidden)]
++        _C,
++    }
++
++    // already non_exhaustive and no markers, should be ignored
++    #[non_exhaustive]
++    enum NonExhaustive {
++        A,
++        B,
++    }
++}
++
++mod structs {
++    struct S {
++        pub a: i32,
++        pub b: i32,
++        _c: (),
++    }
++
++    // user forgot to remove the private field
++    #[non_exhaustive]
++    struct Sp {
++        pub a: i32,
++        pub b: i32,
++        _c: (),
++    }
++
++    // some other fields are private, should be ignored
++    struct PrivateFields {
++        a: i32,
++        pub b: i32,
++        _c: (),
++    }
++
++    // private field name does not start with underscore, should be ignored
++    struct NoUnderscore {
++        pub a: i32,
++        pub b: i32,
++        c: (),
++    }
++
++    // private field is not unit type, should be ignored
++    struct NotUnit {
++        pub a: i32,
++        pub b: i32,
++        _c: i32,
++    }
++
++    // private field is the only field, should be ignored
++    struct OnlyMarker {
++        _a: (),
++    }
++
++    // already non exhaustive and no private fields, should be ignored
++    #[non_exhaustive]
++    struct NonExhaustive {
++        pub a: i32,
++        pub b: i32,
++    }
++}
++
++mod tuple_structs {
++    struct T(pub i32, pub i32, ());
++
++    // user forgot to remove the private field
++    #[non_exhaustive]
++    struct Tp(pub i32, pub i32, ());
++
++    // some other fields are private, should be ignored
++    struct PrivateFields(pub i32, i32, ());
++
++    // private field is not unit type, should be ignored
++    struct NotUnit(pub i32, pub i32, i32);
++
++    // private field is the only field, should be ignored
++    struct OnlyMarker(());
++
++    // already non exhaustive and no private fields, should be ignored
++    #[non_exhaustive]
++    struct NonExhaustive(pub i32, pub i32);
++}
++
++fn main() {}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..613c5e8ca1d45b38ec58c9dfc403f4b5abd37e04
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,103 @@@
++error: this seems like a manual implementation of the non-exhaustive pattern
++  --> $DIR/manual_non_exhaustive.rs:5:5
++   |
++LL |       enum E {
++   |       ^-----
++   |       |
++   |  _____help: add the attribute: `#[non_exhaustive] enum E`
++   | |
++LL | |         A,
++LL | |         B,
++LL | |         #[doc(hidden)]
++LL | |         _C,
++LL | |     }
++   | |_____^
++   |
++   = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
++help: remove this variant
++  --> $DIR/manual_non_exhaustive.rs:9:9
++   |
++LL |         _C,
++   |         ^^
++
++error: this seems like a manual implementation of the non-exhaustive pattern
++  --> $DIR/manual_non_exhaustive.rs:14:5
++   |
++LL | /     enum Ep {
++LL | |         A,
++LL | |         B,
++LL | |         #[doc(hidden)]
++LL | |         _C,
++LL | |     }
++   | |_____^
++   |
++help: remove this variant
++  --> $DIR/manual_non_exhaustive.rs:18:9
++   |
++LL |         _C,
++   |         ^^
++
++error: this seems like a manual implementation of the non-exhaustive pattern
++  --> $DIR/manual_non_exhaustive.rs:68:5
++   |
++LL |       struct S {
++   |       ^-------
++   |       |
++   |  _____help: add the attribute: `#[non_exhaustive] struct S`
++   | |
++LL | |         pub a: i32,
++LL | |         pub b: i32,
++LL | |         _c: (),
++LL | |     }
++   | |_____^
++   |
++help: remove this field
++  --> $DIR/manual_non_exhaustive.rs:71:9
++   |
++LL |         _c: (),
++   |         ^^^^^^
++
++error: this seems like a manual implementation of the non-exhaustive pattern
++  --> $DIR/manual_non_exhaustive.rs:76:5
++   |
++LL | /     struct Sp {
++LL | |         pub a: i32,
++LL | |         pub b: i32,
++LL | |         _c: (),
++LL | |     }
++   | |_____^
++   |
++help: remove this field
++  --> $DIR/manual_non_exhaustive.rs:79:9
++   |
++LL |         _c: (),
++   |         ^^^^^^
++
++error: this seems like a manual implementation of the non-exhaustive pattern
++  --> $DIR/manual_non_exhaustive.rs:117:5
++   |
++LL |     struct T(pub i32, pub i32, ());
++   |     --------^^^^^^^^^^^^^^^^^^^^^^^
++   |     |
++   |     help: add the attribute: `#[non_exhaustive] struct T`
++   |
++help: remove this field
++  --> $DIR/manual_non_exhaustive.rs:117:32
++   |
++LL |     struct T(pub i32, pub i32, ());
++   |                                ^^
++
++error: this seems like a manual implementation of the non-exhaustive pattern
++  --> $DIR/manual_non_exhaustive.rs:121:5
++   |
++LL |     struct Tp(pub i32, pub i32, ());
++   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++   |
++help: remove this field
++  --> $DIR/manual_non_exhaustive.rs:121:33
++   |
++LL |     struct Tp(pub i32, pub i32, ());
++   |                                 ^^
++
++error: aborting due to 6 previous errors
++
index 0bb39d77e461ea9edd610d0f82535537ba1a7654,0000000000000000000000000000000000000000..30415e3b94dc4b1e95458eba5473d2cc8f4f7da1
mode 100644,000000..100644
--- /dev/null
@@@ -1,130 -1,0 +1,152 @@@
 +#![warn(clippy::match_on_vec_items)]
 +
 +fn match_with_wildcard() {
 +    let arr = vec![0, 1, 2, 3];
 +    let range = 1..3;
 +    let idx = 1;
 +
 +    // Lint, may panic
 +    match arr[idx] {
 +        0 => println!("0"),
 +        1 => println!("1"),
 +        _ => {},
 +    }
 +
 +    // Lint, may panic
 +    match arr[range] {
 +        [0, 1] => println!("0 1"),
 +        [1, 2] => println!("1 2"),
 +        _ => {},
 +    }
 +}
 +
 +fn match_without_wildcard() {
 +    let arr = vec![0, 1, 2, 3];
 +    let range = 1..3;
 +    let idx = 2;
 +
 +    // Lint, may panic
 +    match arr[idx] {
 +        0 => println!("0"),
 +        1 => println!("1"),
 +        num => {},
 +    }
 +
 +    // Lint, may panic
 +    match arr[range] {
 +        [0, 1] => println!("0 1"),
 +        [1, 2] => println!("1 2"),
 +        [ref sub @ ..] => {},
 +    }
 +}
 +
 +fn match_wildcard_and_action() {
 +    let arr = vec![0, 1, 2, 3];
 +    let range = 1..3;
 +    let idx = 3;
 +
 +    // Lint, may panic
 +    match arr[idx] {
 +        0 => println!("0"),
 +        1 => println!("1"),
 +        _ => println!("Hello, World!"),
 +    }
 +
 +    // Lint, may panic
 +    match arr[range] {
 +        [0, 1] => println!("0 1"),
 +        [1, 2] => println!("1 2"),
 +        _ => println!("Hello, World!"),
 +    }
 +}
 +
 +fn match_vec_ref() {
 +    let arr = &vec![0, 1, 2, 3];
 +    let range = 1..3;
 +    let idx = 3;
 +
 +    // Lint, may panic
 +    match arr[idx] {
 +        0 => println!("0"),
 +        1 => println!("1"),
 +        _ => {},
 +    }
 +
 +    // Lint, may panic
 +    match arr[range] {
 +        [0, 1] => println!("0 1"),
 +        [1, 2] => println!("1 2"),
 +        _ => {},
 +    }
 +}
 +
 +fn match_with_get() {
 +    let arr = vec![0, 1, 2, 3];
 +    let range = 1..3;
 +    let idx = 3;
 +
 +    // Ok
 +    match arr.get(idx) {
 +        Some(0) => println!("0"),
 +        Some(1) => println!("1"),
 +        _ => {},
 +    }
 +
 +    // Ok
 +    match arr.get(range) {
 +        Some(&[0, 1]) => println!("0 1"),
 +        Some(&[1, 2]) => println!("1 2"),
 +        _ => {},
 +    }
 +}
 +
 +fn match_with_array() {
 +    let arr = [0, 1, 2, 3];
 +    let range = 1..3;
 +    let idx = 3;
 +
 +    // Ok
 +    match arr[idx] {
 +        0 => println!("0"),
 +        1 => println!("1"),
 +        _ => {},
 +    }
 +
 +    // Ok
 +    match arr[range] {
 +        [0, 1] => println!("0 1"),
 +        [1, 2] => println!("1 2"),
 +        _ => {},
 +    }
 +}
 +
++fn match_with_endless_range() {
++    let arr = vec![0, 1, 2, 3];
++    let range = ..;
++
++    // Ok
++    match arr[range] {
++        [0, 1] => println!("0 1"),
++        [1, 2] => println!("1 2"),
++        [0, 1, 2, 3] => println!("0, 1, 2, 3"),
++        _ => {},
++    }
++
++    // Ok
++    match arr[..] {
++        [0, 1] => println!("0 1"),
++        [1, 2] => println!("1 2"),
++        [0, 1, 2, 3] => println!("0, 1, 2, 3"),
++        _ => {},
++    }
++}
++
 +fn main() {
 +    match_with_wildcard();
 +    match_without_wildcard();
 +    match_wildcard_and_action();
 +    match_vec_ref();
 +    match_with_get();
 +    match_with_array();
++    match_with_endless_range();
 +}
index f5fcabf63fd392e6a5abee3fb5df203b86f2f312,0000000000000000000000000000000000000000..e99c98ac79f2a7f4fa97bee33bb41ebb7fba7ef9
mode 100644,000000..100644
--- /dev/null
@@@ -1,160 -1,0 +1,218 @@@
 +// run-rustfix
 +
 +#![warn(clippy::while_let_on_iterator)]
 +#![allow(clippy::never_loop, unreachable_code, unused_mut)]
++#![feature(or_patterns)]
 +
 +fn base() {
 +    let mut iter = 1..20;
 +    for x in iter {
 +        println!("{}", x);
 +    }
 +
 +    let mut iter = 1..20;
 +    for x in iter {
 +        println!("{}", x);
 +    }
 +
 +    let mut iter = 1..20;
 +    for _ in iter {}
 +
 +    let mut iter = 1..20;
 +    while let None = iter.next() {} // this is fine (if nonsensical)
 +
 +    let mut iter = 1..20;
 +    if let Some(x) = iter.next() {
 +        // also fine
 +        println!("{}", x)
 +    }
 +
 +    // the following shouldn't warn because it can't be written with a for loop
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        println!("next: {:?}", iter.next())
 +    }
 +
 +    // neither can this
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        println!("next: {:?}", iter.next());
 +    }
 +
 +    // or this
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        break;
 +    }
 +    println!("Remaining iter {:?}", iter);
 +
 +    // or this
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        iter = 1..20;
 +    }
 +}
 +
 +// Issue #1188
 +fn refutable() {
 +    let a = [42, 1337];
 +    let mut b = a.iter();
 +
 +    // consume all the 42s
 +    while let Some(&42) = b.next() {}
 +
 +    let a = [(1, 2, 3)];
 +    let mut b = a.iter();
 +
 +    while let Some(&(1, 2, 3)) = b.next() {}
 +
 +    let a = [Some(42)];
 +    let mut b = a.iter();
 +
 +    while let Some(&None) = b.next() {}
 +
 +    /* This gives “refutable pattern in `for` loop binding: `&_` not covered”
 +    for &42 in b {}
 +    for &(1, 2, 3) in b {}
 +    for &Option::None in b.next() {}
 +    // */
 +}
 +
++fn refutable2() {
++    // Issue 3780
++    {
++        let v = vec![1, 2, 3];
++        let mut it = v.windows(2);
++        while let Some([x, y]) = it.next() {
++            println!("x: {}", x);
++            println!("y: {}", y);
++        }
++
++        let mut it = v.windows(2);
++        while let Some([x, ..]) = it.next() {
++            println!("x: {}", x);
++        }
++
++        let mut it = v.windows(2);
++        while let Some([.., y]) = it.next() {
++            println!("y: {}", y);
++        }
++
++        let mut it = v.windows(2);
++        for [..] in it {}
++
++        let v = vec![[1], [2], [3]];
++        let mut it = v.iter();
++        while let Some([1]) = it.next() {}
++
++        let mut it = v.iter();
++        for [_x] in it {}
++    }
++
++    // binding
++    {
++        let v = vec![1, 2, 3];
++        let mut it = v.iter();
++        while let Some(x @ 1) = it.next() {
++            println!("{}", x);
++        }
++
++        let v = vec![[1], [2], [3]];
++        let mut it = v.iter();
++        for x @ [_] in it {
++            println!("{:?}", x);
++        }
++    }
++
++    // false negative
++    {
++        let v = vec![1, 2, 3];
++        let mut it = v.iter().map(Some);
++        while let Some(Some(_) | None) = it.next() {
++            println!("1");
++        }
++    }
++}
++
 +fn nested_loops() {
 +    let a = [42, 1337];
 +    let mut y = a.iter();
 +    loop {
 +        // x is reused, so don't lint here
 +        while let Some(_) = y.next() {}
 +    }
 +
 +    let mut y = a.iter();
 +    for _ in 0..2 {
 +        while let Some(_) = y.next() {
 +            // y is reused, don't lint
 +        }
 +    }
 +
 +    loop {
 +        let mut y = a.iter();
 +        for _ in y {
 +            // use a for loop here
 +        }
 +    }
 +}
 +
 +fn issue1121() {
 +    use std::collections::HashSet;
 +    let mut values = HashSet::new();
 +    values.insert(1);
 +
 +    while let Some(&value) = values.iter().next() {
 +        values.remove(&value);
 +    }
 +}
 +
 +fn issue2965() {
 +    // This should not cause an ICE and suggest:
 +    //
 +    // for _ in values.iter() {}
 +    //
 +    use std::collections::HashSet;
 +    let mut values = HashSet::new();
 +    values.insert(1);
 +
 +    while let Some(..) = values.iter().next() {}
 +}
 +
 +fn issue3670() {
 +    let array = [Some(0), None, Some(1)];
 +    let mut iter = array.iter();
 +
 +    while let Some(elem) = iter.next() {
 +        let _ = elem.or_else(|| *iter.next()?);
 +    }
 +}
 +
 +fn issue1654() {
 +    // should not lint if the iterator is generated on every iteration
 +    use std::collections::HashSet;
 +    let mut values = HashSet::new();
 +    values.insert(1);
 +
 +    while let Some(..) = values.iter().next() {
 +        values.remove(&1);
 +    }
 +
 +    while let Some(..) = values.iter().map(|x| x + 1).next() {}
 +
 +    let chars = "Hello, World!".char_indices();
 +    while let Some((i, ch)) = chars.clone().next() {
 +        println!("{}: {}", i, ch);
 +    }
 +}
 +
 +fn main() {
 +    base();
 +    refutable();
++    refutable2();
 +    nested_loops();
 +    issue1121();
 +    issue2965();
 +    issue3670();
 +    issue1654();
 +}
index 04dce8a0289845b0c86518bf4cda1b7fc7383e10,0000000000000000000000000000000000000000..ba13172428e136bc47d8ba47f17387e310133729
mode 100644,000000..100644
--- /dev/null
@@@ -1,160 -1,0 +1,218 @@@
 +// run-rustfix
 +
 +#![warn(clippy::while_let_on_iterator)]
 +#![allow(clippy::never_loop, unreachable_code, unused_mut)]
++#![feature(or_patterns)]
 +
 +fn base() {
 +    let mut iter = 1..20;
 +    while let Option::Some(x) = iter.next() {
 +        println!("{}", x);
 +    }
 +
 +    let mut iter = 1..20;
 +    while let Some(x) = iter.next() {
 +        println!("{}", x);
 +    }
 +
 +    let mut iter = 1..20;
 +    while let Some(_) = iter.next() {}
 +
 +    let mut iter = 1..20;
 +    while let None = iter.next() {} // this is fine (if nonsensical)
 +
 +    let mut iter = 1..20;
 +    if let Some(x) = iter.next() {
 +        // also fine
 +        println!("{}", x)
 +    }
 +
 +    // the following shouldn't warn because it can't be written with a for loop
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        println!("next: {:?}", iter.next())
 +    }
 +
 +    // neither can this
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        println!("next: {:?}", iter.next());
 +    }
 +
 +    // or this
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        break;
 +    }
 +    println!("Remaining iter {:?}", iter);
 +
 +    // or this
 +    let mut iter = 1u32..20;
 +    while let Some(_) = iter.next() {
 +        iter = 1..20;
 +    }
 +}
 +
 +// Issue #1188
 +fn refutable() {
 +    let a = [42, 1337];
 +    let mut b = a.iter();
 +
 +    // consume all the 42s
 +    while let Some(&42) = b.next() {}
 +
 +    let a = [(1, 2, 3)];
 +    let mut b = a.iter();
 +
 +    while let Some(&(1, 2, 3)) = b.next() {}
 +
 +    let a = [Some(42)];
 +    let mut b = a.iter();
 +
 +    while let Some(&None) = b.next() {}
 +
 +    /* This gives “refutable pattern in `for` loop binding: `&_` not covered”
 +    for &42 in b {}
 +    for &(1, 2, 3) in b {}
 +    for &Option::None in b.next() {}
 +    // */
 +}
 +
++fn refutable2() {
++    // Issue 3780
++    {
++        let v = vec![1, 2, 3];
++        let mut it = v.windows(2);
++        while let Some([x, y]) = it.next() {
++            println!("x: {}", x);
++            println!("y: {}", y);
++        }
++
++        let mut it = v.windows(2);
++        while let Some([x, ..]) = it.next() {
++            println!("x: {}", x);
++        }
++
++        let mut it = v.windows(2);
++        while let Some([.., y]) = it.next() {
++            println!("y: {}", y);
++        }
++
++        let mut it = v.windows(2);
++        while let Some([..]) = it.next() {}
++
++        let v = vec![[1], [2], [3]];
++        let mut it = v.iter();
++        while let Some([1]) = it.next() {}
++
++        let mut it = v.iter();
++        while let Some([_x]) = it.next() {}
++    }
++
++    // binding
++    {
++        let v = vec![1, 2, 3];
++        let mut it = v.iter();
++        while let Some(x @ 1) = it.next() {
++            println!("{}", x);
++        }
++
++        let v = vec![[1], [2], [3]];
++        let mut it = v.iter();
++        while let Some(x @ [_]) = it.next() {
++            println!("{:?}", x);
++        }
++    }
++
++    // false negative
++    {
++        let v = vec![1, 2, 3];
++        let mut it = v.iter().map(Some);
++        while let Some(Some(_) | None) = it.next() {
++            println!("1");
++        }
++    }
++}
++
 +fn nested_loops() {
 +    let a = [42, 1337];
 +    let mut y = a.iter();
 +    loop {
 +        // x is reused, so don't lint here
 +        while let Some(_) = y.next() {}
 +    }
 +
 +    let mut y = a.iter();
 +    for _ in 0..2 {
 +        while let Some(_) = y.next() {
 +            // y is reused, don't lint
 +        }
 +    }
 +
 +    loop {
 +        let mut y = a.iter();
 +        while let Some(_) = y.next() {
 +            // use a for loop here
 +        }
 +    }
 +}
 +
 +fn issue1121() {
 +    use std::collections::HashSet;
 +    let mut values = HashSet::new();
 +    values.insert(1);
 +
 +    while let Some(&value) = values.iter().next() {
 +        values.remove(&value);
 +    }
 +}
 +
 +fn issue2965() {
 +    // This should not cause an ICE and suggest:
 +    //
 +    // for _ in values.iter() {}
 +    //
 +    use std::collections::HashSet;
 +    let mut values = HashSet::new();
 +    values.insert(1);
 +
 +    while let Some(..) = values.iter().next() {}
 +}
 +
 +fn issue3670() {
 +    let array = [Some(0), None, Some(1)];
 +    let mut iter = array.iter();
 +
 +    while let Some(elem) = iter.next() {
 +        let _ = elem.or_else(|| *iter.next()?);
 +    }
 +}
 +
 +fn issue1654() {
 +    // should not lint if the iterator is generated on every iteration
 +    use std::collections::HashSet;
 +    let mut values = HashSet::new();
 +    values.insert(1);
 +
 +    while let Some(..) = values.iter().next() {
 +        values.remove(&1);
 +    }
 +
 +    while let Some(..) = values.iter().map(|x| x + 1).next() {}
 +
 +    let chars = "Hello, World!".char_indices();
 +    while let Some((i, ch)) = chars.clone().next() {
 +        println!("{}: {}", i, ch);
 +    }
 +}
 +
 +fn main() {
 +    base();
 +    refutable();
++    refutable2();
 +    nested_loops();
 +    issue1121();
 +    issue2965();
 +    issue3670();
 +    issue1654();
 +}
index 6de138d7227b20b9f50a72f68dafe305b572a6d1,0000000000000000000000000000000000000000..aa980d9965c76b78e0d0f85819d9e5e19a2ac411
mode 100644,000000..100644
--- /dev/null
@@@ -1,28 -1,0 +1,46 @@@
-   --> $DIR/while_let_on_iterator.rs:8:5
 +error: this loop could be written as a `for` loop
-   --> $DIR/while_let_on_iterator.rs:13:5
++  --> $DIR/while_let_on_iterator.rs:9:5
 +   |
 +LL |     while let Option::Some(x) = iter.next() {
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
 +   |
 +   = note: `-D clippy::while-let-on-iterator` implied by `-D warnings`
 +
 +error: this loop could be written as a `for` loop
-   --> $DIR/while_let_on_iterator.rs:18:5
++  --> $DIR/while_let_on_iterator.rs:14:5
 +   |
 +LL |     while let Some(x) = iter.next() {
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
 +
 +error: this loop could be written as a `for` loop
-   --> $DIR/while_let_on_iterator.rs:97:9
++  --> $DIR/while_let_on_iterator.rs:19:5
 +   |
 +LL |     while let Some(_) = iter.next() {}
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter`
 +
 +error: this loop could be written as a `for` loop
- error: aborting due to 4 previous errors
++  --> $DIR/while_let_on_iterator.rs:102:9
++   |
++LL |         while let Some([..]) = it.next() {}
++   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it`
++
++error: this loop could be written as a `for` loop
++  --> $DIR/while_let_on_iterator.rs:109:9
++   |
++LL |         while let Some([_x]) = it.next() {}
++   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it`
++
++error: this loop could be written as a `for` loop
++  --> $DIR/while_let_on_iterator.rs:122:9
++   |
++LL |         while let Some(x @ [_]) = it.next() {
++   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it`
++
++error: this loop could be written as a `for` loop
++  --> $DIR/while_let_on_iterator.rs:154:9
 +   |
 +LL |         while let Some(_) = y.next() {
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y`
 +
++error: aborting due to 7 previous errors
 +
index ed6cc00ef0480a756a7f8282b971837cabf376ff,0000000000000000000000000000000000000000..67423e6ec1d19bca17b3acd4b55227ab6cfae2b8
mode 100644,000000..100644
--- /dev/null
@@@ -1,157 -1,0 +1,230 @@@
 +// run-rustfix
 +// aux-build:wildcard_imports_helper.rs
 +
 +#![warn(clippy::wildcard_imports)]
 +//#![allow(clippy::redundant_pub_crate)]
 +#![allow(unused)]
 +#![warn(unused_imports)]
 +
 +extern crate wildcard_imports_helper;
 +
 +use crate::fn_mod::foo;
 +use crate::mod_mod::inner_mod;
 +use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod};
 +#[macro_use]
 +use crate::struct_mod::{A, inner_struct_mod};
 +
 +#[allow(unused_imports)]
 +use wildcard_imports_helper::inner::inner_for_self_import;
 +use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar;
 +use wildcard_imports_helper::{ExternA, extern_foo};
 +
 +use std::io::prelude::*;
 +
 +struct ReadFoo;
 +
 +impl Read for ReadFoo {
 +    fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
 +        Ok(0)
 +    }
 +}
 +
 +mod fn_mod {
 +    pub fn foo() {}
 +}
 +
 +mod mod_mod {
 +    pub mod inner_mod {
 +        pub fn foo() {}
 +    }
 +}
 +
 +mod multi_fn_mod {
 +    pub fn multi_foo() {}
 +    pub fn multi_bar() {}
 +    pub fn multi_baz() {}
 +    pub mod multi_inner_mod {
 +        pub fn foo() {}
 +    }
 +}
 +
 +mod struct_mod {
 +    pub struct A;
 +    pub struct B;
 +    pub mod inner_struct_mod {
 +        pub struct C;
 +    }
 +
 +    #[macro_export]
 +    macro_rules! double_struct_import_test {
 +        () => {
 +            let _ = A;
 +        };
 +    }
 +}
 +
 +fn main() {
 +    foo();
 +    multi_foo();
 +    multi_bar();
 +    multi_inner_mod::foo();
 +    inner_mod::foo();
 +    extern_foo();
 +    inner_extern_bar();
 +
 +    let _ = A;
 +    let _ = inner_struct_mod::C;
 +    let _ = ExternA;
 +
 +    double_struct_import_test!();
 +    double_struct_import_test!();
 +}
 +
 +mod in_fn_test {
 +    pub use self::inner_exported::*;
 +    #[allow(unused_imports)]
 +    pub(crate) use self::inner_exported2::*;
 +
 +    fn test_intern() {
 +        use crate::fn_mod::foo;
 +
 +        foo();
 +    }
 +
 +    fn test_extern() {
 +        use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo};
 +        use wildcard_imports_helper::{ExternA, extern_foo};
 +
 +        inner_for_self_import::inner_extern_foo();
 +        inner_extern_foo();
 +
 +        extern_foo();
 +
 +        let _ = ExternA;
 +    }
 +
 +    fn test_inner_nested() {
 +        use self::{inner::inner_foo, inner2::inner_bar};
 +
 +        inner_foo();
 +        inner_bar();
 +    }
 +
 +    fn test_extern_reexported() {
 +        use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported};
 +
 +        extern_exported();
 +        let _ = ExternExportedStruct;
 +        let _ = ExternExportedEnum::A;
 +    }
 +
 +    mod inner_exported {
 +        pub fn exported() {}
 +        pub struct ExportedStruct;
 +        pub enum ExportedEnum {
 +            A,
 +        }
 +    }
 +
 +    mod inner_exported2 {
 +        pub(crate) fn exported2() {}
 +    }
 +
 +    mod inner {
 +        pub fn inner_foo() {}
 +    }
 +
 +    mod inner2 {
 +        pub fn inner_bar() {}
 +    }
 +}
 +
 +fn test_reexported() {
 +    use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported};
 +
 +    exported();
 +    let _ = ExportedStruct;
 +    let _ = ExportedEnum::A;
 +}
 +
 +#[rustfmt::skip]
 +fn test_weird_formatting() {
 +    use crate:: in_fn_test::exported;
 +    use crate:: fn_mod::foo;
 +
 +    exported();
 +    foo();
 +}
++
++mod super_imports {
++    fn foofoo() {}
++
++    mod should_be_replaced {
++        use super::foofoo;
++
++        fn with_super() {
++            let _ = foofoo();
++        }
++    }
++
++    mod test_should_pass {
++        use super::*;
++
++        fn with_super() {
++            let _ = foofoo();
++        }
++    }
++
++    mod test_should_pass_inside_function {
++        fn with_super_inside_function() {
++            use super::*;
++            let _ = foofoo();
++        }
++    }
++
++    mod test_should_pass_further_inside {
++        fn insidefoo() {}
++        mod inner {
++            use super::*;
++            fn with_super() {
++                let _ = insidefoo();
++            }
++        }
++    }
++
++    mod should_be_replaced_futher_inside {
++        fn insidefoo() {}
++        mod inner {
++            use super::insidefoo;
++            fn with_super() {
++                let _ = insidefoo();
++            }
++        }
++    }
++
++    mod use_explicit_should_be_replaced {
++        use super_imports::foofoo;
++
++        fn with_explicit() {
++            let _ = foofoo();
++        }
++    }
++
++    mod use_double_super_should_be_replaced {
++        mod inner {
++            use super::super::foofoo;
++
++            fn with_double_super() {
++                let _ = foofoo();
++            }
++        }
++    }
++
++    mod use_super_explicit_should_be_replaced {
++        use super::super::super_imports::foofoo;
++
++        fn with_super_explicit() {
++            let _ = foofoo();
++        }
++    }
++}
index c6d6efaece817fa53f80108ce725e4a498e24a5c,0000000000000000000000000000000000000000..3ad1a29aebad1f985a19e272ac55f071263f511c
mode 100644,000000..100644
--- /dev/null
@@@ -1,158 -1,0 +1,231 @@@
 +// run-rustfix
 +// aux-build:wildcard_imports_helper.rs
 +
 +#![warn(clippy::wildcard_imports)]
 +//#![allow(clippy::redundant_pub_crate)]
 +#![allow(unused)]
 +#![warn(unused_imports)]
 +
 +extern crate wildcard_imports_helper;
 +
 +use crate::fn_mod::*;
 +use crate::mod_mod::*;
 +use crate::multi_fn_mod::*;
 +#[macro_use]
 +use crate::struct_mod::*;
 +
 +#[allow(unused_imports)]
 +use wildcard_imports_helper::inner::inner_for_self_import;
 +use wildcard_imports_helper::inner::inner_for_self_import::*;
 +use wildcard_imports_helper::*;
 +
 +use std::io::prelude::*;
 +
 +struct ReadFoo;
 +
 +impl Read for ReadFoo {
 +    fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
 +        Ok(0)
 +    }
 +}
 +
 +mod fn_mod {
 +    pub fn foo() {}
 +}
 +
 +mod mod_mod {
 +    pub mod inner_mod {
 +        pub fn foo() {}
 +    }
 +}
 +
 +mod multi_fn_mod {
 +    pub fn multi_foo() {}
 +    pub fn multi_bar() {}
 +    pub fn multi_baz() {}
 +    pub mod multi_inner_mod {
 +        pub fn foo() {}
 +    }
 +}
 +
 +mod struct_mod {
 +    pub struct A;
 +    pub struct B;
 +    pub mod inner_struct_mod {
 +        pub struct C;
 +    }
 +
 +    #[macro_export]
 +    macro_rules! double_struct_import_test {
 +        () => {
 +            let _ = A;
 +        };
 +    }
 +}
 +
 +fn main() {
 +    foo();
 +    multi_foo();
 +    multi_bar();
 +    multi_inner_mod::foo();
 +    inner_mod::foo();
 +    extern_foo();
 +    inner_extern_bar();
 +
 +    let _ = A;
 +    let _ = inner_struct_mod::C;
 +    let _ = ExternA;
 +
 +    double_struct_import_test!();
 +    double_struct_import_test!();
 +}
 +
 +mod in_fn_test {
 +    pub use self::inner_exported::*;
 +    #[allow(unused_imports)]
 +    pub(crate) use self::inner_exported2::*;
 +
 +    fn test_intern() {
 +        use crate::fn_mod::*;
 +
 +        foo();
 +    }
 +
 +    fn test_extern() {
 +        use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
 +        use wildcard_imports_helper::*;
 +
 +        inner_for_self_import::inner_extern_foo();
 +        inner_extern_foo();
 +
 +        extern_foo();
 +
 +        let _ = ExternA;
 +    }
 +
 +    fn test_inner_nested() {
 +        use self::{inner::*, inner2::*};
 +
 +        inner_foo();
 +        inner_bar();
 +    }
 +
 +    fn test_extern_reexported() {
 +        use wildcard_imports_helper::*;
 +
 +        extern_exported();
 +        let _ = ExternExportedStruct;
 +        let _ = ExternExportedEnum::A;
 +    }
 +
 +    mod inner_exported {
 +        pub fn exported() {}
 +        pub struct ExportedStruct;
 +        pub enum ExportedEnum {
 +            A,
 +        }
 +    }
 +
 +    mod inner_exported2 {
 +        pub(crate) fn exported2() {}
 +    }
 +
 +    mod inner {
 +        pub fn inner_foo() {}
 +    }
 +
 +    mod inner2 {
 +        pub fn inner_bar() {}
 +    }
 +}
 +
 +fn test_reexported() {
 +    use crate::in_fn_test::*;
 +
 +    exported();
 +    let _ = ExportedStruct;
 +    let _ = ExportedEnum::A;
 +}
 +
 +#[rustfmt::skip]
 +fn test_weird_formatting() {
 +    use crate:: in_fn_test::  * ;
 +    use crate:: fn_mod::
 +        *;
 +
 +    exported();
 +    foo();
 +}
++
++mod super_imports {
++    fn foofoo() {}
++
++    mod should_be_replaced {
++        use super::*;
++
++        fn with_super() {
++            let _ = foofoo();
++        }
++    }
++
++    mod test_should_pass {
++        use super::*;
++
++        fn with_super() {
++            let _ = foofoo();
++        }
++    }
++
++    mod test_should_pass_inside_function {
++        fn with_super_inside_function() {
++            use super::*;
++            let _ = foofoo();
++        }
++    }
++
++    mod test_should_pass_further_inside {
++        fn insidefoo() {}
++        mod inner {
++            use super::*;
++            fn with_super() {
++                let _ = insidefoo();
++            }
++        }
++    }
++
++    mod should_be_replaced_futher_inside {
++        fn insidefoo() {}
++        mod inner {
++            use super::*;
++            fn with_super() {
++                let _ = insidefoo();
++            }
++        }
++    }
++
++    mod use_explicit_should_be_replaced {
++        use super_imports::*;
++
++        fn with_explicit() {
++            let _ = foofoo();
++        }
++    }
++
++    mod use_double_super_should_be_replaced {
++        mod inner {
++            use super::super::*;
++
++            fn with_double_super() {
++                let _ = foofoo();
++            }
++        }
++    }
++
++    mod use_super_explicit_should_be_replaced {
++        use super::super::super_imports::*;
++
++        fn with_super_explicit() {
++            let _ = foofoo();
++        }
++    }
++}
index 050e4c6304f05b49640f208d94bf7b80c2f64e0f,0000000000000000000000000000000000000000..fab43b738eb434d1ab6b453dffbc8967bfeeb222
mode 100644,000000..100644
--- /dev/null
@@@ -1,96 -1,0 +1,126 @@@
- error: aborting due to 15 previous errors
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:11:5
 +   |
 +LL | use crate::fn_mod::*;
 +   |     ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 +   |
 +   = note: `-D clippy::wildcard-imports` implied by `-D warnings`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:12:5
 +   |
 +LL | use crate::mod_mod::*;
 +   |     ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:13:5
 +   |
 +LL | use crate::multi_fn_mod::*;
 +   |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:15:5
 +   |
 +LL | use crate::struct_mod::*;
 +   |     ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:19:5
 +   |
 +LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:20:5
 +   |
 +LL | use wildcard_imports_helper::*;
 +   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:89:13
 +   |
 +LL |         use crate::fn_mod::*;
 +   |             ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:95:75
 +   |
 +LL |         use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
 +   |                                                                           ^ help: try: `inner_extern_foo`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:96:13
 +   |
 +LL |         use wildcard_imports_helper::*;
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:107:20
 +   |
 +LL |         use self::{inner::*, inner2::*};
 +   |                    ^^^^^^^^ help: try: `inner::inner_foo`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:107:30
 +   |
 +LL |         use self::{inner::*, inner2::*};
 +   |                              ^^^^^^^^^ help: try: `inner2::inner_bar`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:114:13
 +   |
 +LL |         use wildcard_imports_helper::*;
 +   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:143:9
 +   |
 +LL |     use crate::in_fn_test::*;
 +   |         ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:152:9
 +   |
 +LL |     use crate:: in_fn_test::  * ;
 +   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
 +
 +error: usage of wildcard import
 +  --> $DIR/wildcard_imports.rs:153:9
 +   |
 +LL |       use crate:: fn_mod::
 +   |  _________^
 +LL | |         *;
 +   | |_________^ help: try: `crate:: fn_mod::foo`
 +
++error: usage of wildcard import
++  --> $DIR/wildcard_imports.rs:164:13
++   |
++LL |         use super::*;
++   |             ^^^^^^^^ help: try: `super::foofoo`
++
++error: usage of wildcard import
++  --> $DIR/wildcard_imports.rs:199:17
++   |
++LL |             use super::*;
++   |                 ^^^^^^^^ help: try: `super::insidefoo`
++
++error: usage of wildcard import
++  --> $DIR/wildcard_imports.rs:207:13
++   |
++LL |         use super_imports::*;
++   |             ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
++
++error: usage of wildcard import
++  --> $DIR/wildcard_imports.rs:216:17
++   |
++LL |             use super::super::*;
++   |                 ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
++
++error: usage of wildcard import
++  --> $DIR/wildcard_imports.rs:225:13
++   |
++LL |         use super::super::super_imports::*;
++   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
++
++error: aborting due to 20 previous errors
 +