diff --git a/Cargo.lock b/Cargo.lock index 8d68be636fa92..7f0076bae73ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -659,7 +659,7 @@ checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clippy" -version = "0.1.99" +version = "0.1.100" dependencies = [ "anstream 0.6.21", "askama", @@ -684,7 +684,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.99" +version = "0.1.100" dependencies = [ "arrayvec", "clippy_utils", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.99" +version = "0.1.100" dependencies = [ "arrayvec", "cargo_metadata 0.23.1", @@ -739,7 +739,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.99" +version = "0.1.100" dependencies = [ "arrayvec", "itertools", @@ -1153,7 +1153,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.99" +version = "0.1.100" [[package]] name = "derive-where" diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index de36ddbe1d10f..102a3013b38ad 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -401,12 +401,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Like for trait refs, verify that `dummy_self` did not leak inside default type // parameters. - let references_self = b.projection_term.args.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); + let references_self = b + .projection_term + .args + .iter() + .skip(1) + .any(|arg| arg.walk().any(|arg| arg == dummy_self.into())); if references_self { let guar = tcx .dcx() diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index ae20d21ea665f..8d21eae971e7b 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -343,11 +343,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { // Avoid inlining into coroutines, since their `optimized_mir` is used for layout computation, // which can create a cycle, even when no attempt is made to inline the function in the other // direction. - if body.coroutine.is_some() { - return false; - } - - true + body.coroutine.is_none() } #[instrument(level = "debug", skip(self, callee_body))] diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 78ccf04d456a3..ec854e25a6aa2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -698,12 +698,7 @@ fn try_prove_negated_where_clause<'tcx>( // FIXME: We could use the assumed_wf_types from both impls, I think, // if that wasn't implemented just for LocalDefId, and we'd need to do // the normalization ourselves since this is totally fallible... - let errors = ocx.resolve_regions(CRATE_DEF_ID, param_env, []); - if !errors.is_empty() { - return false; - } - - true + ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty() } /// Compute the `intercrate_ambiguity_causes` for the new solver using diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index f4b64888972bd..42b087bb009e2 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -863,12 +863,7 @@ pub fn impossible_clauses<'tcx>(tcx: TyCtxt<'tcx>, clauses: Vec // vs user-written impls to AMBIGUOUS, this may return ambiguity even // with no infer vars. There may also be ways to encounter ambiguity due // to post-mono overflow. - let true_errors = ocx.try_evaluate_obligations(); - if !true_errors.no_errors() { - return true; - } - - false + !ocx.try_evaluate_obligations().no_errors() } fn instantiate_and_check_impossible_clauses<'tcx>( diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 94c886649109f..c08f73c95b69b 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -372,13 +372,10 @@ pub(crate) fn is_ci_llvm_available_for_target( ("x86_64-unknown-netbsd", false), ]; - if !supported_platforms.contains(&(&*host_target.triple, asserts)) - && (asserts || !supported_platforms.contains(&(&*host_target.triple, true))) - { - return false; - } - - true + // Check if the host target is available with the requested assertions (true/false), + supported_platforms.contains(&(&*host_target.triple, asserts)) + // if it is not available for the given `asserts`, check if it is available with assertions (superset). + || supported_platforms.contains(&(&*host_target.triple, true)) } #[derive(Clone)] diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 27a400406e144..a04dc3b8afb0d 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -375,11 +375,7 @@ fn ensure_stage1_toolchain_placeholder_exists(stage_path: &str) -> bool { // Take care not to overwrite the file let result = File::options().append(true).create(true).open(&pathbuf); - if result.is_err() { - return false; - } - - true + result.is_ok() } // Used to get the path for `Subcommand::Setup` diff --git a/src/tools/clippy/.github/FUNDING.yml b/src/tools/clippy/.github/FUNDING.yml index 16ac7b6eb9bc9..4268752aca2b9 100644 --- a/src/tools/clippy/.github/FUNDING.yml +++ b/src/tools/clippy/.github/FUNDING.yml @@ -1,2 +1,2 @@ github: rustfoundation -custom: [ "rust-lang.org/funding" ] +custom: [ "https://rust-lang.org/funding" ] diff --git a/src/tools/clippy/.github/deploy.sh b/src/tools/clippy/.github/deploy.sh index 2f062799a3607..724a39db0c58f 100644 --- a/src/tools/clippy/.github/deploy.sh +++ b/src/tools/clippy/.github/deploy.sh @@ -4,6 +4,7 @@ set -ex echo "Removing the current docs for master" rm -rf out/master/ || exit 0 +rm -rf out/main/ || exit 0 echo "Making the docs for master" mkdir out/master/ @@ -12,6 +13,9 @@ cp util/gh-pages/theme.js out/master cp util/gh-pages/script.js out/master cp util/gh-pages/style.css out/master +echo "Copying the docs into the main directory" +cp -Tr out/master/ out/main/ + if [[ -n $TAG_NAME ]]; then echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it" cp -Tr out/master "out/$TAG_NAME" diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 3876af9b2f37b..37f5eb09e5247 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,7 +6,125 @@ document. ## Unreleased / Beta / In Rust Nightly -[b147b68...master](https://github.com/rust-lang/rust-clippy/compare/b147b68...master) +[64c7431...master](https://github.com/rust-lang/rust-clippy/compare/64c7431...master) + +## Rust 1.98 + +Current stable, released 2026-08-20 + +[View all merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2026-05-27T20%3A48%3A30Z..2026-06-25T09%3A21%3A14Z+base%3Amaster) + +### New Lints + +* Added [`unnecessary_unwrap_unchecked`] to `complexity` + [#16252](https://github.com/rust-lang/rust-clippy/pull/16252) +* Added [`chunks_exact_to_as_chunks`] to `style` + [#16931](https://github.com/rust-lang/rust-clippy/pull/16931) +* Added [`by_ref_peekable_peek`] to `suspicious` + [#17042](https://github.com/rust-lang/rust-clippy/pull/17042) +* Added [`with_capacity_zero`] to `pedantic` + [#17192](https://github.com/rust-lang/rust-clippy/pull/17192) +* Added [`manual_isolate_lowest_one`] to `complexity` + [#17037](https://github.com/rust-lang/rust-clippy/pull/17037) +* Added [`for_unbounded_range`] to `suspicious` + [#16257](https://github.com/rust-lang/rust-clippy/pull/16257) +* Added [`unused_async_trait_impl`] to `pedantic` + [#16244](https://github.com/rust-lang/rust-clippy/pull/16244) + +### Moves and Deprecations + +* Moved [`empty_enums`] from `pedantic` to `nursery` + [#17298](https://github.com/rust-lang/rust-clippy/pull/17298) +* Deprecated [`from_iter_instead_of_collect`] + [#17208](https://github.com/rust-lang/rust-clippy/pull/17208) + +### Enhancements + +* [`needless_late_init`] extend to cover grouped assignments, and fix FN for if/match in block expr + [#16746](https://github.com/rust-lang/rust-clippy/pull/16746) +* [`unnecessary_cast`] treat `!` the same as `-`, improving suggestions and precedence handling + [#17278](https://github.com/rust-lang/rust-clippy/pull/17278) +* [`manual_slice_fill`] detect `for` loops over `&mut [T; N]` and suggest `.fill()` + [#16926](https://github.com/rust-lang/rust-clippy/pull/16926) +* [`extra_unused_lifetimes`] detect unused `for<'a>` lifetime bounds + [#17031](https://github.com/rust-lang/rust-clippy/pull/17031) +* [`single_range_in_vec_init`] detect more ranges, including `..end`, `start..`, `start..=end`, + `..=end`, and `..` + [#17146](https://github.com/rust-lang/rust-clippy/pull/17146) +* [`iter_next_slice`] extend lint to support `iter_mut()` + [#17122](https://github.com/rust-lang/rust-clippy/pull/17122) +* [`large_const_arrays`] check nested large arrays + [#17141](https://github.com/rust-lang/rust-clippy/pull/17141) +* [`manual_is_variant_and`] lint `result.ok().is_some_and(f)` + [#17184](https://github.com/rust-lang/rust-clippy/pull/17184) +* [`mem_replace_with_default`] also emit inside macros + [#17191](https://github.com/rust-lang/rust-clippy/pull/17191) +* [`missing_const_for_fn`] lint more cases involving pointer metadata, such as slice lengths + [#17121](https://github.com/rust-lang/rust-clippy/pull/17121) +* [`never_loop`] add notes for non-trivial cases to indicate why a loop is detected as + non-terminating + [#17145](https://github.com/rust-lang/rust-clippy/pull/17145) +* [`double_must_use`] make the lint machine-applicable in the single-attribute case + [#17144](https://github.com/rust-lang/rust-clippy/pull/17144) +* [`result_large_err`] and [`result_unit_err`] fix not triggering on async functions + [#17130](https://github.com/rust-lang/rust-clippy/pull/17130) +* [`unnecessary_lazy_evaluations`] avoid a broken suggestion when the closure has an explicit return + type + [#17216](https://github.com/rust-lang/rust-clippy/pull/17216) +* [`unnecessary_sort_by`] fix the reverse-sort suggestion using the second closure parameter name + instead of the first + [#16868](https://github.com/rust-lang/rust-clippy/pull/16868) +* [`collapsible_match`] fix wrong suggestions when the match body has no braces + [#16749](https://github.com/rust-lang/rust-clippy/pull/16749) +* [`unused_async_trait_impl`] fix suggestions for statements containing `return` + [#17181](https://github.com/rust-lang/rust-clippy/pull/17181) +* [`map_unwrap_or`] avoid suggesting `map_or` when the `unwrap_or` default requires a type adjustment + [#16928](https://github.com/rust-lang/rust-clippy/pull/16928) +* [`doc_markdown`] add common database engines to the whitelist + [#16917](https://github.com/rust-lang/rust-clippy/pull/16917) +* [`std_instead_of_core`] fix MSRV-unaware issues + [#16964](https://github.com/rust-lang/rust-clippy/pull/16964) +* [`extra_unused_type_parameters`] don't suggest an autofix + [#15907](https://github.com/rust-lang/rust-clippy/pull/15907) +* [`extra_unused_lifetimes`] do not lint expanded code + [#17256](https://github.com/rust-lang/rust-clippy/pull/17256) +* [`unnecessary_box_returns`] no longer fires when the boxed type's size depends on generic + parameters, e.g. `Box<[T; N]>` + [#17249](https://github.com/rust-lang/rust-clippy/pull/17249) +* [`inline_trait_bounds`] do not trigger on code automatically derived from procedural macros + [#17131](https://github.com/rust-lang/rust-clippy/pull/17131) +* Fix duplicate diagnostics in `unknown_attribute` and `renamed_builtin_attr` + [#17164](https://github.com/rust-lang/rust-clippy/pull/17164) + +### False Positive Fixes + +* [`manual_option_zip`] don't trigger when the map receiver is a lazily evaluated expression + [#17270](https://github.com/rust-lang/rust-clippy/pull/17270) +* [`std_instead_of_core`] fix FPs for stable items in an unstable module, e.g. `core::io::ErrorKind` + [#16964](https://github.com/rust-lang/rust-clippy/pull/16964) +* [`ref_patterns`] don't trigger on `#[automatically_derived]` annotated code + [#17250](https://github.com/rust-lang/rust-clippy/pull/17250) +* [`needless_borrow`] fix FP for same-name methods, where auto-borrowing might prefer another method + [#17171](https://github.com/rust-lang/rust-clippy/pull/17171) +* [`redundant_closure_call`] fix FP on async closures with early returns + [#17107](https://github.com/rust-lang/rust-clippy/pull/17107) +* [`explicit_counter_loop`] fix FP when the counter is only modified inside the `else` block of a + `let...else` binding + [#17023](https://github.com/rust-lang/rust-clippy/pull/17023) +* [`unnecessary_unwrap_unchecked`] don't trigger inside the `_unchecked` function itself + [#17351](https://github.com/rust-lang/rust-clippy/pull/17351) + +### ICE Fixes + +* [`absurd_extreme_comparisons`] avoid an ICE when const evaluation encounters unsized generic type + args + [#16976](https://github.com/rust-lang/rust-clippy/pull/16976) +* [`uninit_vec`] fix an OOM panic on large types + [#17205](https://github.com/rust-lang/rust-clippy/pull/17205) +* Fix an ICE when the `clippy::author` attribute is applied to an item + [#17245](https://github.com/rust-lang/rust-clippy/pull/17245) +* [`unnecessary_unwrap_unchecked`] fix ICE when resolving a path to a local variable + [#17353](https://github.com/rust-lang/rust-clippy/pull/17353) ## Rust 1.97 @@ -6736,929 +6854,931 @@ Released 2018-09-13 -[`absolute_paths`]: https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths -[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons -[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core -[`allow_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes -[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason -[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range -[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range -[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped -[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant -[`arbitrary_source_item_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering -[`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync -[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects -[`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions -[`as_pointer_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_pointer_underscore -[`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut -[`as_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore -[`assert_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#assert_is_empty -[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants -[`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_result_states -[`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern -[`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops -[`assigning_clones`]: https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones -[`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async -[`await_holding_invalid_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type -[`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock -[`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref -[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask -[`big_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#big_endian_bytes -[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map -[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name -[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints -[`block_in_if_condition_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_expr -[`block_in_if_condition_stmt`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_in_if_condition_stmt -[`block_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#block_scrutinee -[`blocks_in_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_conditions -[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_if_conditions -[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_assert_comparison -[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison -[`bool_to_int_with_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_to_int_with_if -[`borrow_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr -[`borrow_deref_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_deref_ref -[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const -[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box -[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection -[`box_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_default -[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec -[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local -[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code -[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow -[`by_ref_peekable_peek`]: https://rust-lang.github.io/rust-clippy/master/index.html#by_ref_peekable_peek -[`byte_char_slices`]: https://rust-lang.github.io/rust-clippy/master/index.html#byte_char_slices -[`bytes_count_to_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_count_to_len -[`bytes_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_nth -[`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata -[`case_sensitive_file_extension_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#case_sensitive_file_extension_comparisons -[`cast_abs_to_unsigned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned -[`cast_enum_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_constructor -[`cast_enum_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_truncation -[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless -[`cast_nan_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_nan_to_int -[`cast_possible_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation -[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap -[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss -[`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ptr_alignment -[`cast_ref_to_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_ref_to_mut -[`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_sign_loss -[`cast_slice_different_sizes`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_different_sizes -[`cast_slice_from_raw_parts`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_slice_from_raw_parts -[`cfg_not_test`]: https://rust-lang.github.io/rust-clippy/master/index.html#cfg_not_test -[`char_indices_as_byte_indices`]: https://rust-lang.github.io/rust-clippy/master/index.html#char_indices_as_byte_indices -[`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 -[`chunks_exact_to_as_chunks`]: https://rust-lang.github.io/rust-clippy/master/index.html#chunks_exact_to_as_chunks -[`clear_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#clear_with_drain -[`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref -[`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy -[`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_ref_ptr -[`cloned_instead_of_copied`]: https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied -[`cloned_ref_to_slice_refs`]: https://rust-lang.github.io/rust-clippy/master/index.html#cloned_ref_to_slice_refs -[`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 -[`coerce_container_to_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#coerce_container_to_any -[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity -[`collapsible_else_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_else_if -[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if -[`collapsible_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match -[`collapsible_str_replace`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace -[`collection_is_never_read`]: https://rust-lang.github.io/rust-clippy/master/index.html#collection_is_never_read -[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain -[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty -[`confusing_method_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#confusing_method_to_numeric_cast -[`const_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_is_empty -[`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/master/index.html#const_static_lifetime -[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator -[`crate_in_macro_def`]: https://rust-lang.github.io/rust-clippy/master/index.html#crate_in_macro_def -[`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir -[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute -[`cyclomatic_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cyclomatic_complexity -[`dbg_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro -[`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call -[`decimal_bitwise_operands`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_bitwise_operands -[`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_constructed_unit_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_constructed_unit_structs -[`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_instead_of_iter_empty -[`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback -[`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access -[`default_union_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_union_representation -[`definition_in_module_root`]: https://rust-lang.github.io/rust-clippy/master/index.html#definition_in_module_root -[`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr -[`deprecated_clippy_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_clippy_cfg_attr -[`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver -[`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof -[`deref_by_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_by_slicing -[`derivable_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls -[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq -[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord -[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq -[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq -[`disallowed_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_fields -[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros -[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method -[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods -[`disallowed_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names -[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents -[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type -[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types -[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression -[`doc_broken_link`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_broken_link -[`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks -[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg -[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation -[`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code -[`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes -[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown -[`doc_nested_refdefs`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_nested_refdefs -[`doc_overindented_list_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_overindented_list_items -[`doc_paragraphs_missing_punctuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_paragraphs_missing_punctuation -[`doc_suspicious_footnotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_suspicious_footnotes -[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons -[`double_ended_iterator_last`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_ended_iterator_last -[`double_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_must_use -[`double_neg`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_neg -[`double_parens`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_parens -[`drain_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#drain_collect -[`drop_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_bounds -[`drop_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_copy -[`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_non_drop -[`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref -[`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod -[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument -[`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes -[`duration_suboptimal_units`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_suboptimal_units -[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec -[`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute -[`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#elidable_lifetime_names -[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else -[`empty_docs`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_docs -[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop -[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum -[`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum_variants_with_brackets -[`empty_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enums -[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments -[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr -[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop -[`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets -[`enum_clike_unportable_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_clike_unportable_variant -[`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use -[`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names -[`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op -[`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/master/index.html#equatable_if_let -[`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op -[`err_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#err_expect -[`error_impl_error`]: https://rust-lang.github.io/rust-clippy/master/index.html#error_impl_error -[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence -[`excessive_nesting`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting -[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision -[`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_enums -[`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#exhaustive_structs -[`exit`]: https://rust-lang.github.io/rust-clippy/master/index.html#exit -[`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_fun_call -[`expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#expect_used -[`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#expl_impl_clone_on_copy -[`explicit_auto_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref -[`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_counter_loop -[`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_deref_methods -[`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_into_iter_loop -[`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop -[`explicit_write`]: https://rust-lang.github.io/rust-clippy/master/index.html#explicit_write -[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice -[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain -[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes -[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters -[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from -[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default -[`field_scoped_visibility_modifiers`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_scoped_visibility_modifiers -[`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_bool_then`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_bool_then -[`filter_map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_identity -[`filter_map_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next -[`filter_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#filter_next -[`find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#find_map -[`flat_map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_identity -[`flat_map_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#flat_map_option -[`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic -[`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp -[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const -[`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_equality_without_abs -[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons -[`fn_null_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_null_check -[`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools -[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast -[`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_any -[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation -[`for_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_kv_map -[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_option -[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loop_over_result -[`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles -[`for_unbounded_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_unbounded_range -[`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy -[`forget_non_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_non_drop -[`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref -[`format_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_collect -[`format_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_in_format_args -[`format_push_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_push_string -[`four_forward_slashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#four_forward_slashes -[`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect -[`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into -[`from_raw_with_void_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_raw_with_void_ptr -[`from_str_radix_10`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_str_radix_10 -[`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send -[`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first -[`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len -[`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap -[`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes -[`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion -[`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op -[`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex -[`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching -[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result -[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else -[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else -[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none -[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond -[`ignore_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignore_without_reason -[`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ignored_unit_patterns -[`impl_hash_borrow_with_str_and_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_hash_borrow_with_str_and_bytes -[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params -[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone -[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher -[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return -[`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_add -[`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub -[`implied_bounds_in_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#implied_bounds_in_impls -[`impossible_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#impossible_comparisons -[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops -[`incompatible_msrv`]: https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv -[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping -[`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor -[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type -[`incorrect_partial_ord_impl_on_ord_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_partial_ord_impl_on_ord_type -[`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice -[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing -[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask -[`ineffective_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_open_options -[`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 -[`infallible_try_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_try_from -[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter -[`infinite_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_loop -[`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string -[`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string_shadow_display -[`init_numbered_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#init_numbered_fields -[`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always -[`inline_asm_x86_att_syntax`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_asm_x86_att_syntax -[`inline_asm_x86_intel_syntax`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_asm_x86_intel_syntax -[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body -[`inline_modules`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_modules -[`inline_trait_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_trait_bounds -[`inspect_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#inspect_for_each -[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one -[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic -[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division -[`integer_division_remainder_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division_remainder_used -[`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 -[`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_without_iter -[`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering -[`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage -[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref -[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex -[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons -[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked -[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub -[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters -[`io_other_error`]: https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error -[`ip_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#ip_constant -[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix -[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements -[`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module -[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect -[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count -[`iter_filter_is_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_filter_is_ok -[`iter_filter_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_filter_is_some -[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map -[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop -[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice -[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator -[`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth -[`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero -[`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections -[`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_single_items -[`iter_out_of_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_out_of_bounds -[`iter_over_hash_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_over_hash_type -[`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_overeager_cloned -[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next -[`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero -[`iter_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_with_drain -[`iter_without_into_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_without_into_iter -[`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero -[`join_absolute_paths`]: https://rust-lang.github.io/rust-clippy/master/index.html#join_absolute_paths -[`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_futures`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_futures -[`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file -[`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays -[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames -[`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value -[`legacy_numeric_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants -[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_without_is_empty -[`len_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero -[`let_and_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return -[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_drop -[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future -[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock -[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use -[`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_untyped -[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value -[`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore -[`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok -[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist -[`lint_groups_priority`]: https://rust-lang.github.io/rust-clippy/master/index.html#lint_groups_priority -[`literal_string_with_formatting_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#literal_string_with_formatting_args -[`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes -[`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_metavars_in_unsafe`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe -[`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_abs_diff`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_abs_diff -[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert -[`manual_assert_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert_eq -[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn -[`manual_bit_width`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bit_width -[`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits -[`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals -[`manual_checked_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_checked_ops -[`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp -[`manual_clear`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clear -[`manual_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_contains -[`manual_dangling_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_dangling_ptr -[`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil -[`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter -[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map -[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find -[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map -[`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten -[`manual_hash_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one -[`manual_ignore_case_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ignore_case_cmp -[`manual_ilog2`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ilog2 -[`manual_inspect`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_inspect -[`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed -[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check -[`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite -[`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite -[`manual_is_multiple_of`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_multiple_of -[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two -[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and -[`manual_isolate_lowest_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_isolate_lowest_one -[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else -[`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str -[`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map -[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy -[`manual_midpoint`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint -[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back -[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive -[`manual_noop_waker`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_noop_waker -[`manual_ok_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_err -[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or -[`manual_option_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_as_slice -[`manual_option_zip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_zip -[`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison -[`manual_pop_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pop_if -[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains -[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns -[`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid -[`manual_repeat_n`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_repeat_n -[`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain -[`manual_rotate`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rotate -[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic -[`manual_slice_fill`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_fill -[`manual_slice_size_calculation`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_size_calculation -[`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once -[`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat -[`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new -[`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip -[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap -[`manual_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_take -[`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold -[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or -[`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default -[`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some -[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names -[`map_all_any_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_all_any_identity -[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone -[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit -[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry -[`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_err_ignore -[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten -[`map_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_identity -[`map_or_identity`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_or_identity -[`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or -[`map_with_unused_argument_over_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_with_unused_argument_over_ranges -[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_as_ref -[`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool -[`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro -[`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items -[`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm -[`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats -[`match_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_result_ok -[`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms -[`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding -[`match_str_case_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_str_case_mismatch -[`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm -[`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants -[`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter -[`maybe_misused_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_misused_cfg -[`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_option_with_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_some -[`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_ident_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars -[`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_bit_width_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_bit_width_type -[`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os -[`mismatching_type_param_order`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatching_type_param_order -[`misnamed_getters`]: https://rust-lang.github.io/rust-clippy/master/index.html#misnamed_getters -[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op -[`missing_assert_message`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_assert_message -[`missing_asserts_for_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_asserts_for_indexing -[`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn -[`missing_const_for_thread_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_thread_local -[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items -[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames -[`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc -[`missing_fields_in_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_fields_in_debug -[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items -[`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc -[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc -[`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop -[`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods -[`missing_transmute_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_transmute_annotations -[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes -[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style -[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals -[`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression -[`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files -[`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception -[`module_name_repetitions`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions -[`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic -[`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one -[`multi_assignments`]: https://rust-lang.github.io/rust-clippy/master/index.html#multi_assignments -[`multiple_bound_locations`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations -[`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 -[`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_unsafe_ops_per_block -[`must_use_candidate`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate -[`must_use_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_unit -[`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_from_ref -[`mut_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mut -[`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mutex_lock -[`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_range_bound -[`mutable_key_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type -[`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic -[`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer -[`naive_bytecount`]: https://rust-lang.github.io/rust-clippy/master/index.html#naive_bytecount -[`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type -[`needless_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_as_bytes -[`needless_bitwise_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bitwise_bool -[`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool -[`needless_bool_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool_assign -[`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_borrows_for_generic_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args -[`needless_character_iteration`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_character_iteration -[`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_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_else -[`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each -[`needless_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_if -[`needless_ifs`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_ifs -[`needless_late_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init -[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes -[`needless_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_match -[`needless_maybe_sized`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_maybe_sized -[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref -[`needless_option_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_take -[`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_parens_on_range_literals -[`needless_pass_by_ref_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut -[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value -[`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pub_self -[`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark -[`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop -[`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes -[`needless_raw_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_strings -[`needless_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return -[`needless_return_with_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return_with_question_mark -[`needless_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_splitn -[`needless_type_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_type_cast -[`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update -[`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord -[`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply -[`negative_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#negative_feature_names -[`never_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#never_loop -[`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self -[`new_without_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default -[`new_without_default_derive`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default_derive -[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect -[`no_effect_replace`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_replace -[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding -[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi -[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal -[`non_canonical_clone_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_canonical_clone_impl -[`non_canonical_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_canonical_partial_ord_impl -[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg -[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions -[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty -[`non_std_lazy_statics`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_std_lazy_statics -[`non_zero_suggestions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_zero_suggestions -[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool -[`nonnull_unchecked_on_box_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonnull_unchecked_on_box_ptr -[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options -[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces -[`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#not_unsafe_ptr_arg_deref -[`obfuscated_if_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#obfuscated_if_else -[`octal_escapes`]: https://rust-lang.github.io/rust-clippy/master/index.html#octal_escapes -[`ok_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#ok_expect -[`only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#only_used_in_recursion -[`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref -[`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some -[`option_as_ref_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_cloned -[`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref -[`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap -[`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used -[`option_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_filter_map -[`option_if_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else -[`option_map_or_err_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_err_ok -[`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_or_none -[`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unit_fn -[`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or -[`option_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or_else -[`option_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_option -[`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_unwrap_used -[`or_fun_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call -[`or_then_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#or_then_unwrap -[`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#out_of_bounds_indexing -[`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/master/index.html#overflow_check_conditional -[`overly_complex_bool_expr`]: https://rust-lang.github.io/rust-clippy/master/index.html#overly_complex_bool_expr -[`owned_cow`]: https://rust-lang.github.io/rust-clippy/master/index.html#owned_cow -[`panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic -[`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_in_result_fn -[`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params -[`panicking_overflow_checks`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_overflow_checks -[`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap -[`partial_pub_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#partial_pub_fields -[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl -[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none -[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite -[`path_ends_with_ext`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext -[`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push -[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch -[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false -[`pointer_format`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointer_format -[`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointers_in_nomem_asm_block -[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters -[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma -[`possible_missing_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_else -[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence -[`precedence_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence_bits -[`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_in_format_impl -[`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal -[`print_stderr`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr -[`print_stdout`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout -[`print_with_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_with_newline -[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#println_empty_string -[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg -[`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr -[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_cast_constness -[`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq -[`ptr_offset_by_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_by_literal -[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast -[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names -[`pub_underscore_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields -[`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use -[`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_with_shorthand -[`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_without_shorthand -[`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark -[`question_mark_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark_used -[`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one -[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one -[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero -[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len -[`rc_buffer`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer -[`rc_clone_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_clone_in_vec_init -[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex -[`read_line_without_trim`]: https://rust-lang.github.io/rust-clippy/master/index.html#read_line_without_trim -[`read_zero_byte_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#read_zero_byte_vec -[`readonly_write_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#readonly_write_lock -[`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl -[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation -[`redundant_as_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_as_str -[`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_async_block -[`redundant_at_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_at_rest_pattern -[`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_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_comparisons -[`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else -[`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names -[`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names -[`redundant_guards`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_guards -[`redundant_iter_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_iter_cloned -[`redundant_locals`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_locals -[`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern -[`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching -[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate -[`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing -[`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes -[`redundant_test_prefix`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_test_prefix -[`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations -[`ref_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_as_ptr -[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference -[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref -[`ref_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option -[`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref -[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns -[`regex_creation_in_loops`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_creation_in_loops -[`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro -[`renamed_function_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params -[`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once -[`repeat_vec_with_capacity`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity -[`replace_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_box -[`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts -[`repr_packed_without_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi -[`reserve_after_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#reserve_after_initialization -[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs -[`rest_pattern_accessible_field`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pattern_accessible_field -[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used -[`result_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_filter_map -[`result_large_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err -[`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option -[`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn -[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else -[`result_unit_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unit_err -[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used -[`return_and_then`]: https://rust-lang.github.io/rust-clippy/master/index.html#return_and_then -[`return_self_not_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use -[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop -[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges -[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition -[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push -[`same_length_and_capacity`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_length_and_capacity -[`same_name_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_name_method -[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some -[`seek_from_current`]: https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current -[`seek_to_start_instead_of_rewind`]: https://rust-lang.github.io/rust-clippy/master/index.html#seek_to_start_instead_of_rewind -[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment -[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors -[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files -[`self_only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_only_used_in_recursion -[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned -[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block -[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block -[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix -[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse -[`set_contains_or_insert`]: https://rust-lang.github.io/rust-clippy/master/index.html#set_contains_or_insert -[`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 -[`should_panic_without_expect`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_panic_without_expect -[`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee -[`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening -[`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names -[`single_call_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn -[`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str -[`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names -[`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_pattern -[`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_push_str -[`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_component_path_imports -[`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop -[`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match -[`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else -[`single_option_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_option_map -[`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_range_in_vec_init -[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count -[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref -[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next -[`sliced_string_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#sliced_string_as_bytes -[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization -[`some_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#some_filter -[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive -[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc -[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core -[`str_split_at_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_split_at_newline -[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string -[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add -[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign -[`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars -[`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes -[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes -[`string_lit_chars_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_chars_any -[`string_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_slice -[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string -[`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings -[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools -[`struct_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names -[`stutter`]: https://rust-lang.github.io/rust-clippy/master/index.html#stutter -[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops -[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl -[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting -[`suspicious_command_arg_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_command_arg_space -[`suspicious_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_doc_comments -[`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_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_open_options -[`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings -[`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn -[`suspicious_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_to_owned -[`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting -[`suspicious_xor_used_as_pow`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_xor_used_as_pow -[`swap_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#swap_ptr_to_ref -[`swap_with_temporary`]: https://rust-lang.github.io/rust-clippy/master/index.html#swap_with_temporary -[`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 -[`test_attr_in_doctest`]: https://rust-lang.github.io/rust-clippy/master/index.html#test_attr_in_doctest -[`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module -[`thread_local_initializer_can_be_made_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#thread_local_initializer_can_be_made_const -[`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some -[`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display -[`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args -[`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl -[`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo -[`too_long_first_doc_paragraph`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_long_first_doc_paragraph -[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments -[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines -[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg -[`trailing_empty_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#trailing_empty_array -[`trait_duplication_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#trait_duplication_in_bounds -[`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str -[`transmute_float_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_float_to_int -[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool -[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char -[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float -[`transmute_int_to_non_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_non_zero -[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn -[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes -[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr -[`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref -[`transmute_undefined_repr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_undefined_repr -[`transmutes_expressible_as_ptr_casts`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmutes_expressible_as_ptr_casts -[`transmuting_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmuting_null -[`trim_split_whitespace`]: https://rust-lang.github.io/rust-clippy/master/index.html#trim_split_whitespace -[`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex -[`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref -[`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err -[`tuple_array_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions -[`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity -[`type_id_on_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_id_on_box -[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds -[`unbuffered_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#unbuffered_bytes -[`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction -[`unchecked_time_subtraction`]: https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_time_subtraction -[`unconditional_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#unconditional_recursion -[`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks -[`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/master/index.html#undropped_manually_drops -[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc -[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented -[`uninhabited_references`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninhabited_references -[`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init -[`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec -[`uninlined_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args -[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg -[`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp -[`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash -[`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord -[`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints -[`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns -[`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast -[`unnecessary_clippy_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_clippy_cfg -[`unnecessary_debug_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_debug_formatting -[`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions -[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map -[`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map -[`unnecessary_first_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_first_then_check -[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold -[`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_get_then_check -[`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join -[`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations -[`unnecessary_literal_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_bound -[`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap -[`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_on_constructor -[`unnecessary_map_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_or -[`unnecessary_min_or_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_min_or_max -[`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_option_map_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_option_map_or_else -[`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings -[`unnecessary_rest_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_rest_pattern -[`unnecessary_result_map_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_result_map_or_else -[`unnecessary_safety_comment`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_comment -[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc -[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports -[`unnecessary_semicolon`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_semicolon -[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by -[`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_struct_initialization -[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned -[`unnecessary_trailing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_trailing_comma -[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap -[`unnecessary_unwrap_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap_unchecked -[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps -[`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern -[`unneeded_struct_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_struct_pattern -[`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern -[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns -[`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable -[`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal -[`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize -[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name -[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization -[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix -[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute -[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice -[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice -[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async -[`unused_async_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async_trait_impl -[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect -[`unused_enumerate_index`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_enumerate_index -[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs -[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount -[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label -[`unused_peekable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_peekable -[`unused_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_result_ok -[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding -[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self -[`unused_trait_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names -[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit -[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings -[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result -[`unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_default -[`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default -[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used -[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms -[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug -[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self -[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding -[`used_underscore_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items -[`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_borrows_in_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_borrows_in_formatting -[`useless_concat`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_concat -[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion -[`useless_format`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_format -[`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_let_if_seq -[`useless_nonzero_new_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_nonzero_new_unchecked -[`useless_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_transmute -[`useless_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec -[`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box -[`vec_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_init_then_push -[`vec_resize_to_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_resize_to_zero -[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask -[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads -[`volatile_composites`]: https://rust-lang.github.io/rust-clippy/master/index.html#volatile_composites -[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons -[`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/master/index.html#waker_clone_wake -[`while_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_float -[`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 -[`with_capacity_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#with_capacity_zero -[`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_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects -[`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values -[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space -[`zombie_processes`]: https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes -[`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset +[`absolute_paths`]: https://rust-lang.github.io/rust-clippy/main/index.html#absolute_paths +[`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#absurd_extreme_comparisons +[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/main/index.html#alloc_instead_of_core +[`allow_attributes`]: https://rust-lang.github.io/rust-clippy/main/index.html#allow_attributes +[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/main/index.html#allow_attributes_without_reason +[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/main/index.html#almost_complete_letter_range +[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/main/index.html#almost_complete_range +[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/main/index.html#almost_swapped +[`approx_constant`]: https://rust-lang.github.io/rust-clippy/main/index.html#approx_constant +[`arbitrary_source_item_ordering`]: https://rust-lang.github.io/rust-clippy/main/index.html#arbitrary_source_item_ordering +[`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/main/index.html#arc_with_non_send_sync +[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/main/index.html#arithmetic_side_effects +[`as_conversions`]: https://rust-lang.github.io/rust-clippy/main/index.html#as_conversions +[`as_pointer_underscore`]: https://rust-lang.github.io/rust-clippy/main/index.html#as_pointer_underscore +[`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/main/index.html#as_ptr_cast_mut +[`as_underscore`]: https://rust-lang.github.io/rust-clippy/main/index.html#as_underscore +[`assert_is_empty`]: https://rust-lang.github.io/rust-clippy/main/index.html#assert_is_empty +[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/main/index.html#assertions_on_constants +[`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/main/index.html#assertions_on_result_states +[`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#assign_op_pattern +[`assign_ops`]: https://rust-lang.github.io/rust-clippy/main/index.html#assign_ops +[`assigning_clones`]: https://rust-lang.github.io/rust-clippy/main/index.html#assigning_clones +[`async_yields_async`]: https://rust-lang.github.io/rust-clippy/main/index.html#async_yields_async +[`await_holding_invalid_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#await_holding_invalid_type +[`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/main/index.html#await_holding_lock +[`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#await_holding_refcell_ref +[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/main/index.html#bad_bit_mask +[`big_endian_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#big_endian_bytes +[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#bind_instead_of_map +[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/main/index.html#blacklisted_name +[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/main/index.html#blanket_clippy_restriction_lints +[`block_in_if_condition_expr`]: https://rust-lang.github.io/rust-clippy/main/index.html#block_in_if_condition_expr +[`block_in_if_condition_stmt`]: https://rust-lang.github.io/rust-clippy/main/index.html#block_in_if_condition_stmt +[`block_scrutinee`]: https://rust-lang.github.io/rust-clippy/main/index.html#block_scrutinee +[`blocks_in_conditions`]: https://rust-lang.github.io/rust-clippy/main/index.html#blocks_in_conditions +[`blocks_in_if_conditions`]: https://rust-lang.github.io/rust-clippy/main/index.html#blocks_in_if_conditions +[`bool_assert_comparison`]: https://rust-lang.github.io/rust-clippy/main/index.html#bool_assert_comparison +[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/main/index.html#bool_comparison +[`bool_to_int_with_if`]: https://rust-lang.github.io/rust-clippy/main/index.html#bool_to_int_with_if +[`borrow_as_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#borrow_as_ptr +[`borrow_deref_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#borrow_deref_ref +[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/main/index.html#borrow_interior_mutable_const +[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/main/index.html#borrowed_box +[`box_collection`]: https://rust-lang.github.io/rust-clippy/main/index.html#box_collection +[`box_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#box_default +[`box_vec`]: https://rust-lang.github.io/rust-clippy/main/index.html#box_vec +[`boxed_local`]: https://rust-lang.github.io/rust-clippy/main/index.html#boxed_local +[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/main/index.html#branches_sharing_code +[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/main/index.html#builtin_type_shadow +[`by_ref_peekable_peek`]: https://rust-lang.github.io/rust-clippy/main/index.html#by_ref_peekable_peek +[`byte_char_slices`]: https://rust-lang.github.io/rust-clippy/main/index.html#byte_char_slices +[`bytes_count_to_len`]: https://rust-lang.github.io/rust-clippy/main/index.html#bytes_count_to_len +[`bytes_nth`]: https://rust-lang.github.io/rust-clippy/main/index.html#bytes_nth +[`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/main/index.html#cargo_common_metadata +[`case_sensitive_file_extension_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#case_sensitive_file_extension_comparisons +[`cast_abs_to_unsigned`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_abs_to_unsigned +[`cast_enum_constructor`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_enum_constructor +[`cast_enum_truncation`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_enum_truncation +[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_lossless +[`cast_nan_to_int`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_nan_to_int +[`cast_possible_truncation`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_possible_truncation +[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_possible_wrap +[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_precision_loss +[`cast_ptr_alignment`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_ptr_alignment +[`cast_ref_to_mut`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_ref_to_mut +[`cast_sign_loss`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_sign_loss +[`cast_slice_different_sizes`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_slice_different_sizes +[`cast_slice_from_raw_parts`]: https://rust-lang.github.io/rust-clippy/main/index.html#cast_slice_from_raw_parts +[`cfg_not_test`]: https://rust-lang.github.io/rust-clippy/main/index.html#cfg_not_test +[`char_indices_as_byte_indices`]: https://rust-lang.github.io/rust-clippy/main/index.html#char_indices_as_byte_indices +[`char_lit_as_u8`]: https://rust-lang.github.io/rust-clippy/main/index.html#char_lit_as_u8 +[`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/main/index.html#chars_last_cmp +[`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/main/index.html#chars_next_cmp +[`checked_conversions`]: https://rust-lang.github.io/rust-clippy/main/index.html#checked_conversions +[`chunks_exact_to_as_chunks`]: https://rust-lang.github.io/rust-clippy/main/index.html#chunks_exact_to_as_chunks +[`clear_with_drain`]: https://rust-lang.github.io/rust-clippy/main/index.html#clear_with_drain +[`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#clone_double_ref +[`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/main/index.html#clone_on_copy +[`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#clone_on_ref_ptr +[`cloned_instead_of_copied`]: https://rust-lang.github.io/rust-clippy/main/index.html#cloned_instead_of_copied +[`cloned_ref_to_slice_refs`]: https://rust-lang.github.io/rust-clippy/main/index.html#cloned_ref_to_slice_refs +[`cmp_nan`]: https://rust-lang.github.io/rust-clippy/main/index.html#cmp_nan +[`cmp_null`]: https://rust-lang.github.io/rust-clippy/main/index.html#cmp_null +[`cmp_owned`]: https://rust-lang.github.io/rust-clippy/main/index.html#cmp_owned +[`coerce_container_to_any`]: https://rust-lang.github.io/rust-clippy/main/index.html#coerce_container_to_any +[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/main/index.html#cognitive_complexity +[`collapsible_else_if`]: https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_else_if +[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_if +[`collapsible_match`]: https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_match +[`collapsible_str_replace`]: https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_str_replace +[`collection_is_never_read`]: https://rust-lang.github.io/rust-clippy/main/index.html#collection_is_never_read +[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/main/index.html#comparison_chain +[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/main/index.html#comparison_to_empty +[`confusing_method_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/main/index.html#confusing_method_to_numeric_cast +[`const_is_empty`]: https://rust-lang.github.io/rust-clippy/main/index.html#const_is_empty +[`const_static_lifetime`]: https://rust-lang.github.io/rust-clippy/main/index.html#const_static_lifetime +[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/main/index.html#copy_iterator +[`crate_in_macro_def`]: https://rust-lang.github.io/rust-clippy/main/index.html#crate_in_macro_def +[`create_dir`]: https://rust-lang.github.io/rust-clippy/main/index.html#create_dir +[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/main/index.html#crosspointer_transmute +[`cyclomatic_complexity`]: https://rust-lang.github.io/rust-clippy/main/index.html#cyclomatic_complexity +[`dbg_macro`]: https://rust-lang.github.io/rust-clippy/main/index.html#dbg_macro +[`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/main/index.html#debug_assert_with_mut_call +[`decimal_bitwise_operands`]: https://rust-lang.github.io/rust-clippy/main/index.html#decimal_bitwise_operands +[`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/main/index.html#decimal_literal_representation +[`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/main/index.html#declare_interior_mutable_const +[`default_constructed_unit_structs`]: https://rust-lang.github.io/rust-clippy/main/index.html#default_constructed_unit_structs +[`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/main/index.html#default_instead_of_iter_empty +[`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/main/index.html#default_numeric_fallback +[`default_trait_access`]: https://rust-lang.github.io/rust-clippy/main/index.html#default_trait_access +[`default_union_representation`]: https://rust-lang.github.io/rust-clippy/main/index.html#default_union_representation +[`definition_in_module_root`]: https://rust-lang.github.io/rust-clippy/main/index.html#definition_in_module_root +[`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/main/index.html#deprecated_cfg_attr +[`deprecated_clippy_cfg_attr`]: https://rust-lang.github.io/rust-clippy/main/index.html#deprecated_clippy_cfg_attr +[`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/main/index.html#deprecated_semver +[`deref_addrof`]: https://rust-lang.github.io/rust-clippy/main/index.html#deref_addrof +[`deref_by_slicing`]: https://rust-lang.github.io/rust-clippy/main/index.html#deref_by_slicing +[`derivable_impls`]: https://rust-lang.github.io/rust-clippy/main/index.html#derivable_impls +[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/main/index.html#derive_hash_xor_eq +[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/main/index.html#derive_ord_xor_partial_ord +[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/main/index.html#derive_partial_eq_without_eq +[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/main/index.html#derived_hash_with_manual_eq +[`disallowed_fields`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_fields +[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_macros +[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_method +[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_methods +[`disallowed_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_names +[`disallowed_script_idents`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_script_idents +[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_type +[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_types +[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/main/index.html#diverging_sub_expression +[`doc_broken_link`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_broken_link +[`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_comment_double_space_linebreaks +[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_include_without_cfg +[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_lazy_continuation +[`doc_link_code`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_link_code +[`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_link_with_quotes +[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_markdown +[`doc_nested_refdefs`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_nested_refdefs +[`doc_overindented_list_items`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_overindented_list_items +[`doc_paragraphs_missing_punctuation`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_paragraphs_missing_punctuation +[`doc_suspicious_footnotes`]: https://rust-lang.github.io/rust-clippy/main/index.html#doc_suspicious_footnotes +[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#double_comparisons +[`double_ended_iterator_last`]: https://rust-lang.github.io/rust-clippy/main/index.html#double_ended_iterator_last +[`double_must_use`]: https://rust-lang.github.io/rust-clippy/main/index.html#double_must_use +[`double_neg`]: https://rust-lang.github.io/rust-clippy/main/index.html#double_neg +[`double_parens`]: https://rust-lang.github.io/rust-clippy/main/index.html#double_parens +[`drain_collect`]: https://rust-lang.github.io/rust-clippy/main/index.html#drain_collect +[`drop_bounds`]: https://rust-lang.github.io/rust-clippy/main/index.html#drop_bounds +[`drop_copy`]: https://rust-lang.github.io/rust-clippy/main/index.html#drop_copy +[`drop_non_drop`]: https://rust-lang.github.io/rust-clippy/main/index.html#drop_non_drop +[`drop_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#drop_ref +[`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/main/index.html#duplicate_mod +[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/main/index.html#duplicate_underscore_argument +[`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/main/index.html#duplicated_attributes +[`duration_suboptimal_units`]: https://rust-lang.github.io/rust-clippy/main/index.html#duration_suboptimal_units +[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/main/index.html#duration_subsec +[`eager_transmute`]: https://rust-lang.github.io/rust-clippy/main/index.html#eager_transmute +[`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#elidable_lifetime_names +[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#else_if_without_else +[`empty_docs`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_docs +[`empty_drop`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_drop +[`empty_enum`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_enum +[`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_enum_variants_with_brackets +[`empty_enums`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_enums +[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_line_after_doc_comments +[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_line_after_outer_attr +[`empty_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_loop +[`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/main/index.html#empty_structs_with_brackets +[`enum_clike_unportable_variant`]: https://rust-lang.github.io/rust-clippy/main/index.html#enum_clike_unportable_variant +[`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/main/index.html#enum_glob_use +[`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#enum_variant_names +[`eq_op`]: https://rust-lang.github.io/rust-clippy/main/index.html#eq_op +[`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/main/index.html#equatable_if_let +[`erasing_op`]: https://rust-lang.github.io/rust-clippy/main/index.html#erasing_op +[`err_expect`]: https://rust-lang.github.io/rust-clippy/main/index.html#err_expect +[`error_impl_error`]: https://rust-lang.github.io/rust-clippy/main/index.html#error_impl_error +[`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/main/index.html#eval_order_dependence +[`excessive_nesting`]: https://rust-lang.github.io/rust-clippy/main/index.html#excessive_nesting +[`excessive_precision`]: https://rust-lang.github.io/rust-clippy/main/index.html#excessive_precision +[`exhaustive_enums`]: https://rust-lang.github.io/rust-clippy/main/index.html#exhaustive_enums +[`exhaustive_structs`]: https://rust-lang.github.io/rust-clippy/main/index.html#exhaustive_structs +[`exit`]: https://rust-lang.github.io/rust-clippy/main/index.html#exit +[`expect_fun_call`]: https://rust-lang.github.io/rust-clippy/main/index.html#expect_fun_call +[`expect_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#expect_used +[`expl_impl_clone_on_copy`]: https://rust-lang.github.io/rust-clippy/main/index.html#expl_impl_clone_on_copy +[`explicit_auto_deref`]: https://rust-lang.github.io/rust-clippy/main/index.html#explicit_auto_deref +[`explicit_counter_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#explicit_counter_loop +[`explicit_deref_methods`]: https://rust-lang.github.io/rust-clippy/main/index.html#explicit_deref_methods +[`explicit_into_iter_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#explicit_into_iter_loop +[`explicit_iter_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#explicit_iter_loop +[`explicit_write`]: https://rust-lang.github.io/rust-clippy/main/index.html#explicit_write +[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#extend_from_slice +[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/main/index.html#extend_with_drain +[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/main/index.html#extra_unused_lifetimes +[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/main/index.html#extra_unused_type_parameters +[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/main/index.html#fallible_impl_from +[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#field_reassign_with_default +[`field_scoped_visibility_modifiers`]: https://rust-lang.github.io/rust-clippy/main/index.html#field_scoped_visibility_modifiers +[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/main/index.html#filetype_is_file +[`filter_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#filter_map +[`filter_map_bool_then`]: https://rust-lang.github.io/rust-clippy/main/index.html#filter_map_bool_then +[`filter_map_identity`]: https://rust-lang.github.io/rust-clippy/main/index.html#filter_map_identity +[`filter_map_next`]: https://rust-lang.github.io/rust-clippy/main/index.html#filter_map_next +[`filter_next`]: https://rust-lang.github.io/rust-clippy/main/index.html#filter_next +[`find_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#find_map +[`flat_map_identity`]: https://rust-lang.github.io/rust-clippy/main/index.html#flat_map_identity +[`flat_map_option`]: https://rust-lang.github.io/rust-clippy/main/index.html#flat_map_option +[`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/main/index.html#float_arithmetic +[`float_cmp`]: https://rust-lang.github.io/rust-clippy/main/index.html#float_cmp +[`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/main/index.html#float_cmp_const +[`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/main/index.html#float_equality_without_abs +[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#fn_address_comparisons +[`fn_null_check`]: https://rust-lang.github.io/rust-clippy/main/index.html#fn_null_check +[`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/main/index.html#fn_params_excessive_bools +[`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/main/index.html#fn_to_numeric_cast +[`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/main/index.html#fn_to_numeric_cast_any +[`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/main/index.html#fn_to_numeric_cast_with_truncation +[`for_kv_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#for_kv_map +[`for_loop_over_option`]: https://rust-lang.github.io/rust-clippy/main/index.html#for_loop_over_option +[`for_loop_over_result`]: https://rust-lang.github.io/rust-clippy/main/index.html#for_loop_over_result +[`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/main/index.html#for_loops_over_fallibles +[`for_unbounded_range`]: https://rust-lang.github.io/rust-clippy/main/index.html#for_unbounded_range +[`forget_copy`]: https://rust-lang.github.io/rust-clippy/main/index.html#forget_copy +[`forget_non_drop`]: https://rust-lang.github.io/rust-clippy/main/index.html#forget_non_drop +[`forget_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#forget_ref +[`format_collect`]: https://rust-lang.github.io/rust-clippy/main/index.html#format_collect +[`format_in_format_args`]: https://rust-lang.github.io/rust-clippy/main/index.html#format_in_format_args +[`format_push_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#format_push_string +[`four_forward_slashes`]: https://rust-lang.github.io/rust-clippy/main/index.html#four_forward_slashes +[`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/main/index.html#from_iter_instead_of_collect +[`from_over_into`]: https://rust-lang.github.io/rust-clippy/main/index.html#from_over_into +[`from_raw_with_void_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#from_raw_with_void_ptr +[`from_str_radix_10`]: https://rust-lang.github.io/rust-clippy/main/index.html#from_str_radix_10 +[`future_not_send`]: https://rust-lang.github.io/rust-clippy/main/index.html#future_not_send +[`get_first`]: https://rust-lang.github.io/rust-clippy/main/index.html#get_first +[`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/main/index.html#get_last_with_len +[`get_unwrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#get_unwrap +[`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#host_endian_bytes +[`identity_conversion`]: https://rust-lang.github.io/rust-clippy/main/index.html#identity_conversion +[`identity_op`]: https://rust-lang.github.io/rust-clippy/main/index.html#identity_op +[`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/main/index.html#if_let_mutex +[`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/main/index.html#if_let_redundant_pattern_matching +[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/main/index.html#if_let_some_result +[`if_not_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#if_not_else +[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#if_same_then_else +[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/main/index.html#if_then_some_else_none +[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/main/index.html#ifs_same_cond +[`ignore_without_reason`]: https://rust-lang.github.io/rust-clippy/main/index.html#ignore_without_reason +[`ignored_unit_patterns`]: https://rust-lang.github.io/rust-clippy/main/index.html#ignored_unit_patterns +[`impl_hash_borrow_with_str_and_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#impl_hash_borrow_with_str_and_bytes +[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/main/index.html#impl_trait_in_params +[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/main/index.html#implicit_clone +[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/main/index.html#implicit_hasher +[`implicit_return`]: https://rust-lang.github.io/rust-clippy/main/index.html#implicit_return +[`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/main/index.html#implicit_saturating_add +[`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/main/index.html#implicit_saturating_sub +[`implied_bounds_in_impls`]: https://rust-lang.github.io/rust-clippy/main/index.html#implied_bounds_in_impls +[`impossible_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#impossible_comparisons +[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/main/index.html#imprecise_flops +[`incompatible_msrv`]: https://rust-lang.github.io/rust-clippy/main/index.html#incompatible_msrv +[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/main/index.html#inconsistent_digit_grouping +[`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/main/index.html#inconsistent_struct_constructor +[`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#incorrect_clone_impl_on_copy_type +[`incorrect_partial_ord_impl_on_ord_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#incorrect_partial_ord_impl_on_ord_type +[`index_refutable_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#index_refutable_slice +[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/main/index.html#indexing_slicing +[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/main/index.html#ineffective_bit_mask +[`ineffective_open_options`]: https://rust-lang.github.io/rust-clippy/main/index.html#ineffective_open_options +[`inefficient_to_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#inefficient_to_string +[`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/main/index.html#infallible_destructuring_match +[`infallible_try_from`]: https://rust-lang.github.io/rust-clippy/main/index.html#infallible_try_from +[`infinite_iter`]: https://rust-lang.github.io/rust-clippy/main/index.html#infinite_iter +[`infinite_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#infinite_loop +[`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#inherent_to_string +[`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/main/index.html#inherent_to_string_shadow_display +[`init_numbered_fields`]: https://rust-lang.github.io/rust-clippy/main/index.html#init_numbered_fields +[`inline_always`]: https://rust-lang.github.io/rust-clippy/main/index.html#inline_always +[`inline_asm_x86_att_syntax`]: https://rust-lang.github.io/rust-clippy/main/index.html#inline_asm_x86_att_syntax +[`inline_asm_x86_intel_syntax`]: https://rust-lang.github.io/rust-clippy/main/index.html#inline_asm_x86_intel_syntax +[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/main/index.html#inline_fn_without_body +[`inline_modules`]: https://rust-lang.github.io/rust-clippy/main/index.html#inline_modules +[`inline_trait_bounds`]: https://rust-lang.github.io/rust-clippy/main/index.html#inline_trait_bounds +[`inspect_for_each`]: https://rust-lang.github.io/rust-clippy/main/index.html#inspect_for_each +[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/main/index.html#int_plus_one +[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/main/index.html#integer_arithmetic +[`integer_division`]: https://rust-lang.github.io/rust-clippy/main/index.html#integer_division +[`integer_division_remainder_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#integer_division_remainder_used +[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/main/index.html#into_iter_on_array +[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#into_iter_on_ref +[`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/main/index.html#into_iter_without_iter +[`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/main/index.html#invalid_atomic_ordering +[`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/main/index.html#invalid_null_ptr_usage +[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#invalid_ref +[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/main/index.html#invalid_regex +[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#invalid_upcast_comparisons +[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/main/index.html#invalid_utf8_in_unchecked +[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/main/index.html#inverted_saturating_sub +[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/main/index.html#invisible_characters +[`io_other_error`]: https://rust-lang.github.io/rust-clippy/main/index.html#io_other_error +[`ip_constant`]: https://rust-lang.github.io/rust-clippy/main/index.html#ip_constant +[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/main/index.html#is_digit_ascii_radix +[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/main/index.html#items_after_statements +[`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/main/index.html#items_after_test_module +[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_cloned_collect +[`iter_count`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_count +[`iter_filter_is_ok`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_filter_is_ok +[`iter_filter_is_some`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_filter_is_some +[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_kv_map +[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_next_loop +[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_next_slice +[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_not_returning_iterator +[`iter_nth`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_nth +[`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_nth_zero +[`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_on_empty_collections +[`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_on_single_items +[`iter_out_of_bounds`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_out_of_bounds +[`iter_over_hash_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_over_hash_type +[`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_overeager_cloned +[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_skip_next +[`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_skip_zero +[`iter_with_drain`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_with_drain +[`iter_without_into_iter`]: https://rust-lang.github.io/rust-clippy/main/index.html#iter_without_into_iter +[`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#iterator_step_by_zero +[`join_absolute_paths`]: https://rust-lang.github.io/rust-clippy/main/index.html#join_absolute_paths +[`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/main/index.html#just_underscores_and_digits +[`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_const_arrays +[`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_digit_groups +[`large_enum_variant`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_enum_variant +[`large_futures`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_futures +[`large_include_file`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_include_file +[`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_stack_arrays +[`large_stack_frames`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_stack_frames +[`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/main/index.html#large_types_passed_by_value +[`legacy_numeric_constants`]: https://rust-lang.github.io/rust-clippy/main/index.html#legacy_numeric_constants +[`len_without_is_empty`]: https://rust-lang.github.io/rust-clippy/main/index.html#len_without_is_empty +[`len_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#len_zero +[`let_and_return`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_and_return +[`let_underscore_drop`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_underscore_drop +[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_underscore_future +[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_underscore_lock +[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_underscore_must_use +[`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_underscore_untyped +[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_unit_value +[`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/main/index.html#let_with_type_underscore +[`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/main/index.html#lines_filter_map_ok +[`linkedlist`]: https://rust-lang.github.io/rust-clippy/main/index.html#linkedlist +[`lint_groups_priority`]: https://rust-lang.github.io/rust-clippy/main/index.html#lint_groups_priority +[`literal_string_with_formatting_args`]: https://rust-lang.github.io/rust-clippy/main/index.html#literal_string_with_formatting_args +[`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#little_endian_bytes +[`logic_bug`]: https://rust-lang.github.io/rust-clippy/main/index.html#logic_bug +[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#lossy_float_literal +[`macro_metavars_in_unsafe`]: https://rust-lang.github.io/rust-clippy/main/index.html#macro_metavars_in_unsafe +[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/main/index.html#macro_use_imports +[`main_recursion`]: https://rust-lang.github.io/rust-clippy/main/index.html#main_recursion +[`manual_abs_diff`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_abs_diff +[`manual_assert`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_assert +[`manual_assert_eq`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_assert_eq +[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_async_fn +[`manual_bit_width`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_bit_width +[`manual_bits`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_bits +[`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_c_str_literals +[`manual_checked_ops`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_checked_ops +[`manual_clamp`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_clamp +[`manual_clear`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_clear +[`manual_contains`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_contains +[`manual_dangling_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_dangling_ptr +[`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_div_ceil +[`manual_filter`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_filter +[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_filter_map +[`manual_find`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_find +[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_find_map +[`manual_flatten`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_flatten +[`manual_hash_one`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_hash_one +[`manual_ignore_case_cmp`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_ignore_case_cmp +[`manual_ilog2`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_ilog2 +[`manual_inspect`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_inspect +[`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_instant_elapsed +[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_ascii_check +[`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_finite +[`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_infinite +[`manual_is_multiple_of`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_multiple_of +[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_power_of_two +[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_variant_and +[`manual_isolate_lowest_one`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_isolate_lowest_one +[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_let_else +[`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_main_separator_str +[`manual_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_map +[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_memcpy +[`manual_midpoint`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_midpoint +[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_next_back +[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_non_exhaustive +[`manual_noop_waker`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_noop_waker +[`manual_ok_err`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_ok_err +[`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_ok_or +[`manual_option_as_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_option_as_slice +[`manual_option_zip`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_option_zip +[`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_pattern_char_comparison +[`manual_pop_if`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_pop_if +[`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_range_contains +[`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_range_patterns +[`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_rem_euclid +[`manual_repeat_n`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_repeat_n +[`manual_retain`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_retain +[`manual_rotate`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_rotate +[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_saturating_arithmetic +[`manual_slice_fill`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_slice_fill +[`manual_slice_size_calculation`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_slice_size_calculation +[`manual_split_once`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_split_once +[`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_str_repeat +[`manual_string_new`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_string_new +[`manual_strip`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_strip +[`manual_swap`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_swap +[`manual_take`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_take +[`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_try_fold +[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_unwrap_or +[`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_unwrap_or_default +[`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/main/index.html#manual_while_let_some +[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#many_single_char_names +[`map_all_any_identity`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_all_any_identity +[`map_clone`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_clone +[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_collect_result_unit +[`map_entry`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_entry +[`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_err_ignore +[`map_flatten`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_flatten +[`map_identity`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_identity +[`map_or_identity`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_or_identity +[`map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_unwrap_or +[`map_with_unused_argument_over_ranges`]: https://rust-lang.github.io/rust-clippy/main/index.html#map_with_unused_argument_over_ranges +[`match_as_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_as_ref +[`match_bool`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_bool +[`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_like_matches_macro +[`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_on_vec_items +[`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_overlapping_arm +[`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_ref_pats +[`match_result_ok`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_result_ok +[`match_same_arms`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_same_arms +[`match_single_binding`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_single_binding +[`match_str_case_mismatch`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_str_case_mismatch +[`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_wild_err_arm +[`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/main/index.html#match_wildcard_for_single_variants +[`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/main/index.html#maybe_infinite_iter +[`maybe_misused_cfg`]: https://rust-lang.github.io/rust-clippy/main/index.html#maybe_misused_cfg +[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/main/index.html#mem_discriminant_non_enum +[`mem_forget`]: https://rust-lang.github.io/rust-clippy/main/index.html#mem_forget +[`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/main/index.html#mem_replace_option_with_none +[`mem_replace_option_with_some`]: https://rust-lang.github.io/rust-clippy/main/index.html#mem_replace_option_with_some +[`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#mem_replace_with_default +[`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/main/index.html#mem_replace_with_uninit +[`min_ident_chars`]: https://rust-lang.github.io/rust-clippy/main/index.html#min_ident_chars +[`min_max`]: https://rust-lang.github.io/rust-clippy/main/index.html#min_max +[`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/main/index.html#misaligned_transmute +[`mismatched_bit_width_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#mismatched_bit_width_type +[`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/main/index.html#mismatched_target_os +[`mismatching_type_param_order`]: https://rust-lang.github.io/rust-clippy/main/index.html#mismatching_type_param_order +[`misnamed_getters`]: https://rust-lang.github.io/rust-clippy/main/index.html#misnamed_getters +[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/main/index.html#misrefactored_assign_op +[`missing_assert_message`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_assert_message +[`missing_asserts_for_indexing`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_asserts_for_indexing +[`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_const_for_fn +[`missing_const_for_thread_local`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_const_for_thread_local +[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_docs_in_private_items +[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_enforced_import_renames +[`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_errors_doc +[`missing_fields_in_debug`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_fields_in_debug +[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_inline_in_public_items +[`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_panics_doc +[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_safety_doc +[`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_spin_loop +[`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_trait_methods +[`missing_transmute_annotations`]: https://rust-lang.github.io/rust-clippy/main/index.html#missing_transmute_annotations +[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/main/index.html#mistyped_literal_suffixes +[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/main/index.html#mixed_attributes_style +[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/main/index.html#mixed_case_hex_literals +[`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/main/index.html#mixed_read_write_in_expression +[`mod_module_files`]: https://rust-lang.github.io/rust-clippy/main/index.html#mod_module_files +[`module_inception`]: https://rust-lang.github.io/rust-clippy/main/index.html#module_inception +[`module_name_repetitions`]: https://rust-lang.github.io/rust-clippy/main/index.html#module_name_repetitions +[`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/main/index.html#modulo_arithmetic +[`modulo_one`]: https://rust-lang.github.io/rust-clippy/main/index.html#modulo_one +[`multi_assignments`]: https://rust-lang.github.io/rust-clippy/main/index.html#multi_assignments +[`multiple_bound_locations`]: https://rust-lang.github.io/rust-clippy/main/index.html#multiple_bound_locations +[`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/main/index.html#multiple_crate_versions +[`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#multiple_inherent_impl +[`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/main/index.html#multiple_unsafe_ops_per_block +[`must_use_candidate`]: https://rust-lang.github.io/rust-clippy/main/index.html#must_use_candidate +[`must_use_unit`]: https://rust-lang.github.io/rust-clippy/main/index.html#must_use_unit +[`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_from_ref +[`mut_mut`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_mut +[`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_mutex_lock +[`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_range_bound +[`mutable_key_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#mutable_key_type +[`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/main/index.html#mutex_atomic +[`mutex_integer`]: https://rust-lang.github.io/rust-clippy/main/index.html#mutex_integer +[`naive_bytecount`]: https://rust-lang.github.io/rust-clippy/main/index.html#naive_bytecount +[`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_arbitrary_self_type +[`needless_as_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_as_bytes +[`needless_bitwise_bool`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_bitwise_bool +[`needless_bool`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_bool +[`needless_bool_assign`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_bool_assign +[`needless_borrow`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_borrow +[`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_borrowed_reference +[`needless_borrows_for_generic_args`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_borrows_for_generic_args +[`needless_character_iteration`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_character_iteration +[`needless_collect`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_collect +[`needless_continue`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_continue +[`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_doctest_main +[`needless_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_else +[`needless_for_each`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_for_each +[`needless_if`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_if +[`needless_ifs`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_ifs +[`needless_late_init`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_late_init +[`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_lifetimes +[`needless_match`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_match +[`needless_maybe_sized`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_maybe_sized +[`needless_nonzero_get`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_nonzero_get +[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_option_as_deref +[`needless_option_take`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_option_take +[`needless_parens_on_range_literals`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_parens_on_range_literals +[`needless_pass_by_ref_mut`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_pass_by_ref_mut +[`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_pass_by_value +[`needless_pub_self`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_pub_self +[`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_question_mark +[`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_range_loop +[`needless_raw_string_hashes`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_raw_string_hashes +[`needless_raw_strings`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_raw_strings +[`needless_return`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_return +[`needless_return_with_question_mark`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_return_with_question_mark +[`needless_splitn`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_splitn +[`needless_type_cast`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_type_cast +[`needless_update`]: https://rust-lang.github.io/rust-clippy/main/index.html#needless_update +[`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/main/index.html#neg_cmp_op_on_partial_ord +[`neg_multiply`]: https://rust-lang.github.io/rust-clippy/main/index.html#neg_multiply +[`negative_feature_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#negative_feature_names +[`never_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#never_loop +[`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/main/index.html#new_ret_no_self +[`new_without_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#new_without_default +[`new_without_default_derive`]: https://rust-lang.github.io/rust-clippy/main/index.html#new_without_default_derive +[`no_effect`]: https://rust-lang.github.io/rust-clippy/main/index.html#no_effect +[`no_effect_replace`]: https://rust-lang.github.io/rust-clippy/main/index.html#no_effect_replace +[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/main/index.html#no_effect_underscore_binding +[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/main/index.html#no_mangle_with_rust_abi +[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_ascii_literal +[`non_canonical_clone_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_canonical_clone_impl +[`non_canonical_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_canonical_partial_ord_impl +[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_minimal_cfg +[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_octal_unix_permissions +[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_send_fields_in_send_ty +[`non_std_lazy_statics`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_std_lazy_statics +[`non_zero_suggestions`]: https://rust-lang.github.io/rust-clippy/main/index.html#non_zero_suggestions +[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/main/index.html#nonminimal_bool +[`nonnull_unchecked_on_box_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#nonnull_unchecked_on_box_ptr +[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/main/index.html#nonsensical_open_options +[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/main/index.html#nonstandard_macro_braces +[`not_unsafe_ptr_arg_deref`]: https://rust-lang.github.io/rust-clippy/main/index.html#not_unsafe_ptr_arg_deref +[`obfuscated_if_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#obfuscated_if_else +[`octal_escapes`]: https://rust-lang.github.io/rust-clippy/main/index.html#octal_escapes +[`ok_expect`]: https://rust-lang.github.io/rust-clippy/main/index.html#ok_expect +[`only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/main/index.html#only_used_in_recursion +[`op_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#op_ref +[`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_and_then_some +[`option_as_ref_cloned`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_as_ref_cloned +[`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_as_ref_deref +[`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_env_unwrap +[`option_expect_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_expect_used +[`option_filter_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_filter_map +[`option_if_let_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_if_let_else +[`option_map_or_err_ok`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_map_or_err_ok +[`option_map_or_none`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_map_or_none +[`option_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_map_unit_fn +[`option_map_unwrap_or`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_map_unwrap_or +[`option_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_map_unwrap_or_else +[`option_option`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_option +[`option_unwrap_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_unwrap_used +[`option_zip_none`]: https://rust-lang.github.io/rust-clippy/main/index.html#option_zip_none +[`or_fun_call`]: https://rust-lang.github.io/rust-clippy/main/index.html#or_fun_call +[`or_then_unwrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#or_then_unwrap +[`out_of_bounds_indexing`]: https://rust-lang.github.io/rust-clippy/main/index.html#out_of_bounds_indexing +[`overflow_check_conditional`]: https://rust-lang.github.io/rust-clippy/main/index.html#overflow_check_conditional +[`overly_complex_bool_expr`]: https://rust-lang.github.io/rust-clippy/main/index.html#overly_complex_bool_expr +[`owned_cow`]: https://rust-lang.github.io/rust-clippy/main/index.html#owned_cow +[`panic`]: https://rust-lang.github.io/rust-clippy/main/index.html#panic +[`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#panic_in_result_fn +[`panic_params`]: https://rust-lang.github.io/rust-clippy/main/index.html#panic_params +[`panicking_overflow_checks`]: https://rust-lang.github.io/rust-clippy/main/index.html#panicking_overflow_checks +[`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#panicking_unwrap +[`partial_pub_fields`]: https://rust-lang.github.io/rust-clippy/main/index.html#partial_pub_fields +[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#partialeq_ne_impl +[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/main/index.html#partialeq_to_none +[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/main/index.html#path_buf_push_overwrite +[`path_ends_with_ext`]: https://rust-lang.github.io/rust-clippy/main/index.html#path_ends_with_ext +[`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/main/index.html#pathbuf_init_then_push +[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/main/index.html#pattern_type_mismatch +[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/main/index.html#permissions_set_readonly_false +[`pointer_format`]: https://rust-lang.github.io/rust-clippy/main/index.html#pointer_format +[`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/main/index.html#pointers_in_nomem_asm_block +[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/main/index.html#positional_named_format_parameters +[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/main/index.html#possible_missing_comma +[`possible_missing_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#possible_missing_else +[`precedence`]: https://rust-lang.github.io/rust-clippy/main/index.html#precedence +[`precedence_bits`]: https://rust-lang.github.io/rust-clippy/main/index.html#precedence_bits +[`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#print_in_format_impl +[`print_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#print_literal +[`print_stderr`]: https://rust-lang.github.io/rust-clippy/main/index.html#print_stderr +[`print_stdout`]: https://rust-lang.github.io/rust-clippy/main/index.html#print_stdout +[`print_with_newline`]: https://rust-lang.github.io/rust-clippy/main/index.html#print_with_newline +[`println_empty_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#println_empty_string +[`ptr_arg`]: https://rust-lang.github.io/rust-clippy/main/index.html#ptr_arg +[`ptr_as_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#ptr_as_ptr +[`ptr_cast_constness`]: https://rust-lang.github.io/rust-clippy/main/index.html#ptr_cast_constness +[`ptr_eq`]: https://rust-lang.github.io/rust-clippy/main/index.html#ptr_eq +[`ptr_offset_by_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#ptr_offset_by_literal +[`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/main/index.html#ptr_offset_with_cast +[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#pub_enum_variant_names +[`pub_underscore_fields`]: https://rust-lang.github.io/rust-clippy/main/index.html#pub_underscore_fields +[`pub_use`]: https://rust-lang.github.io/rust-clippy/main/index.html#pub_use +[`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/main/index.html#pub_with_shorthand +[`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/main/index.html#pub_without_shorthand +[`question_mark`]: https://rust-lang.github.io/rust-clippy/main/index.html#question_mark +[`question_mark_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#question_mark_used +[`range_minus_one`]: https://rust-lang.github.io/rust-clippy/main/index.html#range_minus_one +[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/main/index.html#range_plus_one +[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#range_step_by_zero +[`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/main/index.html#range_zip_with_len +[`rc_buffer`]: https://rust-lang.github.io/rust-clippy/main/index.html#rc_buffer +[`rc_clone_in_vec_init`]: https://rust-lang.github.io/rust-clippy/main/index.html#rc_clone_in_vec_init +[`rc_mutex`]: https://rust-lang.github.io/rust-clippy/main/index.html#rc_mutex +[`read_line_without_trim`]: https://rust-lang.github.io/rust-clippy/main/index.html#read_line_without_trim +[`read_zero_byte_vec`]: https://rust-lang.github.io/rust-clippy/main/index.html#read_zero_byte_vec +[`readonly_write_lock`]: https://rust-lang.github.io/rust-clippy/main/index.html#readonly_write_lock +[`recursive_format_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#recursive_format_impl +[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_allocation +[`redundant_as_str`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_as_str +[`redundant_async_block`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_async_block +[`redundant_at_rest_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_at_rest_pattern +[`redundant_clone`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_clone +[`redundant_closure`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_closure +[`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_closure_call +[`redundant_closure_for_method_calls`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_closure_for_method_calls +[`redundant_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_comparisons +[`redundant_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_else +[`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_feature_names +[`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_field_names +[`redundant_guards`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_guards +[`redundant_iter_cloned`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_iter_cloned +[`redundant_locals`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_locals +[`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_pattern +[`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_pattern_matching +[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_pub_crate +[`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_slicing +[`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_static_lifetimes +[`redundant_test_prefix`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_test_prefix +[`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/main/index.html#redundant_type_annotations +[`ref_as_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#ref_as_ptr +[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/main/index.html#ref_binding_to_reference +[`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/main/index.html#ref_in_deref +[`ref_option`]: https://rust-lang.github.io/rust-clippy/main/index.html#ref_option +[`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#ref_option_ref +[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/main/index.html#ref_patterns +[`regex_creation_in_loops`]: https://rust-lang.github.io/rust-clippy/main/index.html#regex_creation_in_loops +[`regex_macro`]: https://rust-lang.github.io/rust-clippy/main/index.html#regex_macro +[`renamed_function_params`]: https://rust-lang.github.io/rust-clippy/main/index.html#renamed_function_params +[`repeat_once`]: https://rust-lang.github.io/rust-clippy/main/index.html#repeat_once +[`repeat_vec_with_capacity`]: https://rust-lang.github.io/rust-clippy/main/index.html#repeat_vec_with_capacity +[`replace_box`]: https://rust-lang.github.io/rust-clippy/main/index.html#replace_box +[`replace_consts`]: https://rust-lang.github.io/rust-clippy/main/index.html#replace_consts +[`repr_packed_without_abi`]: https://rust-lang.github.io/rust-clippy/main/index.html#repr_packed_without_abi +[`reserve_after_initialization`]: https://rust-lang.github.io/rust-clippy/main/index.html#reserve_after_initialization +[`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/main/index.html#rest_pat_in_fully_bound_structs +[`rest_pattern_accessible_field`]: https://rust-lang.github.io/rust-clippy/main/index.html#rest_pattern_accessible_field +[`result_expect_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_expect_used +[`result_filter_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_filter_map +[`result_large_err`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_large_err +[`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_map_or_into_option +[`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_map_unit_fn +[`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_map_unwrap_or_else +[`result_unit_err`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_unit_err +[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#result_unwrap_used +[`return_and_then`]: https://rust-lang.github.io/rust-clippy/main/index.html#return_and_then +[`return_self_not_must_use`]: https://rust-lang.github.io/rust-clippy/main/index.html#return_self_not_must_use +[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#reverse_range_loop +[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/main/index.html#reversed_empty_ranges +[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/main/index.html#same_functions_in_if_condition +[`same_item_push`]: https://rust-lang.github.io/rust-clippy/main/index.html#same_item_push +[`same_length_and_capacity`]: https://rust-lang.github.io/rust-clippy/main/index.html#same_length_and_capacity +[`same_name_method`]: https://rust-lang.github.io/rust-clippy/main/index.html#same_name_method +[`search_is_some`]: https://rust-lang.github.io/rust-clippy/main/index.html#search_is_some +[`seek_from_current`]: https://rust-lang.github.io/rust-clippy/main/index.html#seek_from_current +[`seek_to_start_instead_of_rewind`]: https://rust-lang.github.io/rust-clippy/main/index.html#seek_to_start_instead_of_rewind +[`self_assignment`]: https://rust-lang.github.io/rust-clippy/main/index.html#self_assignment +[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/main/index.html#self_named_constructors +[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/main/index.html#self_named_module_files +[`self_only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/main/index.html#self_only_used_in_recursion +[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/main/index.html#semicolon_if_nothing_returned +[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/main/index.html#semicolon_inside_block +[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/main/index.html#semicolon_outside_block +[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/main/index.html#separated_literal_suffix +[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/main/index.html#serde_api_misuse +[`set_contains_or_insert`]: https://rust-lang.github.io/rust-clippy/main/index.html#set_contains_or_insert +[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/main/index.html#shadow_reuse +[`shadow_same`]: https://rust-lang.github.io/rust-clippy/main/index.html#shadow_same +[`shadow_unrelated`]: https://rust-lang.github.io/rust-clippy/main/index.html#shadow_unrelated +[`short_circuit_statement`]: https://rust-lang.github.io/rust-clippy/main/index.html#short_circuit_statement +[`should_assert_eq`]: https://rust-lang.github.io/rust-clippy/main/index.html#should_assert_eq +[`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/main/index.html#should_implement_trait +[`should_panic_without_expect`]: https://rust-lang.github.io/rust-clippy/main/index.html#should_panic_without_expect +[`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/main/index.html#significant_drop_in_scrutinee +[`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/main/index.html#significant_drop_tightening +[`similar_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#similar_names +[`single_call_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_call_fn +[`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_char_add_str +[`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_char_lifetime_names +[`single_char_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_char_pattern +[`single_char_push_str`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_char_push_str +[`single_component_path_imports`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_component_path_imports +[`single_element_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_element_loop +[`single_match`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_match +[`single_match_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_match_else +[`single_option_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_option_map +[`single_range_in_vec_init`]: https://rust-lang.github.io/rust-clippy/main/index.html#single_range_in_vec_init +[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/main/index.html#size_of_in_element_count +[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#size_of_ref +[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/main/index.html#skip_while_next +[`sliced_string_as_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#sliced_string_as_bytes +[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/main/index.html#slow_vector_initialization +[`some_filter`]: https://rust-lang.github.io/rust-clippy/main/index.html#some_filter +[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/main/index.html#stable_sort_primitive +[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/main/index.html#std_instead_of_alloc +[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/main/index.html#std_instead_of_core +[`str_split_at_newline`]: https://rust-lang.github.io/rust-clippy/main/index.html#str_split_at_newline +[`str_to_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#str_to_string +[`string_add`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_add +[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_add_assign +[`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_extend_chars +[`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_from_utf8_as_bytes +[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_lit_as_bytes +[`string_lit_chars_any`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_lit_chars_any +[`string_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_slice +[`string_to_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#string_to_string +[`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/main/index.html#strlen_on_c_strings +[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/main/index.html#struct_excessive_bools +[`struct_field_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#struct_field_names +[`stutter`]: https://rust-lang.github.io/rust-clippy/main/index.html#stutter +[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/main/index.html#suboptimal_flops +[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_arithmetic_impl +[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_assignment_formatting +[`suspicious_command_arg_space`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_command_arg_space +[`suspicious_doc_comments`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_doc_comments +[`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_else_formatting +[`suspicious_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_map +[`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_op_assign_impl +[`suspicious_open_options`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_open_options +[`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_operation_groupings +[`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_splitn +[`suspicious_to_owned`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_to_owned +[`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_unary_op_formatting +[`suspicious_xor_used_as_pow`]: https://rust-lang.github.io/rust-clippy/main/index.html#suspicious_xor_used_as_pow +[`swap_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#swap_ptr_to_ref +[`swap_with_temporary`]: https://rust-lang.github.io/rust-clippy/main/index.html#swap_with_temporary +[`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/main/index.html#tabs_in_doc_comments +[`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/main/index.html#temporary_assignment +[`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#temporary_cstring_as_ptr +[`test_attr_in_doctest`]: https://rust-lang.github.io/rust-clippy/main/index.html#test_attr_in_doctest +[`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/main/index.html#tests_outside_test_module +[`thread_local_initializer_can_be_made_const`]: https://rust-lang.github.io/rust-clippy/main/index.html#thread_local_initializer_can_be_made_const +[`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/main/index.html#to_digit_is_some +[`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/main/index.html#to_string_in_display +[`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/main/index.html#to_string_in_format_args +[`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#to_string_trait_impl +[`todo`]: https://rust-lang.github.io/rust-clippy/main/index.html#todo +[`too_long_first_doc_paragraph`]: https://rust-lang.github.io/rust-clippy/main/index.html#too_long_first_doc_paragraph +[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/main/index.html#too_many_arguments +[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/main/index.html#too_many_lines +[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/main/index.html#toplevel_ref_arg +[`trailing_empty_array`]: https://rust-lang.github.io/rust-clippy/main/index.html#trailing_empty_array +[`trait_duplication_in_bounds`]: https://rust-lang.github.io/rust-clippy/main/index.html#trait_duplication_in_bounds +[`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_bytes_to_str +[`transmute_float_to_int`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_float_to_int +[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_int_to_bool +[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_int_to_char +[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_int_to_float +[`transmute_int_to_non_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_int_to_non_zero +[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_null_to_fn +[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_num_to_bytes +[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_ptr_to_ptr +[`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_ptr_to_ref +[`transmute_undefined_repr`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmute_undefined_repr +[`transmutes_expressible_as_ptr_casts`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmutes_expressible_as_ptr_casts +[`transmuting_null`]: https://rust-lang.github.io/rust-clippy/main/index.html#transmuting_null +[`trim_split_whitespace`]: https://rust-lang.github.io/rust-clippy/main/index.html#trim_split_whitespace +[`trivial_regex`]: https://rust-lang.github.io/rust-clippy/main/index.html#trivial_regex +[`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#trivially_copy_pass_by_ref +[`try_err`]: https://rust-lang.github.io/rust-clippy/main/index.html#try_err +[`tuple_array_conversions`]: https://rust-lang.github.io/rust-clippy/main/index.html#tuple_array_conversions +[`type_complexity`]: https://rust-lang.github.io/rust-clippy/main/index.html#type_complexity +[`type_id_on_box`]: https://rust-lang.github.io/rust-clippy/main/index.html#type_id_on_box +[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/main/index.html#type_repetition_in_bounds +[`unbuffered_bytes`]: https://rust-lang.github.io/rust-clippy/main/index.html#unbuffered_bytes +[`unchecked_duration_subtraction`]: https://rust-lang.github.io/rust-clippy/main/index.html#unchecked_duration_subtraction +[`unchecked_time_subtraction`]: https://rust-lang.github.io/rust-clippy/main/index.html#unchecked_time_subtraction +[`unconditional_recursion`]: https://rust-lang.github.io/rust-clippy/main/index.html#unconditional_recursion +[`undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/main/index.html#undocumented_unsafe_blocks +[`undropped_manually_drops`]: https://rust-lang.github.io/rust-clippy/main/index.html#undropped_manually_drops +[`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/main/index.html#unicode_not_nfc +[`unimplemented`]: https://rust-lang.github.io/rust-clippy/main/index.html#unimplemented +[`uninhabited_references`]: https://rust-lang.github.io/rust-clippy/main/index.html#uninhabited_references +[`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/main/index.html#uninit_assumed_init +[`uninit_vec`]: https://rust-lang.github.io/rust-clippy/main/index.html#uninit_vec +[`uninlined_format_args`]: https://rust-lang.github.io/rust-clippy/main/index.html#uninlined_format_args +[`unit_arg`]: https://rust-lang.github.io/rust-clippy/main/index.html#unit_arg +[`unit_cmp`]: https://rust-lang.github.io/rust-clippy/main/index.html#unit_cmp +[`unit_hash`]: https://rust-lang.github.io/rust-clippy/main/index.html#unit_hash +[`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/main/index.html#unit_return_expecting_ord +[`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/main/index.html#unknown_clippy_lints +[`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_box_returns +[`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_cast +[`unnecessary_clippy_cfg`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_clippy_cfg +[`unnecessary_debug_formatting`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_debug_formatting +[`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_fallible_conversions +[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_filter_map +[`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_find_map +[`unnecessary_first_then_check`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_first_then_check +[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_fold +[`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_get_then_check +[`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_join +[`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_lazy_evaluations +[`unnecessary_literal_bound`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_literal_bound +[`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_literal_unwrap +[`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_map_on_constructor +[`unnecessary_map_or`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_map_or +[`unnecessary_min_or_max`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_min_or_max +[`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_mut_passed +[`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_operation +[`unnecessary_option_map_or_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_option_map_or_else +[`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_owned_empty_strings +[`unnecessary_rest_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_rest_pattern +[`unnecessary_result_map_or_else`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_result_map_or_else +[`unnecessary_safety_comment`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_safety_comment +[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_safety_doc +[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_self_imports +[`unnecessary_semicolon`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_semicolon +[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_sort_by +[`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_struct_initialization +[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_to_owned +[`unnecessary_trailing_comma`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_trailing_comma +[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_unwrap +[`unnecessary_unwrap_unchecked`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_unwrap_unchecked +[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_wraps +[`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#unneeded_field_pattern +[`unneeded_struct_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#unneeded_struct_pattern +[`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/main/index.html#unneeded_wildcard_pattern +[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnested_or_patterns +[`unreachable`]: https://rust-lang.github.io/rust-clippy/main/index.html#unreachable +[`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#unreadable_literal +[`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/main/index.html#unsafe_derive_deserialize +[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/main/index.html#unsafe_removed_from_name +[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/main/index.html#unsafe_vector_initialization +[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/main/index.html#unseparated_literal_suffix +[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/main/index.html#unsound_collection_transmute +[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#unstable_as_mut_slice +[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#unstable_as_slice +[`unused_async`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_async +[`unused_async_trait_impl`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_async_trait_impl +[`unused_collect`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_collect +[`unused_enumerate_index`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_enumerate_index +[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_format_specs +[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_io_amount +[`unused_label`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_label +[`unused_peekable`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_peekable +[`unused_result_ok`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_result_ok +[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_rounding +[`unused_self`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_self +[`unused_trait_names`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_trait_names +[`unused_unit`]: https://rust-lang.github.io/rust-clippy/main/index.html#unused_unit +[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/main/index.html#unusual_byte_groupings +[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_in_result +[`unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_or_default +[`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_or_else_default +[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_used +[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/main/index.html#upper_case_acronyms +[`use_debug`]: https://rust-lang.github.io/rust-clippy/main/index.html#use_debug +[`use_self`]: https://rust-lang.github.io/rust-clippy/main/index.html#use_self +[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/main/index.html#used_underscore_binding +[`used_underscore_items`]: https://rust-lang.github.io/rust-clippy/main/index.html#used_underscore_items +[`useless_asref`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_asref +[`useless_attribute`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_attribute +[`useless_borrows_in_formatting`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_borrows_in_formatting +[`useless_concat`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_concat +[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_conversion +[`useless_format`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_format +[`useless_let_if_seq`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_let_if_seq +[`useless_nonzero_new_unchecked`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_nonzero_new_unchecked +[`useless_transmute`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_transmute +[`useless_vec`]: https://rust-lang.github.io/rust-clippy/main/index.html#useless_vec +[`vec_box`]: https://rust-lang.github.io/rust-clippy/main/index.html#vec_box +[`vec_init_then_push`]: https://rust-lang.github.io/rust-clippy/main/index.html#vec_init_then_push +[`vec_resize_to_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#vec_resize_to_zero +[`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/main/index.html#verbose_bit_mask +[`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/main/index.html#verbose_file_reads +[`volatile_composites`]: https://rust-lang.github.io/rust-clippy/main/index.html#volatile_composites +[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/main/index.html#vtable_address_comparisons +[`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/main/index.html#waker_clone_wake +[`while_float`]: https://rust-lang.github.io/rust-clippy/main/index.html#while_float +[`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/main/index.html#while_immutable_condition +[`while_let_loop`]: https://rust-lang.github.io/rust-clippy/main/index.html#while_let_loop +[`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/main/index.html#while_let_on_iterator +[`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/main/index.html#wildcard_dependencies +[`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/main/index.html#wildcard_enum_match_arm +[`wildcard_imports`]: https://rust-lang.github.io/rust-clippy/main/index.html#wildcard_imports +[`wildcard_in_or_patterns`]: https://rust-lang.github.io/rust-clippy/main/index.html#wildcard_in_or_patterns +[`with_capacity_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#with_capacity_zero +[`write_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#write_literal +[`write_with_newline`]: https://rust-lang.github.io/rust-clippy/main/index.html#write_with_newline +[`writeln_empty_string`]: https://rust-lang.github.io/rust-clippy/main/index.html#writeln_empty_string +[`wrong_pub_self_convention`]: https://rust-lang.github.io/rust-clippy/main/index.html#wrong_pub_self_convention +[`wrong_self_convention`]: https://rust-lang.github.io/rust-clippy/main/index.html#wrong_self_convention +[`wrong_transmute`]: https://rust-lang.github.io/rust-clippy/main/index.html#wrong_transmute +[`zero_divided_by_zero`]: https://rust-lang.github.io/rust-clippy/main/index.html#zero_divided_by_zero +[`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/main/index.html#zero_prefixed_literal +[`zero_ptr`]: https://rust-lang.github.io/rust-clippy/main/index.html#zero_ptr +[`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/main/index.html#zero_repeat_side_effects +[`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/main/index.html#zero_sized_map_values +[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/main/index.html#zero_width_space +[`zombie_processes`]: https://rust-lang.github.io/rust-clippy/main/index.html#zombie_processes +[`zst_offset`]: https://rust-lang.github.io/rust-clippy/main/index.html#zst_offset [`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md index ccfbb0b88387e..7a9e9fce4e9d3 100644 --- a/src/tools/clippy/CONTRIBUTING.md +++ b/src/tools/clippy/CONTRIBUTING.md @@ -8,7 +8,7 @@ something. We appreciate any sort of contributions, and don't want a wall of rul Clippy welcomes contributions from everyone. There are many ways to contribute to Clippy and the following document explains how you can contribute and how to get started. If you have any questions about contributing or need help with -anything, feel free to ask questions on issues or visit the `#clippy` on [Zulip]. +anything, feel free to ask questions on issues or visit the `#t-clippy` on [Zulip]. All contributors are expected to follow the [Rust Code of Conduct]. @@ -24,7 +24,7 @@ All contributors are expected to follow the [Rust Code of Conduct]. - [Contributions](#contributions) - [License](#license) -[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/clippy +[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-clippy [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct ## The Clippy book diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index fe9a2e3b7ad58..b6a70863e7104 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.99" +version = "0.1.100" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index ef224e230d7c9..f1d1bbf93b59f 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -801,4 +801,4 @@ don't hesitate to ask on [Zulip] or in the issue/PR. [nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ [ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html [ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/index.html -[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/clippy +[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-clippy diff --git a/src/tools/clippy/book/src/development/infrastructure/sync.md b/src/tools/clippy/book/src/development/infrastructure/sync.md index 4506ff15d8ff9..c2b62b092dd71 100644 --- a/src/tools/clippy/book/src/development/infrastructure/sync.md +++ b/src/tools/clippy/book/src/development/infrastructure/sync.md @@ -92,7 +92,7 @@ to be run inside the `rust` directory): accelerate the process ping the `@rust-lang/clippy` team in your PR and/or ask them in the [Zulip] stream.) -[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/clippy +[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-clippy [`rust-lang/rust`]: https://github.com/rust-lang/rust ## Performing the sync from Clippy to [`rust-lang/rust`] diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 6869cc56ed956..a782f4aca6c53 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -17,7 +17,7 @@ Which crates to allow absolute paths from --- **Affected lints:** -* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) +* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/main/index.html#absolute_paths) ## `absolute-paths-max-segments` @@ -28,7 +28,7 @@ be linted. --- **Affected lints:** -* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) +* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/main/index.html#absolute_paths) ## `accept-comment-above-attributes` @@ -38,7 +38,7 @@ Whether to accept a safety comment to be placed above the attributes for the `un --- **Affected lints:** -* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/main/index.html#undocumented_unsafe_blocks) ## `accept-comment-above-statement` @@ -48,7 +48,7 @@ Whether to accept a safety comment to be placed above the statement containing t --- **Affected lints:** -* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/main/index.html#undocumented_unsafe_blocks) ## `allow-comparison-to-zero` @@ -58,7 +58,7 @@ Don't lint when comparing the result of a modulo operation to zero. --- **Affected lints:** -* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic) +* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/main/index.html#modulo_arithmetic) ## `allow-dbg-in-tests` @@ -68,7 +68,7 @@ Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` --- **Affected lints:** -* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) +* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/main/index.html#dbg_macro) ## `allow-exact-repetitions` @@ -78,7 +78,7 @@ Whether an item should be allowed to have the same name as its containing module --- **Affected lints:** -* [`module_name_repetitions`](https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions) +* [`module_name_repetitions`](https://rust-lang.github.io/rust-clippy/main/index.html#module_name_repetitions) ## `allow-expect-in-consts` @@ -88,7 +88,7 @@ Whether `expect` should be allowed in code always evaluated at compile time --- **Affected lints:** -* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +* [`expect_used`](https://rust-lang.github.io/rust-clippy/main/index.html#expect_used) ## `allow-expect-in-tests` @@ -98,7 +98,7 @@ Whether `expect` should be allowed in test functions or `#[cfg(test)]` --- **Affected lints:** -* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +* [`expect_used`](https://rust-lang.github.io/rust-clippy/main/index.html#expect_used) ## `allow-indexing-slicing-in-tests` @@ -108,7 +108,7 @@ Whether `indexing_slicing` should be allowed in test functions or `#[cfg(test)]` --- **Affected lints:** -* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) +* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/main/index.html#indexing_slicing) ## `allow-large-stack-frames-in-tests` @@ -118,7 +118,7 @@ Whether functions inside `#[cfg(test)]` modules or test functions should be chec --- **Affected lints:** -* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) +* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/main/index.html#large_stack_frames) ## `allow-mixed-uninlined-format-args` @@ -128,7 +128,7 @@ Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar) --- **Affected lints:** -* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/main/index.html#uninlined_format_args) ## `allow-one-hash-in-raw-strings` @@ -138,7 +138,7 @@ Whether to allow `r#""#` when `r""` can be used --- **Affected lints:** -* [`needless_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_raw_string_hashes) +* [`needless_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/main/index.html#needless_raw_string_hashes) ## `allow-panic-in-tests` @@ -148,7 +148,7 @@ Whether `panic` should be allowed in test functions or `#[cfg(test)]` --- **Affected lints:** -* [`panic`](https://rust-lang.github.io/rust-clippy/master/index.html#panic) +* [`panic`](https://rust-lang.github.io/rust-clippy/main/index.html#panic) ## `allow-print-in-tests` @@ -158,8 +158,8 @@ Whether print macros (ex. `println!`) should be allowed in test functions or `#[ --- **Affected lints:** -* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) -* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) +* [`print_stderr`](https://rust-lang.github.io/rust-clippy/main/index.html#print_stderr) +* [`print_stdout`](https://rust-lang.github.io/rust-clippy/main/index.html#print_stdout) ## `allow-private-module-inception` @@ -169,7 +169,7 @@ Whether to allow module inception if it's not public. --- **Affected lints:** -* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) +* [`module_inception`](https://rust-lang.github.io/rust-clippy/main/index.html#module_inception) ## `allow-renamed-params-for` @@ -191,7 +191,7 @@ default configuration of Clippy. By default, any configuration will replace the --- **Affected lints:** -* [`renamed_function_params`](https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params) +* [`renamed_function_params`](https://rust-lang.github.io/rust-clippy/main/index.html#renamed_function_params) ## `allow-unwrap-in-consts` @@ -201,7 +201,7 @@ Whether `unwrap` should be allowed in code always evaluated at compile time --- **Affected lints:** -* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_used) ## `allow-unwrap-in-tests` @@ -211,7 +211,7 @@ Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` --- **Affected lints:** -* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_used) ## `allow-unwrap-types` @@ -227,8 +227,8 @@ allow-unwrap-types = [ "std::sync::LockResult" ] --- **Affected lints:** -* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) -* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +* [`expect_used`](https://rust-lang.github.io/rust-clippy/main/index.html#expect_used) +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/main/index.html#unwrap_used) ## `allow-useless-vec-in-tests` @@ -238,7 +238,7 @@ Whether `useless_vec` should ignore test functions or `#[cfg(test)]` --- **Affected lints:** -* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/main/index.html#useless_vec) ## `allowed-dotfiles` @@ -248,7 +248,7 @@ Additional dotfiles (files or directories starting with a dot) to allow --- **Affected lints:** -* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) +* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/main/index.html#path_ends_with_ext) ## `allowed-duplicate-crates` @@ -258,7 +258,7 @@ A list of crate names to allow duplicates of --- **Affected lints:** -* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions) +* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/main/index.html#multiple_crate_versions) ## `allowed-idents-below-min-chars` @@ -270,7 +270,7 @@ configuration of Clippy. By default, any configuration will replace the default --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/main/index.html#min_ident_chars) ## `allowed-prefixes` @@ -296,7 +296,7 @@ default configuration of Clippy. By default, any configuration will replace the --- **Affected lints:** -* [`module_name_repetitions`](https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions) +* [`module_name_repetitions`](https://rust-lang.github.io/rust-clippy/main/index.html#module_name_repetitions) ## `allowed-scripts` @@ -306,7 +306,7 @@ The list of unicode scripts allowed to be used in the scope. --- **Affected lints:** -* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) +* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_script_idents) ## `allowed-wildcard-imports` @@ -328,7 +328,7 @@ are already allowed by default. --- **Affected lints:** -* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/main/index.html#wildcard_imports) ## `arithmetic-side-effects-allowed` @@ -351,7 +351,7 @@ A type, say `SomeType`, listed in this configuration has the same behavior of --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/main/index.html#arithmetic_side_effects) ## `arithmetic-side-effects-allowed-binary` @@ -374,7 +374,7 @@ arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/main/index.html#arithmetic_side_effects) ## `arithmetic-side-effects-allowed-unary` @@ -390,7 +390,7 @@ arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/main/index.html#arithmetic_side_effects) ## `array-size-threshold` @@ -400,8 +400,8 @@ The maximum allowed size for arrays on the stack --- **Affected lints:** -* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) -* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) +* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/main/index.html#large_const_arrays) +* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/main/index.html#large_stack_arrays) ## `avoid-breaking-exported-api` @@ -411,25 +411,25 @@ Suppress lints whenever the suggested change would cause breakage for other crat --- **Affected lints:** -* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) -* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) -* [`needless_pass_by_ref_mut`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut) -* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) -* [`owned_cow`](https://rust-lang.github.io/rust-clippy/master/index.html#owned_cow) -* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) -* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) -* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) -* [`ref_option`](https://rust-lang.github.io/rust-clippy/master/index.html#ref_option) -* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) -* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) -* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) -* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) -* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) +* [`box_collection`](https://rust-lang.github.io/rust-clippy/main/index.html#box_collection) +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/main/index.html#enum_variant_names) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/main/index.html#large_types_passed_by_value) +* [`linkedlist`](https://rust-lang.github.io/rust-clippy/main/index.html#linkedlist) +* [`needless_pass_by_ref_mut`](https://rust-lang.github.io/rust-clippy/main/index.html#needless_pass_by_ref_mut) +* [`option_option`](https://rust-lang.github.io/rust-clippy/main/index.html#option_option) +* [`owned_cow`](https://rust-lang.github.io/rust-clippy/main/index.html#owned_cow) +* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/main/index.html#rc_buffer) +* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/main/index.html#rc_mutex) +* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/main/index.html#redundant_allocation) +* [`ref_option`](https://rust-lang.github.io/rust-clippy/main/index.html#ref_option) +* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/main/index.html#single_call_fn) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/main/index.html#trivially_copy_pass_by_ref) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_box_returns) +* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_wraps) +* [`unused_self`](https://rust-lang.github.io/rust-clippy/main/index.html#unused_self) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/main/index.html#upper_case_acronyms) +* [`vec_box`](https://rust-lang.github.io/rust-clippy/main/index.html#vec_box) +* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/main/index.html#wrong_self_convention) ## `await-holding-invalid-types` @@ -439,7 +439,7 @@ The list of types which may not be held across an await point. --- **Affected lints:** -* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) +* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/main/index.html#await_holding_invalid_type) ## `cargo-ignore-publish` @@ -449,7 +449,7 @@ For internal testing only, ignores the current `publish` settings in the Cargo m --- **Affected lints:** -* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata) +* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/main/index.html#cargo_common_metadata) ## `check-grouped-late-init` @@ -480,7 +480,7 @@ let (a, b) = if true { --- **Affected lints:** -* [`needless_late_init`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_late_init) +* [`needless_late_init`](https://rust-lang.github.io/rust-clippy/main/index.html#needless_late_init) ## `check-incompatible-msrv-in-tests` @@ -490,7 +490,7 @@ Whether to check MSRV compatibility in `#[test]` and `#[cfg(test)]` code. --- **Affected lints:** -* [`incompatible_msrv`](https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv) +* [`incompatible_msrv`](https://rust-lang.github.io/rust-clippy/main/index.html#incompatible_msrv) ## `check-inconsistent-struct-field-initializers` @@ -517,7 +517,7 @@ fn main() { --- **Affected lints:** -* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor) +* [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/main/index.html#inconsistent_struct_constructor) ## `check-private-items` @@ -527,10 +527,10 @@ Whether to also run the listed lints on private items. --- **Affected lints:** -* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) -* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc) -* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) -* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc) +* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_errors_doc) +* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_panics_doc) +* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_safety_doc) +* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_safety_doc) ## `cognitive-complexity-threshold` @@ -540,7 +540,7 @@ The maximum cognitive complexity a function can have --- **Affected lints:** -* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) +* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/main/index.html#cognitive_complexity) ## `const-literal-digits-threshold` @@ -550,7 +550,7 @@ The minimum digits a const float literal must have to supress the `excessive_pre --- **Affected lints:** -* [`excessive_precision`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision) +* [`excessive_precision`](https://rust-lang.github.io/rust-clippy/main/index.html#excessive_precision) ## `disallowed-fields` @@ -567,7 +567,7 @@ The list of disallowed fields, written as fully qualified paths. --- **Affected lints:** -* [`disallowed_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_fields) +* [`disallowed_fields`](https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_fields) ## `disallowed-macros` @@ -584,7 +584,7 @@ The list of disallowed macros, written as fully qualified paths. --- **Affected lints:** -* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) +* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_macros) ## `disallowed-methods` @@ -601,7 +601,7 @@ The list of disallowed methods, written as fully qualified paths. --- **Affected lints:** -* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) +* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_methods) ## `disallowed-names` @@ -613,7 +613,7 @@ default configuration of Clippy. By default, any configuration will replace the --- **Affected lints:** -* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) +* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_names) ## `disallowed-types` @@ -630,7 +630,7 @@ The list of disallowed types, written as fully qualified paths. --- **Affected lints:** -* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) +* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/main/index.html#disallowed_types) ## `doc-valid-idents` @@ -640,11 +640,11 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "SQLite", "MySQL", "PostgreSQL", "MariaDB", "MongoDB", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "SQLite", "MySQL", "PostgreSQL", "MariaDB", "MongoDB", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebAuthn", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** -* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) +* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/main/index.html#doc_markdown) ## `enable-raw-pointer-heuristic-for-send` @@ -654,7 +654,7 @@ Whether to apply the raw pointer heuristic to determine if a type is `Send`. --- **Affected lints:** -* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) +* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/main/index.html#non_send_fields_in_send_ty) ## `enforce-iter-loop-reborrow` @@ -680,7 +680,7 @@ for _ in &mut *rmvec {} --- **Affected lints:** -* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop) +* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/main/index.html#explicit_iter_loop) ## `enforced-import-renames` @@ -690,7 +690,7 @@ The list of imports to always rename, a fully qualified path followed by the ren --- **Affected lints:** -* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) +* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_enforced_import_renames) ## `enum-variant-name-threshold` @@ -700,7 +700,7 @@ The minimum number of enum variants for the lints about variant names to trigger --- **Affected lints:** -* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/main/index.html#enum_variant_names) ## `enum-variant-size-threshold` @@ -710,7 +710,7 @@ The maximum size of an enum's variant to avoid box suggestion --- **Affected lints:** -* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) +* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/main/index.html#large_enum_variant) ## `excessive-nesting-threshold` @@ -720,7 +720,7 @@ The maximum amount of nesting a block can reside in --- **Affected lints:** -* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) +* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/main/index.html#excessive_nesting) ## `future-size-threshold` @@ -730,7 +730,7 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large --- **Affected lints:** -* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) +* [`large_futures`](https://rust-lang.github.io/rust-clippy/main/index.html#large_futures) ## `ignore-interior-mutability` @@ -740,10 +740,10 @@ A list of paths to types that should be treated as if they do not contain interi --- **Affected lints:** -* [`borrow_interior_mutable_const`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const) -* [`declare_interior_mutable_const`](https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const) -* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) -* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) +* [`borrow_interior_mutable_const`](https://rust-lang.github.io/rust-clippy/main/index.html#borrow_interior_mutable_const) +* [`declare_interior_mutable_const`](https://rust-lang.github.io/rust-clippy/main/index.html#declare_interior_mutable_const) +* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/main/index.html#ifs_same_cond) +* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/main/index.html#mutable_key_type) ## `inherent-impl-lint-scope` @@ -753,7 +753,7 @@ Sets the scope ("crate", "file", or "module") in which duplicate inherent `impl` --- **Affected lints:** -* [`multiple_inherent_impl`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl) +* [`multiple_inherent_impl`](https://rust-lang.github.io/rust-clippy/main/index.html#multiple_inherent_impl) ## `large-error-ignored` @@ -764,7 +764,7 @@ A list of paths to types that should be ignored as overly large `Err`-variants i --- **Affected lints:** -* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +* [`result_large_err`](https://rust-lang.github.io/rust-clippy/main/index.html#result_large_err) ## `large-error-threshold` @@ -774,7 +774,7 @@ The maximum size of the `Err`-variant in a `Result` returned from a function --- **Affected lints:** -* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +* [`result_large_err`](https://rust-lang.github.io/rust-clippy/main/index.html#result_large_err) ## `lint-commented-code` @@ -785,8 +785,8 @@ that would be collapsed. --- **Affected lints:** -* [`collapsible_else_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_else_if) -* [`collapsible_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if) +* [`collapsible_else_if`](https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_else_if) +* [`collapsible_if`](https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_if) ## `literal-representation-threshold` @@ -796,7 +796,7 @@ The lower bound for linting decimal literals --- **Affected lints:** -* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) +* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/main/index.html#decimal_literal_representation) ## `matches-for-let-else` @@ -807,7 +807,7 @@ be filtering for common types. --- **Affected lints:** -* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_let_else) ## `max-fn-params-bools` @@ -818,7 +818,7 @@ Use `0` to lint on any function with a bool parameter. --- **Affected lints:** -* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) +* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/main/index.html#fn_params_excessive_bools) ## `max-include-file-size` @@ -828,7 +828,7 @@ The maximum size of a file included via `include_bytes!()` or `include_str!()`, --- **Affected lints:** -* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) +* [`large_include_file`](https://rust-lang.github.io/rust-clippy/main/index.html#large_include_file) ## `max-struct-bools` @@ -838,7 +838,7 @@ The maximum number of bool fields a struct can have --- **Affected lints:** -* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) +* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/main/index.html#struct_excessive_bools) ## `max-suggested-slice-pattern-length` @@ -850,7 +850,7 @@ For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. --- **Affected lints:** -* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/main/index.html#index_refutable_slice) ## `max-trait-bounds` @@ -860,7 +860,7 @@ The maximum number of bounds a trait can have to be linted --- **Affected lints:** -* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/main/index.html#type_repetition_in_bounds) ## `min-ident-chars-lint-trait-impl` @@ -870,7 +870,7 @@ Whether to lint idents that have too few chars even when following trait declara --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/main/index.html#min_ident_chars) ## `min-ident-chars-threshold` @@ -880,7 +880,7 @@ Minimum chars an ident can have, anything below or equal to this will be linted. --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/main/index.html#min_ident_chars) ## `missing-docs-allow-unused` @@ -890,7 +890,7 @@ Whether to allow fields starting with an underscore to skip documentation requir --- **Affected lints:** -* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) +* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_docs_in_private_items) ## `missing-docs-in-crate-items` @@ -901,7 +901,7 @@ crate. For example, `pub(crate)` items. --- **Affected lints:** -* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) +* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_docs_in_private_items) ## `module-item-order-groupings` @@ -911,7 +911,7 @@ The named groupings of different source item kinds within modules. --- **Affected lints:** -* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/main/index.html#arbitrary_source_item_ordering) ## `module-items-ordered-within-groupings` @@ -924,7 +924,7 @@ This option can be configured to "all", "none", or a list of specific grouping n --- **Affected lints:** -* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/main/index.html#arbitrary_source_item_ordering) ## `msrv` @@ -934,90 +934,90 @@ The minimum rust version that the project supports. Defaults to the `rust-versio --- **Affected lints:** -* [`allow_attributes`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes) -* [`allow_attributes_without_reason`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason) -* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) -* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) -* [`assigning_clones`](https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones) -* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) -* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) -* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) -* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) -* [`collapsible_match`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match) -* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) -* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) -* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) -* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) -* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) -* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) -* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) -* [`implicit_saturating_sub`](https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub) -* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -* [`inefficient_to_string`](https://rust-lang.github.io/rust-clippy/master/index.html#inefficient_to_string) -* [`io_other_error`](https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error) -* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) -* [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/master/index.html#legacy_numeric_constants) -* [`len_zero`](https://rust-lang.github.io/rust-clippy/master/index.html#len_zero) -* [`lines_filter_map_ok`](https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok) -* [`manual_abs_diff`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_abs_diff) -* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) -* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) -* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) -* [`manual_div_ceil`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil) -* [`manual_flatten`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten) -* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) -* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) -* [`manual_is_power_of_two`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two) -* [`manual_is_variant_and`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and) -* [`manual_isolate_lowest_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_isolate_lowest_one) -* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -* [`manual_midpoint`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_midpoint) -* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) -* [`manual_noop_waker`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_noop_waker) -* [`manual_option_as_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_as_slice) -* [`manual_pattern_char_comparison`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison) -* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) -* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) -* [`manual_repeat_n`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_repeat_n) -* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) -* [`manual_slice_fill`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_fill) -* [`manual_slice_size_calculation`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_size_calculation) -* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) -* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) -* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) -* [`manual_take`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_take) -* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) -* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) -* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) -* [`map_with_unused_argument_over_ranges`](https://rust-lang.github.io/rust-clippy/master/index.html#map_with_unused_argument_over_ranges) -* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) -* [`mem_replace_option_with_some`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_some) -* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) -* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) -* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) -* [`non_std_lazy_statics`](https://rust-lang.github.io/rust-clippy/master/index.html#non_std_lazy_statics) -* [`nonnull_unchecked_on_box_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#nonnull_unchecked_on_box_ptr) -* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) -* [`or_fun_call`](https://rust-lang.github.io/rust-clippy/master/index.html#or_fun_call) -* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) -* [`question_mark`](https://rust-lang.github.io/rust-clippy/master/index.html#question_mark) -* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) -* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) -* [`repeat_vec_with_capacity`](https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity) -* [`same_item_push`](https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push) -* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) -* [`to_digit_is_some`](https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some) -* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) -* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) -* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -* [`unchecked_time_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_time_subtraction) -* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) -* [`unnecessary_unwrap`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap) -* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) -* [`unused_trait_names`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names) -* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -* [`zero_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr) +* [`allow_attributes`](https://rust-lang.github.io/rust-clippy/main/index.html#allow_attributes) +* [`allow_attributes_without_reason`](https://rust-lang.github.io/rust-clippy/main/index.html#allow_attributes_without_reason) +* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/main/index.html#almost_complete_range) +* [`approx_constant`](https://rust-lang.github.io/rust-clippy/main/index.html#approx_constant) +* [`assigning_clones`](https://rust-lang.github.io/rust-clippy/main/index.html#assigning_clones) +* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/main/index.html#borrow_as_ptr) +* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/main/index.html#cast_abs_to_unsigned) +* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/main/index.html#checked_conversions) +* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/main/index.html#cloned_instead_of_copied) +* [`collapsible_match`](https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_match) +* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/main/index.html#collapsible_str_replace) +* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/main/index.html#deprecated_cfg_attr) +* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/main/index.html#derivable_impls) +* [`err_expect`](https://rust-lang.github.io/rust-clippy/main/index.html#err_expect) +* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/main/index.html#filter_map_next) +* [`from_over_into`](https://rust-lang.github.io/rust-clippy/main/index.html#from_over_into) +* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/main/index.html#if_then_some_else_none) +* [`implicit_saturating_sub`](https://rust-lang.github.io/rust-clippy/main/index.html#implicit_saturating_sub) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/main/index.html#index_refutable_slice) +* [`inefficient_to_string`](https://rust-lang.github.io/rust-clippy/main/index.html#inefficient_to_string) +* [`io_other_error`](https://rust-lang.github.io/rust-clippy/main/index.html#io_other_error) +* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/main/index.html#iter_kv_map) +* [`legacy_numeric_constants`](https://rust-lang.github.io/rust-clippy/main/index.html#legacy_numeric_constants) +* [`len_zero`](https://rust-lang.github.io/rust-clippy/main/index.html#len_zero) +* [`lines_filter_map_ok`](https://rust-lang.github.io/rust-clippy/main/index.html#lines_filter_map_ok) +* [`manual_abs_diff`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_abs_diff) +* [`manual_bits`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_bits) +* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_c_str_literals) +* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_clamp) +* [`manual_div_ceil`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_div_ceil) +* [`manual_flatten`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_flatten) +* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_hash_one) +* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_ascii_check) +* [`manual_is_power_of_two`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_power_of_two) +* [`manual_is_variant_and`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_is_variant_and) +* [`manual_isolate_lowest_one`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_isolate_lowest_one) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_let_else) +* [`manual_midpoint`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_midpoint) +* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_non_exhaustive) +* [`manual_noop_waker`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_noop_waker) +* [`manual_option_as_slice`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_option_as_slice) +* [`manual_pattern_char_comparison`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_pattern_char_comparison) +* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_range_contains) +* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_rem_euclid) +* [`manual_repeat_n`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_repeat_n) +* [`manual_retain`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_retain) +* [`manual_slice_fill`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_slice_fill) +* [`manual_slice_size_calculation`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_slice_size_calculation) +* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_split_once) +* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_str_repeat) +* [`manual_strip`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_strip) +* [`manual_take`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_take) +* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/main/index.html#manual_try_fold) +* [`map_clone`](https://rust-lang.github.io/rust-clippy/main/index.html#map_clone) +* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/main/index.html#map_unwrap_or) +* [`map_with_unused_argument_over_ranges`](https://rust-lang.github.io/rust-clippy/main/index.html#map_with_unused_argument_over_ranges) +* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/main/index.html#match_like_matches_macro) +* [`mem_replace_option_with_some`](https://rust-lang.github.io/rust-clippy/main/index.html#mem_replace_option_with_some) +* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/main/index.html#mem_replace_with_default) +* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/main/index.html#missing_const_for_fn) +* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/main/index.html#needless_borrow) +* [`non_std_lazy_statics`](https://rust-lang.github.io/rust-clippy/main/index.html#non_std_lazy_statics) +* [`nonnull_unchecked_on_box_ptr`](https://rust-lang.github.io/rust-clippy/main/index.html#nonnull_unchecked_on_box_ptr) +* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/main/index.html#option_as_ref_deref) +* [`or_fun_call`](https://rust-lang.github.io/rust-clippy/main/index.html#or_fun_call) +* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/main/index.html#ptr_as_ptr) +* [`question_mark`](https://rust-lang.github.io/rust-clippy/main/index.html#question_mark) +* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/main/index.html#redundant_field_names) +* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/main/index.html#redundant_static_lifetimes) +* [`repeat_vec_with_capacity`](https://rust-lang.github.io/rust-clippy/main/index.html#repeat_vec_with_capacity) +* [`same_item_push`](https://rust-lang.github.io/rust-clippy/main/index.html#same_item_push) +* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/main/index.html#seek_from_current) +* [`to_digit_is_some`](https://rust-lang.github.io/rust-clippy/main/index.html#to_digit_is_some) +* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/main/index.html#transmute_ptr_to_ref) +* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/main/index.html#tuple_array_conversions) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/main/index.html#type_repetition_in_bounds) +* [`unchecked_time_subtraction`](https://rust-lang.github.io/rust-clippy/main/index.html#unchecked_time_subtraction) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/main/index.html#uninlined_format_args) +* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_lazy_evaluations) +* [`unnecessary_unwrap`](https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_unwrap) +* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/main/index.html#unnested_or_patterns) +* [`unused_trait_names`](https://rust-lang.github.io/rust-clippy/main/index.html#unused_trait_names) +* [`use_self`](https://rust-lang.github.io/rust-clippy/main/index.html#use_self) +* [`zero_ptr`](https://rust-lang.github.io/rust-clippy/main/index.html#zero_ptr) ## `pass-by-value-size-limit` @@ -1027,7 +1027,7 @@ The minimum size (in bytes) to consider a type for passing by reference instead --- **Affected lints:** -* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/main/index.html#large_types_passed_by_value) ## `pub-underscore-fields-behavior` @@ -1038,7 +1038,7 @@ exported visibility, or whether they are marked as "pub". --- **Affected lints:** -* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) +* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/main/index.html#pub_underscore_fields) ## `recursive-self-in-type-definitions` @@ -1048,7 +1048,7 @@ Whether the type itself in a struct or enum should be replaced with `Self` when --- **Affected lints:** -* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) +* [`use_self`](https://rust-lang.github.io/rust-clippy/main/index.html#use_self) ## `semicolon-inside-block-ignore-singleline` @@ -1058,7 +1058,7 @@ Whether to lint only if it's multiline. --- **Affected lints:** -* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) +* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/main/index.html#semicolon_inside_block) ## `semicolon-outside-block-ignore-multiline` @@ -1068,7 +1068,7 @@ Whether to lint only if it's singleline. --- **Affected lints:** -* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) +* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/main/index.html#semicolon_outside_block) ## `single-char-binding-names-threshold` @@ -1078,7 +1078,7 @@ The maximum number of single char bindings a scope may have --- **Affected lints:** -* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) +* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/main/index.html#many_single_char_names) ## `source-item-ordering` @@ -1088,7 +1088,7 @@ Which kind of elements should be ordered internally, possible values being `enum --- **Affected lints:** -* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/main/index.html#arbitrary_source_item_ordering) ## `stack-size-threshold` @@ -1098,7 +1098,7 @@ The maximum allowed stack size for functions in bytes --- **Affected lints:** -* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) +* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/main/index.html#large_stack_frames) ## `standard-macro-braces` @@ -1112,7 +1112,7 @@ could be used with a full path two `MacroMatcher`s have to be added one with the --- **Affected lints:** -* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) +* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/main/index.html#nonstandard_macro_braces) ## `struct-field-name-threshold` @@ -1122,7 +1122,7 @@ The minimum number of struct fields for the lints about field names to trigger --- **Affected lints:** -* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names) +* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/main/index.html#struct_field_names) ## `suppress-restriction-lint-in-const` @@ -1136,7 +1136,7 @@ if no suggestion can be made. --- **Affected lints:** -* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) +* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/main/index.html#indexing_slicing) ## `too-large-for-stack` @@ -1146,8 +1146,8 @@ The maximum size of objects (in bytes) that will be linted. Larger objects are o --- **Affected lints:** -* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) -* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) +* [`boxed_local`](https://rust-lang.github.io/rust-clippy/main/index.html#boxed_local) +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/main/index.html#useless_vec) ## `too-many-arguments-threshold` @@ -1157,7 +1157,7 @@ The maximum number of argument a function or method can have --- **Affected lints:** -* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) +* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/main/index.html#too_many_arguments) ## `too-many-lines-threshold` @@ -1167,7 +1167,7 @@ The maximum number of lines a function or method can have --- **Affected lints:** -* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) +* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/main/index.html#too_many_lines) ## `trait-assoc-item-kinds-order` @@ -1177,7 +1177,7 @@ The order of associated items in traits. --- **Affected lints:** -* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/main/index.html#arbitrary_source_item_ordering) ## `trait-impl-item-order` @@ -1201,7 +1201,7 @@ trait-impl-item-order = "alphabetical_or_trait_item_ordering" --- **Affected lints:** -* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/main/index.html#arbitrary_source_item_ordering) ## `trivial-copy-size-limit` @@ -1212,7 +1212,7 @@ reference. --- **Affected lints:** -* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/main/index.html#trivially_copy_pass_by_ref) ## `type-complexity-threshold` @@ -1222,7 +1222,7 @@ The maximum complexity a type can have --- **Affected lints:** -* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) +* [`type_complexity`](https://rust-lang.github.io/rust-clippy/main/index.html#type_complexity) ## `unnecessary-box-size` @@ -1232,7 +1232,7 @@ The byte size a `T` in `Box` can have, below which it triggers the `clippy::u --- **Affected lints:** -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_box_returns) ## `unreadable-literal-lint-fractions` @@ -1242,7 +1242,7 @@ Should the fraction of a decimal be linted to include separators. --- **Affected lints:** -* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) +* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/main/index.html#unreadable_literal) ## `upper-case-acronyms-aggressive` @@ -1252,7 +1252,7 @@ Enables verbose mode. Triggers if there is more than one uppercase char next to --- **Affected lints:** -* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/main/index.html#upper_case_acronyms) ## `vec-box-size-threshold` @@ -1262,7 +1262,7 @@ The size of the boxed type in bytes, where boxing in a `Vec` is allowed --- **Affected lints:** -* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +* [`vec_box`](https://rust-lang.github.io/rust-clippy/main/index.html#vec_box) ## `verbose-bit-mask-threshold` @@ -1272,7 +1272,7 @@ The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' --- **Affected lints:** -* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) +* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/main/index.html#verbose_bit_mask) ## `warn-on-all-wildcard-imports` @@ -1283,7 +1283,7 @@ or for `pub use` reexports. --- **Affected lints:** -* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/main/index.html#wildcard_imports) ## `warn-unsafe-macro-metavars-in-private-macros` @@ -1293,4 +1293,4 @@ Whether to also emit warnings for unsafe blocks with metavariable expansions in --- **Affected lints:** -* [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe) +* [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/main/index.html#macro_metavars_in_unsafe) diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index d81431d58434f..e230f61d558a6 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.99" +version = "0.1.100" edition = "2024" publish = false diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 13c73e9445818..7b2a7e0010f76 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -37,7 +37,7 @@ static DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", - "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", + "WebAuthn", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", diff --git a/src/tools/clippy/clippy_config/src/metadata.rs b/src/tools/clippy/clippy_config/src/metadata.rs index 740ba3750948b..415a7738011fc 100644 --- a/src/tools/clippy/clippy_config/src/metadata.rs +++ b/src/tools/clippy/clippy_config/src/metadata.rs @@ -34,7 +34,7 @@ impl ConfMetadata { .format_with("\n", |doc, f| f(&doc.strip_prefix(" ").unwrap_or(doc))), self.0.default, self.0.lints.iter().format_with("\n", |name, f| f(&format_args!( - "* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})" + "* [`{name}`](https://rust-lang.github.io/rust-clippy/main/index.html#{name})" ))), ) } diff --git a/src/tools/clippy/clippy_dev/src/generate.rs b/src/tools/clippy/clippy_dev/src/generate.rs index f1c3375e1c7c1..4d86da4ada580 100644 --- a/src/tools/clippy/clippy_dev/src/generate.rs +++ b/src/tools/clippy/clippy_dev/src/generate.rs @@ -11,7 +11,7 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u // Use that command to update this file and do not edit by hand.\n\ // Manual edits will be overwritten.\n\n"; -const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; +const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/main/index.html"; impl LintData<'_> { #[expect(clippy::too_many_lines)] diff --git a/src/tools/clippy/clippy_dev/src/setup/intellij.rs b/src/tools/clippy/clippy_dev/src/setup/intellij.rs index c56811ee0a01e..db4f0a7c23dbe 100644 --- a/src/tools/clippy/clippy_dev/src/setup/intellij.rs +++ b/src/tools/clippy/clippy_dev/src/setup/intellij.rs @@ -155,7 +155,6 @@ fn inject_deps_into_manifest( // etc let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); - // println!("{new_manifest}"); let mut file = File::create(manifest_path)?; file.write_all(new_manifest.as_bytes())?; diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 893ab32d19c1b..dc6b27bf027ff 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.99" +version = "0.1.100" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index 3502b01eddab2..290738514b69d 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -188,7 +188,7 @@ fn clone_source_borrows_from_dest(cx: &LateContext<'_>, lhs: &Expr<'_>, call_spa .find(|stmt| { !matches!(stmt.kind, mir::StatementKind::StorageDead(_) | mir::StatementKind::StorageLive(_)) }) - && let mir::StatementKind::Assign(box (borrowed, _)) = &assignment.kind + && let mir::StatementKind::Assign((borrowed, _)) = &assignment.kind && let Some(borrowers) = borrow_map.get(&borrowed.local) { borrowers.contains(source.local) diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index 0c6e3a0db71b8..23d5adfb201a4 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -572,9 +572,8 @@ impl PostExpansionEarlyAttributes { } impl EarlyLintPass for PostExpansionEarlyAttributes { - fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, _krate: &ast::Crate) { blanket_clippy_restriction_lints::check_command_line(cx); - duplicated_attributes::check(cx, &krate.attrs); } fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { @@ -630,8 +629,15 @@ impl EarlyLintPass for PostExpansionEarlyAttributes { } mixed_attributes_style::check(cx, item.span, &item.attrs); - duplicated_attributes::check(cx, &item.attrs); } - extract_msrv_attr!(); + fn check_attributes(&mut self, cx: &EarlyContext<'_>, attrs: &[Attribute]) { + self.msrv.check_attributes(attrs); + duplicated_attributes::check(cx, attrs); + msrvs::check_attrs(cx.sess(), attrs); + } + + fn check_attributes_post(&mut self, _cx: &EarlyContext<'_>, attrs: &[Attribute]) { + self.msrv.check_attributes_post(attrs); + } } diff --git a/src/tools/clippy/clippy_lints/src/bit_width.rs b/src/tools/clippy/clippy_lints/src/bit_width.rs index 0f740327b32a0..cd08188866ead 100644 --- a/src/tools/clippy/clippy_lints/src/bit_width.rs +++ b/src/tools/clippy/clippy_lints/src/bit_width.rs @@ -98,35 +98,29 @@ impl ManualBitWidth { impl LateLintPass<'_> for ManualBitWidth { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { - if expr.span.in_external_macro(cx.sess().source_map()) { - return; - } - - match expr.kind { - // `T::BITS - n.leading_zeros()` - ExprKind::Binary(op, left, right) - if op.node == BinOpKind::Sub - && let ExprKind::MethodCall(leading_zeros, recv, [], _) = right.kind - && leading_zeros.ident.name == sym::leading_zeros - && let ExprKind::Path(QPath::TypeRelative(hir_ty, segment)) = left.kind - && segment.ident.name == sym::BITS - && let right_ty = cx.typeck_results().expr_ty(recv) - && let Some(right_int_kind) = get_int_kind(cx, right_ty) - && let left_ty = cx.typeck_results().node_type(hir_ty.hir_id) - && let Some(left_int_kind) = get_int_kind(cx, left_ty) - && self.msrv.meets(cx, msrvs::BIT_WIDTH) - && left.span.eq_ctxt(right.span) - && !is_from_proc_macro(cx, expr) => - { - if left_int_kind == right_int_kind { - // manual implementation of bit_width - emit_manual_bit_width(cx, recv, expr, right_int_kind); - } else { - // mismatched calling types - emit_type_mismatch(cx, recv, expr, right_int_kind); - } - }, - _ => {}, + // `T::BITS - n.leading_zeros()` + if let ExprKind::Binary(op, left, right) = expr.kind + && op.node == BinOpKind::Sub + && let ExprKind::MethodCall(leading_zeros, recv, [], _) = right.kind + && leading_zeros.ident.name == sym::leading_zeros + && let ExprKind::Path(QPath::TypeRelative(hir_ty, segment)) = left.kind + && segment.ident.name == sym::BITS + && !expr.span.in_external_macro(cx.sess().source_map()) + && let right_ty = cx.typeck_results().expr_ty(recv) + && let Some(right_int_kind) = get_int_kind(cx, right_ty) + && let left_ty = cx.typeck_results().node_type(hir_ty.hir_id) + && let Some(left_int_kind) = get_int_kind(cx, left_ty) + && self.msrv.meets(cx, msrvs::BIT_WIDTH) + && left.span.eq_ctxt(right.span) + && !is_from_proc_macro(cx, expr) + { + if left_int_kind == right_int_kind { + // manual implementation of bit_width + emit_manual_bit_width(cx, recv, expr, right_int_kind); + } else { + // mismatched calling types + emit_type_mismatch(cx, recv, expr, right_int_kind); + } } } } diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs index 4de35746d6452..b3cdde3385fba 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs @@ -1,8 +1,8 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_block_with_applicability; use clippy_utils::{contains_return, higher, is_from_proc_macro, leaks_droppable_temporary}; use rustc_errors::Applicability; -use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource}; +use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource, Node}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; declare_clippy_lint! { @@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { BLOCKS_IN_CONDITIONS, cond.span, BRACED_EXPR_MESSAGE, - "try", + "remove the braces", snippet_block_with_applicability(cx, ex.span, "..", Some(expr.span), &mut applicability), applicability, ); @@ -116,19 +116,35 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { if span.from_expansion() || is_from_proc_macro(cx, cond) { return; } - // move block higher - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( + + span_lint_and_then( cx, BLOCKS_IN_CONDITIONS, expr.span.with_hi(cond.span.hi()), complex_block_message, - "try", - format!( - "let res = {}; {keyword} res", - snippet_block_with_applicability(cx, block.span, "..", Some(expr.span), &mut applicability), - ), - applicability, + |diag| { + // Only suggest fix where let binding is easy to apply i.e. parent node is a block. + // See issue #17068 + if let Node::Block(_) | Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id) { + // move block higher + let mut applicability = Applicability::MachineApplicable; + diag.span_suggestion( + expr.span.with_hi(cond.span.hi()), + "use a binding instead", + format!( + "let res = {}; {keyword} res", + snippet_block_with_applicability( + cx, + block.span, + "..", + Some(expr.span), + &mut applicability + ), + ), + applicability, + ); + } + }, ); } } diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index 0591afaa6c585..f758fb0042301 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -184,16 +184,18 @@ fn offer_suggestion( diag: &mut Diag<'_, ()>, ) { let cast_to_snip = snippet(cx, cast_to_span, ".."); + let mut applicability = Applicability::Unspecified; + let sugg = Sugg::hir_with_context(cx, cast_expr, expr.span.ctxt(), "..", &mut applicability); let suggestion = if cast_to_snip == "_" { - format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_paren()) + format!("{}.try_into()", sugg.maybe_paren()) } else { - format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, "..")) + format!("{cast_to_snip}::try_from({sugg})") }; diag.span_suggestion_verbose( expr.span, "... or use `try_from` and handle the error accordingly", suggestion, - Applicability::Unspecified, + applicability, ); } diff --git a/src/tools/clippy/clippy_lints/src/combined_early_pass.rs b/src/tools/clippy/clippy_lints/src/combined_early_pass.rs index 7494711c1f240..8c01237720a29 100644 --- a/src/tools/clippy/clippy_lints/src/combined_early_pass.rs +++ b/src/tools/clippy/clippy_lints/src/combined_early_pass.rs @@ -10,7 +10,7 @@ //! method disappears entirely, and the passes that do override become direct, //! inlined calls. No vtable, no per-node dynamic dispatch. //! -//! Unlike the late combine there is no `active` gate. rustc drops fully-disabled +//! Unlike the late combine fields are not optional. rustc drops fully-disabled //! late passes via `skippable_lints`, but the early pass runner has //! no such filtering, so a plain forward is equivalent and loses nothing. //! @@ -79,8 +79,8 @@ macro_rules! combined_early_lint_pass { } fn get_lints(&self) -> rustc_lint::LintVec { // Reserve at least one slot per pass up front to skip the early reallocations. - let mut lints = Vec::with_capacity([$(stringify!($field)),*].len()); - $(lints.extend(self.$field.get_lints());)* + let mut lints = Vec::with_capacity(${count($field)}); + $(lints.extend(<$fty>::lint_vec());)* lints } } diff --git a/src/tools/clippy/clippy_lints/src/combined_late_pass.rs b/src/tools/clippy/clippy_lints/src/combined_late_pass.rs index 135603fd15d08..54aec34d61790 100644 --- a/src/tools/clippy/clippy_lints/src/combined_late_pass.rs +++ b/src/tools/clippy/clippy_lints/src/combined_late_pass.rs @@ -5,26 +5,11 @@ //! concrete types and `#[inline(always)]`, unoverridden methods are DCE'd and the //! rest become direct calls, so there is no vtable or per-node dynamic dispatch. //! -//! Mirrors rustc's `declare_combined_late_lint_pass!`, but wraps each field in -//! [`Gated`] with a precomputed `active` flag (the same "lint still needs to run" -//! predicate `rustc_lint::late` uses). Disabled passes are skipped by a branch -//! rather than dropped from a `Vec`, keeping clippy's allow-by-default fast path. - -use rustc_lint::{LintPass, LintVec}; - -/// A pass paired with its precomputed "still needs to run" flag. -pub struct Gated

{ - pub(crate) active: bool, - pub(crate) pass: P, -} - -impl Gated

{ - #[inline] - pub fn new bool>(is_active: &F, pass: P) -> Self { - let active = is_active(&pass.get_lints()); - Gated { active, pass } - } -} +//! Mirrors rustc's `declare_combined_late_lint_pass!`, but wraps each field in an +//! `Option` that is set to `None` if a pass can be skipped (determined by the same +//! "lint still needs to run" predicate `rustc_lint::late` uses). Disabled passes +//! are skipped by a branch rather than dropped from a `Vec`, keeping clippy's +//! allow-by-default fast path. /// Run one field's `check_*`, if that field is active. /// @@ -36,8 +21,8 @@ impl Gated

{ #[macro_export] macro_rules! run_combined_late_lint_pass_field { ($self:ident, $field:ident, $name:ident, ($($arg:expr),* $(,)?)) => { - if $self.$field.active { - rustc_lint::LateLintPass::$name(&mut $self.$field.pass, $($arg),*); + if let Some(pass) = &mut $self.$field { + rustc_lint::LateLintPass::$name(pass, $($arg),*); } }; } @@ -61,7 +46,7 @@ macro_rules! expand_combined_late_lint_pass_methods { ) } -/// Declare the combined struct (one [`Gated`] field per pass) plus its +/// Declare the combined struct (one optional field per pass) plus its /// `LintPass`/`LateLintPass` impls. The method list comes from /// `rustc_lint::late_lint_methods!` so it can't drift from rustc's. /// @@ -75,13 +60,13 @@ macro_rules! combined_late_lint_pass { ) => { #[allow(non_snake_case)] pub struct $name<'tcx> { - $($field: $crate::combined_late_pass::Gated<$fty>,)* + $($field: Option<$fty>,)* } impl<'tcx> $name<'tcx> { pub fn new bool>($($pname: $pty,)* is_active: &F) -> Self { Self { - $($field: $crate::combined_late_pass::Gated::new(is_active, $ctor),)* + $($field: is_active(&<$fty>::lint_vec()).then(|| $ctor),)* } } } @@ -93,8 +78,8 @@ macro_rules! combined_late_lint_pass { } fn get_lints(&self) -> rustc_lint::LintVec { // Reserve at least one slot per pass up front to skip the early reallocations. - let mut lints = Vec::with_capacity([$(stringify!($field)),*].len()); - $(lints.extend(self.$field.pass.get_lints());)* + let mut lints = Vec::with_capacity(${count($field)}); + $(lints.extend(<$fty>::lint_vec());)* lints } } diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 681b36cfb3607..2258ae7659285 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -462,6 +462,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::methods::OPTION_AS_REF_DEREF_INFO, crate::methods::OPTION_FILTER_MAP_INFO, crate::methods::OPTION_MAP_OR_NONE_INFO, + crate::methods::OPTION_ZIP_NONE_INFO, crate::methods::OR_FUN_CALL_INFO, crate::methods::OR_THEN_UNWRAP_INFO, crate::methods::PATH_BUF_PUSH_OVERWRITE_INFO, @@ -572,6 +573,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::needless_ifs::NEEDLESS_IFS_INFO, crate::needless_late_init::NEEDLESS_LATE_INIT_INFO, crate::needless_maybe_sized::NEEDLESS_MAYBE_SIZED_INFO, + crate::needless_nonzero_get::NEEDLESS_NONZERO_GET_INFO, crate::needless_parens_on_range_literals::NEEDLESS_PARENS_ON_RANGE_LITERALS_INFO, crate::needless_pass_by_ref_mut::NEEDLESS_PASS_BY_REF_MUT_INFO, crate::needless_pass_by_value::NEEDLESS_PASS_BY_VALUE_INFO, diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 27fd68531d504..d6812cc29173a 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -101,7 +101,8 @@ impl<'tcx> LateLintPass<'tcx> for Default { format!("calling `{replacement}` is more clear than this expression"), "try", replacement, - Applicability::Unspecified, // First resolve the TODO above + // The trimmed path may not be in scope, so the suggestion cannot be machine-applicable. + Applicability::Unspecified, ); } } diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs index 6e92707510aa1..8b49e88ff96bd 100644 --- a/src/tools/clippy/clippy_lints/src/double_parens.rs +++ b/src/tools/clippy/clippy_lints/src/double_parens.rs @@ -73,7 +73,7 @@ impl EarlyLintPass for DoubleParens { // ^^^^^^^^^ expr // ^^^ arg // ^ inner - ExprKind::Call(_, args) | ExprKind::MethodCall(box MethodCall { args, .. }) + ExprKind::Call(_, args) | ExprKind::MethodCall(MethodCall { args, .. }) if let [arg] = &**args && let ExprKind::Paren(inner) = &arg.kind && expr.span.eq_ctxt(arg.span) diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index f5e721ad6b52a..f8e4a779da6f1 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -57,8 +57,11 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { // HIR nodes inside `format!`'s own expansion (its outer block's tail, its nested // `format_args!`), which would otherwise also pass `first_node_in_macro` and cause the // lint to fire multiple times per call. - if let Some(macro_call) = matching_root_macro_call(cx, expr.span, sym::format_macro) - && first_node_in_macro(cx, expr).is_some_and(|p_expn| p_expn != macro_call.expn) + // + // `first_node_in_macro` is checked first because it is cheaper. + if let Some(p_expn) = first_node_in_macro(cx, expr) + && let Some(macro_call) = matching_root_macro_call(cx, expr.span, sym::format_macro) + && p_expn != macro_call.expn && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 1b7db66366b87..95eb581bcacb3 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -139,7 +139,7 @@ fn check_needless_must_use( attrs: &[Attribute], sig: &FnSig<'_>, ) { - if item_span.in_external_macro(cx.sess().source_map()) { + if item_span.in_external_macro(cx.sess().source_map()) || attr_span.from_expansion() { return; } if returns_unit(decl) { diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs index e4e2145f56d90..a3ced258e2270 100644 --- a/src/tools/clippy/clippy_lints/src/large_futures.rs +++ b/src/tools/clippy/clippy_lints/src/large_futures.rs @@ -7,6 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; +use rustc_middle::ty; declare_clippy_lint! { /// ### What it does @@ -64,9 +65,13 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture { && let ty = cx.typeck_results().expr_ty(arg) && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() && implements_trait(cx, ty, future_trait_def_id, &[]) - && let Ok(layout) = cx - .tcx - .layout_of(cx.typing_env().with_codegen_normalized(cx.tcx).as_query_input(ty)) + && let typing_env = cx.typing_env().with_codegen_normalized(cx.tcx) + // Aliases that were rigid during type checking can be revealed in codegen mode. + && let Ok(ty) = cx.tcx.try_normalize_erasing_regions( + typing_env, + ty::set_aliases_to_non_rigid(cx.tcx, ty), + ) + && let Ok(layout) = cx.tcx.layout_of(typing_env.as_query_input(ty)) && let size = layout.layout.size() && size >= Size::from_bytes(self.future_size_threshold) { diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c539edddf6a4d..f7f5341772623 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -1,10 +1,11 @@ -#![feature(box_patterns)] #![feature(control_flow_into_value)] +#![feature(deref_patterns)] #![feature(exact_div)] #![feature(f128)] #![feature(f16)] #![feature(iter_intersperse)] #![feature(iter_partition_in_place)] +#![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![feature(never_type)] #![feature(rustc_private)] @@ -263,6 +264,7 @@ mod needless_for_each; mod needless_ifs; mod needless_late_init; mod needless_maybe_sized; +mod needless_nonzero_get; mod needless_parens_on_range_literals; mod needless_pass_by_ref_mut; mod needless_pass_by_value; @@ -867,6 +869,7 @@ rustc_lint::late_lint_methods!( RestWhenDestructuringStruct: rest_when_destructuring_struct::RestWhenDestructuringStruct = rest_when_destructuring_struct::RestWhenDestructuringStruct, BlockScrutinee: block_scrutinee::BlockScrutinee = block_scrutinee::BlockScrutinee, NonnullUncheckedOnBoxPtr: nonnull_unchecked_on_box_ptr::NonnullUncheckedOnBoxPtr = nonnull_unchecked_on_box_ptr::NonnullUncheckedOnBoxPtr::new(conf), + NeedlessNonzeroGet: needless_nonzero_get::NeedlessNonzeroGet = needless_nonzero_get::NeedlessNonzeroGet::new(conf), // add late passes here, used by `cargo dev new_lint` ]] ); diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 0ded5b69f56f8..d5ada16a5c9a6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -1,9 +1,12 @@ +use std::hash::{Hash, Hasher}; +use std::{iter, mem}; + use super::NEEDLESS_RANGE_LOOP; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::ty::has_iter_method; use clippy_utils::visitors::is_local_used; -use clippy_utils::{SpanlessEq, contains_name, higher, is_integer_literal, peel_hir_expr_while, sugg}; +use clippy_utils::{SpanlessEq, SpanlessHash, contains_name, higher, is_integer_literal, peel_hir_expr_while, sugg}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::Applicability; @@ -14,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::middle::region; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{Symbol, sym}; -use std::{iter, mem}; +use rustc_span::{Span, SyntaxContext}; /// Checks for looping over a range and then indexing a sequence with it. /// The iteratee must be a range literal. @@ -53,14 +56,10 @@ pub(super) fn check<'tcx>( if visitor.indexed_indirectly.is_empty() && !visitor.unnamed_indexed_indirectly && !visitor.unnamed_indexed_directly - && visitor.indexed_directly.len() == 1 + && let mut indexed_directly_iter = visitor.indexed_directly.into_iter() + && let Some(((indexed, indexed_extended), (indexed_extent, indexed_span))) = indexed_directly_iter.next() + && indexed_directly_iter.next().is_none() { - let (indexed, (indexed_extent, indexed_ty)) = visitor - .indexed_directly - .into_iter() - .next() - .expect("already checked that we have exactly 1 element"); - // ensure that the indexed variable was declared before the loop, see #601 if let Some(indexed_extent) = indexed_extent { let parent_def_id = cx.tcx.hir_get_parent_item(expr.hir_id); @@ -72,6 +71,7 @@ pub(super) fn check<'tcx>( } // don't lint if the container that is indexed does not have .iter() method + let indexed_ty = cx.typeck_results().expr_ty(indexed_extended.expr); let has_iter = has_iter_method(cx, indexed_ty); if has_iter.is_none() { return; @@ -147,44 +147,50 @@ pub(super) fn check<'tcx>( mem::swap(&mut method_1, &mut method_2); } - if visitor.nonindex { - span_lint_and_then( - cx, - NEEDLESS_RANGE_LOOP, - span, - format!("the loop variable `{}` is used to index `{indexed}`", ident.name), - |diag| { + let indexed_extended_snippet = snippet(cx, indexed_extended.expr.span, ".."); + span_lint_and_then( + cx, + NEEDLESS_RANGE_LOOP, + span, + if visitor.nonindex { + format!( + "the loop variable `{}` is used to index `{indexed_extended_snippet}`", + ident.name + ) + } else { + format!( + "the loop variable `{}` is only used to index `{indexed_extended_snippet}`", + ident.name + ) + }, + |diag| { + diag.span_note(indexed_span, "for this index operation"); + if visitor.nonindex { diag.multipart_suggestion( - "consider using an iterator and enumerate()", + "consider using an iterator and `.enumerate()`", vec![ (pat.span, format!("({}, )", ident.name)), - (span, format!("{indexed}.{method}().enumerate(){method_1}{method_2}")), + ( + span, + format!("{indexed_extended_snippet}.{method}().enumerate(){method_1}{method_2}"), + ), ], Applicability::HasPlaceholders, ); - }, - ); - } 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, - span, - format!("the loop variable `{}` is only used to index `{indexed}`", ident.name), - |diag| { + } else { + let repl = if starts_at_zero && take_is_empty { + format!("&{ref_mut}{indexed_extended_snippet}") + } else { + format!("{indexed_extended_snippet}.{method}(){method_1}{method_2}") + }; diag.multipart_suggestion( "consider using an iterator", vec![(pat.span, "".to_string()), (span, repl)], Applicability::HasPlaceholders, ); - }, - ); - } + } + }, + ); } } } @@ -236,7 +242,7 @@ struct VarVisitor<'a, 'tcx> { unnamed_indexed_indirectly: bool, /// 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: FxIndexMap, Ty<'tcx>)>, + indexed_directly: FxIndexMap<(Symbol, SpanlessExpr<'a, 'tcx>), (Option, Span)>, /// directly indexed literals, like `[1, 2, 3][i]` unnamed_indexed_directly: bool, /// Any names that are used outside an index operation. @@ -262,13 +268,24 @@ impl<'tcx> VarVisitor<'_, 'tcx> { index_used_directly &= matches!(idx.kind, ExprKind::Path(_)); } // Handle nested indices - let seqexpr = peel_hir_expr_while(seqexpr, |e| { - if let ExprKind::Index(e, idx, _) = e.kind { - if is_local_used(self.cx, idx, self.var) { - used_cnt += 1; - index_used_directly &= matches!(idx.kind, ExprKind::Path(_)); - } - Some(e) + // For example, in `a.b[0][i][i]`, we will have `nested_seqexpr` be `a.b[0]`, with the corresponding + // `nested_seqexpr_index_span` be the span of `a.b[0][i]`, and `seqexpr` be `a.b`. + let mut nested_seqexpr_index_span = expr.span; + let nested_seqexpr = peel_hir_expr_while(seqexpr, |e| { + if let ExprKind::Index(inner, idx, _) = e.kind + && is_local_used(self.cx, idx, self.var) + { + used_cnt += 1; + index_used_directly &= matches!(idx.kind, ExprKind::Path(_)); + nested_seqexpr_index_span = e.span; + Some(inner) + } else { + None + } + }); + let seqexpr = peel_hir_expr_while(nested_seqexpr, |e| { + if let ExprKind::Index(inner, _, _) | ExprKind::Field(inner, _) = e.kind { + Some(inner) } else { None } @@ -300,8 +317,15 @@ impl<'tcx> VarVisitor<'_, 'tcx> { .unwrap(); if index_used_directly { self.indexed_directly.insert( - seqvar.segments[0].ident.name, - (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)), + ( + seqvar.segments[0].ident.name, + SpanlessExpr { + cx: self.cx, + expr: nested_seqexpr, + ctxt: seqexpr.span.ctxt(), + }, + ), + (Some(extent), nested_seqexpr_index_span), ); } else { self.indexed_indirectly @@ -312,8 +336,15 @@ impl<'tcx> VarVisitor<'_, 'tcx> { Res::Def(DefKind::Static { .. } | DefKind::Const { .. }, ..) => { if index_used_directly { self.indexed_directly.insert( - seqvar.segments[0].ident.name, - (None, self.cx.typeck_results().node_type(seqexpr.hir_id)), + ( + seqvar.segments[0].ident.name, + SpanlessExpr { + cx: self.cx, + expr: nested_seqexpr, + ctxt: seqexpr.span.ctxt(), + }, + ), + (None, nested_seqexpr_index_span), ); } else { self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); @@ -425,3 +456,26 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> { self.prefer_mutable = old; } } + +struct SpanlessExpr<'cx, 'tcx> { + cx: &'cx LateContext<'tcx>, + expr: &'cx Expr<'tcx>, + ctxt: SyntaxContext, +} + +impl PartialEq for SpanlessExpr<'_, '_> { + fn eq(&self, other: &Self) -> bool { + let mut eq = SpanlessEq::new(self.cx); + eq.eq_expr(self.ctxt, self.expr, other.expr) + } +} + +impl Eq for SpanlessExpr<'_, '_> {} + +impl Hash for SpanlessExpr<'_, '_> { + fn hash(&self, state: &mut H) { + let mut hash = SpanlessHash::new(self.cx); + hash.hash_expr(self.expr); + state.write_u64(hash.finish()); + } +} diff --git a/src/tools/clippy/clippy_lints/src/manual_assert_eq.rs b/src/tools/clippy/clippy_lints/src/manual_assert_eq.rs index 402e9e882ccb8..324976632d8fa 100644 --- a/src/tools/clippy/clippy_lints/src/manual_assert_eq.rs +++ b/src/tools/clippy/clippy_lints/src/manual_assert_eq.rs @@ -2,11 +2,12 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::{PanicCall, find_assert_args, root_macro_call_first_node}; use clippy_utils::source::walk_span_to_context; -use clippy_utils::ty::implements_trait; +use clippy_utils::ty::{deref_chain, implements_trait}; use clippy_utils::{is_in_const_context, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; +use rustc_middle::ty::{self, Ty}; declare_clippy_lint! { /// ### What it does @@ -16,6 +17,12 @@ declare_clippy_lint! { /// `assert_{eq,ne}!` and `debug_assert_{eq,ne}!` achieves the same goal, and provides some /// additional debug information /// + /// ### Known problems + /// This lint cannot determine how large the `Debug` output of the compared values will be. + /// To avoid producing excessively large assertion output, it ignores comparisons involving + /// byte-slice-like types. These include byte slices and types that dereference to a byte slice + /// or implement `AsRef<[u8]>` without also implementing `AsRef`. + /// /// ### Example /// ```no_run /// assert!(2 * 2 == 4); @@ -81,6 +88,9 @@ impl LateLintPass<'_> for ManualAssertEq { // Printing raw pointers isn't very useful && !lhs_ty.is_raw_ptr() && !rhs_ty.is_raw_ptr() + // Byte buffers can be large and their debug output is rarely useful + && !is_byte_slice_like(cx, lhs_ty) + && !is_byte_slice_like(cx, rhs_ty) // The output of `(debug_)assert_eq` isn't very useful when one of the sides is a constant value && if eq_kind == EqKind::Ne { let ecx = ConstEvalCtxt::new(cx); @@ -119,3 +129,31 @@ impl LateLintPass<'_> for ManualAssertEq { } } } + +fn is_byte_slice_like<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + let byte_slice = Ty::new_slice(cx.tcx, cx.tcx.types.u8); + let ty = ty.peel_refs(); + + if ty == byte_slice { + return true; + } + if matches!(ty.kind(), ty::Adt(..)) + && cx.tcx.get_diagnostic_item(sym::AsRef).is_some_and(|trait_id| { + implements_trait(cx, ty, trait_id, &[byte_slice.into()]) + && !implements_trait(cx, ty, trait_id, &[cx.tcx.types.str_.into()]) + }) + { + return true; + } + + for (depth, ty) in deref_chain(cx, ty).enumerate().skip(1) { + if !cx.tcx.recursion_limit().value_within_limit(depth) { + return false; + } + if ty == byte_slice { + return true; + } + } + + false +} diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 7bccc30b9e95c..87523cd0e8c81 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -122,11 +122,7 @@ fn is_arms_disjointed(cx: &LateContext<'_>, arm1: &Arm<'_>, arm2: &Arm<'_>) -> b return false; } - if !is_enum_variant(cx, arm1.pat) || !is_enum_variant(cx, arm2.pat) { - return false; - } - - true + is_enum_variant(cx, arm1.pat) && is_enum_variant(cx, arm2.pat) } /// Returns `true` if the given pattern is a variant of an enum. diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 7605c7dda8820..f1c50b55f9eec 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -1209,15 +1209,18 @@ impl<'tcx> LateLintPass<'tcx> for Matches { ); needless_match::check_if_let(cx, expr, &if_let); } - } else { - if expr.span.in_external_macro(cx.tcx.sess.source_map()) { - return; - } - if let Some(while_let) = higher::WhileLet::hir(expr) { - significant_drop_in_scrutinee::check_while_let(cx, expr, while_let.let_expr, while_let.if_then); - } + } else if let Some(while_let) = higher::WhileLet::hir(expr) + && !expr.span.in_external_macro(cx.tcx.sess.source_map()) + { + significant_drop_in_scrutinee::check_while_let(cx, expr, while_let.let_expr, while_let.if_then); if !from_expansion { - redundant_pattern_match::check(cx, expr); + redundant_pattern_match::check_while_let( + cx, + expr, + while_let.let_pat, + while_let.let_expr, + while_let.let_span, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index 037276f868e2b..787e6147d8526 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -4,7 +4,7 @@ use clippy_utils::res::{MaybeDef as _, MaybeTypeckRes as _}; use clippy_utils::sugg::{Sugg, make_unop}; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr_without_closures}; -use clippy_utils::{get_parent_expr, higher, is_expn_of, sym}; +use clippy_utils::{get_parent_expr, is_expn_of, sym}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::attrs::lang_items::LangItem::{ @@ -18,17 +18,15 @@ use rustc_span::{Span, Symbol, kw}; use std::fmt::Write as _; use std::ops::ControlFlow; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::WhileLet { - let_pat, - let_expr, - let_span, - .. - }) = higher::WhileLet::hir(expr) - { - find_method_sugg_for_if_let(cx, expr, let_pat, let_expr, kw::While, false, let_span); - find_if_let_true(cx, let_pat, let_expr, let_span); - } +pub(super) fn check_while_let<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + pat: &'tcx Pat<'_>, + scrutinee: &'tcx Expr<'_>, + let_span: Span, +) { + find_method_sugg_for_if_let(cx, expr, pat, scrutinee, kw::While, false, let_span); + find_if_let_true(cx, pat, scrutinee, let_span); } pub(super) fn check_if_let<'tcx>( diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs b/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs index f1d399e1bbd2f..58453a3c08774 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_contains.rs @@ -3,6 +3,7 @@ use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::peel_hir_pat_refs; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; +use clippy_utils::usage::local_used_in; use rustc_ast::UnOp; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -80,7 +81,7 @@ fn try_get_eligible_arg<'tcx>( } }, _ => { - if switch_to_eager_eval(cx, expr) { + if switch_to_eager_eval(cx, expr) && !local_used_in(cx, closure_arg_id, expr) { Some((get_snippet(expr, true), expr)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 6c7a8d8e143be..84decf478295e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -94,6 +94,7 @@ mod open_options; mod option_as_ref_cloned; mod option_as_ref_deref; mod option_map_or_none; +mod option_zip_none; mod or_fun_call; mod or_then_unwrap; mod path_buf_push_overwrite; @@ -384,7 +385,7 @@ declare_clippy_lint! { /// let (chunks, remainder) = slice.as_chunks::<2>(); /// for chunk in chunks {} /// ``` - #[clippy::version = "1.93.0"] + #[clippy::version = "1.98.0"] pub CHUNKS_EXACT_TO_AS_CHUNKS, style, "using `chunks_exact` with constant when `as_chunks` is more ergonomic" @@ -2978,6 +2979,28 @@ declare_clippy_lint! { "using `Option.map_or(None, f)`, which is more succinctly expressed as `and_then(f)`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calls of the form `Option::zip(_, None)` or `Option::zip(None, _)`. + /// + /// ### Why is this bad? + /// `Option::zip` with `None` always returns `None`. + /// + /// ### Example + /// ```ignore + /// let foo = Some(5); + /// foo.zip(None); + /// ``` + /// Use instead: + /// ```ignore + /// None + /// ``` + #[clippy::version = "1.99.0"] + pub OPTION_ZIP_NONE, + suspicious, + "calling `.zip(None)` on an `Option` always returns `None`" +} + declare_clippy_lint! { /// ### What it does /// Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, @@ -4281,7 +4304,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `fold` when a more succinct alternative exists. /// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, - /// `sum` or `product`. + /// `sum` or `product`, and for folds over an `Option`'s iterator which could be + /// replaced by `map_or`. /// /// ### Why is this bad? /// Readability. @@ -4289,11 +4313,15 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// (0..3).fold(false, |acc, x| acc || x > 2); + /// # let opt = Some(1); + /// opt.iter().fold(0, |acc, x| acc | x); /// ``` /// /// Use instead: /// ```no_run /// (0..3).any(|x| x > 2); + /// # let opt = Some(1); + /// opt.as_ref().map_or(0, |x| 0 | x); /// ``` #[clippy::version = "pre 1.29.0"] pub UNNECESSARY_FOLD, @@ -4429,37 +4457,41 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Converts some constructs mapping an Enum value for equality comparison. + /// Converts some constructs mapping an enum value for equality or variant checks. /// /// ### Why is this bad? /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome, /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`. /// Also, calls such as `opt.map_or(true, |val| val == 5)` can be reduced to /// `opt.is_none_or(|val| val == 5)`. + /// Calls that map the two variants of a `Result` to opposite boolean constants can be + /// reduced to `is_ok()` or `is_err()`. /// This lint offers readability and conciseness improvements. /// /// ### Example /// ```no_run - /// pub fn a(x: Option) -> (bool, bool) { + /// pub fn a(x: Option, result: Result) -> (bool, bool, bool) { /// ( /// x.map_or(false, |n| n == 5), /// x.map_or(true, |n| n > 5), + /// result.map_or_else(|_| false, |_| true), /// ) /// } /// ``` /// Use instead: /// ```no_run - /// pub fn a(x: Option) -> (bool, bool) { + /// pub fn a(x: Option, result: Result) -> (bool, bool, bool) { /// ( /// x == Some(5), /// x.is_none_or(|n| n > 5), + /// result.is_ok(), /// ) /// } /// ``` #[clippy::version = "1.84.0"] pub UNNECESSARY_MAP_OR, style, - "reduce unnecessary calls to `.map_or(bool, …)`" + "reduce unnecessary calls to `.map_or(bool, …)` and `.map_or_else(…, …)`" } declare_clippy_lint! { @@ -5018,6 +5050,7 @@ impl_lint_pass!(Methods => [ OPTION_AS_REF_DEREF, OPTION_FILTER_MAP, OPTION_MAP_OR_NONE, + OPTION_ZIP_NONE, OR_FUN_CALL, OR_THEN_UNWRAP, PATH_BUF_PUSH_OVERWRITE, @@ -5172,6 +5205,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { &self.unwrap_allowed_ids, &self.unwrap_allowed_aliases, ); + option_zip_none::check_call(cx, expr, func, args); }, ExprKind::MethodCall(..) => { self.check_methods(cx, expr); @@ -5520,7 +5554,7 @@ impl Methods { }, (sym::fold, [init, acc]) => { manual_try_fold::check(cx, expr, init, acc, call_span, self.msrv); - unnecessary_fold::check(cx, expr, init, acc, span); + unnecessary_fold::check(cx, expr, recv, init, acc, span); }, (sym::for_each, [arg]) => match method_call(recv) { Some((sym::inspect, _, [_], span2, _)) => inspect_for_each::check(cx, expr, span2), @@ -5638,6 +5672,7 @@ impl Methods { (sym::map_or_else, [def, map]) => { result_map_or_else_none::check(cx, expr, recv, def, map); unnecessary_map_or_else::check(cx, expr, recv, def, map, call_span); + unnecessary_map_or::check_map_or_else(cx, expr, recv, def, map); }, (sym::next, []) => { if let Some((name2, recv2, args2, _, _)) = method_call(recv) { @@ -5995,6 +6030,9 @@ impl Methods { unwrap_expect_used::Variant::Unwrap, ); }, + (sym::zip, [arg]) => { + option_zip_none::check_method(cx, expr, recv, arg); + }, _ => {}, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_zip_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_zip_none.rs new file mode 100644 index 0000000000000..784cac392d360 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/option_zip_none.rs @@ -0,0 +1,87 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::res::{MaybeDef as _, MaybeTypeckRes as _}; +use clippy_utils::source::snippet_with_context; +use clippy_utils::{is_none_expr, sym}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; + +use super::OPTION_ZIP_NONE; + +fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { + let recv_is_none = is_none_expr(cx, recv); + let arg_is_none = is_none_expr(cx, arg); + + if !recv_is_none && !arg_is_none { + return; + } + + span_lint_and_then( + cx, + OPTION_ZIP_NONE, + expr.span, + "calling `.zip()` on an `Option` where one side is `None` always returns `None`", + |diag| { + let mut app = Applicability::MaybeIncorrect; + let ctxt = expr.span.ctxt(); + let none_snippet = if recv_is_none { + snippet_with_context(cx, recv.span, ctxt, "_", &mut app).0 + } else { + snippet_with_context(cx, arg.span, ctxt, "_", &mut app).0 + }; + + if let ExprKind::MethodCall(_, _, _, call_span) = expr.kind { + if recv_is_none && !arg_is_none { + let arg_snip = snippet_with_context(cx, arg.span, ctxt, "_", &mut app).0; + diag.span_suggestion( + expr.span, + "if you meant to zip the contents of the `Option` with `None`, use `Option::map`", + format!("{arg_snip}.map(|n| ({none_snippet}, n))"), + app, + ); + } else if !recv_is_none && arg_is_none { + diag.span_suggestion( + call_span, + "if you meant to zip the contents of the `Option` with `None`, use `Option::map`", + format!("map(|n| (n, {none_snippet}))"), + app, + ); + } + } + }, + ); +} + +pub(super) fn check_call(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>]) { + if let [left, right] = args + && let ExprKind::Path(ref qpath) = func.kind + && let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() + && cx.tcx.item_name(def_id) == sym::zip + && def_id.opt_parent(cx).opt_impl_ty(cx).is_some_and(|impl_ty| { + impl_ty + .instantiate_identity() + .skip_norm_wip() + .ty_adt_def() + .is_some_and(|adt| cx.tcx.is_diagnostic_item(sym::Option, adt.did())) + }) + { + emit_lint(cx, expr, left, right); + } +} + +pub(super) fn check_method(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { + if cx + .ty_based_def(expr) + .opt_parent(cx) + .opt_impl_ty(cx) + .is_some_and(|impl_ty| { + impl_ty + .instantiate_identity() + .skip_norm_wip() + .ty_adt_def() + .is_some_and(|adt| cx.tcx.is_diagnostic_item(sym::Option, adt.did())) + }) + { + emit_lint(cx, expr, recv, arg); + } +} diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index 12f1e25ca117b..1e6e27afc6775 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -1,6 +1,10 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _, MaybeResPath as _, MaybeTypeckRes as _}; use clippy_utils::source::snippet_with_context; +use clippy_utils::ty::is_copy; +use clippy_utils::visitors::for_each_expr; use clippy_utils::{DefinedTy, ExprUseNode, get_expr_use_site, peel_blocks, strip_pat_refs}; use rustc_ast::ast; use rustc_data_structures::packed::Pu128; @@ -178,7 +182,7 @@ fn check_fold_with_method( fold_span: Span, method: Symbol, replacement: Replacement, -) { +) -> bool { // Extract the name of the function passed to `fold` if let Res::Def(DefKind::AssocFn, fn_did) = acc.res_if_named(cx, method) // Check if the function belongs to the operator @@ -204,12 +208,15 @@ fn check_fold_with_method( replacement.maybe_add_note(diag); }, ); + return true; } + false } pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, + recv: &'tcx hir::Expr<'tcx>, init: &hir::Expr<'_>, acc: &hir::Expr<'_>, fold_span: Span, @@ -219,6 +226,21 @@ pub(super) fn check<'tcx>( return; } + if check_standard_fold(cx, expr, init, acc, fold_span) { + return; + } + check_option_fold(cx, expr, recv, init, acc, fold_span); +} + +/// Checks for the `any`/`all`/`sum`/`product` replacements. Returns `true` +/// when a lint was emitted. +fn check_standard_fold<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + init: &hir::Expr<'_>, + acc: &hir::Expr<'_>, + fold_span: Span, +) -> bool { // Check if the first argument to .fold is a suitable literal if let hir::ExprKind::Lit(lit) = init.kind { match lit.node { @@ -229,7 +251,7 @@ pub(super) fn check<'tcx>( has_generic_return: false, is_short_circuiting: true, }; - check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, replacement); + check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, replacement) }, ast::LitKind::Bool(true) => { let replacement = Replacement { @@ -238,7 +260,7 @@ pub(super) fn check<'tcx>( has_generic_return: false, is_short_circuiting: true, }; - check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, replacement); + check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, replacement) }, ast::LitKind::Int(Pu128(0), _) => { let replacement = Replacement { @@ -247,9 +269,8 @@ pub(super) fn check<'tcx>( has_generic_return: needs_turbofish(cx, expr), is_short_circuiting: false, }; - if !check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, replacement) { - check_fold_with_method(cx, expr, acc, fold_span, sym::add, replacement); - } + check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, replacement) + || check_fold_with_method(cx, expr, acc, fold_span, sym::add, replacement) }, ast::LitKind::Int(Pu128(1), _) => { let replacement = Replacement { @@ -258,11 +279,118 @@ pub(super) fn check<'tcx>( has_generic_return: needs_turbofish(cx, expr), is_short_circuiting: false, }; - if !check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, replacement) { - check_fold_with_method(cx, expr, acc, fold_span, sym::mul, replacement); - } + check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, replacement) + || check_fold_with_method(cx, expr, acc, fold_span, sym::mul, replacement) }, - _ => (), + _ => false, + } + } else { + false + } +} + +/// Checks whether `expr` is a path to a closure parameter. +/// +/// Such a binding cannot be used as the substituted `init`: when folds are +/// nested, the enclosing closure may be an accumulator this lint removes in +/// another suggestion, which would leave the copied name unresolved. +fn is_closure_param(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + if let Some(binding_id) = expr.res_local_id() { + let mut in_param = false; + for (_, node) in cx.tcx.hir_parent_iter(binding_id) { + match node { + hir::Node::Pat(_) | hir::Node::PatField(_) => {}, + hir::Node::Param(_) => in_param = true, + hir::Node::Expr(parent) => return in_param && matches!(parent.kind, hir::ExprKind::Closure(_)), + _ => return false, + } } } + false +} + +/// Folding over an `Option`'s iterator visits zero/one items. +/// This is the same as `map_or` if the `init` is `Copy` or a literal. +fn check_option_fold<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + recv: &'tcx hir::Expr<'tcx>, + init: &hir::Expr<'_>, + acc: &hir::Expr<'_>, + fold_span: Span, +) { + let ctxt = expr.span.ctxt(); + match init.kind { + hir::ExprKind::Lit(_) => {}, + hir::ExprKind::Path(_) if is_copy(cx, cx.typeck_results().expr_ty(init)) && !is_closure_param(cx, init) => {}, + _ => return, + } + if let hir::ExprKind::MethodCall(iter_path, option_expr, [], _) = recv.kind + && let adapter = match iter_path.ident.name { + sym::iter => "as_ref().", + sym::iter_mut => "as_mut().", + sym::into_iter => "", + _ => return, + } + && cx.typeck_results().expr_ty(option_expr).is_diag_item(cx, sym::Option) + && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind + && let closure_body = cx.tcx.hir_body(body) + && let [param_acc, param_item] = closure_body.params + // The suggestion rewrites source spans, so bail out when any part + // comes from a different syntax context. + && recv.span.ctxt() == ctxt + && param_acc.pat.span.ctxt() == ctxt + && param_item.pat.span.ctxt() == ctxt + { + // Collect the accumulator uses to substitute with `init`. + // A `mut` accumulator is likely reassigned in the closure body, which + // would turn the substitution into nonsense like `0 += x`. + let acc_id = match strip_pat_refs(param_acc.pat).kind { + PatKind::Binding(hir::BindingMode::NONE, id, ..) => Some(id), + PatKind::Wild => None, + _ => return, + }; + let mut acc_uses: Vec = Vec::new(); + let mut acc_uses_ok = true; + if let Some(acc_id) = acc_id { + for_each_expr(cx.tcx, closure_body.value, |sub_expr| { + if sub_expr.res_local_id() == Some(acc_id) { + if sub_expr.span.ctxt() == ctxt { + acc_uses.push(sub_expr.span); + } else { + acc_uses_ok = false; + } + } + ControlFlow::<()>::Continue(()) + }); + } + if !acc_uses_ok { + return; + } + + let mut applicability = Applicability::MachineApplicable; + let (init_snippet, _) = snippet_with_context(cx, init.span, ctxt, "..", &mut applicability); + + // `.iter().fold(` -> `.as_ref().map_or(`, drop the accumulator + // parameter, and substitute `init` for each use of the accumulator. + acc_uses.sort(); + let mut parts = vec![ + ( + recv.span.with_lo(option_expr.span.hi()).with_hi(init.span.lo()), + format!(".{adapter}map_or("), + ), + (param_acc.pat.span.with_hi(param_item.pat.span.lo()), String::new()), + ]; + parts.extend(acc_uses.into_iter().map(|span| (span, init_snippet.to_string()))); + + span_lint_and_then( + cx, + UNNECESSARY_FOLD, + fold_span.with_hi(expr.span.hi()), + "this `.fold` can be written more succinctly using another method", + |diag| { + diag.multipart_suggestion("try", parts, applicability); + }, + ); + } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs index f8906bb23282d..dff23e1cce061 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs @@ -1,12 +1,13 @@ use std::borrow::Cow; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::sugg::{Sugg, make_binop}; -use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::visitors::is_local_used; +use clippy_utils::ty::{implements_trait, is_copy, needs_ordered_drop}; +use clippy_utils::visitors::{any_temporaries_need_ordered_drop, is_local_used}; use clippy_utils::{get_parent_expr, is_from_proc_macro}; use rustc_ast::LitKind; use rustc_errors::Applicability; @@ -36,15 +37,103 @@ impl Variant { } } -pub(super) fn check<'a>( - cx: &LateContext<'a>, - expr: &Expr<'a>, - recv: &Expr<'_>, - def: &Expr<'_>, - map: &Expr<'_>, +/// Evaluates `expr` and returns its value if it is a constant boolean. +fn bool_constant(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { + let Some(Constant::Bool(value)) = ConstEvalCtxt::new(cx).eval(expr) else { + return None; + }; + Some(value) +} + +/// Returns the constant boolean produced by a one-parameter closure. +fn closure_bool_constant(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { + let ExprKind::Closure(closure) = expr.kind else { + return None; + }; + let body = cx.tcx.hir_body(closure.body); + let [_] = body.params else { + return None; + }; + bool_constant(cx, body.value) +} + +/// Checks whether a `Result::{map_or, map_or_else}` call is a variant query. +/// +/// `expr` is the complete method call, `recv` is its `Result` receiver, `def` is the default +/// argument, and `map` is the mapping closure. `check_if_bool` accounts for the eager default in +/// `map_or` and the closure default in `map_or_else`. +fn check_result_variant_query<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + def: &'tcx Expr<'tcx>, + map: &'tcx Expr<'tcx>, + check_if_bool: impl FnOnce(&LateContext<'tcx>, &'tcx Expr<'tcx>) -> Option, +) -> bool { + let ExprKind::MethodCall(path, _, _, call_span) = expr.kind else { + return false; + }; + let recv_ty = cx.typeck_results().expr_ty_adjusted(recv); + if recv_ty.opt_diag_name(cx) != Some(sym::Result) { + return false; + } + + let def_bool = check_if_bool(cx, def); + let Some((def_bool, map_bool)) = def_bool.zip(closure_bool_constant(cx, map)) else { + return false; + }; + if def_bool == map_bool || is_from_proc_macro(cx, expr) { + return false; + } + + let suggested_name = if map_bool { "is_ok" } else { "is_err" }; + let changes_drop_order = needs_ordered_drop(cx, recv_ty) || any_temporaries_need_ordered_drop(cx, recv); + let applicability = if changes_drop_order { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; + + span_lint_and_then( + cx, + UNNECESSARY_MAP_OR, + path.ident.span, + format!("this `{}` can be simplified", path.ident.name), + |diag| { + diag.span_suggestion( + call_span, + format!("use `{suggested_name}` instead"), + format!("{suggested_name}()"), + applicability, + ); + if changes_drop_order { + diag.note("this will change drop order of the result, as well as all temporaries"); + diag.note("add `#[allow(clippy::unnecessary_map_or)]` if this is important"); + } + }, + ); + true +} + +/// Checks a `map_or` call for both `Result` variant queries and the existing `Option`/`Result` +/// simplifications. +/// +/// `expr` is the complete method call, `recv` is its receiver, `def` is the eager default, and +/// `map` is the mapping closure. `method_span` identifies `map_or` in diagnostics, while `msrv` +/// controls which replacement methods can be suggested. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + def: &'tcx Expr<'tcx>, + map: &'tcx Expr<'tcx>, method_span: Span, msrv: Msrv, ) { + if check_result_variant_query(cx, expr, recv, def, map, bool_constant) { + return; + } + let ExprKind::Lit(def_kind) = def.kind else { return; }; @@ -158,3 +247,17 @@ pub(super) fn check<'a>( }, ); } + +/// Checks a `map_or_else` call for a `Result` variant query. +/// +/// `expr` is the complete method call, `recv` is its `Result` receiver, `def` is the lazy default +/// closure, and `map` is the mapping closure. +pub(super) fn check_map_or_else<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + def: &'tcx Expr<'tcx>, + map: &'tcx Expr<'tcx>, +) { + check_result_variant_query(cx, expr, recv, def, map, closure_bool_constant); +} diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index 3c6b60355a823..ddc61b2449824 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -1,10 +1,13 @@ use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::sugg::Sugg; -use clippy_utils::{SpanlessEq, fulfill_or_allowed, get_parent_expr, in_automatically_derived, last_path_segment}; +use clippy_utils::{fulfill_or_allowed, in_automatically_derived}; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, Stmt, StmtKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{BinOpKind, Expr, ExprKind, HirId, Node, QPath, Stmt, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; +use rustc_middle::ty; +use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -124,122 +127,137 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if expr.span.in_external_macro(cx.sess().source_map()) - || expr.span.desugaring_kind().is_some() - || in_automatically_derived(cx.tcx, expr.hir_id) - { - return; - } - - used_underscore_binding(cx, expr); - used_underscore_items(cx, expr); + check_used_underscore(cx, expr); } } -fn used_underscore_items<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let (def_id, ident) = match expr.kind { - ExprKind::Call(func, ..) => { - if let ExprKind::Path(QPath::Resolved(.., path)) = func.kind - && let Some(last_segment) = path.segments.last() - && let Res::Def(_, def_id) = last_segment.res - { - (def_id, last_segment.ident) - } else { - return; - } - }, - ExprKind::MethodCall(path, ..) => { - if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { - (def_id, path.ident) - } else { - return; - } - }, - ExprKind::Struct(QPath::Resolved(_, path), ..) => { - if let Some(last_segment) = path.segments.last() - && let Res::Def(_, def_id) = last_segment.res - { - (def_id, last_segment.ident) - } else { - return; - } - }, - _ => return, - }; +#[derive(Clone, Copy)] +enum Id<'tcx> { + /// A local binding. + Binding(HirId), + /// A resolved local definition. + LocalDef(LocalDefId), + /// An unresolved type-relative definition. + TyRel, + /// A field of an unresolved type. + FieldOf(&'tcx Expr<'tcx>), +} +impl Id<'_> { + fn from_res(res: Res) -> Option { + match res { + Res::Local(id) => Some(Self::Binding(id)), + Res::Def(_, id) => id.as_local().map(Self::LocalDef), + _ => None, + } + } - let name = ident.name.as_str(); - let definition_span = cx.tcx.def_span(def_id); - if name.starts_with('_') - && !name.starts_with("__") - && !definition_span.from_expansion() - && def_id.is_local() - && !cx.tcx.is_foreign_item(def_id) - { - span_lint_and_then( - cx, - USED_UNDERSCORE_ITEMS, - expr.span, - "used underscore-prefixed item".to_string(), - |diag| { - diag.span_note(definition_span, "item is defined here".to_string()); + fn get_local_def(self, cx: &LateContext<'_>, e: &Expr<'_>, name: Symbol) -> Option<(HirId, Span)> { + let id = match self { + Self::Binding(id) if let Node::Pat(p) = cx.tcx.hir_node(id) => return Some((id, p.span)), + Self::LocalDef(id) => id, + Self::TyRel => cx.typeck_results().type_dependent_def_id(e.hir_id)?.as_local()?, + Self::FieldOf(e) + if let ty::Adt(adt, _) = *cx.typeck_results().expr_ty_adjusted(e).kind() + && adt.did().is_local() + && let [variant] = &adt.variants().raw + && let Some(f) = variant.fields.iter().find(|&f| f.name == name) + && match *cx.tcx.type_of(f.did).instantiate_identity().skip_normalization().kind() { + ty::Adt(adt, _) => !adt.is_phantom_data(), + _ => true, + } + && let Some(id) = f.did.as_local() => + { + id }, - ); + Self::FieldOf(_) | Self::Binding(_) => return None, + }; + if cx.tcx.is_foreign_item(id) { + None + } else { + Some((cx.tcx.local_def_id_to_hir_id(id), cx.tcx.def_span(id))) + } } } -fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let (definition_hir_id, ident) = match expr.kind { - ExprKind::Path(ref qpath) => { - if let QPath::Resolved(None, path) = qpath - && let Res::Local(id) = path.res - && is_used(cx, expr) +fn check_used_underscore<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { + let (ident, id) = match e.kind { + ExprKind::Path(path) => match path { + QPath::Resolved(_, path) + if let Some(id) = Id::from_res(path.res) + && let [.., seg] = path.segments => { - (id, last_path_segment(qpath).ident) - } else { - return; - } + (seg.ident, id) + }, + QPath::Resolved(..) => return, + QPath::TypeRelative(_, seg) => (seg.ident, Id::TyRel), }, - ExprKind::Field(recv, ident) => { - if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def() - && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name) - && let Some(local_did) = field.did.as_local() - && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data() + ExprKind::MethodCall(path, ..) => (path.ident, Id::TyRel), + ExprKind::Struct(path, ..) => match path { + QPath::Resolved(_, path) + if let Some(id) = Id::from_res(path.res) + && let [.., seg] = path.segments => { - (cx.tcx.local_def_id_to_hir_id(local_did), ident) - } else { - return; - } + (seg.ident, id) + }, + QPath::Resolved(..) => return, + QPath::TypeRelative(_, seg) => (seg.ident, Id::TyRel), }, + ExprKind::Field(base, ident) => (ident, Id::FieldOf(base)), _ => return, }; - let name = ident.name.as_str(); - if name.starts_with('_') - && !name.starts_with("__") - && let definition_span = cx.tcx.hir_span(definition_hir_id) - && !definition_span.from_expansion() - && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id]) + if !e.span.from_expansion() + && !ident.span.from_expansion() + && ident + .name + .as_str() + .strip_prefix('_') + .is_some_and(|x| !x.starts_with('_')) + && let Some((def_hir_id, def_sp)) = id.get_local_def(cx, e, ident.name) + && !def_sp.from_expansion() + // Only lint when rustc's `unused_variables` would trigger + && (!matches!(id, Id::Binding(_)) || is_used(cx, e)) + && !in_automatically_derived(cx.tcx, e.hir_id) + && let (lint, msg, help_msg) = match id { + Id::Binding(_) | Id::FieldOf(_) => ( + USED_UNDERSCORE_BINDING, + "used underscore-prefixed binding", + "binding is defined here", + ), + Id::TyRel | Id::LocalDef(_) => ( + USED_UNDERSCORE_ITEMS, + "used underscore-prefixed item", + "item is defined here", + ), + } + && !fulfill_or_allowed(cx, lint, [def_hir_id]) { - span_lint_and_then( - cx, - USED_UNDERSCORE_BINDING, - expr.span, - "used underscore-prefixed binding".to_string(), - |diag| { - diag.span_note(definition_span, "binding is defined here".to_string()); - }, - ); + span_lint_and_then(cx, lint, e.span, msg, |diag| { + diag.span_note(def_sp, help_msg); + }); } } -/// Heuristic to see if an expression is used. Should be compatible with -/// `unused_variables`'s idea -/// of what it means for an expression to be "used". fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - get_parent_expr(cx, expr).is_none_or(|parent| match parent.kind { - ExprKind::Assign(_, rhs, _) | ExprKind::AssignOp(_, _, rhs) => { - SpanlessEq::new(cx).eq_expr(parent.span.ctxt(), rhs, expr) - }, - _ => is_used(cx, parent), - }) + let mut child = expr.hir_id; + let typeck = cx.typeck_results(); + for (id, node) in cx.tcx.hir_parent_iter(child) { + match node { + Node::Expr(e) => match e.kind { + ExprKind::Field(base, ..) if typeck.expr_adjustments(base).is_empty() => child = id, + ExprKind::Assign(lhs, ..) if child == lhs.hir_id => return false, + // Only primitive types are considered unused for compound assignment. + // Everything else uses takes a mutable borrow of the lhs. + ExprKind::AssignOp(_, lhs, _) + if child == lhs.hir_id + && let ty::Int(_) | ty::Uint(_) | ty::Float(_) = *typeck.node_type(child).kind() => + { + return false; + }, + _ => return true, + }, + _ => return true, + } + } + true } diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs index 2d836c862dde1..81a48f9a92a1a 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs @@ -59,10 +59,11 @@ fn is_thread_local_initializer( fn_kind: intravisit::FnKind<'_>, span: rustc_span::Span, ) -> Option { - let macro_def_id = span.source_callee()?.macro_def_id?; Some( - cx.tcx.is_diagnostic_item(sym::thread_local_macro, macro_def_id) - && matches!(fn_kind, intravisit::FnKind::ItemFn(..)), + matches!(fn_kind, intravisit::FnKind::ItemFn(..)) + && cx + .tcx + .is_diagnostic_item(sym::thread_local_macro, span.source_callee()?.macro_def_id?), ) } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index f1baa6a697d78..8b8a471cffbc4 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint; use rustc_hir::{ImplItem, ImplItemKind, Item, ItemKind, OwnerId, TraitFn, TraitItem, TraitItemKind, find_attr}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; -use rustc_structures::CrateType; use rustc_span::Span; +use rustc_structures::CrateType; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index e7a5dcaf2581f..6b3f38565bed3 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -42,7 +42,7 @@ declare_clippy_lint! { /// order of sub-expressions. /// /// ### Why restrict this? - /// While [the evaluation order of sub-expressions] is fully specified in Rust, + /// While [the evaluation order of sub-expressions][order] is fully specified in Rust, /// it still may be confusing to read an expression where the evaluation order /// affects its behavior. /// @@ -71,7 +71,7 @@ declare_clippy_lint! { /// let a = tmp + x; /// ``` /// - /// [order]: (https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands) + /// [order]: https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands #[clippy::version = "pre 1.29.0"] pub MIXED_READ_WRITE_IN_EXPRESSION, restriction, diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index 7ca34f4f5c08b..6a16804200908 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -7,7 +7,9 @@ use clippy_utils::{ }; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::DefId; +use rustc_hir::{Block, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::SyntaxContext; @@ -16,6 +18,9 @@ declare_clippy_lint! { /// Checks for expressions of the form `if c { true } else { /// false }` (or vice versa) and suggests using the condition directly. /// + /// This also covers the early-return guard form, where a condition returns a + /// tuple-like based on it. + /// /// ### Why is this bad? /// Redundant code. /// @@ -42,6 +47,23 @@ declare_clippy_lint! { /// !x /// # ; /// ``` + /// + /// Or, for the early-return guard form: + /// ``` + /// # fn f(c: bool) -> Result { + /// if c { + /// return Ok(true); + /// } + /// Ok(false) + /// # } + /// ``` + /// + /// Use instead: + /// ``` + /// # fn f(c: bool) -> Result { + /// Ok(c) + /// # } + /// ``` #[clippy::version = "pre 1.29.0"] pub NEEDLESS_BOOL, complexity, @@ -197,6 +219,117 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool { } } } + + fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { + // Detect the early-return form: + // if c { + // return Ok(true); + // } + // Ok(false) + // and reduce it to `Ok(c)`. The optional `Ok(..)` wrapper can be any tuple-like + // constructor (or absent), as long as the guard and the trailing expression use the + // same one. Constructors are pure, so folding the condition in keeps the behavior. + if let Some(tail) = block.expr + && !tail.span.from_expansion() + && let [.., last_stmt] = block.stmts + && let StmtKind::Semi(if_expr) | StmtKind::Expr(if_expr) = last_stmt.kind + && !if_expr.span.from_expansion() + && let Some(higher::If { + cond, + then, + r#else: None, + }) = higher::If::hir(if_expr) + && let ExprKind::Ret(Some(ret)) = peel_blocks_with_stmt(then).kind + && let Some((then_func, then_val)) = fetch_bool_and_wrapper(ret) + && let Some((tail_func, tail_val)) = fetch_bool_and_wrapper(tail) + // `if c { return Ok(true) } Ok(true)` is always the same value; the condition might + // have side effects, so don't touch it. Comparing the values here is cheap, so do it + // before the constructor resolution in `wrapper_ctors_match`, which needs `qpath_res`. + && then_val != tail_val + && wrapper_ctors_match(cx, then_func, tail_func) + { + // If there is another `if _ { return ..; }` before the `if_expr`, don't lint. Replacing the last + // `if` won't decrease complexity, without refactoring the entire block. + if block.stmts.len() >= 2 + && let [.., prev_stmt, _] = block.stmts + && let StmtKind::Semi(prev_if_expr) | StmtKind::Expr(prev_if_expr) = prev_stmt.kind + && let Some(higher::If { + cond: _, + then: prev_then, + r#else: None, + }) = higher::If::hir(prev_if_expr) + && let ExprKind::Ret(Some(_)) = peel_blocks_with_stmt(prev_then).kind + { + return; + } + + let span = if_expr.span.to(tail.span); + if span_contains_comment(cx, span) { + return; + } + + let mut applicability = Applicability::MachineApplicable; + let mut snip = Sugg::hir_with_context(cx, cond, span.ctxt(), "..", &mut applicability); + // `then_val` is the value returned when the condition holds, so a `false` there means + // the result is the negation of the condition. + if !then_val { + snip = !snip; + } + let sugg = match tail_func { + Some(func) => { + let func_snip = snippet_with_context(cx, func.span, span.ctxt(), "..", &mut applicability).0; + format!("{func_snip}({snip})") + }, + None => snip.to_string(), + }; + + span_lint_and_sugg( + cx, + NEEDLESS_BOOL, + span, + "this `if` guard returns a bool literal and is followed by another", + "you can reduce it to", + sugg, + applicability, + ); + } + } +} + +/// Returns the optional constructor call wrapping a bool literal (e.g. the `Ok` in `Ok(true)`) +/// along with the bool value. The constructor is returned as the unresolved callee expression; +/// resolving it to a `DefId` (via [`wrapper_ctors_match`]) needs `qpath_res`, which is +/// comparatively expensive, so callers should only do that once the cheap bool-value comparison +/// has passed. A bare bool literal yields `None`. +fn fetch_bool_and_wrapper<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(Option<&'tcx Expr<'tcx>>, bool)> { + let expr = peel_blocks(expr); + if let Some(value) = fetch_bool_expr(expr) { + return Some((None, value)); + } + if let ExprKind::Call(func, [arg]) = expr.kind + && let Some(value) = fetch_bool_expr(arg) + { + return Some((Some(func), value)); + } + None +} + +/// Checks whether two optional wrapper-constructor call expressions (as returned by +/// [`fetch_bool_and_wrapper`]) are absent on both sides, or call the same tuple-like constructor. +fn wrapper_ctors_match(cx: &LateContext<'_>, a: Option<&Expr<'_>>, b: Option<&Expr<'_>>) -> bool { + fn resolve_ctor(cx: &LateContext<'_>, func: &Expr<'_>) -> Option { + if let ExprKind::Path(qpath) = &func.kind + && let Res::Def(DefKind::Ctor(..), did) = cx.qpath_res(qpath, func.hir_id) + { + return Some(did); + } + None + } + match (a, b) { + (None, None) => true, + (Some(a), Some(b)) => resolve_ctor(cx, a).is_some_and(|a| Some(a) == resolve_ctor(cx, b)), + _ => false, + } } enum Expression { diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index 1aa07f76feadb..953c6d507bffb 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -370,7 +370,7 @@ fn referent_used_exactly_once<'tcx>( && let [location] = *local_assignments(mir, local).as_slice() && let block_data = &mir.basic_blocks[location.block] && let Some(statement) = block_data.statements.get(location.statement_index) - && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind + && let StatementKind::Assign((_, Rvalue::Ref(_, _, place))) = statement.kind && !place.is_indirect_first_projection() { let body_owner_local_def_id = cx.tcx.hir_enclosing_body_owner(reference.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/needless_nonzero_get.rs b/src/tools/clippy/clippy_lints/src/needless_nonzero_get.rs new file mode 100644 index 0000000000000..ee55cbebd522b --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/needless_nonzero_get.rs @@ -0,0 +1,231 @@ +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::Msrv; +use clippy_utils::ty::implements_trait; +use clippy_utils::{binop_traits, is_from_proc_macro, span_contains_comment, sym}; +use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; +use rustc_hir::{AssignOpKind, BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; +use rustc_middle::ty::{self, Ty}; +use rustc_span::{Span, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for `NonZero::get` calls that are immediately followed by a method or operator + /// which `NonZero` provides itself, with the same return type. + /// + /// ### Why is this bad? + /// The `get` call adds nothing but noise, as the method could be called on the + /// `NonZero` value directly. + /// + /// ### Example + /// ```no_run + /// # use std::num::NonZero; + /// # let nz = NonZero::new(1u32).unwrap(); + /// let _ = nz.get().leading_zeros(); + /// ``` + /// Use instead: + /// ```no_run + /// # use std::num::NonZero; + /// # let nz = NonZero::new(1u32).unwrap(); + /// let _ = nz.leading_zeros(); + /// ``` + /// + /// The lint also handles division and remainder operators: + /// ```no_run + /// # use std::num::NonZero; + /// # let nz = NonZero::new(2u32).unwrap(); + /// let _ = 4 / nz.get(); + /// ``` + /// Use instead: + /// ```no_run + /// # use std::num::NonZero; + /// # let nz = NonZero::new(2u32).unwrap(); + /// let _ = 4 / nz; + /// ``` + #[clippy::version = "1.99.0"] + pub NEEDLESS_NONZERO_GET, + complexity, + "unnecessary `NonZero::get` call" +} + +impl_lint_pass!(NeedlessNonzeroGet => [NEEDLESS_NONZERO_GET]); + +pub struct NeedlessNonzeroGet { + msrv: Msrv, +} + +impl NeedlessNonzeroGet { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv.into() } + } +} + +impl<'tcx> LateLintPass<'tcx> for NeedlessNonzeroGet { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + match expr.kind { + // `.get().()` + ExprKind::MethodCall(method, get_call, [], _) + if let Some((recv, nz_ty, nonzero_did, get_span)) = nonzero_get(cx, get_call) + // The outer call must resolve to an inherent method. A trait method of the same + // name could resolve differently once the receiver becomes a `NonZero`. + && let Some(method_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && cx.tcx.trait_of_assoc(method_did).is_none() + // Dropping `get` must leave the expression's type unchanged. Methods whose + // `NonZero` version returns a `NonZero` deliberately do not match. + && let ret_ty = cx.typeck_results().expr_ty(expr) + && has_matching_method(cx, nonzero_did, nz_ty, method.ident.name, ret_ty, self.msrv) => + { + emit_unnecessary_get(cx, expr, get_call, recv, get_span, method.ident.name.as_str()); + }, + + // ` / .get()` and ` % .get()` + ExprKind::Binary(op, lhs, get_call) + if matches!(op.node, BinOpKind::Div | BinOpKind::Rem) + && let Some((recv, nz_ty, _, get_span)) = nonzero_get(cx, get_call) + && let Some((trait_lang_item, _)) = binop_traits(op.node) + && let Some(trait_id) = cx.tcx.lang_items().get(trait_lang_item) + && has_nonzero_operator(cx, lhs, recv, nz_ty, trait_id, self.msrv) => + { + emit_unnecessary_get(cx, expr, get_call, recv, get_span, op.node.as_str()); + }, + + // ` /= .get()` and ` %= .get()` + ExprKind::AssignOp(op, lhs, get_call) + if matches!(op.node, AssignOpKind::DivAssign | AssignOpKind::RemAssign) + && let Some((recv, nz_ty, _, get_span)) = nonzero_get(cx, get_call) + && let Some((_, trait_lang_item)) = binop_traits(op.node.into()) + && let Some(trait_id) = cx.tcx.lang_items().get(trait_lang_item) + && has_nonzero_operator(cx, lhs, recv, nz_ty, trait_id, self.msrv) => + { + emit_unnecessary_get(cx, expr, get_call, recv, get_span, op.node.as_str()); + }, + + _ => {}, + } + } +} + +/// Returns the receiver, its `NonZero` type and definition, and the `get` identifier span when +/// `expr` is an inherent `NonZero::get()` call. +fn nonzero_get<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, +) -> Option<(&'tcx Expr<'tcx>, Ty<'tcx>, DefId, Span)> { + let ExprKind::MethodCall(get, recv, [], get_span) = expr.kind else { + return None; + }; + if get.ident.name != sym::get { + return None; + } + let get_did = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; + if cx.tcx.trait_of_assoc(get_did).is_some() { + return None; + } + let nz_ty = cx.typeck_results().expr_ty_adjusted(recv); + let ty::Adt(adt, _) = nz_ty.kind() else { + return None; + }; + if !cx.tcx.is_diagnostic_item(sym::NonZero, adt.did()) { + return None; + } + + Some((recv, nz_ty, adt.did(), get_span)) +} + +fn emit_unnecessary_get<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + get_call: &Expr<'tcx>, + recv: &Expr<'tcx>, + get_span: Span, + operation: &str, +) { + // Removing `.get()` means editing the span between the receiver and the surrounding + // expression, which is only meaningful when both are written out in the same context. + if expr.span.from_expansion() + || !recv.span.eq_ctxt(expr.span) + || !get_call.span.eq_ctxt(expr.span) + || is_from_proc_macro(cx, expr) + { + return; + } + + span_lint_and_then( + cx, + NEEDLESS_NONZERO_GET, + get_span, + format!("unnecessary `get` before `{operation}`"), + |diag| { + // Covers `.get()` including the dot and any whitespace before it. + let removal_span = get_call.span.with_lo(recv.span.hi()); + let applicability = if span_contains_comment(cx, removal_span) { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; + diag.span_suggestion_verbose(removal_span, "remove this", "", applicability); + }, + ); +} + +/// Checks whether replacing the right-hand primitive operand with its `NonZero` receiver resolves +/// to an unsigned standard-library operator implementation that is usable under `msrv`. In a +/// `const` context that means const-stable, which the `NonZero` operator implementations are not. +fn has_nonzero_operator<'tcx>( + cx: &LateContext<'tcx>, + lhs: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + nz_ty: Ty<'tcx>, + trait_id: DefId, + msrv: Msrv, +) -> bool { + let lhs_ty = cx.typeck_results().expr_ty(lhs); + let ty::Adt(_, args) = nz_ty.kind() else { + return false; + }; + let inner_ty = args.type_at(0); + + // Primitive operators forward some reference operands, whereas the `NonZero` implementations + // do not. Require the exact written operand types so the replacement is guaranteed to resolve. + lhs_ty == inner_ty + && cx.typeck_results().expr_ty(recv) == nz_ty + && matches!(lhs_ty.kind(), ty::Uint(_)) + && implements_trait(cx, lhs_ty, trait_id, &[nz_ty.into()]) + && cx.tcx.non_blanket_impls_for_ty(trait_id, lhs_ty).any(|impl_id| { + let trait_ref = cx.tcx.impl_trait_ref(impl_id).instantiate_identity().skip_norm_wip(); + trait_ref.args.type_at(1) == nz_ty && msrv.is_stable_or_const_stable(cx, impl_id) + }) +} + +/// Checks whether `nz_ty` has an inherent method `name` taking nothing but `self` and returning +/// exactly `ret_ty`, which is usable under `msrv` (const-stable when in a `const` context, stable +/// otherwise). +fn has_matching_method<'tcx>( + cx: &LateContext<'tcx>, + nonzero_did: DefId, + nz_ty: Ty<'tcx>, + name: Symbol, + ret_ty: Ty<'tcx>, + msrv: Msrv, +) -> bool { + cx.tcx.inherent_impls(nonzero_did).iter().any(|&impl_did| { + // The integer methods live in concrete `impl NonZero`-style blocks, so their + // signatures need no instantiation. Restricting to the impl matching the receiver also + // keeps signed-only methods off unsigned `NonZero`s and vice versa. + cx.tcx.type_of(impl_did).instantiate_identity().skip_norm_wip() == nz_ty + && cx + .tcx + .associated_items(impl_did) + .filter_by_name_unhygienic(name) + .any(|item| { + item.is_fn() && { + let sig = cx.tcx.fn_sig(item.def_id).instantiate_identity().skip_binder(); + sig.inputs().len() == 1 + && sig.output() == ret_ty + && msrv.is_stable_or_const_stable(cx, item.def_id) + } + }) + }) +} diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 81ffd0f48c763..0f59c7696bf54 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -403,7 +403,7 @@ impl EarlyLintPass for NonExpressiveNames { return; } - if let ItemKind::Fn(box ast::Fn { + if let ItemKind::Fn(ast::Fn { ref sig, body: Some(ref blk), .. @@ -418,7 +418,7 @@ impl EarlyLintPass for NonExpressiveNames { return; } - if let AssocItemKind::Fn(box ast::Fn { + if let AssocItemKind::Fn(ast::Fn { ref sig, body: Some(ref blk), .. diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index e7ee8535e5f5a..ea3b93c071526 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -186,11 +186,7 @@ fn ty_allowed_without_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty return true; } - if is_copy(cx, ty) && !contains_pointer_like(cx, ty) { - return true; - } - - false + is_copy(cx, ty) && !contains_pointer_like(cx, ty) } /// Heuristic to allow cases like `Vec<*const u8>` diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index 0cb764bbe2c33..1bd954bf1421e 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -1095,6 +1095,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators { self.arithmetic_context.check_binary(cx, e, bin_op, lhs, rhs); misrefactored_assign_op::check(cx, e, bin_op, lhs, rhs); modulo_arithmetic::check(cx, e, bin_op, lhs, rhs, false); + integer_division_remainder_used::check(cx, bin_op, lhs, rhs, e.span); }, ExprKind::Assign(lhs, rhs, _) => { assign_op_pattern::check(cx, e, lhs, rhs, self.msrv); diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs index 11eb17590353b..4220ed9b5f50a 100644 --- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs @@ -34,7 +34,7 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]); impl EarlyLintPass for OptionEnvUnwrap { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &expr.kind + if let ExprKind::MethodCall(MethodCall { seg, receiver, .. }) = &expr.kind && matches!(seg.ident.name, sym::expect | sym::unwrap) && is_direct_expn_of(receiver.span, sym::option_env).is_some() { diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 996c8d00ed15c..d696296301893 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -41,11 +41,11 @@ declare_lint_pass!(RedundantAsyncBlock => [REDUNDANT_ASYNC_BLOCK]); impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let span = expr.span; - if !span.in_external_macro(cx.tcx.sess.source_map()) && - let Some(body_expr) = desugar_async_block(cx, expr) && + if let Some(body_expr) = desugar_async_block(cx, expr) && let Some(expr) = desugar_await(peel_blocks(body_expr)) && // The await prefix must not come from a macro as its content could change in the future. expr.span.eq_ctxt(body_expr.span) && + !span.in_external_macro(cx.tcx.sess.source_map()) && // The await prefix must implement Future, as implementing IntoFuture is not enough. let Some(future_trait) = cx.tcx.lang_items().future_trait() && implements_trait(cx, cx.typeck_results().expr_ty(expr), future_trait, &[]) && diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index 1a2603640e008..c48c7f25f3522 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -14,15 +14,6 @@ use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::LocalDefId; use rustc_span::{BytePos, Span}; -macro_rules! unwrap_or_continue { - ($x:expr) => { - match $x { - Some(x) => x, - None => continue, - } - }; -} - declare_clippy_lint! { /// ### What it does /// Checks for a redundant `clone()` (and its relatives) which clones an owned @@ -94,8 +85,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { continue; } - let (fn_def_id, arg, arg_ty, clone_ret) = - unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind)); + let Some((fn_def_id, arg, arg_ty, clone_ret)) = is_call_with_ref_arg(cx, mir, &terminator.kind) else { + continue; + }; let fn_name = cx.tcx.get_diagnostic_name(fn_def_id); @@ -116,7 +108,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { } // `{ arg = &cloned; clone(move arg); }` or `{ arg = &cloned; to_path_buf(arg); }` - let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb)); + let Some((cloned, cannot_move_out)) = find_stmt_assigns_to(cx, mir, arg, from_borrow, bb) else { + continue; + }; let loc = mir::Location { block: bb, @@ -157,8 +151,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { continue; }; - let (local, cannot_move_out) = - unwrap_or_continue!(find_stmt_assigns_to(cx, mir, pred_arg, true, ps[0])); + let Some((local, cannot_move_out)) = find_stmt_assigns_to(cx, mir, pred_arg, true, ps[0]) else { + continue; + }; let loc = mir::Location { block: bb, statement_index: mir.basic_blocks[bb].statements.len(), @@ -285,7 +280,7 @@ fn find_stmt_assigns_to<'tcx>( bb: mir::BasicBlock, ) -> Option<(mir::Local, CannotMoveOut)> { let rvalue = mir.basic_blocks[bb].statements.iter().rev().find_map(|stmt| { - if let mir::StatementKind::Assign(box (mir::Place { local, .. }, v)) = &stmt.kind { + if let mir::StatementKind::Assign((mir::Place { local, .. }, v)) = &stmt.kind { return if *local == to_local { Some(v) } else { None }; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index eafea40927fd8..25c137dec7375 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -163,10 +163,6 @@ fn get_parent_call_exprs<'tcx>( impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if expr.span.in_external_macro(cx.sess().source_map()) { - return; - } - if let ExprKind::Call(recv, _) = expr.kind // don't lint if the receiver is a call, too. // we do this in order to prevent linting multiple times; consider: @@ -174,6 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { // ^^ we only want to lint for this call (but we walk up the calls to consider both calls). // without this check, we'd end up linting twice. && !matches!(recv.kind, ExprKind::Call(..)) + && !expr.span.in_external_macro(cx.sess().source_map()) // Check if `recv` comes from a macro expansion. If it does, make sure that it's an expansion that is // the same as the one the call is in. // For instance, let's assume `x!()` returns a closure: diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index de80781d64ded..273ea7506431e 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -94,13 +94,13 @@ impl EarlyLintPass for RedundantStaticLifetimes { } if !item.span.from_expansion() { - if let ItemKind::Const(box ConstItem { ty: ref var_type, .. }) = item.kind { + if let ItemKind::Const(ConstItem { ty: ref var_type, .. }) = item.kind { Self::visit_type(var_type, cx, "constants have by default a `'static` lifetime"); // Don't check associated consts because `'static` cannot be elided on those (issue // #2438) } - if let ItemKind::Static(box StaticItem { ty: ref var_type, .. }) = item.kind { + if let ItemKind::Static(StaticItem { ty: ref var_type, .. }) = item.kind { Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } diff --git a/src/tools/clippy/clippy_lints/src/rest_when_destructuring_struct.rs b/src/tools/clippy/clippy_lints/src/rest_when_destructuring_struct.rs index 865bb28689e5f..89af7a520ce3e 100644 --- a/src/tools/clippy/clippy_lints/src/rest_when_destructuring_struct.rs +++ b/src/tools/clippy/clippy_lints/src/rest_when_destructuring_struct.rs @@ -91,8 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for RestWhenDestructuringStruct { && let qty = cx.typeck_results().qpath_res(&path, pat.hir_id) && let ty = cx.typeck_results().pat_ty(pat) && let ty::Adt(a, _) = ty.kind() - && let Some(vid) = qty.opt_def_id().map(|x| a.variant_index_with_id(x)) - && let Some(variant) = a.variants().get(vid) + && let variant = a.variant_of_res(qty) { let mut missing_suggestions = String::new(); let mut needs_dotdot = variant.field_list_has_applicable_non_exhaustive(); diff --git a/src/tools/clippy/clippy_lints/src/returns/let_and_return.rs b/src/tools/clippy/clippy_lints/src/returns/let_and_return.rs index 1041dadaf4d10..33d3e15412060 100644 --- a/src/tools/clippy/clippy_lints/src/returns/let_and_return.rs +++ b/src/tools/clippy/clippy_lints/src/returns/let_and_return.rs @@ -6,8 +6,8 @@ use clippy_utils::visitors::for_each_expr; use clippy_utils::{binary_expr_needs_parentheses, fn_def_id, span_contains_non_whitespace}; use core::ops::ControlFlow; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, PatKind, StmtKind}; -use rustc_lint::{LateContext, LintContext as _}; +use rustc_hir::{Block, Expr, PatKind, Stmt, StmtKind}; +use rustc_lint::{LateContext, Level, LintContext as _}; use rustc_middle::ty::GenericArgKind; use rustc_span::edition::Edition; @@ -28,7 +28,7 @@ pub(super) fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>) && !initexpr.span.in_external_macro(cx.sess().source_map()) && !retexpr.span.in_external_macro(cx.sess().source_map()) && !local.span.from_expansion() - && !span_contains_non_whitespace(cx, stmt.span.between(retexpr.span), false) + && has_lint_attrs_or_only_whitespace_between(cx, retexpr, stmt) { span_lint_hir_and_then( cx, @@ -86,3 +86,16 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) }) .is_some() } + +/// Returns true if the return expression has lint-level attributes, +/// or if there is only whitespace between `let` and return expression. +/// Non-lint attrs like `#[cfg]` should still block. +fn has_lint_attrs_or_only_whitespace_between(cx: &LateContext<'_>, retexpr: &Expr<'_>, stmt: &Stmt<'_>) -> bool { + // TODO: Turn into find_attr! when lint level attr parsing is done. + let retexpr_attrs = cx.tcx.hir_attrs(retexpr.hir_id); + + retexpr_attrs + .iter() + .any(|a| a.name().is_some_and(|name| Level::from_symbol(name).is_some())) + || !span_contains_non_whitespace(cx, stmt.span.between(retexpr.span), false) +} diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs index ffed62015ddaf..45eca1f95fb41 100644 --- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_automatically_derived; use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::{Block, ExprKind}; @@ -39,6 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned { if !block.span.from_expansion() && let Some(expr) = block.expr && !from_attr_macro(expr.span) + && !in_automatically_derived(cx.tcx, expr.hir_id) && let t_expr = cx.typeck_results().expr_ty(expr) && t_expr.is_unit() && let mut app = Applicability::MachineApplicable diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index bd23aabeb08a3..d97a1205d4378 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -320,11 +320,11 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { ); } - if !e.span.in_external_macro(cx.sess().source_map()) - && let ExprKind::MethodCall(path, receiver, ..) = &e.kind + if let ExprKind::MethodCall(path, receiver, ..) = &e.kind && path.ident.name == sym::as_bytes && let ExprKind::Lit(lit) = &receiver.kind && let LitKind::Str(lit_content, _) = &lit.node + && !e.span.in_external_macro(cx.sess().source_map()) { let callsite = snippet(cx, receiver.span.source_callsite(), r#""foo""#); let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index 3ebe96c177c6e..23c137c25f823 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -247,7 +247,13 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec, focus_idx: usize // FIXME(pin_ergonomics): handle pinned patterns | Ref(_, _, Mutability::Not) // Dealt with elsewhere. - | Or(_) | Paren(_) | Deref(_) | Guard(..) => false, + | Or(_) | Paren(_) | Guard(..) => false, + // Transform `deref!(x) | ... | deref!(y)` into `deref!(x | y)`. + Deref(target) => extend_with_matching( + target, start, alternatives, + |k| matches!(k, Deref(_)), + |k| always_pat!(k, Deref(p) => *p), + ), // Transform `box x | ... | box y` into `box (x | y)`. // // The cases below until `Slice(...)` deal with *singleton* products. diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index cb61559855a02..dcd82e29a0bee 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -156,10 +156,7 @@ fn non_consuming_ok_arm<'a>(cx: &LateContext<'a>, arm: &hir::Arm<'a>) -> bool { return false; } - if is_ok_wild_or_dotdot_pattern(cx, arm.pat) { - return true; - } - false + is_ok_wild_or_dotdot_pattern(cx, arm.pat) } fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs index 887b622b50eb7..3f7055d8674ce 100644 --- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs +++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs @@ -33,7 +33,7 @@ declare_clippy_lint! { declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]); fn is_useless_rounding(cx: &EarlyContext<'_>, expr: &Expr) -> Option<(Symbol, String)> { - if let ExprKind::MethodCall(box MethodCall { + if let ExprKind::MethodCall(MethodCall { seg: name_ident, receiver, .. diff --git a/src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs b/src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs index b5a12606fb3ec..1d6b958084635 100644 --- a/src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs +++ b/src/tools/clippy/clippy_lints_internal/src/almost_standard_lint_formulation.rs @@ -3,8 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use regex::Regex; use rustc_ast::token::DocFragmentKind; use rustc_hir::{Attribute, Item, ItemKind, Mutability}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_lint::{LateContext, LateLintPass, declare_tool_lint, impl_lint_pass}; use rustc_span::{Span, Symbol}; declare_tool_lint! { diff --git a/src/tools/clippy/clippy_lints_internal/src/collapsible_span_lint_calls.rs b/src/tools/clippy/clippy_lints_internal/src/collapsible_span_lint_calls.rs index 77a17110bf81a..14fb62e467db1 100644 --- a/src/tools/clippy/clippy_lints_internal/src/collapsible_span_lint_calls.rs +++ b/src/tools/clippy/clippy_lints_internal/src/collapsible_span_lint_calls.rs @@ -3,8 +3,7 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::{SpanlessEq, is_lint_allowed, peel_blocks_with_stmt, sym}; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{LateContext, LateLintPass, declare_lint_pass, declare_tool_lint}; use rustc_span::{Span, SyntaxContext}; use std::borrow::{Borrow as _, Cow}; diff --git a/src/tools/clippy/clippy_lints_internal/src/lib.rs b/src/tools/clippy/clippy_lints_internal/src/lib.rs index 5fd3f239fdf20..2d06940981795 100644 --- a/src/tools/clippy/clippy_lints_internal/src/lib.rs +++ b/src/tools/clippy/clippy_lints_internal/src/lib.rs @@ -21,7 +21,6 @@ extern crate rustc_errors; extern crate rustc_hir; extern crate rustc_lint; extern crate rustc_middle; -extern crate rustc_session; extern crate rustc_span; mod almost_standard_lint_formulation; diff --git a/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs index c944dead678b1..5cf5d5a85bf13 100644 --- a/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs @@ -8,9 +8,8 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; use rustc_hir::{CRATE_HIR_ID, ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, declare_tool_lint, impl_lint_pass}; use rustc_middle::hir::nested_filter; -use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Symbol; use rustc_span::{Span, Spanned}; diff --git a/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs index 52f911b494fbb..1c0cf79b4c485 100644 --- a/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs +++ b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs @@ -4,9 +4,8 @@ use clippy_utils::source::snippet; use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_lint::{LateContext, LateLintPass, LintContext as _}; +use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass, declare_tool_lint}; use rustc_middle::ty::{self, GenericArgKind}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_tool_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints_internal/src/produce_ice.rs b/src/tools/clippy/clippy_lints_internal/src/produce_ice.rs index 9beab9568abb5..82a6bcdf36af6 100644 --- a/src/tools/clippy/clippy_lints_internal/src/produce_ice.rs +++ b/src/tools/clippy/clippy_lints_internal/src/produce_ice.rs @@ -1,7 +1,6 @@ use rustc_ast::ast::NodeId; use rustc_ast::visit::FnKind; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext as _}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext as _, declare_lint_pass, declare_tool_lint}; use rustc_span::Span; declare_tool_lint! { diff --git a/src/tools/clippy/clippy_lints_internal/src/repeated_is_diagnostic_item.rs b/src/tools/clippy/clippy_lints_internal/src/repeated_is_diagnostic_item.rs index a7599ae21350c..a2d85c056d3fa 100644 --- a/src/tools/clippy/clippy_lints_internal/src/repeated_is_diagnostic_item.rs +++ b/src/tools/clippy/clippy_lints_internal/src/repeated_is_diagnostic_item.rs @@ -9,9 +9,8 @@ use clippy_utils::visitors::for_each_expr; use clippy_utils::{eq_expr_value, if_sequence, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Node, StmtKind, UnOp}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, declare_lint_pass, declare_tool_lint}; use rustc_middle::ty::print::with_forced_trimmed_paths; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; declare_tool_lint! { diff --git a/src/tools/clippy/clippy_lints_internal/src/symbols.rs b/src/tools/clippy/clippy_lints_internal/src/symbols.rs index ae74186ea90c2..d0a5b3590fbae 100644 --- a/src/tools/clippy/clippy_lints_internal/src/symbols.rs +++ b/src/tools/clippy/clippy_lints_internal/src/symbols.rs @@ -5,10 +5,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, Lit, Node, Pat, PatExprKind, PatKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, declare_tool_lint, impl_lint_pass}; use rustc_middle::mir::ConstValue; use rustc_middle::ty; -use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol::Symbol; use rustc_span::{Span, sym}; diff --git a/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs b/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs index 9ca4ae31d455c..8e4a83b7be4e1 100644 --- a/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs +++ b/src/tools/clippy/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs @@ -1,8 +1,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::sym; use rustc_ast::ast::{Crate, ItemKind, ModKind}; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{EarlyContext, EarlyLintPass, declare_lint_pass, declare_tool_lint}; declare_tool_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints_internal/src/unusual_names.rs b/src/tools/clippy/clippy_lints_internal/src/unusual_names.rs index 4f2dd8cfc8093..f7a5b1e591030 100644 --- a/src/tools/clippy/clippy_lints_internal/src/unusual_names.rs +++ b/src/tools/clippy/clippy_lints_internal/src/unusual_names.rs @@ -5,9 +5,8 @@ use itertools::Itertools as _; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, Pat, PatKind, Stmt, StmtKind}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, declare_lint_pass, declare_tool_lint}; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::kw; use rustc_span::{Span, Symbol}; diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index db6108cc9861e..b829b1100d377 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.99" +version = "0.1.100" edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md index 9aa097f8863ec..95fd1bd0ee7fc 100644 --- a/src/tools/clippy/clippy_utils/README.md +++ b/src/tools/clippy/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-08-07 +nightly-2026-08-23 ``` diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index f3c4ae3500af7..39c0e424b6585 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -28,7 +28,7 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { // Always use .0 because we do not generate separate lint doc pages for rust patch releases Some("stable") => concat!("rust-1.", env!("CARGO_PKG_VERSION_PATCH"), ".0"), Some("beta") => "beta", - _ => "master", + _ => "main", } )); } diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 736369ba78577..442eda329a475 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -370,9 +370,14 @@ impl<'a> VecArgs<'a> { pub fn hir(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option> { if let ExprKind::Call(fun, args) = expr.kind && let ExprKind::Path(ref qpath) = fun.kind - && is_expn_of(fun.span, sym::vec).is_some() && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id) + && matches!( + name, + sym::vec_from_elem | sym::box_assume_init_into_vec_unsafe | sym::vec_new + ) + // Do the cheap checks first, since `is_expn_of` walks the whole expansion chain. + && is_expn_of(fun.span, sym::vec).is_some() { return match (name, args) { (sym::vec_from_elem, [elem, size]) => { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 19388e6cd35dd..75987ea96ce90 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1424,7 +1424,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_name(path.ident.name); }, } - // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s); } pub fn hash_pat_expr(&mut self, lit: &PatExpr<'_>) { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 9e69df1640e5e..8b47c79aa6da2 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,4 +1,5 @@ #![feature(box_patterns)] +#![feature(deref_patterns)] #![feature(macro_metavar_expr)] #![feature(rustc_private)] #![feature(unwrap_infallible)] @@ -134,12 +135,12 @@ macro_rules! extract_msrv_attr { () => { fn check_attributes(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); - self.msrv.check_attributes(sess, attrs); + self.msrv.check_attributes(attrs); } fn check_attributes_post(&mut self, cx: &rustc_lint::EarlyContext<'_>, attrs: &[rustc_ast::ast::Attribute]) { let sess = rustc_lint::LintContext::sess(cx); - self.msrv.check_attributes_post(sess, attrs); + self.msrv.check_attributes_post(attrs); } }; } diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 40c553d1c9e69..56fcaa637cb88 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -183,7 +183,7 @@ pub fn local_assignments(mir: &Body<'_>, local: Local) -> Vec { fn is_local_assignment(mir: &Body<'_>, local: Local, location: Location) -> bool { match mir.stmt_at(location) { Either::Left(statement) => { - if let StatementKind::Assign(box (place, _)) = statement.kind { + if let StatementKind::Assign((place, _)) = statement.kind { place.as_local() == Some(local) } else { false diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index dae6661c5ee1a..7ed28d1846ca5 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -157,7 +157,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { match rvalue { Use(op, _) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op), Aggregate(_, ops) => ops.iter().for_each(visit_op), - BinaryOp(_, box (lhs, rhs)) => { + BinaryOp(_, (lhs, rhs)) => { visit_op(lhs); visit_op(rhs); }, diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 48819d53da771..4f4d8f3990d2e 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -1,11 +1,12 @@ -use crate::sym; +use crate::{is_in_const_context, sym}; use rustc_ast::Attribute; use rustc_ast::attr::AttributeExt; use rustc_attr_parsing::parse_version; use rustc_data_structures::smallvec::SmallVec; use rustc_hir::attrs::RustcVersion; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{HirId, StabilityLevel, StableSince}; +use rustc_hir::{Constness, HirId, StabilityLevel, StableSince}; use rustc_lint::LateContext; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -137,7 +138,7 @@ impl Msrv { fn for_attrs(self, tcx: TyCtxt<'_>, node: HirId) -> Option { once(node) .chain(tcx.hir_parent_id_iter(node)) - .find_map(|id| parse_attrs(tcx.sess, tcx.hir_attrs(id))) + .find_map(|id| parse_attrs(tcx.hir_attrs(id))) .or(self.0) } @@ -157,8 +158,46 @@ impl Msrv { } pub fn is_stable(self, cx: &LateContext<'_>, def_id: DefId) -> bool { - cx.tcx.lookup_stability(def_id).is_none_or(|stability| { - if let StabilityLevel::Stable { since, .. } = stability.level { + self.stability_met(cx, cx.tcx.lookup_stability(def_id).map(|stability| stability.level)) + } + + /// Checks whether `def_id` is `const` and const-stable since a version met by the MSRV. + /// + /// `def_id` must identify a function-like definition or an impl. + /// + /// Nothing in the crate being linted carries a const-stability attribute, so `const` fns and + /// impls defined there are treated as meeting any MSRV, mirroring + /// [`is_stable`](Self::is_stable). + pub fn is_const_stable(self, cx: &LateContext<'_>, def_id: DefId) -> bool { + let constness = match cx.tcx.def_kind(def_id) { + // The constness of a trait impl is not encoded in crate metadata, where `constness` + // would decode as its default of `Const`. It is only available from the impl header. + DefKind::Impl { of_trait: true } => cx.tcx.impl_trait_header(def_id).constness, + _ => cx.tcx.constness(def_id), + }; + + matches!(constness, Constness::Const { .. }) + && self.stability_met( + cx, + cx.tcx.lookup_const_stability(def_id).map(|stability| stability.level), + ) + } + + /// Checks the stability relevant to where we are: const-stability inside a `const` context, + /// regular stability everywhere else. + /// + /// Like [`is_in_const_context`], this requires the `LateContext` to have an enclosing body. + pub fn is_stable_or_const_stable(self, cx: &LateContext<'_>, def_id: DefId) -> bool { + if is_in_const_context(cx) { + self.is_const_stable(cx, def_id) + } else { + self.is_stable(cx, def_id) + } + } + + fn stability_met(self, cx: &LateContext<'_>, level: Option) -> bool { + level.is_none_or(|level| { + if let StabilityLevel::Stable { since, .. } = level { let version = match since { StableSince::Version(version) => version, StableSince::Current => RustcVersion::CURRENT, @@ -201,24 +240,34 @@ impl MsrvStack { self.current().is_none_or(|msrv| msrv >= required) } - pub fn check_attributes(&mut self, sess: &Session, attrs: &[Attribute]) { - if let Some(version) = parse_attrs(sess, attrs) { + pub fn check_attributes(&mut self, attrs: &[Attribute]) { + if let Some(version) = parse_attrs(attrs) { SEEN_MSRV_ATTR.store(true, Ordering::Relaxed); self.stack.push(version); } } - pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[Attribute]) { - if parse_attrs(sess, attrs).is_some() { + pub fn check_attributes_post(&mut self, attrs: &[Attribute]) { + if parse_attrs(attrs).is_some() { self.stack.pop(); } } } -fn parse_attrs(sess: &Session, attrs: &[impl AttributeExt]) -> Option { +fn parse_attrs(attrs: &[impl AttributeExt]) -> Option { + let msrv_attr = attrs.iter().find(|attr| attr.path_matches(&[sym::clippy, sym::msrv]))?; + + let msrv = msrv_attr.value_str()?; + + parse_version(msrv) +} + +pub fn check_attrs(sess: &Session, attrs: &[impl AttributeExt]) { let mut msrv_attrs = attrs.iter().filter(|attr| attr.path_matches(&[sym::clippy, sym::msrv])); - let msrv_attr = msrv_attrs.next()?; + let Some(msrv_attr) = msrv_attrs.next() else { + return; + }; if let Some(duplicate) = msrv_attrs.next_back() { sess.dcx() @@ -229,14 +278,11 @@ fn parse_attrs(sess: &Session, attrs: &[impl AttributeExt]) -> Option Vec { path.set_extension("d"); fs::read_to_string(path).unwrap() }; - let mut crates = BTreeMap::<&str, &str>::new(); + // Map `crate_name` -> (`hash`, [`path1`, `path2`, ...]). Important for `rlib`s, as cargo now + // defaults to `-Zembed-metadata=no`, so the `rlib` only contains a metadata stub. + let mut crates = BTreeMap::<&str, (&str, Vec<&str>)>::new(); for line in current_exe_depinfo.lines() { // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:` let parse_name_path = || { @@ -61,20 +63,25 @@ fn internal_extern_flags() -> Vec { } let path_str = line.strip_suffix(':')?; let path = Path::new(path_str); - if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") { + if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll" | "rmeta") { return None; } - let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?; + let (name, hash) = path.file_stem()?.to_str()?.rsplit_once('-')?; // the "lib" prefix is not present for dll files let name = name.strip_prefix("lib").unwrap_or(name); - Some((name, path_str)) + Some((name, hash, path_str)) }; - if let Some((name, path)) = parse_name_path() + if let Some((name, hash, path)) = parse_name_path() && INTERNAL_TEST_DEPENDENCIES.contains(&name) { - // A dependency may be listed twice if it is available in sysroot, - // and the sysroot dependencies are listed first. - crates.insert(name, path); + // A dependency may be listed twice (identified by the hash) if it is available in sysroot, + // and the sysroot dependencies are listed first. So only keep the last dependency. + let (old_hash, items) = crates.entry(name).or_insert((hash, Vec::new())); + if *old_hash != hash { + *old_hash = hash; + items.clear(); + } + items.push(path); } } let not_found: Vec<&str> = INTERNAL_TEST_DEPENDENCIES @@ -93,7 +100,7 @@ fn internal_extern_flags() -> Vec { let mut args: Vec = crates .into_iter() - .map(|(name, path)| format!("--extern={name}={path}")) + .flat_map(|(name, (_, paths))| paths.into_iter().map(move |path| format!("--extern={name}={path}"))) .collect(); if deps_path.ends_with("deps") { diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs index 897002949e67e..681b42516a2d2 100644 --- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs +++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs @@ -4,7 +4,6 @@ #[macro_use] extern crate rustc_middle; #[macro_use] -extern crate rustc_session; extern crate rustc_lint; /////////////////////// diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr index 952bc94403033..357b3d5119ffd 100644 --- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr +++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr @@ -1,5 +1,5 @@ error: this item has an invalid `clippy::version` attribute - --> tests/ui-internal/check_clippy_version_attribute.rs:40:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:39:1 | LL | / declare_tool_lint! { LL | | @@ -19,7 +19,7 @@ LL | #![deny(clippy::invalid_clippy_version_attribute, clippy::missing_clippy_ve = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this item has an invalid `clippy::version` attribute - --> tests/ui-internal/check_clippy_version_attribute.rs:49:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:48:1 | LL | / declare_tool_lint! { LL | | @@ -34,7 +34,7 @@ LL | | } = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value - --> tests/ui-internal/check_clippy_version_attribute.rs:61:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:60:1 | LL | / declare_tool_lint! { LL | | @@ -54,7 +54,7 @@ LL | #![deny(clippy::invalid_clippy_version_attribute, clippy::missing_clippy_ve = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value - --> tests/ui-internal/check_clippy_version_attribute.rs:70:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:69:1 | LL | / declare_tool_lint! { LL | | diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.rs b/src/tools/clippy/tests/ui-internal/check_formulation.rs index bcbb0d783198e..c1e8382dbe1f4 100644 --- a/src/tools/clippy/tests/ui-internal/check_formulation.rs +++ b/src/tools/clippy/tests/ui-internal/check_formulation.rs @@ -5,7 +5,6 @@ #[macro_use] extern crate rustc_middle; #[macro_use] -extern crate rustc_session; extern crate rustc_lint; declare_tool_lint! { diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.stderr b/src/tools/clippy/tests/ui-internal/check_formulation.stderr index 9aeb9e1f2d49c..f498f04c5fe0d 100644 --- a/src/tools/clippy/tests/ui-internal/check_formulation.stderr +++ b/src/tools/clippy/tests/ui-internal/check_formulation.stderr @@ -1,5 +1,5 @@ error: non-standard lint formulation - --> tests/ui-internal/check_formulation.rs:24:5 + --> tests/ui-internal/check_formulation.rs:23:5 | LL | /// Check for lint formulations that are correct | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::almost_standard_lint_formulation)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-standard lint formulation - --> tests/ui-internal/check_formulation.rs:35:5 + --> tests/ui-internal/check_formulation.rs:34:5 | LL | /// Detects uses of incorrect formulations | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed index 2b646a38b534f..dc9b9a12da93c 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -6,14 +6,12 @@ extern crate clippy_utils; extern crate rustc_ast; extern crate rustc_errors; extern crate rustc_lint; -extern crate rustc_session; extern crate rustc_span; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use rustc_ast::ast::Expr; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{EarlyContext, EarlyLintPass, declare_lint_pass, declare_tool_lint}; declare_tool_lint! { pub clippy::TEST_LINT, diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs index 500552370053c..83ea66652268d 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs @@ -6,14 +6,12 @@ extern crate clippy_utils; extern crate rustc_ast; extern crate rustc_errors; extern crate rustc_lint; -extern crate rustc_session; extern crate rustc_span; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; use rustc_ast::ast::Expr; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{EarlyContext, EarlyLintPass, declare_lint_pass, declare_tool_lint}; declare_tool_lint! { pub clippy::TEST_LINT, diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr index 76b4530192709..380127902aa16 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -1,5 +1,5 @@ error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:35:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:33:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -14,7 +14,7 @@ LL | #![deny(clippy::collapsible_span_lint_calls)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:39:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:37:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -23,7 +23,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:43:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:41:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -32,7 +32,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:47:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:45:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -41,7 +41,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:51:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:49:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -50,7 +50,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:72:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:70:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -62,7 +62,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:81:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:79:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -71,7 +71,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}"))` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:85:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:83:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -80,7 +80,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}"))` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:89:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:87:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | @@ -89,7 +89,7 @@ LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}"))` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:93:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:91:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { LL | | diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr index 884d3d035a29d..2e4d53104fba1 100644 --- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr @@ -20,7 +20,7 @@ note: please make sure that you have updated to the latest nightly note: rustc running on -note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no +note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no -Z next-solver=coherence note: Clippy version: foo diff --git a/src/tools/clippy/tests/ui-internal/default_lint.rs b/src/tools/clippy/tests/ui-internal/default_lint.rs index 809f2c4d080dc..eb7ef999a6f59 100644 --- a/src/tools/clippy/tests/ui-internal/default_lint.rs +++ b/src/tools/clippy/tests/ui-internal/default_lint.rs @@ -5,7 +5,6 @@ #[macro_use] extern crate rustc_middle; #[macro_use] -extern crate rustc_session; extern crate rustc_lint; declare_tool_lint! { diff --git a/src/tools/clippy/tests/ui-internal/default_lint.stderr b/src/tools/clippy/tests/ui-internal/default_lint.stderr index 2c700ec82dcd4..62fa6bf6eaa36 100644 --- a/src/tools/clippy/tests/ui-internal/default_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/default_lint.stderr @@ -1,5 +1,5 @@ error: the lint `TEST_LINT_DEFAULT` has the default lint description - --> tests/ui-internal/default_lint.rs:18:1 + --> tests/ui-internal/default_lint.rs:17:1 | LL | / declare_tool_lint! { LL | | diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed index 238ef9ae6d0ac..b1ee7dfe91580 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -4,10 +4,9 @@ extern crate rustc_ast; extern crate rustc_hir; +#[macro_use] extern crate rustc_lint; extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; use clippy_utils::extract_msrv_attr; use clippy_utils::msrvs::MsrvStack; use rustc_hir::Expr; diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs index 7753dcaad7139..746478b4af4b9 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -4,10 +4,9 @@ extern crate rustc_ast; extern crate rustc_hir; +#[macro_use] extern crate rustc_lint; extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; use clippy_utils::extract_msrv_attr; use clippy_utils::msrvs::MsrvStack; use rustc_hir::Expr; diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr index d5928d8c0c2de..d65d86f0fd5a6 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.stderr @@ -1,5 +1,5 @@ error: `extract_msrv_attr!` macro missing from `EarlyLintPass` implementation - --> tests/ui-internal/invalid_msrv_attr_impl.rs:28:1 + --> tests/ui-internal/invalid_msrv_attr_impl.rs:27:1 | LL | impl EarlyLintPass for Pass { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs index 6b649132aca31..c42e66c576226 100644 --- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs @@ -5,7 +5,6 @@ #[macro_use] extern crate rustc_middle; #[macro_use] -extern crate rustc_session; extern crate rustc_lint; use rustc_lint::{LintPass, LintVec}; diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr index 3798293f4c111..8069a1d69d084 100644 --- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr @@ -1,5 +1,5 @@ error: the lint `TEST_LINT` is not added to any `LintPass` - --> tests/ui-internal/lint_without_lint_pass.rs:12:1 + --> tests/ui-internal/lint_without_lint_pass.rs:11:1 | LL | / declare_tool_lint! { LL | | diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed index 900ca5b2ab9d8..00cf76a2e41de 100644 --- a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed @@ -3,10 +3,9 @@ #![feature(rustc_private)] extern crate rustc_hir; +#[macro_use] extern crate rustc_lint; extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs index bcfc42aa2ac75..148803f974ec1 100644 --- a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs @@ -3,10 +3,9 @@ #![feature(rustc_private)] extern crate rustc_hir; +#[macro_use] extern crate rustc_lint; extern crate rustc_middle; -#[macro_use] -extern crate rustc_session; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr index b86138a5d45d2..65b5d8e4d28e6 100644 --- a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr @@ -1,5 +1,5 @@ error: usage of `outer_expn().expn_data()` - --> tests/ui-internal/outer_expn_data.rs:23:34 + --> tests/ui-internal/outer_expn_data.rs:22:34 | LL | let _ = expr.span.ctxt().outer_expn().expn_data(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `outer_expn_data()` diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs index ddee6e5566fa6..c3256827ba237 100644 --- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs +++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs @@ -1,4 +1,4 @@ -#![feature(proc_macro_hygiene, proc_macro_quote, box_patterns)] +#![feature(proc_macro_hygiene, proc_macro_quote, deref_patterns)] #![allow(clippy::uninlined_format_args, clippy::useless_conversion)] extern crate proc_macro; @@ -10,8 +10,8 @@ use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::token::Star; use syn::{ - FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem, - Type, Visibility, parse_macro_input, parse_quote, + Attribute, FnArg, ImplItem, Item, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent, PatType, + Signature, TraitItem, Type, Visibility, parse_macro_input, parse_quote, }; #[proc_macro_attribute] @@ -42,6 +42,57 @@ pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream { TokenStream::from(quote!(#item)) } +fn add_must_use_attr(attrs: &mut Vec) { + attrs.push(parse_quote!(#[must_use])); +} + +fn desugar_async(attrs: &mut Vec, sig: &mut Signature) { + sig.asyncness = None; + add_must_use_attr(attrs); +} + +#[proc_macro_attribute] +pub fn add_must_use(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut item = parse_macro_input!(input as Item); + + match &mut item { + Item::Fn(item) => add_must_use_attr(&mut item.attrs), + Item::Struct(item) => add_must_use_attr(&mut item.attrs), + Item::Union(item) => add_must_use_attr(&mut item.attrs), + Item::Enum(item) => add_must_use_attr(&mut item.attrs), + Item::Trait(item) => add_must_use_attr(&mut item.attrs), + _ => {}, + } + + TokenStream::from(quote!(#item)) +} + +#[proc_macro_attribute] +pub fn add_must_use_to_async(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut item = parse_macro_input!(input as Item); + + match &mut item { + Item::Fn(item) => desugar_async(&mut item.attrs, &mut item.sig), + Item::Trait(item) => { + for trait_item in &mut item.items { + if let TraitItem::Fn(method) = trait_item { + desugar_async(&mut method.attrs, &mut method.sig); + } + } + }, + Item::Impl(item) => { + for impl_item in &mut item.items { + if let ImplItem::Fn(method) = impl_item { + desugar_async(&mut method.attrs, &mut method.sig); + } + } + }, + _ => {}, + } + + TokenStream::from(quote!(#item)) +} + #[proc_macro_attribute] pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStream { fn make_name(count: usize) -> String { @@ -67,7 +118,7 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea for inner in &mut item.items { if let ImplItem::Fn(method) = inner && let Some(FnArg::Typed(pat_type)) = mut_receiver_of(&mut method.sig) - && let box Type::Reference(reference) = &mut pat_type.ty + && let Type::Reference(reference) = &mut pat_type.ty { // Target only unnamed lifetimes let name = match &reference.lifetime { diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr index c8745628dd977..a01501e87dc68 100644 --- a/src/tools/clippy/tests/ui/blocks_in_conditions.stderr +++ b/src/tools/clippy/tests/ui/blocks_in_conditions.stderr @@ -10,7 +10,7 @@ LL | | } { | = note: `-D clippy::blocks-in-conditions` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]` -help: try +help: use a binding instead | LL ~ let res = { LL + @@ -23,13 +23,13 @@ error: omit braces around single expression condition --> tests/ui/blocks_in_conditions.rs:36:8 | LL | if { true } { 6 } else { 10 } - | ^^^^^^^^ help: try: `true` + | ^^^^^^^^ help: remove the braces: `true` error: omit braces around single expression condition --> tests/ui/blocks_in_conditions.rs:136:15 | LL | match { Foo.foo() } { - | ^^^^^^^^^^^^^ help: try: `Foo.foo()` + | ^^^^^^^^^^^^^ help: remove the braces: `Foo.foo()` error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr index 497ee9d679dde..23ded8924333d 100644 --- a/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr +++ b/src/tools/clippy/tests/ui/blocks_in_conditions_2021.stderr @@ -10,7 +10,7 @@ LL | | } { | = note: `-D clippy::blocks-in-conditions` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]` -help: try +help: use a binding instead | LL ~ let res = { LL + diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_unfixable.rs b/src/tools/clippy/tests/ui/blocks_in_conditions_unfixable.rs new file mode 100644 index 0000000000000..e800dd0a49539 --- /dev/null +++ b/src/tools/clippy/tests/ui/blocks_in_conditions_unfixable.rs @@ -0,0 +1,25 @@ +fn issue_17068() { + fn nop() {} + + match Some(()) { + Some(()) => match { + //~^ ERROR: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + nop(); + 42 + } { + 42 => nop(), + _ => nop(), + }, + None => nop(), + } + + let _x = if { + //~^ ERROR: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + let v = 1; + v == 1 + } { + 1 + } else { + 2 + }; +} diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions_unfixable.stderr b/src/tools/clippy/tests/ui/blocks_in_conditions_unfixable.stderr new file mode 100644 index 0000000000000..fadeedbe6007f --- /dev/null +++ b/src/tools/clippy/tests/ui/blocks_in_conditions_unfixable.stderr @@ -0,0 +1,27 @@ +error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + --> tests/ui/blocks_in_conditions_unfixable.rs:5:21 + | +LL | ... Some(()) => match { + | ___________________^ +LL | | ... +LL | | ... nop(); +LL | | ... 42 +LL | | ... } { + | |_______^ + | + = note: `-D clippy::blocks-in-conditions` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]` + +error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + --> tests/ui/blocks_in_conditions_unfixable.rs:16:14 + | +LL | let _x = if { + | ______________^ +LL | | +LL | | let v = 1; +LL | | v == 1 +LL | | } { + | |_____^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs index 6ee003664117d..bf239f13e1e89 100644 --- a/src/tools/clippy/tests/ui/cast.rs +++ b/src/tools/clippy/tests/ui/cast.rs @@ -592,3 +592,13 @@ fn issue16045() { Ok(()) } } + +fn issue_17501() { + macro_rules! cast_from_macro { + () => { + 5_i64 + }; + } + let _ = cast_from_macro!() as i32; + //~^ cast_possible_truncation +} diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr index 14b84b1ff1ef2..6b44ff344392e 100644 --- a/src/tools/clippy/tests/ui/cast.stderr +++ b/src/tools/clippy/tests/ui/cast.stderr @@ -770,5 +770,18 @@ error: casting `u8` to `i8` may wrap around the value LL | _ = val? as i8; | ^^^^^^^^^^ help: if this is intentional, use `cast_signed()` instead: `val?.cast_signed()` -error: aborting due to 95 previous errors +error: casting `i64` to `i32` may truncate the value + --> tests/ui/cast.rs:602:13 + | +LL | let _ = cast_from_macro!() as i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL - let _ = cast_from_macro!() as i32; +LL + let _ = i32::try_from(cast_from_macro!()); + | + +error: aborting due to 96 previous errors diff --git a/src/tools/clippy/tests/ui/default_trait_access_unfixable.rs b/src/tools/clippy/tests/ui/default_trait_access_unfixable.rs new file mode 100644 index 0000000000000..1e968f7359bc5 --- /dev/null +++ b/src/tools/clippy/tests/ui/default_trait_access_unfixable.rs @@ -0,0 +1,7 @@ +//@no-rustfix: the trimmed replacement path may not be in scope +#![warn(clippy::default_trait_access)] + +fn main() { + let _: std::time::Duration = Default::default(); + //~^ default_trait_access +} diff --git a/src/tools/clippy/tests/ui/default_trait_access_unfixable.stderr b/src/tools/clippy/tests/ui/default_trait_access_unfixable.stderr new file mode 100644 index 0000000000000..feb48d84a1d35 --- /dev/null +++ b/src/tools/clippy/tests/ui/default_trait_access_unfixable.stderr @@ -0,0 +1,11 @@ +error: calling `Duration::default()` is more clear than this expression + --> tests/ui/default_trait_access_unfixable.rs:5:34 + | +LL | let _: std::time::Duration = Default::default(); + | ^^^^^^^^^^^^^^^^^^ help: try: `Duration::default()` + | + = note: `-D clippy::default-trait-access` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::default_trait_access)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed index 0fc156f2c19e0..bc68acf366dd1 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -82,7 +82,7 @@ fn test_units() { /// OCaml /// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry /// OpenType -/// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport +/// WebAuthn WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport /// TensorFlow /// TrueType /// iOS macOS FreeBSD NetBSD OpenBSD NixOS diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs index cfb8b67afc012..f13e5e882d85b 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -82,7 +82,7 @@ fn test_units() { /// OCaml /// OpenAL OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry /// OpenType -/// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport +/// WebAuthn WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport /// TensorFlow /// TrueType /// iOS macOS FreeBSD NetBSD OpenBSD NixOS diff --git a/src/tools/clippy/tests/ui/double_must_use_proc_macro.rs b/src/tools/clippy/tests/ui/double_must_use_proc_macro.rs new file mode 100644 index 0000000000000..b8c68318f16b7 --- /dev/null +++ b/src/tools/clippy/tests/ui/double_must_use_proc_macro.rs @@ -0,0 +1,87 @@ +//@aux-build:proc_macro_attr.rs +//@no-rustfix +#![warn(clippy::double_must_use, clippy::must_use_unit)] +#![allow(dead_code)] + +extern crate proc_macro_attr; + +use proc_macro_attr::{add_must_use, add_must_use_to_async, dummy}; + +#[add_must_use_to_async] +async fn function() -> Result<(), ()> { + Ok(()) +} + +#[add_must_use_to_async] +async fn unit_function() {} + +#[add_must_use_to_async] +trait AsyncTrait { + async fn method(&self) -> Result<(), ()>; +} + +struct Struct; + +#[add_must_use_to_async] +impl Struct { + async fn method(&self) -> Result<(), ()> { + Ok(()) + } +} + +#[add_must_use] +struct MustUseStruct; + +#[add_must_use] +union MustUseUnion { + field: u32, +} + +#[add_must_use] +enum MustUseEnum { + Variant, +} + +#[add_must_use] +trait MustUseTrait {} + +impl MustUseTrait for u32 {} + +#[add_must_use] +fn macro_must_use() -> Result<(), ()> { + Ok(()) +} + +#[must_use] +fn returns_must_use_struct() -> MustUseStruct { + //~^ double_must_use + MustUseStruct +} + +#[must_use] +fn returns_must_use_union() -> MustUseUnion { + //~^ double_must_use + MustUseUnion { field: 0 } +} + +#[must_use] +fn returns_must_use_enum() -> MustUseEnum { + //~^ double_must_use + MustUseEnum::Variant +} + +#[must_use] +fn returns_must_use_trait() -> impl MustUseTrait { + //~^ double_must_use + 0u32 +} + +#[dummy] +#[must_use] +#[inline] +fn user_must_use() -> Result<(), ()> { + //~^ double_must_use + Ok(()) +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/double_must_use_proc_macro.stderr b/src/tools/clippy/tests/ui/double_must_use_proc_macro.stderr new file mode 100644 index 0000000000000..e89b14d966b45 --- /dev/null +++ b/src/tools/clippy/tests/ui/double_must_use_proc_macro.stderr @@ -0,0 +1,62 @@ +error: this function has a `#[must_use]` attribute with no message, but returns a type already considered as `#[must_use]` + --> tests/ui/double_must_use_proc_macro.rs:56:1 + | +LL | #[must_use] + | ----------- help: remove the attribute +LL | fn returns_must_use_struct() -> MustUseStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: alternatively, you may add an explicit reason to the `must_use` attribute + = note: `-D clippy::double-must-use` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]` + +error: this function has a `#[must_use]` attribute with no message, but returns a type already considered as `#[must_use]` + --> tests/ui/double_must_use_proc_macro.rs:62:1 + | +LL | #[must_use] + | ----------- help: remove the attribute +LL | fn returns_must_use_union() -> MustUseUnion { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: alternatively, you may add an explicit reason to the `must_use` attribute + +error: this function has a `#[must_use]` attribute with no message, but returns a type already considered as `#[must_use]` + --> tests/ui/double_must_use_proc_macro.rs:68:1 + | +LL | #[must_use] + | ----------- help: remove the attribute +LL | fn returns_must_use_enum() -> MustUseEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: alternatively, you may add an explicit reason to the `must_use` attribute + +error: this function has a `#[must_use]` attribute with no message, but returns a type already considered as `#[must_use]` + --> tests/ui/double_must_use_proc_macro.rs:74:1 + | +LL | #[must_use] + | ----------- help: remove the attribute +LL | fn returns_must_use_trait() -> impl MustUseTrait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the return type is implementer of `MustUseTrait` + --> tests/ui/double_must_use_proc_macro.rs:74:32 + | +LL | fn returns_must_use_trait() -> impl MustUseTrait { + | ^^^^^^^^^^^^^^^^^ + = note: alternatively, you may add an explicit reason to the `must_use` attribute + +error: this function has a `#[must_use]` attribute with no message, but returns a type already considered as `#[must_use]` + --> tests/ui/double_must_use_proc_macro.rs:82:1 + | +LL | fn user_must_use() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `must_use` + --> tests/ui/double_must_use_proc_macro.rs:80:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + = note: alternatively, you may add an explicit reason to the `must_use` attribute + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/integer_division_remainder_used.rs b/src/tools/clippy/tests/ui/integer_division_remainder_used.rs index 2c57c23904ec1..f8d303b04bfc8 100644 --- a/src/tools/clippy/tests/ui/integer_division_remainder_used.rs +++ b/src/tools/clippy/tests/ui/integer_division_remainder_used.rs @@ -38,6 +38,13 @@ fn main() { let i = a / &4; //~^ integer_division_remainder_used + // should trigger on DivAssign and RemAssign + let mut j = 10; + j /= 2; + //~^ integer_division_remainder_used + j %= 3; + //~^ integer_division_remainder_used + // should not trigger on custom Div and Rem let w = CustomOps(3); let x = CustomOps(4); diff --git a/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr b/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr index 3fda04619aab8..84fa20020adc1 100644 --- a/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr +++ b/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr @@ -55,5 +55,17 @@ error: use of `/` has been disallowed in this context LL | let i = a / &4; | ^^^^^^ -error: aborting due to 9 previous errors +error: use of `/` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:43:5 + | +LL | j /= 2; + | ^^^^^^ + +error: use of `%` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:45:5 + | +LL | j %= 3; + | ^^^^^^ + +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/large_futures_next_solver.rs b/src/tools/clippy/tests/ui/large_futures_next_solver.rs new file mode 100644 index 0000000000000..86017484f5b43 --- /dev/null +++ b/src/tools/clippy/tests/ui/large_futures_next_solver.rs @@ -0,0 +1,16 @@ +//@ check-pass +//@ revisions: current next +//@[next] compile-flags: -Znext-solver=globally + +// https://github.com/rust-lang/rust/issues/161495 + +#![warn(clippy::large_futures)] + +async fn callee() {} + +async fn caller() { + callee().await; + std::pin::pin!(callee()).await; +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/let_and_return.edition2021.fixed b/src/tools/clippy/tests/ui/let_and_return.edition2021.fixed index ed9843c3e13d3..c904d882d9472 100644 --- a/src/tools/clippy/tests/ui/let_and_return.edition2021.fixed +++ b/src/tools/clippy/tests/ui/let_and_return.edition2021.fixed @@ -278,6 +278,24 @@ fn has_comment() -> Vec { v } +mod issue16451 { + + fn expect_on_return_expr() -> std::collections::BTreeMap<(), ()> { + let stuff = std::collections::BTreeMap::new(); + + // TODO: Fill `stuff` + + #[expect(clippy::let_and_return)] + stuff + } + + fn cfg_on_return_expr() -> i32 { + let x = 5; + #[cfg(debug_assertions)] + x + } +} + fn wrongly_unmangled_macros() -> i32 { let x = 1; macro_rules! plus_one { diff --git a/src/tools/clippy/tests/ui/let_and_return.edition2021.stderr b/src/tools/clippy/tests/ui/let_and_return.edition2021.stderr index 8312b6711a6ac..c91b355c42d08 100644 --- a/src/tools/clippy/tests/ui/let_and_return.edition2021.stderr +++ b/src/tools/clippy/tests/ui/let_and_return.edition2021.stderr @@ -149,7 +149,7 @@ LL ~ ({ true } || { false } && { 2 <= 3 }) | error: returning the result of a `let` binding from a block - --> tests/ui/let_and_return.rs:290:5 + --> tests/ui/let_and_return.rs:308:5 | LL | let y = plus_one!(x); | --------------------- unnecessary `let` binding diff --git a/src/tools/clippy/tests/ui/let_and_return.edition2024.fixed b/src/tools/clippy/tests/ui/let_and_return.edition2024.fixed index 964d4b9f98d89..e931e1ec7ff22 100644 --- a/src/tools/clippy/tests/ui/let_and_return.edition2024.fixed +++ b/src/tools/clippy/tests/ui/let_and_return.edition2024.fixed @@ -278,6 +278,24 @@ fn has_comment() -> Vec { v } +mod issue16451 { + + fn expect_on_return_expr() -> std::collections::BTreeMap<(), ()> { + let stuff = std::collections::BTreeMap::new(); + + // TODO: Fill `stuff` + + #[expect(clippy::let_and_return)] + stuff + } + + fn cfg_on_return_expr() -> i32 { + let x = 5; + #[cfg(debug_assertions)] + x + } +} + fn wrongly_unmangled_macros() -> i32 { let x = 1; macro_rules! plus_one { diff --git a/src/tools/clippy/tests/ui/let_and_return.edition2024.stderr b/src/tools/clippy/tests/ui/let_and_return.edition2024.stderr index 98ded31b1954f..7407e504b7c54 100644 --- a/src/tools/clippy/tests/ui/let_and_return.edition2024.stderr +++ b/src/tools/clippy/tests/ui/let_and_return.edition2024.stderr @@ -225,7 +225,7 @@ LL + }? | error: returning the result of a `let` binding from a block - --> tests/ui/let_and_return.rs:290:5 + --> tests/ui/let_and_return.rs:308:5 | LL | let y = plus_one!(x); | --------------------- unnecessary `let` binding diff --git a/src/tools/clippy/tests/ui/let_and_return.rs b/src/tools/clippy/tests/ui/let_and_return.rs index e7239e90cb3a6..f7cf1c7d0439b 100644 --- a/src/tools/clippy/tests/ui/let_and_return.rs +++ b/src/tools/clippy/tests/ui/let_and_return.rs @@ -278,6 +278,24 @@ fn has_comment() -> Vec { v } +mod issue16451 { + + fn expect_on_return_expr() -> std::collections::BTreeMap<(), ()> { + let stuff = std::collections::BTreeMap::new(); + + // TODO: Fill `stuff` + + #[expect(clippy::let_and_return)] + stuff + } + + fn cfg_on_return_expr() -> i32 { + let x = 5; + #[cfg(debug_assertions)] + x + } +} + fn wrongly_unmangled_macros() -> i32 { let x = 1; macro_rules! plus_one { diff --git a/src/tools/clippy/tests/ui/manual_assert_eq.fixed b/src/tools/clippy/tests/ui/manual_assert_eq.fixed index 9753d346479c3..8f7118fc7d9c0 100644 --- a/src/tools/clippy/tests/ui/manual_assert_eq.fixed +++ b/src/tools/clippy/tests/ui/manual_assert_eq.fixed @@ -85,6 +85,98 @@ fn main() { assert!(nd == id); } + // Don't lint: byte buffers can contain too much data for useful debug output + { + use std::borrow::Cow; + use std::ops::Deref; + use std::rc::Rc; + use std::sync::Arc; + + #[derive(Debug, PartialEq)] + struct ByteBuf(Vec); + + impl Deref for ByteBuf { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + let vec = vec![1_u8]; + assert!(vec == vec![1]); + + let slice: &[u8] = &[1]; + let expected_slice: &[u8] = &[1]; + assert!(slice == expected_slice); + + let boxed: Box<[u8]> = Box::new([1]); + assert!(boxed == Box::new([1])); + + let cow: Cow<'_, [u8]> = Cow::Borrowed(&[1]); + assert!(cow == Cow::Borrowed(&[1])); + + let rc: Rc<[u8]> = Rc::new([1]); + assert!(rc == Rc::new([1])); + + let arc: Arc<[u8]> = Arc::new([1]); + assert!(arc == Arc::new([1])); + + let custom = ByteBuf(vec![1]); + assert!(custom == ByteBuf(vec![1])); + + #[derive(Debug, PartialEq)] + struct InnerPiece([u8; 1024]); + + #[derive(Debug, PartialEq)] + struct Piece(InnerPiece); + + impl Deref for Piece { + type Target = InnerPiece; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl AsRef<[u8]> for Piece { + fn as_ref(&self) -> &[u8] { + &self.0.0 + } + } + + let piece = Piece(InnerPiece([0; 1024])); + assert!(piece == Piece(InnerPiece([0; 1024]))); + + #[derive(Debug, PartialEq)] + struct Grow(std::marker::PhantomData); + + impl Deref for Grow { + type Target = Grow<(T,)>; + + fn deref(&self) -> &Self::Target { + unreachable!() + } + } + + assert_eq!(Grow::(std::marker::PhantomData), Grow(std::marker::PhantomData)); + //~^ manual_assert_eq + + #[derive(Debug, PartialEq)] + struct SelfDerefer; + + impl Deref for SelfDerefer { + type Target = Self; + + fn deref(&self) -> &Self::Target { + self + } + } + + assert_eq!(SelfDerefer, SelfDerefer); + //~^ manual_assert_eq + } + // Don't lint: in const context const { assert!(5 == 2 + 3); diff --git a/src/tools/clippy/tests/ui/manual_assert_eq.rs b/src/tools/clippy/tests/ui/manual_assert_eq.rs index d667136f3b5ec..6c59333bae15d 100644 --- a/src/tools/clippy/tests/ui/manual_assert_eq.rs +++ b/src/tools/clippy/tests/ui/manual_assert_eq.rs @@ -85,6 +85,98 @@ fn main() { assert!(nd == id); } + // Don't lint: byte buffers can contain too much data for useful debug output + { + use std::borrow::Cow; + use std::ops::Deref; + use std::rc::Rc; + use std::sync::Arc; + + #[derive(Debug, PartialEq)] + struct ByteBuf(Vec); + + impl Deref for ByteBuf { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + let vec = vec![1_u8]; + assert!(vec == vec![1]); + + let slice: &[u8] = &[1]; + let expected_slice: &[u8] = &[1]; + assert!(slice == expected_slice); + + let boxed: Box<[u8]> = Box::new([1]); + assert!(boxed == Box::new([1])); + + let cow: Cow<'_, [u8]> = Cow::Borrowed(&[1]); + assert!(cow == Cow::Borrowed(&[1])); + + let rc: Rc<[u8]> = Rc::new([1]); + assert!(rc == Rc::new([1])); + + let arc: Arc<[u8]> = Arc::new([1]); + assert!(arc == Arc::new([1])); + + let custom = ByteBuf(vec![1]); + assert!(custom == ByteBuf(vec![1])); + + #[derive(Debug, PartialEq)] + struct InnerPiece([u8; 1024]); + + #[derive(Debug, PartialEq)] + struct Piece(InnerPiece); + + impl Deref for Piece { + type Target = InnerPiece; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl AsRef<[u8]> for Piece { + fn as_ref(&self) -> &[u8] { + &self.0.0 + } + } + + let piece = Piece(InnerPiece([0; 1024])); + assert!(piece == Piece(InnerPiece([0; 1024]))); + + #[derive(Debug, PartialEq)] + struct Grow(std::marker::PhantomData); + + impl Deref for Grow { + type Target = Grow<(T,)>; + + fn deref(&self) -> &Self::Target { + unreachable!() + } + } + + assert!(Grow::(std::marker::PhantomData) == Grow(std::marker::PhantomData)); + //~^ manual_assert_eq + + #[derive(Debug, PartialEq)] + struct SelfDerefer; + + impl Deref for SelfDerefer { + type Target = Self; + + fn deref(&self) -> &Self::Target { + self + } + } + + assert!(SelfDerefer == SelfDerefer); + //~^ manual_assert_eq + } + // Don't lint: in const context const { assert!(5 == 2 + 3); diff --git a/src/tools/clippy/tests/ui/manual_assert_eq.stderr b/src/tools/clippy/tests/ui/manual_assert_eq.stderr index a33d599a24790..d09448f9d5d62 100644 --- a/src/tools/clippy/tests/ui/manual_assert_eq.stderr +++ b/src/tools/clippy/tests/ui/manual_assert_eq.stderr @@ -84,5 +84,29 @@ LL - assert!(vec![1] == vec![1, 2, 3]); LL + assert_eq!(vec![1], vec![1, 2, 3]); | -error: aborting due to 7 previous errors +error: used `assert!` with an equality comparison + --> tests/ui/manual_assert_eq.rs:162:9 + | +LL | assert!(Grow::(std::marker::PhantomData) == Grow(std::marker::PhantomData)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert_eq!(..)` + | +LL - assert!(Grow::(std::marker::PhantomData) == Grow(std::marker::PhantomData)); +LL + assert_eq!(Grow::(std::marker::PhantomData), Grow(std::marker::PhantomData)); + | + +error: used `assert!` with an equality comparison + --> tests/ui/manual_assert_eq.rs:176:9 + | +LL | assert!(SelfDerefer == SelfDerefer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert_eq!(..)` + | +LL - assert!(SelfDerefer == SelfDerefer); +LL + assert_eq!(SelfDerefer, SelfDerefer); + | + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/manual_contains.fixed b/src/tools/clippy/tests/ui/manual_contains.fixed index 340b439f6c40a..41b0f10a0598b 100644 --- a/src/tools/clippy/tests/ui/manual_contains.fixed +++ b/src/tools/clippy/tests/ui/manual_contains.fixed @@ -50,6 +50,15 @@ fn should_lint() { let values = &vec[..]; let _ = values.contains(&(4 + 1)); //~^ manual_contains + + // Eager bitwise expressions still lint when they do not mention the element. + let mask = 0x0f_u8; + let other = 0x03_u8; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.contains(&(mask & other)); + //~^ manual_contains + let _ = values.contains(&(mask | other)); + //~^ manual_contains } fn should_not_lint() { @@ -85,6 +94,14 @@ fn should_not_lint() { }; let _ = values.iter().any(|&v| v == count()); let _ = values.iter().any(|&v| v == v * 2); + + // Don't fire when both sides use the slice element. #17563 + let mask = 0x0f_u8; + let values: &[u8] = &[1, 2, 3]; + let _ = values.iter().any(|&i| i & mask == i); + let _ = values.iter().any(|&i| i == i & mask); + let _ = values.iter().any(|&i| i == !i); + let _ = values.iter().any(|i| *i == *i & mask); } fn foo(values: &[u8]) -> bool { diff --git a/src/tools/clippy/tests/ui/manual_contains.rs b/src/tools/clippy/tests/ui/manual_contains.rs index 75c701f170b41..0609651765be3 100644 --- a/src/tools/clippy/tests/ui/manual_contains.rs +++ b/src/tools/clippy/tests/ui/manual_contains.rs @@ -50,6 +50,15 @@ fn should_lint() { let values = &vec[..]; let _ = values.iter().any(|&v| v == 4 + 1); //~^ manual_contains + + // Eager bitwise expressions still lint when they do not mention the element. + let mask = 0x0f_u8; + let other = 0x03_u8; + let values: [u8; 6] = [3, 14, 15, 92, 6, 5]; + let _ = values.iter().any(|&v| v == mask & other); + //~^ manual_contains + let _ = values.iter().any(|&v| mask | other == v); + //~^ manual_contains } fn should_not_lint() { @@ -85,6 +94,14 @@ fn should_not_lint() { }; let _ = values.iter().any(|&v| v == count()); let _ = values.iter().any(|&v| v == v * 2); + + // Don't fire when both sides use the slice element. #17563 + let mask = 0x0f_u8; + let values: &[u8] = &[1, 2, 3]; + let _ = values.iter().any(|&i| i & mask == i); + let _ = values.iter().any(|&i| i == i & mask); + let _ = values.iter().any(|&i| i == !i); + let _ = values.iter().any(|i| *i == *i & mask); } fn foo(values: &[u8]) -> bool { diff --git a/src/tools/clippy/tests/ui/manual_contains.stderr b/src/tools/clippy/tests/ui/manual_contains.stderr index e6e2dea560c60..2ccb3ed35600c 100644 --- a/src/tools/clippy/tests/ui/manual_contains.stderr +++ b/src/tools/clippy/tests/ui/manual_contains.stderr @@ -62,16 +62,28 @@ LL | let _ = values.iter().any(|&v| v == 4 + 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&(4 + 1))` error: using `contains()` instead of `iter().any()` is more efficient - --> tests/ui/manual_contains.rs:91:5 + --> tests/ui/manual_contains.rs:58:13 + | +LL | let _ = values.iter().any(|&v| v == mask & other); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&(mask & other))` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:60:13 + | +LL | let _ = values.iter().any(|&v| mask | other == v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&(mask | other))` + +error: using `contains()` instead of `iter().any()` is more efficient + --> tests/ui/manual_contains.rs:108:5 | LL | values.iter().any(|&v| v == 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&10)` error: using `contains()` instead of `iter().any()` is more efficient - --> tests/ui/manual_contains.rs:96:5 + --> tests/ui/manual_contains.rs:113:5 | LL | values.iter().any(|&v| v == 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `values.contains(&10)` -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/manual_option_zip.fixed b/src/tools/clippy/tests/ui/manual_option_zip.fixed index 8b821f8737cbb..799fdb8d61bc6 100644 --- a/src/tools/clippy/tests/ui/manual_option_zip.fixed +++ b/src/tools/clippy/tests/ui/manual_option_zip.fixed @@ -1,5 +1,6 @@ #![warn(clippy::manual_option_zip)] #![expect(clippy::bind_instead_of_map)] +#![allow(clippy::option_zip_none)] fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_option_zip.rs b/src/tools/clippy/tests/ui/manual_option_zip.rs index 5d059a98ee12c..76b3ccb7555df 100644 --- a/src/tools/clippy/tests/ui/manual_option_zip.rs +++ b/src/tools/clippy/tests/ui/manual_option_zip.rs @@ -1,5 +1,6 @@ #![warn(clippy::manual_option_zip)] #![expect(clippy::bind_instead_of_map)] +#![allow(clippy::option_zip_none)] fn main() {} diff --git a/src/tools/clippy/tests/ui/manual_option_zip.stderr b/src/tools/clippy/tests/ui/manual_option_zip.stderr index 55175660b7a26..758f016868706 100644 --- a/src/tools/clippy/tests/ui/manual_option_zip.stderr +++ b/src/tools/clippy/tests/ui/manual_option_zip.stderr @@ -1,5 +1,5 @@ error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:10:13 + --> tests/ui/manual_option_zip.rs:11:13 | LL | let _ = a.and_then(|a| b.map(|b| (a, b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `a.zip(b)` @@ -8,37 +8,37 @@ LL | let _ = a.and_then(|a| b.map(|b| (a, b))); = help: to override `-D warnings` add `#[allow(clippy::manual_option_zip)]` error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:16:13 + --> tests/ui/manual_option_zip.rs:17:13 | LL | let _ = a.and_then(|a| b.map(|b| (a, b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `a.zip(b)` error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:21:13 + --> tests/ui/manual_option_zip.rs:22:13 | LL | let _ = None::.and_then(|a| b.map(|b| (a, b))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `None::.zip(b)` error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:27:13 + --> tests/ui/manual_option_zip.rs:28:13 | LL | let _ = a.and_then(|a| b.map(|b| (b, a))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.zip(a)` error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:34:13 + --> tests/ui/manual_option_zip.rs:35:13 | LL | let _ = a.and_then(|a| { b.map(|b| (a, b)) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `a.zip(b)` error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:37:13 + --> tests/ui/manual_option_zip.rs:38:13 | LL | let _ = a.and_then(|a| b.map(|b| { (a, b) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `a.zip(b)` error: manual implementation of `Option::zip` - --> tests/ui/manual_option_zip.rs:40:13 + --> tests/ui/manual_option_zip.rs:41:13 | LL | let _ = a.and_then(|a| { b.map(|b| { (a, b) }) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `a.zip(b)` diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs index c8409d78ed77c..64a28d38747e4 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![feature(custom_inner_attributes)] #![clippy::msrv = "invalid.version"] //~^ ERROR: `invalid.version` is not a valid Rust version diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr index dbc276ed89df3..8fff1a70da35b 100644 --- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr +++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr @@ -1,35 +1,35 @@ error: `invalid.version` is not a valid Rust version - --> tests/ui/min_rust_version_invalid_attr.rs:4:1 + --> tests/ui/min_rust_version_invalid_attr.rs:2:1 | LL | #![clippy::msrv = "invalid.version"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `invalid.version` is not a valid Rust version - --> tests/ui/min_rust_version_invalid_attr.rs:9:1 + --> tests/ui/min_rust_version_invalid_attr.rs:7:1 | LL | #[clippy::msrv = "invalid.version"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `clippy::msrv` is defined multiple times - --> tests/ui/min_rust_version_invalid_attr.rs:16:5 + --> tests/ui/min_rust_version_invalid_attr.rs:14:5 | LL | #![clippy::msrv = "1.10.1"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first definition found here - --> tests/ui/min_rust_version_invalid_attr.rs:14:5 + --> tests/ui/min_rust_version_invalid_attr.rs:12:5 | LL | #![clippy::msrv = "1.40"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `clippy::msrv` is defined multiple times - --> tests/ui/min_rust_version_invalid_attr.rs:21:9 + --> tests/ui/min_rust_version_invalid_attr.rs:19:9 | LL | #![clippy::msrv = "1.0.0"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first definition found here - --> tests/ui/min_rust_version_invalid_attr.rs:20:9 + --> tests/ui/min_rust_version_invalid_attr.rs:18:9 | LL | #![clippy::msrv = "1.0"] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/needless_bool/early_return.fixed b/src/tools/clippy/tests/ui/needless_bool/early_return.fixed new file mode 100644 index 0000000000000..2ca2aed982029 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_bool/early_return.fixed @@ -0,0 +1,102 @@ +#![warn(clippy::needless_bool)] +#![allow(dead_code, unused, clippy::needless_return)] + +// The motivating case from uutils/coreutils#12689: a guard returning a wrapped bool +// followed by a trailing wrapped bool literal. +fn is_sparse(blocks: u64, size: u64) -> Result { + Ok(blocks < size / 512) + //~^^^^ needless_bool +} + +fn bare(x: bool) -> bool { + x + //~^^^^ needless_bool +} + +fn bare_negated(x: bool) -> bool { + !x + //~^^^^ needless_bool +} + +fn option_wrapped(x: bool) -> Option { + Some(!x) + //~^^^^ needless_bool +} + +fn complex_condition(a: i32, b: i32) -> Result { + Ok(!(a < b && b > 0)) + //~^^^^ needless_bool +} + +fn multi_if_complex_previous_if(x: bool, y: bool) -> Result { + if y { + let z = x && y; + if z { + return Ok(x); + } + return Ok(true); + } + Ok(x) + //~^^^^ needless_bool +} + +// Do NOT lint: the two values are equal, and the condition might have side effects. +fn same_value(x: bool) -> Result { + if x { + return Ok(true); + } + Ok(true) +} + +// Do NOT lint: mismatched wrappers. +fn mismatched_wrappers(x: bool) -> Result { + if x { + return Err(()); + } + Ok(false) +} + +// Do NOT lint: the guard body has a side effect besides the return. +fn side_effect(x: bool) -> Result { + if x { + println!("hi"); + return Ok(true); + } + Ok(false) +} + +// Do NOT lint: not a constructor, just a function call (could have side effects). +fn make(b: bool) -> bool { + b +} +fn not_a_ctor(x: bool) -> bool { + if x { + return make(true); + } + make(false) +} + +// Do NOT lint: multiple if statements chained one after another. +fn multi_if(x: bool, y: bool) -> Result { + if y { + return Ok(true); + } + if x { + return Ok(true); + } + Ok(false) +} + +// Do NOT lint: multiple if statements chained one after another, even if they have different return +// values. +fn multi_if_different_values(x: bool, y: bool) -> bool { + if y { + return false; + } + if x { + return true; + } + false +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_bool/early_return.rs b/src/tools/clippy/tests/ui/needless_bool/early_return.rs new file mode 100644 index 0000000000000..f1451f7fe415a --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_bool/early_return.rs @@ -0,0 +1,120 @@ +#![warn(clippy::needless_bool)] +#![allow(dead_code, unused, clippy::needless_return)] + +// The motivating case from uutils/coreutils#12689: a guard returning a wrapped bool +// followed by a trailing wrapped bool literal. +fn is_sparse(blocks: u64, size: u64) -> Result { + if blocks < size / 512 { + return Ok(true); + } + Ok(false) + //~^^^^ needless_bool +} + +fn bare(x: bool) -> bool { + if x { + return true; + } + false + //~^^^^ needless_bool +} + +fn bare_negated(x: bool) -> bool { + if x { + return false; + } + true + //~^^^^ needless_bool +} + +fn option_wrapped(x: bool) -> Option { + if x { + return Some(false); + } + Some(true) + //~^^^^ needless_bool +} + +fn complex_condition(a: i32, b: i32) -> Result { + if a < b && b > 0 { + return Ok(false); + } + Ok(true) + //~^^^^ needless_bool +} + +fn multi_if_complex_previous_if(x: bool, y: bool) -> Result { + if y { + let z = x && y; + if z { + return Ok(x); + } + return Ok(true); + } + if x { + return Ok(true); + } + Ok(false) + //~^^^^ needless_bool +} + +// Do NOT lint: the two values are equal, and the condition might have side effects. +fn same_value(x: bool) -> Result { + if x { + return Ok(true); + } + Ok(true) +} + +// Do NOT lint: mismatched wrappers. +fn mismatched_wrappers(x: bool) -> Result { + if x { + return Err(()); + } + Ok(false) +} + +// Do NOT lint: the guard body has a side effect besides the return. +fn side_effect(x: bool) -> Result { + if x { + println!("hi"); + return Ok(true); + } + Ok(false) +} + +// Do NOT lint: not a constructor, just a function call (could have side effects). +fn make(b: bool) -> bool { + b +} +fn not_a_ctor(x: bool) -> bool { + if x { + return make(true); + } + make(false) +} + +// Do NOT lint: multiple if statements chained one after another. +fn multi_if(x: bool, y: bool) -> Result { + if y { + return Ok(true); + } + if x { + return Ok(true); + } + Ok(false) +} + +// Do NOT lint: multiple if statements chained one after another, even if they have different return +// values. +fn multi_if_different_values(x: bool, y: bool) -> bool { + if y { + return false; + } + if x { + return true; + } + false +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_bool/early_return.stderr b/src/tools/clippy/tests/ui/needless_bool/early_return.stderr new file mode 100644 index 0000000000000..488e41e993516 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_bool/early_return.stderr @@ -0,0 +1,59 @@ +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/needless_bool/early_return.rs:7:5 + | +LL | / if blocks < size / 512 { +LL | | return Ok(true); +LL | | } +LL | | Ok(false) + | |_____________^ help: you can reduce it to: `Ok(blocks < size / 512)` + | + = note: `-D clippy::needless-bool` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_bool)]` + +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/needless_bool/early_return.rs:15:5 + | +LL | / if x { +LL | | return true; +LL | | } +LL | | false + | |_________^ help: you can reduce it to: `x` + +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/needless_bool/early_return.rs:23:5 + | +LL | / if x { +LL | | return false; +LL | | } +LL | | true + | |________^ help: you can reduce it to: `!x` + +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/needless_bool/early_return.rs:31:5 + | +LL | / if x { +LL | | return Some(false); +LL | | } +LL | | Some(true) + | |______________^ help: you can reduce it to: `Some(!x)` + +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/needless_bool/early_return.rs:39:5 + | +LL | / if a < b && b > 0 { +LL | | return Ok(false); +LL | | } +LL | | Ok(true) + | |____________^ help: you can reduce it to: `Ok(!(a < b && b > 0))` + +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/needless_bool/early_return.rs:54:5 + | +LL | / if x { +LL | | return Ok(true); +LL | | } +LL | | Ok(false) + | |_____________^ help: you can reduce it to: `Ok(x)` + +error: aborting due to 6 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_nonzero_get.fixed b/src/tools/clippy/tests/ui/needless_nonzero_get.fixed new file mode 100644 index 0000000000000..4e64b735178d2 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_nonzero_get.fixed @@ -0,0 +1,257 @@ +//@aux-build:proc_macros.rs + +#![warn(clippy::needless_nonzero_get)] +// the `msrv` functions below deliberately use items newer than their MSRV +#![allow(clippy::incompatible_msrv)] + +extern crate proc_macros; + +use proc_macros::with_span; +use std::num::{NonZero, NonZeroI32, NonZeroU32}; + +fn unsigned(nz: NonZero) { + let _ = nz.leading_zeros(); + //~^ needless_nonzero_get + let _ = nz.trailing_zeros(); + //~^ needless_nonzero_get + let _ = nz.is_power_of_two(); + //~^ needless_nonzero_get + let _ = nz.ilog2(); + //~^ needless_nonzero_get + let _ = nz.ilog10(); + //~^ needless_nonzero_get +} + +fn signed(nz: NonZero) { + let _ = nz.leading_zeros(); + //~^ needless_nonzero_get + let _ = nz.trailing_zeros(); + //~^ needless_nonzero_get + let _ = nz.is_positive(); + //~^ needless_nonzero_get + let _ = nz.is_negative(); + //~^ needless_nonzero_get +} + +fn unsigned_widths(a: NonZero, b: NonZero, c: NonZero, d: NonZero, e: NonZero) { + let _ = a.leading_zeros(); + //~^ needless_nonzero_get + let _ = b.trailing_zeros(); + //~^ needless_nonzero_get + let _ = c.ilog2(); + //~^ needless_nonzero_get + let _ = d.is_power_of_two(); + //~^ needless_nonzero_get + let _ = e.ilog10(); + //~^ needless_nonzero_get +} + +fn signed_widths(f: NonZero, g: NonZero, h: NonZero, i: NonZero, j: NonZero) { + let _ = f.is_negative(); + //~^ needless_nonzero_get + let _ = g.is_positive(); + //~^ needless_nonzero_get + let _ = h.leading_zeros(); + //~^ needless_nonzero_get + let _ = i.trailing_zeros(); + //~^ needless_nonzero_get + let _ = j.leading_zeros(); + //~^ needless_nonzero_get +} + +fn aliases_and_receivers(a: NonZeroU32, b: NonZeroI32, r: &NonZero) { + let _ = a.ilog2(); + //~^ needless_nonzero_get + let _ = b.is_positive(); + //~^ needless_nonzero_get + let _ = r.leading_zeros(); + //~^ needless_nonzero_get + + // more complex receiver expressions + let _ = NonZero::new(5u32).unwrap().leading_zeros(); + //~^ needless_nonzero_get + let _ = (a).trailing_zeros(); + //~^ needless_nonzero_get + + // multi-line chain + let _ = a + //~^ needless_nonzero_get + .leading_zeros(); +} + +fn operators(mut value: u32, other: u32, nz: NonZero) { + let _ = other / nz; + //~^ needless_nonzero_get + let _ = other % nz; + //~^ needless_nonzero_get + value /= nz; + //~^ needless_nonzero_get + value %= nz; + //~^ needless_nonzero_get +} + +// The `NonZero` operator implementations carry `#[rustc_const_unstable(feature = "const_ops")]`, +// so they are not usable in a `const` context even though `Div`/`Rem` themselves are stable. +const fn const_operators(mut value: u32, nz: NonZero) -> u32 { + value /= nz.get(); + value / nz.get() +} + +// `NonZero::leading_zeros` is const-stable since 1.53.0, so the `get` can go even in a `const fn`. +const fn const_methods(nz: NonZero) -> u32 { + nz.leading_zeros() + //~^ needless_nonzero_get +} + +fn no_lint(nz: NonZero, signed: NonZero, plain: u32) { + // `NonZero`'s version returns `NonZero` rather than `u32`, so the `get` would only move + // rather than disappear + let _ = nz.get().bit_width(); + let _ = nz.get().count_ones(); + let _ = nz.get().isqrt(); + let _ = nz.get().checked_add(1); + let _ = nz.get().saturating_mul(2); + let _ = signed.get().abs(); + let _ = signed.get().cast_unsigned(); + let _ = signed.get().unsigned_abs(); + let _ = signed.get().wrapping_neg(); + let _ = signed.get().overflowing_neg(); + + // `highest_one`/`lowest_one` return `Option` on integers but `u32` on `NonZero` + let _ = nz.get().highest_one(); + let _ = nz.get().lowest_one(); + + // no `NonZero` equivalent at all + let _ = nz.get().to_string(); + let _ = nz.get().count_zeros(); + + // `i32::ilog2` exists but `NonZero::ilog2` does not, so the impls must not cross over + let _ = signed.get().ilog2(); + + // The `NonZero` division and remainder implementations are unsigned-only. + let signed_value = signed.get(); + let _ = signed_value / signed.get(); + let _ = signed_value % signed.get(); + + // Primitive operators forward references, but the `NonZero` operators do not. + let value_ref = &plain; + let _ = value_ref / nz.get(); + let _ = value_ref % nz.get(); + + let nz_ref = &nz; + let _ = plain / nz_ref.get(); + let _ = plain % nz_ref.get(); + + // not a `NonZero` receiver + let _ = plain.leading_zeros(); + + // `get` is not immediately followed by the method + let x = nz.get(); + let _ = x.leading_zeros(); + + // takes arguments + let _ = nz.get().rotate_left(2); + + // a shadowing trait method must not be rewritten + let _ = nz.get().shadowed(); +} + +trait Shadowed { + fn shadowed(self) -> u32; +} + +impl Shadowed for u32 { + fn shadowed(self) -> u32 { + self + } +} + +impl Shadowed for NonZero { + fn shadowed(self) -> u32 { + 0 + } +} + +// `NonZero::leading_zeros` was stabilized in 1.53.0 +#[clippy::msrv = "1.52"] +fn below_msrv(nz: NonZero) { + let _ = nz.get().leading_zeros(); +} + +#[clippy::msrv = "1.53"] +fn meets_msrv(nz: NonZero) { + let _ = nz.leading_zeros(); + //~^ needless_nonzero_get +} + +// `NonZero::ilog2` was stabilized in 1.67.0, later than `leading_zeros` +#[clippy::msrv = "1.66"] +fn below_ilog2_msrv(nz: NonZero) { + let _ = nz.get().ilog2(); + let _ = nz.leading_zeros(); + //~^ needless_nonzero_get +} + +// `Div>` and `Rem>` were stabilized in 1.51.0 +#[clippy::msrv = "1.50"] +fn below_nonzero_div_msrv(value: u32, nz: NonZero) { + let _ = value / nz.get(); + let _ = value % nz.get(); +} + +#[clippy::msrv = "1.51"] +fn meets_nonzero_div_msrv(value: u32, nz: NonZero) { + let _ = value / nz; + //~^ needless_nonzero_get + let _ = value % nz; + //~^ needless_nonzero_get +} + +// `DivAssign>` and `RemAssign>` were stabilized in 1.79.0 +#[clippy::msrv = "1.78"] +fn below_nonzero_div_assign_msrv(mut value: u32, nz: NonZero) { + value /= nz.get(); + value %= nz.get(); +} + +#[clippy::msrv = "1.79"] +fn meets_nonzero_div_assign_msrv(mut value: u32, nz: NonZero) { + value /= nz; + //~^ needless_nonzero_get + value %= nz; + //~^ needless_nonzero_get +} + +// The whole expression is written in the macro, so the suggestion would point at code the caller +// cannot edit. +macro_rules! leading_zeros_of_five { + () => {{ + let nz = NonZero::new(5u32).unwrap(); + nz.get().leading_zeros() + }}; +} + +// Only the receiver comes from the macro, so the removal span would start in the expansion and end +// at the call site. +macro_rules! five { + () => { + NonZero::new(5u32).unwrap() + }; +} + +// Only `.get()` comes from the macro: the receiver is a macro argument and keeps its call site +// span. +macro_rules! get_of { + ($nz:expr) => { + $nz.get() + }; +} + +fn from_macros(nz: NonZero) { + let _ = leading_zeros_of_five!(); + let _ = five!().get().leading_zeros(); + let _ = get_of!(nz).leading_zeros(); + let _ = with_span!(span nz.get().leading_zeros()); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_nonzero_get.rs b/src/tools/clippy/tests/ui/needless_nonzero_get.rs new file mode 100644 index 0000000000000..4c7108af04dda --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_nonzero_get.rs @@ -0,0 +1,258 @@ +//@aux-build:proc_macros.rs + +#![warn(clippy::needless_nonzero_get)] +// the `msrv` functions below deliberately use items newer than their MSRV +#![allow(clippy::incompatible_msrv)] + +extern crate proc_macros; + +use proc_macros::with_span; +use std::num::{NonZero, NonZeroI32, NonZeroU32}; + +fn unsigned(nz: NonZero) { + let _ = nz.get().leading_zeros(); + //~^ needless_nonzero_get + let _ = nz.get().trailing_zeros(); + //~^ needless_nonzero_get + let _ = nz.get().is_power_of_two(); + //~^ needless_nonzero_get + let _ = nz.get().ilog2(); + //~^ needless_nonzero_get + let _ = nz.get().ilog10(); + //~^ needless_nonzero_get +} + +fn signed(nz: NonZero) { + let _ = nz.get().leading_zeros(); + //~^ needless_nonzero_get + let _ = nz.get().trailing_zeros(); + //~^ needless_nonzero_get + let _ = nz.get().is_positive(); + //~^ needless_nonzero_get + let _ = nz.get().is_negative(); + //~^ needless_nonzero_get +} + +fn unsigned_widths(a: NonZero, b: NonZero, c: NonZero, d: NonZero, e: NonZero) { + let _ = a.get().leading_zeros(); + //~^ needless_nonzero_get + let _ = b.get().trailing_zeros(); + //~^ needless_nonzero_get + let _ = c.get().ilog2(); + //~^ needless_nonzero_get + let _ = d.get().is_power_of_two(); + //~^ needless_nonzero_get + let _ = e.get().ilog10(); + //~^ needless_nonzero_get +} + +fn signed_widths(f: NonZero, g: NonZero, h: NonZero, i: NonZero, j: NonZero) { + let _ = f.get().is_negative(); + //~^ needless_nonzero_get + let _ = g.get().is_positive(); + //~^ needless_nonzero_get + let _ = h.get().leading_zeros(); + //~^ needless_nonzero_get + let _ = i.get().trailing_zeros(); + //~^ needless_nonzero_get + let _ = j.get().leading_zeros(); + //~^ needless_nonzero_get +} + +fn aliases_and_receivers(a: NonZeroU32, b: NonZeroI32, r: &NonZero) { + let _ = a.get().ilog2(); + //~^ needless_nonzero_get + let _ = b.get().is_positive(); + //~^ needless_nonzero_get + let _ = r.get().leading_zeros(); + //~^ needless_nonzero_get + + // more complex receiver expressions + let _ = NonZero::new(5u32).unwrap().get().leading_zeros(); + //~^ needless_nonzero_get + let _ = (a).get().trailing_zeros(); + //~^ needless_nonzero_get + + // multi-line chain + let _ = a + .get() + //~^ needless_nonzero_get + .leading_zeros(); +} + +fn operators(mut value: u32, other: u32, nz: NonZero) { + let _ = other / nz.get(); + //~^ needless_nonzero_get + let _ = other % nz.get(); + //~^ needless_nonzero_get + value /= nz.get(); + //~^ needless_nonzero_get + value %= nz.get(); + //~^ needless_nonzero_get +} + +// The `NonZero` operator implementations carry `#[rustc_const_unstable(feature = "const_ops")]`, +// so they are not usable in a `const` context even though `Div`/`Rem` themselves are stable. +const fn const_operators(mut value: u32, nz: NonZero) -> u32 { + value /= nz.get(); + value / nz.get() +} + +// `NonZero::leading_zeros` is const-stable since 1.53.0, so the `get` can go even in a `const fn`. +const fn const_methods(nz: NonZero) -> u32 { + nz.get().leading_zeros() + //~^ needless_nonzero_get +} + +fn no_lint(nz: NonZero, signed: NonZero, plain: u32) { + // `NonZero`'s version returns `NonZero` rather than `u32`, so the `get` would only move + // rather than disappear + let _ = nz.get().bit_width(); + let _ = nz.get().count_ones(); + let _ = nz.get().isqrt(); + let _ = nz.get().checked_add(1); + let _ = nz.get().saturating_mul(2); + let _ = signed.get().abs(); + let _ = signed.get().cast_unsigned(); + let _ = signed.get().unsigned_abs(); + let _ = signed.get().wrapping_neg(); + let _ = signed.get().overflowing_neg(); + + // `highest_one`/`lowest_one` return `Option` on integers but `u32` on `NonZero` + let _ = nz.get().highest_one(); + let _ = nz.get().lowest_one(); + + // no `NonZero` equivalent at all + let _ = nz.get().to_string(); + let _ = nz.get().count_zeros(); + + // `i32::ilog2` exists but `NonZero::ilog2` does not, so the impls must not cross over + let _ = signed.get().ilog2(); + + // The `NonZero` division and remainder implementations are unsigned-only. + let signed_value = signed.get(); + let _ = signed_value / signed.get(); + let _ = signed_value % signed.get(); + + // Primitive operators forward references, but the `NonZero` operators do not. + let value_ref = &plain; + let _ = value_ref / nz.get(); + let _ = value_ref % nz.get(); + + let nz_ref = &nz; + let _ = plain / nz_ref.get(); + let _ = plain % nz_ref.get(); + + // not a `NonZero` receiver + let _ = plain.leading_zeros(); + + // `get` is not immediately followed by the method + let x = nz.get(); + let _ = x.leading_zeros(); + + // takes arguments + let _ = nz.get().rotate_left(2); + + // a shadowing trait method must not be rewritten + let _ = nz.get().shadowed(); +} + +trait Shadowed { + fn shadowed(self) -> u32; +} + +impl Shadowed for u32 { + fn shadowed(self) -> u32 { + self + } +} + +impl Shadowed for NonZero { + fn shadowed(self) -> u32 { + 0 + } +} + +// `NonZero::leading_zeros` was stabilized in 1.53.0 +#[clippy::msrv = "1.52"] +fn below_msrv(nz: NonZero) { + let _ = nz.get().leading_zeros(); +} + +#[clippy::msrv = "1.53"] +fn meets_msrv(nz: NonZero) { + let _ = nz.get().leading_zeros(); + //~^ needless_nonzero_get +} + +// `NonZero::ilog2` was stabilized in 1.67.0, later than `leading_zeros` +#[clippy::msrv = "1.66"] +fn below_ilog2_msrv(nz: NonZero) { + let _ = nz.get().ilog2(); + let _ = nz.get().leading_zeros(); + //~^ needless_nonzero_get +} + +// `Div>` and `Rem>` were stabilized in 1.51.0 +#[clippy::msrv = "1.50"] +fn below_nonzero_div_msrv(value: u32, nz: NonZero) { + let _ = value / nz.get(); + let _ = value % nz.get(); +} + +#[clippy::msrv = "1.51"] +fn meets_nonzero_div_msrv(value: u32, nz: NonZero) { + let _ = value / nz.get(); + //~^ needless_nonzero_get + let _ = value % nz.get(); + //~^ needless_nonzero_get +} + +// `DivAssign>` and `RemAssign>` were stabilized in 1.79.0 +#[clippy::msrv = "1.78"] +fn below_nonzero_div_assign_msrv(mut value: u32, nz: NonZero) { + value /= nz.get(); + value %= nz.get(); +} + +#[clippy::msrv = "1.79"] +fn meets_nonzero_div_assign_msrv(mut value: u32, nz: NonZero) { + value /= nz.get(); + //~^ needless_nonzero_get + value %= nz.get(); + //~^ needless_nonzero_get +} + +// The whole expression is written in the macro, so the suggestion would point at code the caller +// cannot edit. +macro_rules! leading_zeros_of_five { + () => {{ + let nz = NonZero::new(5u32).unwrap(); + nz.get().leading_zeros() + }}; +} + +// Only the receiver comes from the macro, so the removal span would start in the expansion and end +// at the call site. +macro_rules! five { + () => { + NonZero::new(5u32).unwrap() + }; +} + +// Only `.get()` comes from the macro: the receiver is a macro argument and keeps its call site +// span. +macro_rules! get_of { + ($nz:expr) => { + $nz.get() + }; +} + +fn from_macros(nz: NonZero) { + let _ = leading_zeros_of_five!(); + let _ = five!().get().leading_zeros(); + let _ = get_of!(nz).leading_zeros(); + let _ = with_span!(span nz.get().leading_zeros()); +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_nonzero_get.stderr b/src/tools/clippy/tests/ui/needless_nonzero_get.stderr new file mode 100644 index 0000000000000..1b7ea10e09543 --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_nonzero_get.stderr @@ -0,0 +1,437 @@ +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:13:16 + | +LL | let _ = nz.get().leading_zeros(); + | ^^^^^ + | + = note: `-D clippy::needless-nonzero-get` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_nonzero_get)]` +help: remove this + | +LL - let _ = nz.get().leading_zeros(); +LL + let _ = nz.leading_zeros(); + | + +error: unnecessary `get` before `trailing_zeros` + --> tests/ui/needless_nonzero_get.rs:15:16 + | +LL | let _ = nz.get().trailing_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().trailing_zeros(); +LL + let _ = nz.trailing_zeros(); + | + +error: unnecessary `get` before `is_power_of_two` + --> tests/ui/needless_nonzero_get.rs:17:16 + | +LL | let _ = nz.get().is_power_of_two(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().is_power_of_two(); +LL + let _ = nz.is_power_of_two(); + | + +error: unnecessary `get` before `ilog2` + --> tests/ui/needless_nonzero_get.rs:19:16 + | +LL | let _ = nz.get().ilog2(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().ilog2(); +LL + let _ = nz.ilog2(); + | + +error: unnecessary `get` before `ilog10` + --> tests/ui/needless_nonzero_get.rs:21:16 + | +LL | let _ = nz.get().ilog10(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().ilog10(); +LL + let _ = nz.ilog10(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:26:16 + | +LL | let _ = nz.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().leading_zeros(); +LL + let _ = nz.leading_zeros(); + | + +error: unnecessary `get` before `trailing_zeros` + --> tests/ui/needless_nonzero_get.rs:28:16 + | +LL | let _ = nz.get().trailing_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().trailing_zeros(); +LL + let _ = nz.trailing_zeros(); + | + +error: unnecessary `get` before `is_positive` + --> tests/ui/needless_nonzero_get.rs:30:16 + | +LL | let _ = nz.get().is_positive(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().is_positive(); +LL + let _ = nz.is_positive(); + | + +error: unnecessary `get` before `is_negative` + --> tests/ui/needless_nonzero_get.rs:32:16 + | +LL | let _ = nz.get().is_negative(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().is_negative(); +LL + let _ = nz.is_negative(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:37:15 + | +LL | let _ = a.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = a.get().leading_zeros(); +LL + let _ = a.leading_zeros(); + | + +error: unnecessary `get` before `trailing_zeros` + --> tests/ui/needless_nonzero_get.rs:39:15 + | +LL | let _ = b.get().trailing_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = b.get().trailing_zeros(); +LL + let _ = b.trailing_zeros(); + | + +error: unnecessary `get` before `ilog2` + --> tests/ui/needless_nonzero_get.rs:41:15 + | +LL | let _ = c.get().ilog2(); + | ^^^^^ + | +help: remove this + | +LL - let _ = c.get().ilog2(); +LL + let _ = c.ilog2(); + | + +error: unnecessary `get` before `is_power_of_two` + --> tests/ui/needless_nonzero_get.rs:43:15 + | +LL | let _ = d.get().is_power_of_two(); + | ^^^^^ + | +help: remove this + | +LL - let _ = d.get().is_power_of_two(); +LL + let _ = d.is_power_of_two(); + | + +error: unnecessary `get` before `ilog10` + --> tests/ui/needless_nonzero_get.rs:45:15 + | +LL | let _ = e.get().ilog10(); + | ^^^^^ + | +help: remove this + | +LL - let _ = e.get().ilog10(); +LL + let _ = e.ilog10(); + | + +error: unnecessary `get` before `is_negative` + --> tests/ui/needless_nonzero_get.rs:50:15 + | +LL | let _ = f.get().is_negative(); + | ^^^^^ + | +help: remove this + | +LL - let _ = f.get().is_negative(); +LL + let _ = f.is_negative(); + | + +error: unnecessary `get` before `is_positive` + --> tests/ui/needless_nonzero_get.rs:52:15 + | +LL | let _ = g.get().is_positive(); + | ^^^^^ + | +help: remove this + | +LL - let _ = g.get().is_positive(); +LL + let _ = g.is_positive(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:54:15 + | +LL | let _ = h.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = h.get().leading_zeros(); +LL + let _ = h.leading_zeros(); + | + +error: unnecessary `get` before `trailing_zeros` + --> tests/ui/needless_nonzero_get.rs:56:15 + | +LL | let _ = i.get().trailing_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = i.get().trailing_zeros(); +LL + let _ = i.trailing_zeros(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:58:15 + | +LL | let _ = j.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = j.get().leading_zeros(); +LL + let _ = j.leading_zeros(); + | + +error: unnecessary `get` before `ilog2` + --> tests/ui/needless_nonzero_get.rs:63:15 + | +LL | let _ = a.get().ilog2(); + | ^^^^^ + | +help: remove this + | +LL - let _ = a.get().ilog2(); +LL + let _ = a.ilog2(); + | + +error: unnecessary `get` before `is_positive` + --> tests/ui/needless_nonzero_get.rs:65:15 + | +LL | let _ = b.get().is_positive(); + | ^^^^^ + | +help: remove this + | +LL - let _ = b.get().is_positive(); +LL + let _ = b.is_positive(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:67:15 + | +LL | let _ = r.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = r.get().leading_zeros(); +LL + let _ = r.leading_zeros(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:71:41 + | +LL | let _ = NonZero::new(5u32).unwrap().get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = NonZero::new(5u32).unwrap().get().leading_zeros(); +LL + let _ = NonZero::new(5u32).unwrap().leading_zeros(); + | + +error: unnecessary `get` before `trailing_zeros` + --> tests/ui/needless_nonzero_get.rs:73:17 + | +LL | let _ = (a).get().trailing_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = (a).get().trailing_zeros(); +LL + let _ = (a).trailing_zeros(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:78:10 + | +LL | .get() + | ^^^^^ + | +help: remove this + | +LL - let _ = a +LL - .get() +LL + let _ = a + | + +error: unnecessary `get` before `/` + --> tests/ui/needless_nonzero_get.rs:84:24 + | +LL | let _ = other / nz.get(); + | ^^^^^ + | +help: remove this + | +LL - let _ = other / nz.get(); +LL + let _ = other / nz; + | + +error: unnecessary `get` before `%` + --> tests/ui/needless_nonzero_get.rs:86:24 + | +LL | let _ = other % nz.get(); + | ^^^^^ + | +help: remove this + | +LL - let _ = other % nz.get(); +LL + let _ = other % nz; + | + +error: unnecessary `get` before `/=` + --> tests/ui/needless_nonzero_get.rs:88:17 + | +LL | value /= nz.get(); + | ^^^^^ + | +help: remove this + | +LL - value /= nz.get(); +LL + value /= nz; + | + +error: unnecessary `get` before `%=` + --> tests/ui/needless_nonzero_get.rs:90:17 + | +LL | value %= nz.get(); + | ^^^^^ + | +help: remove this + | +LL - value %= nz.get(); +LL + value %= nz; + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:103:8 + | +LL | nz.get().leading_zeros() + | ^^^^^ + | +help: remove this + | +LL - nz.get().leading_zeros() +LL + nz.leading_zeros() + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:184:16 + | +LL | let _ = nz.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().leading_zeros(); +LL + let _ = nz.leading_zeros(); + | + +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get.rs:192:16 + | +LL | let _ = nz.get().leading_zeros(); + | ^^^^^ + | +help: remove this + | +LL - let _ = nz.get().leading_zeros(); +LL + let _ = nz.leading_zeros(); + | + +error: unnecessary `get` before `/` + --> tests/ui/needless_nonzero_get.rs:205:24 + | +LL | let _ = value / nz.get(); + | ^^^^^ + | +help: remove this + | +LL - let _ = value / nz.get(); +LL + let _ = value / nz; + | + +error: unnecessary `get` before `%` + --> tests/ui/needless_nonzero_get.rs:207:24 + | +LL | let _ = value % nz.get(); + | ^^^^^ + | +help: remove this + | +LL - let _ = value % nz.get(); +LL + let _ = value % nz; + | + +error: unnecessary `get` before `/=` + --> tests/ui/needless_nonzero_get.rs:220:17 + | +LL | value /= nz.get(); + | ^^^^^ + | +help: remove this + | +LL - value /= nz.get(); +LL + value /= nz; + | + +error: unnecessary `get` before `%=` + --> tests/ui/needless_nonzero_get.rs:222:17 + | +LL | value %= nz.get(); + | ^^^^^ + | +help: remove this + | +LL - value %= nz.get(); +LL + value %= nz; + | + +error: aborting due to 36 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_nonzero_get_unfixable.rs b/src/tools/clippy/tests/ui/needless_nonzero_get_unfixable.rs new file mode 100644 index 0000000000000..211cc57ef177e --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_nonzero_get_unfixable.rs @@ -0,0 +1,26 @@ +//@no-rustfix: the suggestion would remove the comment before `.get()` + +#![warn(clippy::needless_nonzero_get)] + +use std::num::NonZero; + +fn main() { + let nz = NonZero::new(1u32).unwrap(); + let mut value = 10u32; + + // This comment must not be removed by an automatic fix. + let _ = nz /* keep this comment */ + .get() + //~^ needless_nonzero_get + .leading_zeros(); + + // The operator suggestions share the same removal span, so they must preserve comments too. + let _ = value + / nz /* keep this comment */ + .get(); + //~^ needless_nonzero_get + + value %= nz /* keep this comment */ + .get(); + //~^ needless_nonzero_get +} diff --git a/src/tools/clippy/tests/ui/needless_nonzero_get_unfixable.stderr b/src/tools/clippy/tests/ui/needless_nonzero_get_unfixable.stderr new file mode 100644 index 0000000000000..100dce7181a3b --- /dev/null +++ b/src/tools/clippy/tests/ui/needless_nonzero_get_unfixable.stderr @@ -0,0 +1,43 @@ +error: unnecessary `get` before `leading_zeros` + --> tests/ui/needless_nonzero_get_unfixable.rs:13:10 + | +LL | .get() + | ^^^^^ + | + = note: `-D clippy::needless-nonzero-get` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_nonzero_get)]` +help: remove this + | +LL - let _ = nz /* keep this comment */ +LL - .get() +LL + let _ = nz + | + +error: unnecessary `get` before `/` + --> tests/ui/needless_nonzero_get_unfixable.rs:20:14 + | +LL | .get(); + | ^^^^^ + | +help: remove this + | +LL - / nz /* keep this comment */ +LL - .get(); +LL + / nz; + | + +error: unnecessary `get` before `%=` + --> tests/ui/needless_nonzero_get_unfixable.rs:24:10 + | +LL | .get(); + | ^^^^^ + | +help: remove this + | +LL - value %= nz /* keep this comment */ +LL - .get(); +LL + value %= nz; + | + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/needless_range_loop.rs b/src/tools/clippy/tests/ui/needless_range_loop.rs index dcb7026266048..7ad61ce90c721 100644 --- a/src/tools/clippy/tests/ui/needless_range_loop.rs +++ b/src/tools/clippy/tests/ui/needless_range_loop.rs @@ -237,3 +237,43 @@ fn issue_15068() { let _ = a[0][i]; } } + +fn issue16631() { + let mut matrix: Vec> = Vec::new(); + for i in 0..=2 { + //~^ needless_range_loop + matrix[i][i] = true; + } + + let values = [[0; 4]; 4]; + let col = 2; + for i in 0..4 { + //~^ needless_range_loop + let _ = values[i][col]; + } + + let mut colors = [[0; 3]; 4]; + for i in 0..3 { + colors[2][i] = ((u16::from(colors[0][i]) * 2 + u16::from(colors[1][i]) + 1) / 3) as u8; + colors[3][i] = ((u16::from(colors[0][i]) + u16::from(colors[1][i]) * 2 + 1) / 3) as u8; + } + + let mut colors = [[0; 3]; 4]; + let i = 0; + for j in 0..3 { + colors[i][j] = colors[0][j]; + } + + let mut colors = [[0; 3]; 4]; + for j in 0..3 { + //~^ needless_range_loop + let _ = colors[0][j]; + } + + struct Wrapper(T); + let mut wrapper = Wrapper([0; 3]); + for i in 0..3 { + //~^ needless_range_loop + let _ = wrapper.0[i]; + } +} diff --git a/src/tools/clippy/tests/ui/needless_range_loop.stderr b/src/tools/clippy/tests/ui/needless_range_loop.stderr index ab9693bb46d6b..755e9b8657b3a 100644 --- a/src/tools/clippy/tests/ui/needless_range_loop.stderr +++ b/src/tools/clippy/tests/ui/needless_range_loop.stderr @@ -4,6 +4,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:14:24 + | +LL | println!("{}", vec[i]); + | ^^^^^^ = note: `-D clippy::needless-range-loop` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_range_loop)]` help: consider using an iterator @@ -18,6 +23,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:25:17 + | +LL | let _ = vec[i]; + | ^^^^^^ help: consider using an iterator | LL - for i in 0..vec.len() { @@ -30,6 +40,11 @@ error: the loop variable `j` is only used to index `STATIC` LL | for j in 0..4 { | ^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:32:26 + | +LL | println!("{:?}", STATIC[j]); + | ^^^^^^^^^ help: consider using an iterator | LL - for j in 0..4 { @@ -42,6 +57,11 @@ error: the loop variable `j` is only used to index `CONST` LL | for j in 0..4 { | ^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:38:26 + | +LL | println!("{:?}", CONST[j]); + | ^^^^^^^^ help: consider using an iterator | LL - for j in 0..4 { @@ -54,7 +74,12 @@ error: the loop variable `i` is used to index `vec` LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ | -help: consider using an iterator and enumerate() +note: for this index operation + --> tests/ui/needless_range_loop.rs:44:27 + | +LL | println!("{} {}", vec[i], i); + | ^^^^^^ +help: consider using an iterator and `.enumerate()` | LL - for i in 0..vec.len() { LL + for (i, ) in vec.iter().enumerate() { @@ -66,6 +91,11 @@ error: the loop variable `i` is only used to index `vec2` LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:54:24 + | +LL | println!("{}", vec2[i]); + | ^^^^^^^ help: consider using an iterator | LL - for i in 0..vec.len() { @@ -78,6 +108,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:60:24 + | +LL | println!("{}", vec[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 5..vec.len() { @@ -90,6 +125,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:66:24 + | +LL | println!("{}", vec[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 0..MAX_LEN { @@ -102,6 +142,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 0..=MAX_LEN { | ^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:72:24 + | +LL | println!("{}", vec[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 0..=MAX_LEN { @@ -114,6 +159,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 5..10 { | ^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:78:24 + | +LL | println!("{}", vec[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 5..10 { @@ -126,6 +176,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in 5..=10 { | ^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:84:24 + | +LL | println!("{}", vec[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 5..=10 { @@ -138,7 +193,12 @@ error: the loop variable `i` is used to index `vec` LL | for i in 5..vec.len() { | ^^^^^^^^^^^^ | -help: consider using an iterator and enumerate() +note: for this index operation + --> tests/ui/needless_range_loop.rs:90:27 + | +LL | println!("{} {}", vec[i], i); + | ^^^^^^ +help: consider using an iterator and `.enumerate()` | LL - for i in 5..vec.len() { LL + for (i, ) in vec.iter().enumerate().skip(5) { @@ -150,7 +210,12 @@ error: the loop variable `i` is used to index `vec` LL | for i in 5..10 { | ^^^^^ | -help: consider using an iterator and enumerate() +note: for this index operation + --> tests/ui/needless_range_loop.rs:96:27 + | +LL | println!("{} {}", vec[i], i); + | ^^^^^^ +help: consider using an iterator and `.enumerate()` | LL - for i in 5..10 { LL + for (i, ) in vec.iter().enumerate().take(10).skip(5) { @@ -162,7 +227,12 @@ error: the loop variable `i` is used to index `vec` LL | for i in 0..vec.len() { | ^^^^^^^^^^^^ | -help: consider using an iterator and enumerate() +note: for this index operation + --> tests/ui/needless_range_loop.rs:103:9 + | +LL | vec[i] = Some(1).unwrap_or_else(|| panic!("error on {}", i)); + | ^^^^^^ +help: consider using an iterator and `.enumerate()` | LL - for i in 0..vec.len() { LL + for (i, ) in vec.iter_mut().enumerate() { @@ -174,23 +244,101 @@ error: the loop variable `i` is used to index `a` LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ | -help: consider using an iterator and enumerate() +note: for this index operation + --> tests/ui/needless_range_loop.rs:232:17 + | +LL | let _ = a[i][i]; + | ^^^^ +help: consider using an iterator and `.enumerate()` | LL - for i in 0..MAX_LEN { LL + for (i, ) in a.iter().enumerate().take(MAX_LEN) { | -error: the loop variable `i` is only used to index `a` +error: the loop variable `i` is only used to index `a[0]` --> tests/ui/needless_range_loop.rs:235:14 | LL | for i in 0..MAX_LEN { | ^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop.rs:237:17 + | +LL | let _ = a[0][i]; + | ^^^^^^^ help: consider using an iterator | LL - for i in 0..MAX_LEN { -LL + for in a.iter().take(MAX_LEN) { +LL + for in a[0].iter().take(MAX_LEN) { + | + +error: the loop variable `i` is used to index `matrix` + --> tests/ui/needless_range_loop.rs:243:14 + | +LL | for i in 0..=2 { + | ^^^^^ + | +note: for this index operation + --> tests/ui/needless_range_loop.rs:245:9 + | +LL | matrix[i][i] = true; + | ^^^^^^^^^ +help: consider using an iterator and `.enumerate()` + | +LL - for i in 0..=2 { +LL + for (i, ) in matrix.iter_mut().enumerate().take(2 + 1) { + | + +error: the loop variable `i` is only used to index `values` + --> tests/ui/needless_range_loop.rs:250:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: for this index operation + --> tests/ui/needless_range_loop.rs:252:17 + | +LL | let _ = values[i][col]; + | ^^^^^^^^^ +help: consider using an iterator + | +LL - for i in 0..4 { +LL + for in &values { + | + +error: the loop variable `j` is only used to index `colors[0]` + --> tests/ui/needless_range_loop.rs:268:14 + | +LL | for j in 0..3 { + | ^^^^ + | +note: for this index operation + --> tests/ui/needless_range_loop.rs:270:17 + | +LL | let _ = colors[0][j]; + | ^^^^^^^^^^^^ +help: consider using an iterator + | +LL - for j in 0..3 { +LL + for in &colors[0] { + | + +error: the loop variable `i` is only used to index `wrapper.0` + --> tests/ui/needless_range_loop.rs:275:14 + | +LL | for i in 0..3 { + | ^^^^ + | +note: for this index operation + --> tests/ui/needless_range_loop.rs:277:17 + | +LL | let _ = wrapper.0[i]; + | ^^^^^^^^^^^^ +help: consider using an iterator + | +LL - for i in 0..3 { +LL + for in &wrapper.0 { | -error: aborting due to 16 previous errors +error: aborting due to 20 previous errors diff --git a/src/tools/clippy/tests/ui/needless_range_loop2.stderr b/src/tools/clippy/tests/ui/needless_range_loop2.stderr index cb979b3f3c243..36d2f443ef526 100644 --- a/src/tools/clippy/tests/ui/needless_range_loop2.stderr +++ b/src/tools/clippy/tests/ui/needless_range_loop2.stderr @@ -4,6 +4,11 @@ error: the loop variable `i` is only used to index `ns` LL | for i in 3..10 { | ^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:14:24 + | +LL | println!("{}", ns[i]); + | ^^^^^ = note: `-D clippy::needless-range-loop` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_range_loop)]` help: consider using an iterator @@ -18,6 +23,11 @@ error: the loop variable `i` is only used to index `ms` LL | for i in 0..ms.len() { | ^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:37:9 + | +LL | ms[i] *= 2; + | ^^^^^ help: consider using an iterator | LL - for i in 0..ms.len() { @@ -30,6 +40,11 @@ error: the loop variable `i` is only used to index `ms` LL | for i in 0..ms.len() { | ^^^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:45:22 + | +LL | let x = &mut ms[i]; + | ^^^^^ help: consider using an iterator | LL - for i in 0..ms.len() { @@ -42,6 +57,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in x..x + 4 { | ^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:71:9 + | +LL | vec[i] += 1; + | ^^^^^^ help: consider using an iterator | LL - for i in x..x + 4 { @@ -54,6 +74,11 @@ error: the loop variable `i` is only used to index `vec` LL | for i in x..=x + 4 { | ^^^^^^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:80:9 + | +LL | vec[i] += 1; + | ^^^^^^ help: consider using an iterator | LL - for i in x..=x + 4 { @@ -66,6 +91,11 @@ error: the loop variable `i` is only used to index `arr` LL | for i in 0..3 { | ^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:88:24 + | +LL | println!("{}", arr[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 0..3 { @@ -78,6 +108,11 @@ error: the loop variable `i` is only used to index `arr` LL | for i in 0..2 { | ^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:94:24 + | +LL | println!("{}", arr[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 0..2 { @@ -90,6 +125,11 @@ error: the loop variable `i` is only used to index `arr` LL | for i in 1..3 { | ^^^^ | +note: for this index operation + --> tests/ui/needless_range_loop2.rs:100:24 + | +LL | println!("{}", arr[i]); + | ^^^^^^ help: consider using an iterator | LL - for i in 1..3 { diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions.fixed b/src/tools/clippy/tests/ui/non_zero_suggestions.fixed index b714a6cf6ede7..75209018f1275 100644 --- a/src/tools/clippy/tests/ui/non_zero_suggestions.fixed +++ b/src/tools/clippy/tests/ui/non_zero_suggestions.fixed @@ -1,4 +1,6 @@ #![warn(clippy::non_zero_suggestions)] +#![allow(clippy::needless_nonzero_get)] + use std::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; fn main() { diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions.rs b/src/tools/clippy/tests/ui/non_zero_suggestions.rs index 0e4cd3cc36528..6b24ffb60fc6a 100644 --- a/src/tools/clippy/tests/ui/non_zero_suggestions.rs +++ b/src/tools/clippy/tests/ui/non_zero_suggestions.rs @@ -1,4 +1,6 @@ #![warn(clippy::non_zero_suggestions)] +#![allow(clippy::needless_nonzero_get)] + use std::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; fn main() { diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions.stderr b/src/tools/clippy/tests/ui/non_zero_suggestions.stderr index 4b5a8a3fc6ff7..8138a13044228 100644 --- a/src/tools/clippy/tests/ui/non_zero_suggestions.stderr +++ b/src/tools/clippy/tests/ui/non_zero_suggestions.stderr @@ -1,5 +1,5 @@ error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:9:18 + --> tests/ui/non_zero_suggestions.rs:11:18 | LL | let r1 = x / u64::from(y.get()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)` @@ -8,31 +8,31 @@ LL | let r1 = x / u64::from(y.get()); = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:12:18 + --> tests/ui/non_zero_suggestions.rs:14:18 | LL | let r2 = x % u64::from(y.get()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)` error: consider using `NonZeroU32::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:18:18 + --> tests/ui/non_zero_suggestions.rs:20:18 | LL | let r3 = a / u32::from(b.get()); | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU32::from(b)` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:21:13 + --> tests/ui/non_zero_suggestions.rs:23:13 | LL | let x = u64::from(NonZeroU32::new(5).unwrap().get()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(5).unwrap())` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:58:9 + --> tests/ui/non_zero_suggestions.rs:60:9 | LL | x / u64::from(y.get()) | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:68:22 + --> tests/ui/non_zero_suggestions.rs:70:22 | LL | self.value / u64::from(divisor.get()) | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(divisor)` diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs index 85e74d74d7b9b..0ce41d3ac5dcb 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs @@ -66,6 +66,7 @@ fn issue3847(a: u32, b: u32) -> bool { return false; } true + //~^^^^ needless_bool } fn issue4548() { diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index 5197f105da448..dd8348c3cbf63 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -159,8 +159,20 @@ LL - let _ = a != b && !(a != b && c == d); LL + let _ = a != b && c != d; | +error: this `if` guard returns a bool literal and is followed by another + --> tests/ui/nonminimal_bool.rs:65:5 + | +LL | / if a < THRESHOLD && b >= THRESHOLD || a >= THRESHOLD && b < THRESHOLD { +LL | | return false; +LL | | } +LL | | true + | |________^ help: you can reduce it to: `!(a < THRESHOLD && b >= THRESHOLD || a >= THRESHOLD && b < THRESHOLD)` + | + = note: `-D clippy::needless-bool` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_bool)]` + error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:89:8 + --> tests/ui/nonminimal_bool.rs:90:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -172,37 +184,37 @@ LL + if matches!(true, true) { | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:171:8 | LL | if !(12 == a) {} | ^^^^^^^^^^ help: try: `(12 != a)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:173:8 | LL | if !(a == 12) {} | ^^^^^^^^^^ help: try: `(a != 12)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:174:8 + --> tests/ui/nonminimal_bool.rs:175:8 | LL | if !(12 != a) {} | ^^^^^^^^^^ help: try: `(12 == a)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:176:8 + --> tests/ui/nonminimal_bool.rs:177:8 | LL | if !(a != 12) {} | ^^^^^^^^^^ help: try: `(a == 12)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:181:8 + --> tests/ui/nonminimal_bool.rs:182:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try: `b != true` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:181:8 + --> tests/ui/nonminimal_bool.rs:182:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try: `!b` @@ -211,55 +223,55 @@ LL | if !b == true {} = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:184:8 + --> tests/ui/nonminimal_bool.rs:185:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try: `b == true` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:184:8 + --> tests/ui/nonminimal_bool.rs:185:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try: `b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:187:8 + --> tests/ui/nonminimal_bool.rs:188:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try: `true != b` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:187:8 + --> tests/ui/nonminimal_bool.rs:188:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:190:8 + --> tests/ui/nonminimal_bool.rs:191:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try: `true == b` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:190:8 + --> tests/ui/nonminimal_bool.rs:191:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try: `b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:193:8 + --> tests/ui/nonminimal_bool.rs:194:8 | LL | if !b == !c {} | ^^^^^^^^ help: try: `b == c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:195:8 + --> tests/ui/nonminimal_bool.rs:196:8 | LL | if !b != !c {} | ^^^^^^^^ help: try: `b != c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:211:8 + --> tests/ui/nonminimal_bool.rs:212:8 | LL | if !(a < 2.0 && !b) { | ^^^^^^^^^^^^^^^^ @@ -271,7 +283,7 @@ LL + if a >= 2.0 || b { | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:230:12 + --> tests/ui/nonminimal_bool.rs:231:12 | LL | if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -283,16 +295,16 @@ LL + if !matches!(ty, TyKind::Ref(_, _, _)) || is_mutable(&expr) { | error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:250:8 + --> tests/ui/nonminimal_bool.rs:251:8 | LL | if !S != true {} | ^^^^^^^^^^ help: try: `S == true` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:250:8 + --> tests/ui/nonminimal_bool.rs:251:8 | LL | if !S != true {} | ^^^^^^^^^^ help: try: `!!S` -error: aborting due to 31 previous errors +error: aborting due to 32 previous errors diff --git a/src/tools/clippy/tests/ui/option_zip_none.fixed b/src/tools/clippy/tests/ui/option_zip_none.fixed new file mode 100644 index 0000000000000..0e002c90113aa --- /dev/null +++ b/src/tools/clippy/tests/ui/option_zip_none.fixed @@ -0,0 +1,78 @@ +#![warn(clippy::option_zip_none)] +#![allow(clippy::needless_borrow)] +mod edge_case { + trait MyZip { + fn zip(self, other: Option<()>) -> &'static str; + } + + impl MyZip for &Option { + fn zip(self, _other: Option<()>) -> &'static str { + "not Option::zip" + } + } + + pub fn test_custom_trait() { + let opt = Some(1); + let _ = (&opt).zip(None::<()>); + } + + enum MyOption { + Some(i32), + None, + } + + impl MyOption { + fn zip(self, _other: Option<()>) -> &'static str { + "not Option::zip" + } + } + + pub fn test_custom_enum() { + let opt = MyOption::Some(1); + let _ = opt.zip(None::<()>); + } +} + +fn main() { + let opt = Some(5); + + let _ = opt.map(|n| (n, None::<()>)); + //~^ option_zip_none + + let _ = opt.zip(Some(42)); + + let iter = vec![1, 2, 3].into_iter(); + let _ = iter.zip(std::iter::empty::()); + + let standard_opt = Some(1); + let _ = (&standard_opt).map(|n| (n, None::<()>)); + //~^ option_zip_none + + let _ = Some(1).map(|n| (None::, n)); + //~^ option_zip_none + + let _ = Some(1).map(|n| (n, None::<()>)); + //~^ option_zip_none + + macro_rules! macro_none { + () => { + None::<()> + }; + } + let opt = Some(1); + let _ = opt.map(|n| (n, macro_none!())); + //~^ option_zip_none + + macro_rules! macro_zip { + ($opt:expr) => { + $opt.zip(None::<()>) + }; + } + let _ = macro_zip!(Some(1)); + macro_rules! macro_zip_arg { + ($opt:expr, $arg:expr) => { + $opt.zip($arg) + }; + } + let _ = macro_zip_arg!(Some(1), None::<()>); +} diff --git a/src/tools/clippy/tests/ui/option_zip_none.rs b/src/tools/clippy/tests/ui/option_zip_none.rs new file mode 100644 index 0000000000000..0e2c9efcb6cb1 --- /dev/null +++ b/src/tools/clippy/tests/ui/option_zip_none.rs @@ -0,0 +1,78 @@ +#![warn(clippy::option_zip_none)] +#![allow(clippy::needless_borrow)] +mod edge_case { + trait MyZip { + fn zip(self, other: Option<()>) -> &'static str; + } + + impl MyZip for &Option { + fn zip(self, _other: Option<()>) -> &'static str { + "not Option::zip" + } + } + + pub fn test_custom_trait() { + let opt = Some(1); + let _ = (&opt).zip(None::<()>); + } + + enum MyOption { + Some(i32), + None, + } + + impl MyOption { + fn zip(self, _other: Option<()>) -> &'static str { + "not Option::zip" + } + } + + pub fn test_custom_enum() { + let opt = MyOption::Some(1); + let _ = opt.zip(None::<()>); + } +} + +fn main() { + let opt = Some(5); + + let _ = opt.zip(None::<()>); + //~^ option_zip_none + + let _ = opt.zip(Some(42)); + + let iter = vec![1, 2, 3].into_iter(); + let _ = iter.zip(std::iter::empty::()); + + let standard_opt = Some(1); + let _ = (&standard_opt).zip(None::<()>); + //~^ option_zip_none + + let _ = None::.zip(Some(1)); + //~^ option_zip_none + + let _ = Some(1).zip(None::<()>); + //~^ option_zip_none + + macro_rules! macro_none { + () => { + None::<()> + }; + } + let opt = Some(1); + let _ = opt.zip(macro_none!()); + //~^ option_zip_none + + macro_rules! macro_zip { + ($opt:expr) => { + $opt.zip(None::<()>) + }; + } + let _ = macro_zip!(Some(1)); + macro_rules! macro_zip_arg { + ($opt:expr, $arg:expr) => { + $opt.zip($arg) + }; + } + let _ = macro_zip_arg!(Some(1), None::<()>); +} diff --git a/src/tools/clippy/tests/ui/option_zip_none.stderr b/src/tools/clippy/tests/ui/option_zip_none.stderr new file mode 100644 index 0000000000000..0f5f53c6469f1 --- /dev/null +++ b/src/tools/clippy/tests/ui/option_zip_none.stderr @@ -0,0 +1,64 @@ +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none.rs:39:13 + | +LL | let _ = opt.zip(None::<()>); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::option-zip-none` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::option_zip_none)]` +help: if you meant to zip the contents of the `Option` with `None`, use `Option::map` + | +LL - let _ = opt.zip(None::<()>); +LL + let _ = opt.map(|n| (n, None::<()>)); + | + +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none.rs:48:13 + | +LL | let _ = (&standard_opt).zip(None::<()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if you meant to zip the contents of the `Option` with `None`, use `Option::map` + | +LL - let _ = (&standard_opt).zip(None::<()>); +LL + let _ = (&standard_opt).map(|n| (n, None::<()>)); + | + +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none.rs:51:13 + | +LL | let _ = None::.zip(Some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if you meant to zip the contents of the `Option` with `None`, use `Option::map` + | +LL - let _ = None::.zip(Some(1)); +LL + let _ = Some(1).map(|n| (None::, n)); + | + +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none.rs:54:13 + | +LL | let _ = Some(1).zip(None::<()>); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if you meant to zip the contents of the `Option` with `None`, use `Option::map` + | +LL - let _ = Some(1).zip(None::<()>); +LL + let _ = Some(1).map(|n| (n, None::<()>)); + | + +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none.rs:63:13 + | +LL | let _ = opt.zip(macro_none!()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: if you meant to zip the contents of the `Option` with `None`, use `Option::map` + | +LL - let _ = opt.zip(macro_none!()); +LL + let _ = opt.map(|n| (n, macro_none!())); + | + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/option_zip_none_unfixable.rs b/src/tools/clippy/tests/ui/option_zip_none_unfixable.rs new file mode 100644 index 0000000000000..e893f3b1ccf4a --- /dev/null +++ b/src/tools/clippy/tests/ui/option_zip_none_unfixable.rs @@ -0,0 +1,9 @@ +//@no-rustfix +#![warn(clippy::option_zip_none)] + +fn main() { + let _: Option<(i32, ())> = Option::zip(Some(1), None::<()>); + //~^ option_zip_none + let _: Option<((), i32)> = Option::zip(None::<()>, Some(1)); + //~^ option_zip_none +} diff --git a/src/tools/clippy/tests/ui/option_zip_none_unfixable.stderr b/src/tools/clippy/tests/ui/option_zip_none_unfixable.stderr new file mode 100644 index 0000000000000..64a4ed5138d93 --- /dev/null +++ b/src/tools/clippy/tests/ui/option_zip_none_unfixable.stderr @@ -0,0 +1,17 @@ +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none_unfixable.rs:5:32 + | +LL | let _: Option<(i32, ())> = Option::zip(Some(1), None::<()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::option-zip-none` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::option_zip_none)]` + +error: calling `.zip()` on an `Option` where one side is `None` always returns `None` + --> tests/ui/option_zip_none_unfixable.rs:7:32 + | +LL | let _: Option<((), i32)> = Option::zip(None::<()>, Some(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed index bbb81fea529bd..a46d3bb92a335 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed @@ -160,3 +160,6 @@ mod issue12123 { async fn main() {} } } + +#[derive(Debug, Clone)] +struct DerivedStruct(i32); diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs index d962f2ef6c411..de68d6c168098 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs @@ -160,3 +160,6 @@ mod issue12123 { async fn main() {} } } + +#[derive(Debug, Clone)] +struct DerivedStruct(i32); diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.fixed b/src/tools/clippy/tests/ui/unnecessary_fold.fixed index e0883b6ed58f1..5dbe45e6a4401 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fold.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_fold.fixed @@ -199,4 +199,72 @@ fn wrongly_unmangled_macros() { //~^ unnecessary_fold } +/// Folding over an `Option`'s iterator is `map_or` in disguise (issue #1658) +fn option_fold() { + let opt: Option = Some(2); + + // `.iter()`: suggest `opt.as_ref().map_or(...)` + let _ = opt.as_ref().map_or(10, |x| 10 + x); + //~^ unnecessary_fold + + // `.into_iter()`: `Option` is consumed, suggest plain `map_or` + let _ = opt.map_or(10, |x| 10 * x); + //~^ unnecessary_fold + + // `.iter_mut()`: suggest `opt.as_mut().map_or(...)` + let mut opt_mut: Option = Some(3); + let _ = opt_mut.as_mut().map_or(10, |x| 10 + *x); + //~^ unnecessary_fold + + // accumulator unused in the closure body + let _ = opt.as_ref().map_or(10, |x| *x); + //~^ unnecessary_fold + + // accumulator used more than once: a literal can be duplicated freely + let _ = opt.as_ref().map_or(2, |x| 2 * 2 + x); + //~^ unnecessary_fold + + // a binding of a `Copy` type can also be duplicated freely + let init = 10; + let _ = opt.as_ref().map_or(init, |x| init + x); + //~^ unnecessary_fold + + // `Option` expression receiver (not a binding) + let _ = Some(1).map_or(5, |x| 5 - x); + //~^ unnecessary_fold + + // should NOT lint: `acc` is bound by the enclosing fold's closure, and + // substituting a closure parameter is not safe when folds are nested + let _ = (0..3).fold(0, |acc, x| opt.iter().fold(acc, |a, b| a + b) + x); + + // an option fold nested in a standard fold is still linted when its init + // is a literal + let _ = (0..3).fold(0, |acc, x| opt.as_ref().map_or(1, |b| 1 + b) + x); + //~^ unnecessary_fold + + // should NOT lint: a `mut` accumulator is likely reassigned in the body, + // and substituting into the assignment would not compile + let _ = opt.iter().fold(0, |mut acc, x| { + acc += x; + acc + }); + + // should NOT lint: substituting a call would re-evaluate it + fn compute() -> i32 { + 42 + } + let _ = opt.iter().fold(compute(), |acc, x| acc + x); + + // should NOT lint: substituting a non-`Copy` binding would move it twice + let owned = String::from("a"); + let _ = opt.iter().fold(owned, |acc, x| acc + &x.to_string()); + + // should NOT lint: fold over a general iterator with non-literal init + let _ = (0..3).fold(init, |acc, x| acc + x); + + // should NOT lint: `Result` iterators are out of scope here + let res: Result = Ok(1); + let _ = res.iter().fold(init, |acc, x| acc + x); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.rs b/src/tools/clippy/tests/ui/unnecessary_fold.rs index 76b149bf5e2de..ebfe75f73ffd4 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fold.rs +++ b/src/tools/clippy/tests/ui/unnecessary_fold.rs @@ -199,4 +199,72 @@ fn wrongly_unmangled_macros() { //~^ unnecessary_fold } +/// Folding over an `Option`'s iterator is `map_or` in disguise (issue #1658) +fn option_fold() { + let opt: Option = Some(2); + + // `.iter()`: suggest `opt.as_ref().map_or(...)` + let _ = opt.iter().fold(10, |acc, x| acc + x); + //~^ unnecessary_fold + + // `.into_iter()`: `Option` is consumed, suggest plain `map_or` + let _ = opt.into_iter().fold(10, |acc, x| acc * x); + //~^ unnecessary_fold + + // `.iter_mut()`: suggest `opt.as_mut().map_or(...)` + let mut opt_mut: Option = Some(3); + let _ = opt_mut.iter_mut().fold(10, |acc, x| acc + *x); + //~^ unnecessary_fold + + // accumulator unused in the closure body + let _ = opt.iter().fold(10, |_, x| *x); + //~^ unnecessary_fold + + // accumulator used more than once: a literal can be duplicated freely + let _ = opt.iter().fold(2, |acc, x| acc * acc + x); + //~^ unnecessary_fold + + // a binding of a `Copy` type can also be duplicated freely + let init = 10; + let _ = opt.iter().fold(init, |acc, x| acc + x); + //~^ unnecessary_fold + + // `Option` expression receiver (not a binding) + let _ = Some(1).into_iter().fold(5, |acc, x| acc - x); + //~^ unnecessary_fold + + // should NOT lint: `acc` is bound by the enclosing fold's closure, and + // substituting a closure parameter is not safe when folds are nested + let _ = (0..3).fold(0, |acc, x| opt.iter().fold(acc, |a, b| a + b) + x); + + // an option fold nested in a standard fold is still linted when its init + // is a literal + let _ = (0..3).fold(0, |acc, x| opt.iter().fold(1, |a, b| a + b) + x); + //~^ unnecessary_fold + + // should NOT lint: a `mut` accumulator is likely reassigned in the body, + // and substituting into the assignment would not compile + let _ = opt.iter().fold(0, |mut acc, x| { + acc += x; + acc + }); + + // should NOT lint: substituting a call would re-evaluate it + fn compute() -> i32 { + 42 + } + let _ = opt.iter().fold(compute(), |acc, x| acc + x); + + // should NOT lint: substituting a non-`Copy` binding would move it twice + let owned = String::from("a"); + let _ = opt.iter().fold(owned, |acc, x| acc + &x.to_string()); + + // should NOT lint: fold over a general iterator with non-literal init + let _ = (0..3).fold(init, |acc, x| acc + x); + + // should NOT lint: `Result` iterators are out of scope here + let res: Result = Ok(1); + let _ = res.iter().fold(init, |acc, x| acc + x); +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.stderr b/src/tools/clippy/tests/ui/unnecessary_fold.stderr index 266ced07eb827..2bffa211562e1 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fold.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_fold.stderr @@ -263,5 +263,101 @@ LL | let _ = (0..3).fold(false, |acc: bool, x| acc || test_expr!(x)); | = note: the `any` method is short circuiting and may change the program semantics if the iterator has side effects -error: aborting due to 41 previous errors +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:207:24 + | +LL | let _ = opt.iter().fold(10, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = opt.iter().fold(10, |acc, x| acc + x); +LL + let _ = opt.as_ref().map_or(10, |x| 10 + x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:211:29 + | +LL | let _ = opt.into_iter().fold(10, |acc, x| acc * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = opt.into_iter().fold(10, |acc, x| acc * x); +LL + let _ = opt.map_or(10, |x| 10 * x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:216:32 + | +LL | let _ = opt_mut.iter_mut().fold(10, |acc, x| acc + *x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = opt_mut.iter_mut().fold(10, |acc, x| acc + *x); +LL + let _ = opt_mut.as_mut().map_or(10, |x| 10 + *x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:220:24 + | +LL | let _ = opt.iter().fold(10, |_, x| *x); + | ^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = opt.iter().fold(10, |_, x| *x); +LL + let _ = opt.as_ref().map_or(10, |x| *x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:224:24 + | +LL | let _ = opt.iter().fold(2, |acc, x| acc * acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = opt.iter().fold(2, |acc, x| acc * acc + x); +LL + let _ = opt.as_ref().map_or(2, |x| 2 * 2 + x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:229:24 + | +LL | let _ = opt.iter().fold(init, |acc, x| acc + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = opt.iter().fold(init, |acc, x| acc + x); +LL + let _ = opt.as_ref().map_or(init, |x| init + x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:233:33 + | +LL | let _ = Some(1).into_iter().fold(5, |acc, x| acc - x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = Some(1).into_iter().fold(5, |acc, x| acc - x); +LL + let _ = Some(1).map_or(5, |x| 5 - x); + | + +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold.rs:242:48 + | +LL | let _ = (0..3).fold(0, |acc, x| opt.iter().fold(1, |a, b| a + b) + x); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let _ = (0..3).fold(0, |acc, x| opt.iter().fold(1, |a, b| a + b) + x); +LL + let _ = (0..3).fold(0, |acc, x| opt.as_ref().map_or(1, |b| 1 + b) + x); + | + +error: aborting due to 49 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_fold_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_fold_unfixable.rs new file mode 100644 index 0000000000000..4ab48e4f92eff --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_fold_unfixable.rs @@ -0,0 +1,15 @@ +//@no-rustfix: the suggestion substitutes a literal into the inner fold's +// init position, which makes the inner fold lintable in a second pass, so a +// single rustfix application does not reach a fixpoint (`cargo fix` converges +// by iterating). +#![warn(clippy::unnecessary_fold)] + +fn main() { + let opt: Option = Some(2); + let opt2: Option = Some(4); + + // Only the outer fold is linted: the inner fold's init is the outer + // closure's accumulator parameter. + let _ = opt.iter().fold(0, |acc, x| opt2.iter().fold(acc, |a, b| a + b) + x); + //~^ unnecessary_fold +} diff --git a/src/tools/clippy/tests/ui/unnecessary_fold_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_fold_unfixable.stderr new file mode 100644 index 0000000000000..bbd3d03530044 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_fold_unfixable.stderr @@ -0,0 +1,16 @@ +error: this `.fold` can be written more succinctly using another method + --> tests/ui/unnecessary_fold_unfixable.rs:13:24 + | +LL | let _ = opt.iter().fold(0, |acc, x| opt2.iter().fold(acc, |a, b| a + b) + x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-fold` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fold)]` +help: try + | +LL - let _ = opt.iter().fold(0, |acc, x| opt2.iter().fold(acc, |a, b| a + b) + x); +LL + let _ = opt.as_ref().map_or(0, |x| opt2.iter().fold(0, |a, b| a + b) + x); + | + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.fixed b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.fixed new file mode 100644 index 0000000000000..2f93f608c5233 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.fixed @@ -0,0 +1,51 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::unnecessary_map_or)] + +#[macro_use] +extern crate proc_macros; + +const TRUE: bool = true; +const FALSE: bool = false; + +fn main() { + let result = Ok::(1); + + let _ = result.is_ok(); + //~^ unnecessary_map_or + let _ = result.is_err(); + //~^ unnecessary_map_or + let _ = result.is_ok(); + //~^ unnecessary_map_or + let _ = result.is_ok(); + //~^ unnecessary_map_or + + let _ = result.is_ok(); + //~^ unnecessary_map_or + let _ = result.is_err(); + //~^ unnecessary_map_or + let _ = result.is_ok(); + //~^ unnecessary_map_or + let _ = result.is_ok(); + //~^ unnecessary_map_or + + // Calls in a closure body may have side effects. The lint does not inspect the callee body. + let _ = result.map_or_else( + |_| { + std::hint::black_box(()); + false + }, + |_| true, + ); + let _ = result.map_or_else(|error| error > 0, |_| true); + let _ = result.map_or_else(|_| false, |value| value > 0); + + external! { + let _ = Ok::(1).map_or(false, |_| true); + let _ = Ok::(1).map_or_else(|_| false, |_| true); + } + + with_span! { + let _ = Ok::(1).map_or(false, |_| true); + let _ = Ok::(1).map_or_else(|_| false, |_| true); + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.rs b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.rs new file mode 100644 index 0000000000000..3fe4181bdac4e --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.rs @@ -0,0 +1,51 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::unnecessary_map_or)] + +#[macro_use] +extern crate proc_macros; + +const TRUE: bool = true; +const FALSE: bool = false; + +fn main() { + let result = Ok::(1); + + let _ = result.map_or(false, |_| true); + //~^ unnecessary_map_or + let _ = result.map_or(true, |_| false); + //~^ unnecessary_map_or + let _ = result.map_or(false, |_: i32| true); + //~^ unnecessary_map_or + let _ = result.map_or(!true, |_| TRUE); + //~^ unnecessary_map_or + + let _ = result.map_or_else(|_| false, |_| true); + //~^ unnecessary_map_or + let _ = result.map_or_else(|_| true, |_| false); + //~^ unnecessary_map_or + let _ = result.map_or_else(|_: i32| false, |_: i32| true); + //~^ unnecessary_map_or + let _ = result.map_or_else(|_| FALSE, |_| !false); + //~^ unnecessary_map_or + + // Calls in a closure body may have side effects. The lint does not inspect the callee body. + let _ = result.map_or_else( + |_| { + std::hint::black_box(()); + false + }, + |_| true, + ); + let _ = result.map_or_else(|error| error > 0, |_| true); + let _ = result.map_or_else(|_| false, |value| value > 0); + + external! { + let _ = Ok::(1).map_or(false, |_| true); + let _ = Ok::(1).map_or_else(|_| false, |_| true); + } + + with_span! { + let _ = Ok::(1).map_or(false, |_| true); + let _ = Ok::(1).map_or_else(|_| false, |_| true); + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.stderr new file mode 100644 index 0000000000000..e0d6c9bde2a60 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool.stderr @@ -0,0 +1,69 @@ +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:13:20 + | +LL | let _ = result.map_or(false, |_| true); + | ^^^^^^----------------- + | | + | help: use `is_ok` instead: `is_ok()` + | + = note: `-D clippy::unnecessary-map-or` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:15:20 + | +LL | let _ = result.map_or(true, |_| false); + | ^^^^^^----------------- + | | + | help: use `is_err` instead: `is_err()` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:17:20 + | +LL | let _ = result.map_or(false, |_: i32| true); + | ^^^^^^---------------------- + | | + | help: use `is_ok` instead: `is_ok()` + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:19:20 + | +LL | let _ = result.map_or(!true, |_| TRUE); + | ^^^^^^----------------- + | | + | help: use `is_ok` instead: `is_ok()` + +error: this `map_or_else` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:22:20 + | +LL | let _ = result.map_or_else(|_| false, |_| true); + | ^^^^^^^^^^^--------------------- + | | + | help: use `is_ok` instead: `is_ok()` + +error: this `map_or_else` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:24:20 + | +LL | let _ = result.map_or_else(|_| true, |_| false); + | ^^^^^^^^^^^--------------------- + | | + | help: use `is_err` instead: `is_err()` + +error: this `map_or_else` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:26:20 + | +LL | let _ = result.map_or_else(|_: i32| false, |_: i32| true); + | ^^^^^^^^^^^------------------------------- + | | + | help: use `is_ok` instead: `is_ok()` + +error: this `map_or_else` can be simplified + --> tests/ui/unnecessary_map_or_result_bool.rs:28:20 + | +LL | let _ = result.map_or_else(|_| FALSE, |_| !false); + | ^^^^^^^^^^^----------------------- + | | + | help: use `is_ok` instead: `is_ok()` + +error: aborting due to 8 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool_unfixable.rs b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool_unfixable.rs new file mode 100644 index 0000000000000..f17632129f6ca --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool_unfixable.rs @@ -0,0 +1,14 @@ +//@no-rustfix: `is_ok` and `is_err` can change significant drop order +#![warn(clippy::unnecessary_map_or)] + +fn main() { + let mutex = std::sync::Mutex::new(()); + + let result = Ok::<_, ()>(mutex.lock().unwrap()); + let _ = result.map_or(false, |_| true); + //~^ unnecessary_map_or + + let result = Err::<(), _>(mutex.lock().unwrap()); + let _ = result.map_or_else(|_| true, |_| false); + //~^ unnecessary_map_or +} diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool_unfixable.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool_unfixable.stderr new file mode 100644 index 0000000000000..f642845bcfa07 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_map_or_result_bool_unfixable.stderr @@ -0,0 +1,26 @@ +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or_result_bool_unfixable.rs:8:20 + | +LL | let _ = result.map_or(false, |_| true); + | ^^^^^^----------------- + | | + | help: use `is_ok` instead: `is_ok()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::unnecessary_map_or)]` if this is important + = note: `-D clippy::unnecessary-map-or` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]` + +error: this `map_or_else` can be simplified + --> tests/ui/unnecessary_map_or_result_bool_unfixable.rs:12:20 + | +LL | let _ = result.map_or_else(|_| true, |_| false); + | ^^^^^^^^^^^--------------------- + | | + | help: use `is_err` instead: `is_err()` + | + = note: this will change drop order of the result, as well as all temporaries + = note: add `#[allow(clippy::unnecessary_map_or)]` if this is important + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_rest_pattern.fixed b/src/tools/clippy/tests/ui/unnecessary_rest_pattern.fixed index 830f868226678..016bc8b3d741d 100644 --- a/src/tools/clippy/tests/ui/unnecessary_rest_pattern.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_rest_pattern.fixed @@ -32,6 +32,10 @@ mod m { } } +type Variant = VariantKind; + +struct VariantKind; + fn main() { let s = S { a: 1, b: 2, c: 3 }; @@ -87,4 +91,14 @@ fn main() { let Sm { .. } = Sm::default(); let Sm { a: _, b: _, .. } = Sm::default(); + + let variant = Variant {}; + + let Variant { } = variant; + //~^ unnecessary_rest_pattern + + match variant { + Variant { } => {}, + //~^ unnecessary_rest_pattern + } } diff --git a/src/tools/clippy/tests/ui/unnecessary_rest_pattern.rs b/src/tools/clippy/tests/ui/unnecessary_rest_pattern.rs index 51ed4b1e18042..d8b3f9623603a 100644 --- a/src/tools/clippy/tests/ui/unnecessary_rest_pattern.rs +++ b/src/tools/clippy/tests/ui/unnecessary_rest_pattern.rs @@ -32,6 +32,10 @@ mod m { } } +type Variant = VariantKind; + +struct VariantKind; + fn main() { let s = S { a: 1, b: 2, c: 3 }; @@ -87,4 +91,14 @@ fn main() { let Sm { .. } = Sm::default(); let Sm { a: _, b: _, .. } = Sm::default(); + + let variant = Variant {}; + + let Variant { .. } = variant; + //~^ unnecessary_rest_pattern + + match variant { + Variant { .. } => {}, + //~^ unnecessary_rest_pattern + } } diff --git a/src/tools/clippy/tests/ui/unnecessary_rest_pattern.stderr b/src/tools/clippy/tests/ui/unnecessary_rest_pattern.stderr index 2c8e66f9d1034..346d8895e4c2d 100644 --- a/src/tools/clippy/tests/ui/unnecessary_rest_pattern.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_rest_pattern.stderr @@ -1,5 +1,5 @@ error: unnecessary rest pattern (`..`) - --> tests/ui/unnecessary_rest_pattern.rs:38:9 + --> tests/ui/unnecessary_rest_pattern.rs:42:9 | LL | let S { a, b, c, .. } = s; | ^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + let S { a, b, c, } = s; | error: unnecessary rest pattern (`..`) - --> tests/ui/unnecessary_rest_pattern.rs:45:9 + --> tests/ui/unnecessary_rest_pattern.rs:49:9 | LL | E::B { b1, b2, .. } => (), | ^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + E::B { b1, b2, } => (), | error: unnecessary rest pattern (`..`) - --> tests/ui/unnecessary_rest_pattern.rs:47:9 + --> tests/ui/unnecessary_rest_pattern.rs:51:9 | LL | E::C { .. } => (), | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + E::C { } => (), | error: unnecessary rest pattern (`..`) - --> tests/ui/unnecessary_rest_pattern.rs:80:9 + --> tests/ui/unnecessary_rest_pattern.rs:84:9 | LL | let LocalNonExhaustive { field: _, .. } = ne; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -48,5 +48,29 @@ LL - let LocalNonExhaustive { field: _, .. } = ne; LL + let LocalNonExhaustive { field: _, } = ne; | -error: aborting due to 4 previous errors +error: unnecessary rest pattern (`..`) + --> tests/ui/unnecessary_rest_pattern.rs:97:9 + | +LL | let Variant { .. } = variant; + | ^^^^^^^^^^^^^^ + | +help: consider removing the unnecessary rest pattern (`..`) + | +LL - let Variant { .. } = variant; +LL + let Variant { } = variant; + | + +error: unnecessary rest pattern (`..`) + --> tests/ui/unnecessary_rest_pattern.rs:101:9 + | +LL | Variant { .. } => {}, + | ^^^^^^^^^^^^^^ + | +help: consider removing the unnecessary rest pattern (`..`) + | +LL - Variant { .. } => {}, +LL + Variant { } => {}, + | + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed index f96088bd39a6d..a191cbb391a26 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed +++ b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed @@ -1,4 +1,4 @@ -#![feature(box_patterns)] +#![feature(deref_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::manual_range_patterns)] #![expect(irrefutable_let_patterns)] @@ -12,9 +12,9 @@ fn main() { // Should be ignored by this lint, as nesting requires more characters. if let &0 | &2 = &0 {} - if let box (0 | 2) = Box::new(0) {} + if let deref!(0 | 2) = Box::new(0) {} //~^ unnested_or_patterns - if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + if let deref!(0 | 1 | 2 | 3 | 4) = Box::new(0) {} //~^ unnested_or_patterns const C0: Option = Some(1); if let Some(1 | 2) | C0 = None {} diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.rs b/src/tools/clippy/tests/ui/unnested_or_patterns.rs index 6f4ef615e9d16..8e1418f1b2168 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns.rs +++ b/src/tools/clippy/tests/ui/unnested_or_patterns.rs @@ -1,4 +1,4 @@ -#![feature(box_patterns)] +#![feature(deref_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::manual_range_patterns)] #![expect(irrefutable_let_patterns)] @@ -12,9 +12,9 @@ fn main() { // Should be ignored by this lint, as nesting requires more characters. if let &0 | &2 = &0 {} - if let box 0 | box 2 = Box::new(0) {} + if let deref!(0) | deref!(2) = Box::new(0) {} //~^ unnested_or_patterns - if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} + if let deref!(0 | 1) | deref!(2 | 3) | deref!(4) = Box::new(0) {} //~^ unnested_or_patterns const C0: Option = Some(1); if let Some(1) | C0 | Some(2) = None {} diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr index 7298eabaa03e6..2e2ce28a6a225 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr +++ b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr @@ -1,27 +1,27 @@ error: unnested or-patterns --> tests/ui/unnested_or_patterns.rs:15:12 | -LL | if let box 0 | box 2 = Box::new(0) {} - | ^^^^^^^^^^^^^ +LL | if let deref!(0) | deref!(2) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnested-or-patterns` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnested_or_patterns)]` help: nest the patterns | -LL - if let box 0 | box 2 = Box::new(0) {} -LL + if let box (0 | 2) = Box::new(0) {} +LL - if let deref!(0) | deref!(2) = Box::new(0) {} +LL + if let deref!(0 | 2) = Box::new(0) {} | error: unnested or-patterns --> tests/ui/unnested_or_patterns.rs:17:12 | -LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let deref!(0 | 1) | deref!(2 | 3) | deref!(4) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: nest the patterns | -LL - if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} -LL + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} +LL - if let deref!(0 | 1) | deref!(2 | 3) | deref!(4) = Box::new(0) {} +LL + if let deref!(0 | 1 | 2 | 3 | 4) = Box::new(0) {} | error: unnested or-patterns diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed index d9625e78c246d..0e75a66690e93 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed +++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed @@ -1,4 +1,4 @@ -#![feature(box_patterns)] +#![feature(deref_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::manual_range_patterns)] @@ -15,8 +15,8 @@ fn main() { //~^ unnested_or_patterns if let 0 | 1 | 2 = 0 {} //~^ unnested_or_patterns - if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} + if let deref!(0 | 1 | 2 | 3 | 4) = Box::new(0) {} //~^ unnested_or_patterns - if let box (box (0 | 2 | 4)) = Box::new(Box::new(0)) {} + if let deref!(deref!(0 | 2 | 4)) = Box::new(Box::new(0)) {} //~^ unnested_or_patterns } diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs index d5215966fcb13..353060f1bf26d 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns2.rs +++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.rs @@ -1,4 +1,4 @@ -#![feature(box_patterns)] +#![feature(deref_patterns)] #![warn(clippy::unnested_or_patterns)] #![allow(clippy::manual_range_patterns)] @@ -15,8 +15,8 @@ fn main() { //~^ unnested_or_patterns if let 0 | (1 | 2) = 0 {} //~^ unnested_or_patterns - if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} + if let deref!(0 | 1) | (deref!(2) | deref!(3 | 4)) = Box::new(0) {} //~^ unnested_or_patterns - if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} + if let deref!(deref!(0)) | deref!(deref!(2) | deref!(4)) = Box::new(Box::new(0)) {} //~^ unnested_or_patterns } diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr index 776589e294ba5..e1cd2b36b11e1 100644 --- a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr +++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr @@ -75,25 +75,25 @@ LL + if let 0 | 1 | 2 = 0 {} error: unnested or-patterns --> tests/ui/unnested_or_patterns2.rs:18:12 | -LL | if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let deref!(0 | 1) | (deref!(2) | deref!(3 | 4)) = Box::new(0) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: nest the patterns | -LL - if let box (0 | 1) | (box 2 | box (3 | 4)) = Box::new(0) {} -LL + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} +LL - if let deref!(0 | 1) | (deref!(2) | deref!(3 | 4)) = Box::new(0) {} +LL + if let deref!(0 | 1 | 2 | 3 | 4) = Box::new(0) {} | error: unnested or-patterns --> tests/ui/unnested_or_patterns2.rs:20:12 | -LL | if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let deref!(deref!(0)) | deref!(deref!(2) | deref!(4)) = Box::new(Box::new(0)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: nest the patterns | -LL - if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {} -LL + if let box (box (0 | 2 | 4)) = Box::new(Box::new(0)) {} +LL - if let deref!(deref!(0)) | deref!(deref!(2) | deref!(4)) = Box::new(Box::new(0)) {} +LL + if let deref!(deref!(0 | 2 | 4)) = Box::new(Box::new(0)) {} | error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs index b2a8fdcc0ce77..1c9f9e034e394 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.rs +++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs @@ -1,153 +1,150 @@ -//@aux-build:proc_macro_derive.rs -#![feature(rustc_private)] -#![warn(clippy::used_underscore_binding)] -#![expect(clippy::disallowed_names, clippy::eq_op, clippy::uninlined_format_args)] - -#[macro_use] -extern crate proc_macro_derive; - -// This should not trigger the lint. There's underscore binding inside the external derive that -// would trigger the `used_underscore_binding` lint. -#[derive(DeriveSomething)] -struct Baz; - -macro_rules! test_macro { - () => {{ - let _foo = 42; - _foo + 1 - }}; -} - -/// Tests that we lint if we use a binding with a single leading underscore -fn prefix_underscore(_foo: u32) -> u32 { - _foo + 1 - //~^ used_underscore_binding -} - -/// Tests that we lint if we use a `_`-variable defined outside within a macro expansion -fn in_macro_or_desugar(_foo: u32) { - println!("{}", _foo); - //~^ used_underscore_binding - assert_eq!(_foo, _foo); - //~^ used_underscore_binding - //~| used_underscore_binding - - test_macro!() + 1; -} - -// Struct for testing use of fields prefixed with an underscore -struct StructFieldTest { - _underscore_field: u32, -} - -/// Tests that we lint the use of a struct field which is prefixed with an underscore -fn in_struct_field() { - let mut s = StructFieldTest { _underscore_field: 0 }; - s._underscore_field += 1; - //~^ used_underscore_binding -} - -/// Tests that we do not lint if the struct field is used in code created with derive. -#[derive(Clone, Debug)] -pub struct UnderscoreInStruct { - _foo: u32, -} - -/// Tests that we do not lint if the underscore is not a prefix -fn non_prefix_underscore(some_foo: u32) -> u32 { - some_foo + 1 -} - -/// Tests that we do not lint if we do not use the binding (simple case) -fn unused_underscore_simple(_foo: u32) -> u32 { - 1 -} - -/// Tests that we do not lint if we do not use the binding (complex case). This checks for -/// compatibility with the built-in `unused_variables` lint. -fn unused_underscore_complex(mut _foo: u32) -> u32 { - _foo += 1; - _foo = 2; - 1 -} - -/// Test that we do not lint for multiple underscores -fn multiple_underscores(__foo: u32) -> u32 { - __foo + 1 -} - -// Non-variable bindings with preceding underscore -fn _fn_test() {} -struct _StructTest; -enum _EnumTest { - _Empty, - _Value(_StructTest), -} - -/// Tests that we do not lint for non-variable bindings -fn non_variables() { - _fn_test(); - let _s = _StructTest; - let _e = match _EnumTest::_Value(_StructTest) { - _EnumTest::_Empty => 0, - _EnumTest::_Value(_st) => 1, - }; - let f = _fn_test; - f(); -} - -// Tests that we do not lint if the binding comes from await desugaring, -// but we do lint the awaited expression. See issue 5360. -async fn await_desugaring() { - async fn foo() {} - fn uses_i(_i: i32) {} +//@aux-build:proc_macros.rs - foo().await; - ({ - let _i = 5; - uses_i(_i); - //~^ used_underscore_binding - foo() - }) - .await -} - -struct PhantomField { - _marker: std::marker::PhantomData, -} - -impl std::fmt::Debug for PhantomField { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("PhantomField").field("_marker", &self._marker).finish() - } -} +#![warn(clippy::used_underscore_binding)] +#![expect(clippy::explicit_auto_deref, clippy::no_effect)] -struct AllowedField { - #[allow(clippy::used_underscore_binding)] - _allowed: usize, -} +extern crate proc_macros; -struct ExpectedField { - #[expect(clippy::used_underscore_binding)] - _expected: usize, -} - -fn lint_levels(allowed: AllowedField, expected: ExpectedField) { - let _ = allowed._allowed; - let _ = expected._expected; -} +use core::marker::PhantomData; +use proc_macros::{external, inline_macros}; +#[inline_macros] fn main() { - let foo = 0u32; - // tests of unused_underscore lint - let _ = prefix_underscore(foo); - in_macro_or_desugar(foo); - in_struct_field(); - // possible false positives - let _ = non_prefix_underscore(foo); - let _ = unused_underscore_simple(foo); - let _ = unused_underscore_complex(foo); - let _ = multiple_underscores(foo); - non_variables(); - await_desugaring(); + // Declaration only. + { + let _a = 0; + } + // Check various reads. + { + let _a = 0; + let _b = &0; + let _c = (0, &0); + let _d = String::new(); + + _a; //~ used_underscore_binding + *_b; //~ used_underscore_binding + _c.0; //~ used_underscore_binding + *_c.1; //~ used_underscore_binding + _d.is_empty(); //~ used_underscore_binding + } + // Check that we match rustc on what a use is. + { + let mut _a = 0; + let mut _b = (0, 0); + let mut c = 0; + let mut _c = &mut c; + let mut d = (0, 0); + let _d = &mut d; + + _a = 0; + _b.0 = 0; + _c = &mut c; + *_c = 0; //~ used_underscore_binding + _d.0 = 0; //~ used_underscore_binding + (*_d).0 = 0; //~ used_underscore_binding + } + // Check field access. + { + struct X<'a> { + _x: &'a mut (u32, u32), + }; + + let mut a = (0, 0); + let mut b = (0, 0); + let mut c = X { _x: &mut a }; + + c._x; //~ used_underscore_binding + c._x = &mut b; //~ used_underscore_binding + *c._x; //~ used_underscore_binding + *c._x = (0, 0); //~ used_underscore_binding + (*c._x).0 = 0; //~ used_underscore_binding + c._x.0 = 0; //~ used_underscore_binding + } + // Await desugaring contains a used underscore binding. + { + async fn f1() {} + async fn f2() { + f1().await; + { + let _a = 0; + _a; //~ used_underscore_binding + f1() + } + .await; + } + } + // Ignore phantom fields + { + struct X { + _marker: PhantomData, + } + let a = X { _marker: PhantomData }; + a._marker; + } + // Ignore multiple underscores + { + struct X { + __x: u32, + } + let __a = 0; + let b = X { __x: 0 }; + __a; + b.__x; + } + // Check compound assignment + { + let mut _a = 0; + let mut _b = (0, 0); + let mut _c = 0.0; + let mut _d = String::new(); + + _a += 0; + _b.0 -= 0; + _b.1 |= 0; + _c *= 1.0; + _d += ""; //~ used_underscore_binding + } + // Expect on the binding + { + struct X { + #[expect(clippy::used_underscore_binding)] + _x: u32, + } + #[expect(clippy::used_underscore_binding)] + let _a = 0; + let b = X { _x: 0 }; + + _a; + b._x; + } + // Check macros + { + struct X { + _x: u32, + }; + + let _a = 0; + let _b = (0, 0); + let mut _c = 0; + let mut _d = (0, 0); + let e = X { _x: 0 }; + let mut f = X { _x: 0 }; + + inline!({ + $(@expr _a); //~ used_underscore_binding + $(@expr _b.0); //~ used_underscore_binding + $(@expr _c) = 0; + $(@expr _d.0) = 0; + $(@expr e._x); //~ used_underscore_binding + $(@expr f._x) = 0; //~ used_underscore_binding + }); + external!({ + $_a; //~ used_underscore_binding + $(_b.0); //~ used_underscore_binding + $_c = 0; + $(_d.0) = 0; + $(e._x); //~ used_underscore_binding + $(f._x) = 0; //~ used_underscore_binding + }); + } } diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr index 7d94d79f9b3b5..8675f5fe49850 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr +++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr @@ -1,76 +1,292 @@ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:23:5 + --> tests/ui/used_underscore_binding.rs:24:9 | -LL | _foo + 1 - | ^^^^ +LL | _a; + | ^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:22:22 + --> tests/ui/used_underscore_binding.rs:19:13 | -LL | fn prefix_underscore(_foo: u32) -> u32 { - | ^^^^ +LL | let _a = 0; + | ^^ = note: `-D clippy::used-underscore-binding` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::used_underscore_binding)]` error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:29:20 + --> tests/ui/used_underscore_binding.rs:25:10 + | +LL | *_b; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:20:13 + | +LL | let _b = &0; + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:26:9 + | +LL | _c.0; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:21:13 + | +LL | let _c = (0, &0); + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:27:10 + | +LL | *_c.1; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:21:13 + | +LL | let _c = (0, &0); + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:28:9 + | +LL | _d.is_empty(); + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:22:13 + | +LL | let _d = String::new(); + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:42:10 + | +LL | *_c = 0; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:35:13 + | +LL | let mut _c = &mut c; + | ^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:43:9 + | +LL | _d.0 = 0; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:37:13 + | +LL | let _d = &mut d; + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:44:11 + | +LL | (*_d).0 = 0; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:37:13 + | +LL | let _d = &mut d; + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:56:9 + | +LL | c._x; + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:49:13 + | +LL | _x: &'a mut (u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:57:9 + | +LL | c._x = &mut b; + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:49:13 + | +LL | _x: &'a mut (u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:58:10 + | +LL | *c._x; + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:49:13 + | +LL | _x: &'a mut (u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:59:10 + | +LL | *c._x = (0, 0); + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:49:13 + | +LL | _x: &'a mut (u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:60:11 + | +LL | (*c._x).0 = 0; + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:49:13 + | +LL | _x: &'a mut (u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:61:9 | -LL | println!("{}", _foo); - | ^^^^ +LL | c._x.0 = 0; + | ^^^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:28:24 + --> tests/ui/used_underscore_binding.rs:49:13 | -LL | fn in_macro_or_desugar(_foo: u32) { - | ^^^^ +LL | _x: &'a mut (u32, u32), + | ^^^^^^^^^^^^^^^^^^^^^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:31:16 + --> tests/ui/used_underscore_binding.rs:70:17 | -LL | assert_eq!(_foo, _foo); - | ^^^^ +LL | _a; + | ^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:28:24 + --> tests/ui/used_underscore_binding.rs:69:21 | -LL | fn in_macro_or_desugar(_foo: u32) { - | ^^^^ +LL | let _a = 0; + | ^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:31:22 + --> tests/ui/used_underscore_binding.rs:105:9 | -LL | assert_eq!(_foo, _foo); - | ^^^^ +LL | _d += ""; + | ^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:28:24 + --> tests/ui/used_underscore_binding.rs:99:13 | -LL | fn in_macro_or_desugar(_foo: u32) { - | ^^^^ +LL | let mut _d = String::new(); + | ^^^^^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:46:5 + --> tests/ui/used_underscore_binding.rs:134:21 | -LL | s._underscore_field += 1; - | ^^^^^^^^^^^^^^^^^^^ +LL | $(@expr _a); + | ^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:40:5 + --> tests/ui/used_underscore_binding.rs:126:13 | -LL | _underscore_field: u32, - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | let _a = 0; + | ^^ error: used underscore-prefixed binding - --> tests/ui/used_underscore_binding.rs:108:16 + --> tests/ui/used_underscore_binding.rs:135:21 | -LL | uses_i(_i); - | ^^ +LL | $(@expr _b.0); + | ^^ | note: binding is defined here - --> tests/ui/used_underscore_binding.rs:107:13 + --> tests/ui/used_underscore_binding.rs:127:13 | -LL | let _i = 5; +LL | let _b = (0, 0); | ^^ -error: aborting due to 6 previous errors +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:138:21 + | +LL | $(@expr e._x); + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:123:13 + | +LL | _x: u32, + | ^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:139:21 + | +LL | $(@expr f._x) = 0; + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:123:13 + | +LL | _x: u32, + | ^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:142:14 + | +LL | $_a; + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:126:13 + | +LL | let _a = 0; + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:143:15 + | +LL | $(_b.0); + | ^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:127:13 + | +LL | let _b = (0, 0); + | ^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:146:15 + | +LL | $(e._x); + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:123:13 + | +LL | _x: u32, + | ^^^^^^^ + +error: used underscore-prefixed binding + --> tests/ui/used_underscore_binding.rs:147:15 + | +LL | $(f._x) = 0; + | ^^^^ + | +note: binding is defined here + --> tests/ui/used_underscore_binding.rs:123:13 + | +LL | _x: u32, + | ^^^^^^^ + +error: aborting due to 24 previous errors diff --git a/src/tools/clippy/tests/ui/used_underscore_items.rs b/src/tools/clippy/tests/ui/used_underscore_items.rs index 08660eefc3226..f459c32466508 100644 --- a/src/tools/clippy/tests/ui/used_underscore_items.rs +++ b/src/tools/clippy/tests/ui/used_underscore_items.rs @@ -1,81 +1,149 @@ //@aux-build:external_item.rs +//@aux-build:proc_macros.rs + #![warn(clippy::used_underscore_items)] +#![allow(clippy::no_effect)] extern crate external_item; +extern crate proc_macros; -// should not lint macro -macro_rules! macro_wrap_func { - () => { - fn _marco_foo() {} - }; -} +use proc_macros::{external, inline_macros}; -macro_wrap_func!(); +#[inline_macros] +fn main() { + { + fn _f() {} + const _C: u32 = 0; + static _S: u32 = 0; + struct _X; + enum Z { + _A, + } -struct _FooStruct {} + struct X; + impl X { + fn _m(self) {} + } -impl _FooStruct { - fn _method_call(self) {} -} + _f; //~ used_underscore_items + _f(); //~ used_underscore_items + _C; //~ used_underscore_items + _S; //~ used_underscore_items + _X; //~ used_underscore_items + _X {}; //~ used_underscore_items + Z::_A; //~ used_underscore_items + X::_m; //~ used_underscore_items + X._m(); //~ used_underscore_items + } + // Non-underscore names. + { + fn f1() {} + const C1: u32 = 0; + static S1: u32 = 0; + struct X1; + enum Z1 { + A1, + } -fn _foo1() {} + struct X; + impl X { + fn m1(self) {} + } -fn _foo2() -> i32 { - 0 -} + f1; + f1(); + C1; + S1; + X1; + X1 {}; + Z1::A1; + X::m1; + X.m1(); + } + // Don't lint external items. The names may not be changeable. + { + let x = external_item::_ExternalStruct {}; + x._foo(); + external_item::_external_foo(); + } + // Don't lint foreign functions. The names may not be changeable. + { + unsafe extern "C" { + pub fn _exit(code: i32) -> !; + } + unsafe { _exit(1) } + } + // Don't lint in macros. + { + fn _f() {} + const _C: u32 = 0; + static _S: u32 = 0; + struct _X; + enum Z { + _A, + } -mod a { - pub mod b { - pub mod c { - pub fn _foo3() {} + inline! { + _f(); + _C; + _S; + _X; + _X; + Z::_A; + } + } + // Make sure expect works on the item. + { + #[expect(clippy::used_underscore_items)] + fn _f() {} + #[expect(clippy::used_underscore_items)] + const _C: u32 = 0; + #[expect(clippy::used_underscore_items)] + static _S: u32 = 0; + #[expect(clippy::used_underscore_items)] + struct _X; + enum Z { + #[expect(clippy::used_underscore_items)] + _A, + } - pub struct _FooStruct2 {} + struct X; + impl X { + #[expect(clippy::used_underscore_items)] + fn _m(self) {} + } - impl _FooStruct2 { - pub fn _method_call(self) {} + _f; + _f(); + _C; + _S; + _X; + _X {}; + Z::_A; + X::_m; + X._m(); + } + // Ignore anything automatically derived. + { + struct S; + #[automatically_derived] + impl S { + fn f() { + fn _f() {} + const _C: u32 = 0; + static _S: u32 = 0; + struct _X; + enum Z { + _A, + } + + _f(); + _C; + _S; + _X; + _X {}; + Z::_A; } } } } - -fn main() { - _foo1(); - //~^ used_underscore_items - let _ = _foo2(); - //~^ used_underscore_items - a::b::c::_foo3(); - //~^ used_underscore_items - let _ = &_FooStruct {}; - //~^ used_underscore_items - let _ = _FooStruct {}; - //~^ used_underscore_items - - let foo_struct = _FooStruct {}; - //~^ used_underscore_items - foo_struct._method_call(); - //~^ used_underscore_items - - let foo_struct2 = a::b::c::_FooStruct2 {}; - //~^ used_underscore_items - foo_struct2._method_call(); - //~^ used_underscore_items -} - -// should not lint external crate. -// user cannot control how others name their items -fn external_item_call() { - let foo_struct3 = external_item::_ExternalStruct {}; - foo_struct3._foo(); - - external_item::_external_foo(); -} - -// should not lint foreign functions. -// issue #14156 -unsafe extern "C" { - pub fn _exit(code: i32) -> !; -} - -fn _f() { - unsafe { _exit(1) } -} diff --git a/src/tools/clippy/tests/ui/used_underscore_items.stderr b/src/tools/clippy/tests/ui/used_underscore_items.stderr index b2f9e2db0dfc4..2274769c5eaf9 100644 --- a/src/tools/clippy/tests/ui/used_underscore_items.stderr +++ b/src/tools/clippy/tests/ui/used_underscore_items.stderr @@ -1,112 +1,112 @@ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:42:5 + --> tests/ui/used_underscore_items.rs:28:9 | -LL | _foo1(); - | ^^^^^^^ +LL | _f; + | ^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:21:1 + --> tests/ui/used_underscore_items.rs:15:9 | -LL | fn _foo1() {} - | ^^^^^^^^^^ +LL | fn _f() {} + | ^^^^^^^ = note: `-D clippy::used-underscore-items` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::used_underscore_items)]` error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:44:13 + --> tests/ui/used_underscore_items.rs:29:9 | -LL | let _ = _foo2(); - | ^^^^^^^ +LL | _f(); + | ^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:23:1 + --> tests/ui/used_underscore_items.rs:15:9 | -LL | fn _foo2() -> i32 { - | ^^^^^^^^^^^^^^^^^ +LL | fn _f() {} + | ^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:46:5 + --> tests/ui/used_underscore_items.rs:30:9 | -LL | a::b::c::_foo3(); - | ^^^^^^^^^^^^^^^^ +LL | _C; + | ^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:30:13 + --> tests/ui/used_underscore_items.rs:16:9 | -LL | pub fn _foo3() {} - | ^^^^^^^^^^^^^^ +LL | const _C: u32 = 0; + | ^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:48:14 + --> tests/ui/used_underscore_items.rs:31:9 | -LL | let _ = &_FooStruct {}; - | ^^^^^^^^^^^^^ +LL | _S; + | ^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:15:1 + --> tests/ui/used_underscore_items.rs:17:9 | -LL | struct _FooStruct {} - | ^^^^^^^^^^^^^^^^^ +LL | static _S: u32 = 0; + | ^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:50:13 + --> tests/ui/used_underscore_items.rs:32:9 | -LL | let _ = _FooStruct {}; - | ^^^^^^^^^^^^^ +LL | _X; + | ^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:15:1 + --> tests/ui/used_underscore_items.rs:18:9 | -LL | struct _FooStruct {} - | ^^^^^^^^^^^^^^^^^ +LL | struct _X; + | ^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:53:22 + --> tests/ui/used_underscore_items.rs:33:9 | -LL | let foo_struct = _FooStruct {}; - | ^^^^^^^^^^^^^ +LL | _X {}; + | ^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:15:1 + --> tests/ui/used_underscore_items.rs:18:9 | -LL | struct _FooStruct {} - | ^^^^^^^^^^^^^^^^^ +LL | struct _X; + | ^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:55:5 + --> tests/ui/used_underscore_items.rs:34:9 | -LL | foo_struct._method_call(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Z::_A; + | ^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:18:5 + --> tests/ui/used_underscore_items.rs:20:13 | -LL | fn _method_call(self) {} - | ^^^^^^^^^^^^^^^^^^^^^ +LL | _A, + | ^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:58:23 + --> tests/ui/used_underscore_items.rs:35:9 | -LL | let foo_struct2 = a::b::c::_FooStruct2 {}; - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | X::_m; + | ^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:32:13 + --> tests/ui/used_underscore_items.rs:25:13 | -LL | pub struct _FooStruct2 {} - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn _m(self) {} + | ^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:60:5 + --> tests/ui/used_underscore_items.rs:36:9 | -LL | foo_struct2._method_call(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | X._m(); + | ^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:35:17 + --> tests/ui/used_underscore_items.rs:25:13 | -LL | pub fn _method_call(self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn _m(self) {} + | ^^^^^^^^^^^ error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/workspace.rs b/src/tools/clippy/tests/workspace.rs index 19ccc7ae96070..c32333d51f20b 100644 --- a/src/tools/clippy/tests/workspace.rs +++ b/src/tools/clippy/tests/workspace.rs @@ -29,6 +29,7 @@ fn test_module_style_with_dep_in_subdir() { let output = Command::new(&*CARGO_CLIPPY_PATH) .current_dir(&cwd) .env("CARGO_INCREMENTAL", "0") + .env("CARGO_TERM_COLOR", "never") .env("CARGO_TARGET_DIR", &target_dir) .arg("clippy") .args(["-p", "pass-no-mod-with-dep-in-subdir"]) @@ -68,6 +69,7 @@ fn test_no_deps_ignores_path_deps_in_workspaces() { let output = Command::new(&*CARGO_CLIPPY_PATH) .current_dir(&cwd) .env("CARGO_INCREMENTAL", "0") + .env("CARGO_TERM_COLOR", "never") .env("CARGO_TARGET_DIR", &target_dir) .arg("clippy") .args(["-p", "subcrate"]) @@ -88,6 +90,7 @@ fn test_no_deps_ignores_path_deps_in_workspaces() { let output = Command::new(&*CARGO_CLIPPY_PATH) .current_dir(&cwd) .env("CARGO_INCREMENTAL", "0") + .env("CARGO_TERM_COLOR", "never") .env("CARGO_TARGET_DIR", &target_dir) .arg("clippy") .args(["-p", "subcrate"]) @@ -115,6 +118,7 @@ fn test_no_deps_ignores_path_deps_in_workspaces() { let output = Command::new(&*CARGO_CLIPPY_PATH) .current_dir(&cwd) .env("CARGO_INCREMENTAL", "0") + .env("CARGO_TERM_COLOR", "never") .env("CARGO_TARGET_DIR", &target_dir) .arg("clippy") .args(["-p", "subcrate"]) diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index 55f9ca05999d8..7ebff7f79606c 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -97,7 +97,6 @@ users_on_vacation = [ "matthiaskrgr", "Alexendoo", "y21", - "blyxyas", "ada4a", "samueltardieu" ] @@ -115,6 +114,7 @@ users_on_vacation = [ "@y21", "@samueltardieu", "@ada4a", + "@blyxyas", ] # Require community reviews before automatic assignment