summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /src/tools/clippy
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/clippy')
-rw-r--r--src/tools/clippy/.github/driver.sh7
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml7
-rw-r--r--src/tools/clippy/CHANGELOG.md182
-rw-r--r--src/tools/clippy/Cargo.toml6
-rw-r--r--src/tools/clippy/book/src/README.md2
-rw-r--r--src/tools/clippy/book/src/installation.md2
-rw-r--r--src/tools/clippy/build.rs14
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs3
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/almost_complete_range.rs (renamed from src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs)24
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs161
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/fallible_impl_from.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/fn_null_check.rs106
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_impl.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_include_file.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs91
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_filter.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs174
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs66
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_trait_methods.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mut.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/octal_escapes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs85
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/identity_op.rs74
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_option_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_block.rs137
-rw-r--r--src/tools/clippy/clippy_lints/src/size_of_ref.rs73
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs64
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types/type_complexity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs4
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs49
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs52
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs40
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs11
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/rustc_tools_util/CHANGELOG.md6
-rw-r--r--src/tools/clippy/rustc_tools_util/Cargo.toml2
-rw-r--r--src/tools/clippy/rustc_tools_util/README.md38
-rw-r--r--src/tools/clippy/rustc_tools_util/src/lib.rs48
-rw-r--r--src/tools/clippy/src/driver.rs6
-rw-r--r--src/tools/clippy/src/main.rs1
-rw-r--r--src/tools/clippy/tests/integration.rs9
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr16
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs123
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr58
-rw-r--r--src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/clippy.toml12
-rw-r--r--src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr36
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs60
-rw-r--r--src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr70
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr3
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_letter_range.stderr113
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.fixed (renamed from src/tools/clippy/tests/ui/almost_complete_letter_range.fixed)49
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.rs (renamed from src/tools/clippy/tests/ui/almost_complete_letter_range.rs)49
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_range.stderr235
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs225
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr502
-rw-r--r--src/tools/clippy/tests/ui/async_yields_async.stderr6
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs4
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed18
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs10
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr16
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed67
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs13
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr66
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.fixed6
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_integer.rs6
-rw-r--r--src/tools/clippy/tests/ui/clone_on_copy.stderr2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_str_replace.fixed11
-rw-r--r--src/tools/clippy/tests/ui/collapsible_str_replace.rs11
-rw-r--r--src/tools/clippy/tests/ui/collapsible_str_replace.stderr34
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6252.stderr9
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6254.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6255.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6256.rs2
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.stderr52
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.fixed8
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.stderr16
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed21
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs23
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr23
-rw-r--r--src/tools/clippy/tests/ui/derive.rs11
-rw-r--r--src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr59
-rw-r--r--src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs (renamed from src/tools/clippy/tests/ui/derive_hash_xor_eq.rs)21
-rw-r--r--src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr29
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.rs23
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.stderr38
-rw-r--r--src/tools/clippy/tests/ui/explicit_counter_loop.rs30
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs21
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.fixed9
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.rs9
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.stderr44
-rw-r--r--src/tools/clippy/tests/ui/fn_null_check.rs21
-rw-r--r--src/tools/clippy/tests/ui/fn_null_check.stderr43
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.fixed7
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs7
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.stderr10
-rw-r--r--src/tools/clippy/tests/ui/identity_op.fixed6
-rw-r--r--src/tools/clippy/tests/ui/identity_op.rs4
-rw-r--r--src/tools/clippy/tests/ui/identity_op.stderr12
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.fixed10
-rw-r--r--src/tools/clippy/tests/ui/implicit_clone.rs10
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.rs6
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.stderr44
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.fixed35
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.rs39
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.stderr114
-rw-r--r--src/tools/clippy/tests/ui/large_stack_arrays.rs1
-rw-r--r--src/tools/clippy/tests/ui/large_stack_arrays.stderr10
-rw-r--r--src/tools/clippy/tests/ui/len_zero.fixed40
-rw-r--r--src/tools/clippy/tests/ui/len_zero.rs40
-rw-r--r--src/tools/clippy/tests/ui/len_zero.stderr74
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed5
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.fixed5
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.rs5
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.fixed41
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.rs41
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.fixed13
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.rs13
-rw-r--r--src/tools/clippy/tests/ui/manual_is_ascii_check.stderr64
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.rs7
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr15
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_retain.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.fixed13
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.rs14
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.stderr27
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed22
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs22
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr8
-rw-r--r--src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed2
-rw-r--r--src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed15
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs15
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr110
-rw-r--r--src/tools/clippy/tests/ui/permissions_set_readonly_false.rs29
-rw-r--r--src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr13
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed6
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.rs6
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr10
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed4
-rw-r--r--src/tools/clippy/tests/ui/rename.rs4
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr98
-rw-r--r--src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr5
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed6
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs6
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_inside_block.fixed85
-rw-r--r--src/tools/clippy/tests/ui/semicolon_inside_block.rs85
-rw-r--r--src/tools/clippy/tests/ui/semicolon_inside_block.stderr54
-rw-r--r--src/tools/clippy/tests/ui/semicolon_outside_block.fixed85
-rw-r--r--src/tools/clippy/tests/ui/semicolon_outside_block.rs85
-rw-r--r--src/tools/clippy/tests/ui/semicolon_outside_block.stderr54
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.fixed27
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.rs26
-rw-r--r--src/tools/clippy/tests/ui/single_element_loop.stderr29
-rw-r--r--src/tools/clippy/tests/ui/size_of_ref.rs27
-rw-r--r--src/tools/clippy/tests/ui/size_of_ref.stderr27
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.fixed6
-rw-r--r--src/tools/clippy/tests/ui/string_lit_as_bytes.rs6
-rw-r--r--src/tools/clippy/tests/ui/suspicious_to_owned.stderr8
-rw-r--r--src/tools/clippy/tests/ui/transmute_null_to_fn.rs28
-rw-r--r--src/tools/clippy/tests/ui/transmute_null_to_fn.stderr27
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed3
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed3
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr26
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.rs3
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clone.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.fixed20
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.rs20
-rw-r--r--src/tools/clippy/tests/ui/unused_self.rs10
-rw-r--r--src/tools/clippy/tests/ui/unused_self.stderr18
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed73
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs73
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr54
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.fixed1
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.rs1
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports.stderr42
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed240
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr132
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed240
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr132
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.rs241
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_2021.stderr132
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr_no_std.fixed21
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr_no_std.rs21
-rw-r--r--src/tools/clippy/tests/ui/zero_ptr_no_std.stderr26
-rw-r--r--src/tools/clippy/tests/versioncheck.rs1
-rw-r--r--src/tools/clippy/triagebot.toml2
304 files changed, 6778 insertions, 1509 deletions
diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh
index 6ff189fc8..798782340 100644
--- a/src/tools/clippy/.github/driver.sh
+++ b/src/tools/clippy/.github/driver.sh
@@ -17,6 +17,13 @@ test "$sysroot" = $desired_sysroot
sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot)
test "$sysroot" = $desired_sysroot
+# Check that the --sysroot argument is only passed once (SYSROOT is ignored)
+(
+ cd rustc_tools_util
+ touch src/lib.rs
+ SYSROOT=/tmp RUSTFLAGS="--sysroot=$(rustc --print sysroot)" ../target/debug/cargo-clippy clippy --verbose
+)
+
# Make sure this isn't set - clippy-driver should cope without it
unset CARGO_MANIFEST_DIR
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 6448b2d40..1bc457a94 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -82,13 +82,6 @@ jobs:
with:
github_token: "${{ secrets.github_token }}"
- - name: Install dependencies (Linux-i686)
- run: |
- sudo dpkg --add-architecture i386
- sudo apt-get update
- sudo apt-get install gcc-multilib libssl-dev:i386 libgit2-dev:i386
- if: matrix.host == 'i686-unknown-linux-gnu'
-
- name: Checkout
uses: actions/checkout@v3.0.2
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 23912bb3e..8e31e8f0d 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,181 @@ document.
## Unreleased / Beta / In Rust Nightly
-[b52fb523...master](https://github.com/rust-lang/rust-clippy/compare/b52fb523...master)
+[4f142aa1...master](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...master)
+
+## Rust 1.66
+
+Current stable, released 2022-12-15
+
+[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
+
+### New Lints
+
+* [`manual_clamp`]
+ [#9484](https://github.com/rust-lang/rust-clippy/pull/9484)
+* [`missing_trait_methods`]
+ [#9670](https://github.com/rust-lang/rust-clippy/pull/9670)
+* [`unused_format_specs`]
+ [#9637](https://github.com/rust-lang/rust-clippy/pull/9637)
+* [`iter_kv_map`]
+ [#9409](https://github.com/rust-lang/rust-clippy/pull/9409)
+* [`manual_filter`]
+ [#9451](https://github.com/rust-lang/rust-clippy/pull/9451)
+* [`box_default`]
+ [#9511](https://github.com/rust-lang/rust-clippy/pull/9511)
+* [`implicit_saturating_add`]
+ [#9549](https://github.com/rust-lang/rust-clippy/pull/9549)
+* [`as_ptr_cast_mut`]
+ [#9572](https://github.com/rust-lang/rust-clippy/pull/9572)
+* [`disallowed_macros`]
+ [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
+* [`partial_pub_fields`]
+ [#9658](https://github.com/rust-lang/rust-clippy/pull/9658)
+* [`uninlined_format_args`]
+ [#9233](https://github.com/rust-lang/rust-clippy/pull/9233)
+* [`cast_nan_to_int`]
+ [#9617](https://github.com/rust-lang/rust-clippy/pull/9617)
+
+### Moves and Deprecations
+
+* `positional_named_format_parameters` was uplifted to rustc under the new name
+ `named_arguments_used_positionally`
+ [#8518](https://github.com/rust-lang/rust-clippy/pull/8518)
+* Moved [`implicit_saturating_sub`] to `style` (Now warn-by-default)
+ [#9584](https://github.com/rust-lang/rust-clippy/pull/9584)
+* Moved `derive_partial_eq_without_eq` to `nursery` (now allow-by-default)
+ [#9536](https://github.com/rust-lang/rust-clippy/pull/9536)
+
+### Enhancements
+
+* [`nonstandard_macro_braces`]: Now includes `matches!()` in the default lint config
+ [#9471](https://github.com/rust-lang/rust-clippy/pull/9471)
+* [`suboptimal_flops`]: Now supports multiplication and subtraction operations
+ [#9581](https://github.com/rust-lang/rust-clippy/pull/9581)
+* [`arithmetic_side_effects`]: Now detects cases with literals behind references
+ [#9587](https://github.com/rust-lang/rust-clippy/pull/9587)
+* [`upper_case_acronyms`]: Now also checks enum names
+ [#9580](https://github.com/rust-lang/rust-clippy/pull/9580)
+* [`needless_borrowed_reference`]: Now lints nested patterns
+ [#9573](https://github.com/rust-lang/rust-clippy/pull/9573)
+* [`unnecessary_cast`]: Now works for non-trivial non-literal expressions
+ [#9576](https://github.com/rust-lang/rust-clippy/pull/9576)
+* [`arithmetic_side_effects`]: Now detects operations with custom types
+ [#9559](https://github.com/rust-lang/rust-clippy/pull/9559)
+* [`disallowed_methods`], [`disallowed_types`]: Not correctly lints types, functions and macros
+ with the same path
+ [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
+* [`self_named_module_files`], [`mod_module_files`]: Now take remapped path prefixes into account
+ [#9475](https://github.com/rust-lang/rust-clippy/pull/9475)
+* [`bool_to_int_with_if`]: Now detects the inverse if case
+ [#9476](https://github.com/rust-lang/rust-clippy/pull/9476)
+
+### False Positive Fixes
+
+* [`arithmetic_side_effects`]: Now allows operations that can't overflow
+ [#9474](https://github.com/rust-lang/rust-clippy/pull/9474)
+* [`unnecessary_lazy_evaluations`]: No longer lints in external macros
+ [#9486](https://github.com/rust-lang/rust-clippy/pull/9486)
+* [`needless_borrow`], [`explicit_auto_deref`]: No longer lint on unions that require the reference
+ [#9490](https://github.com/rust-lang/rust-clippy/pull/9490)
+* [`almost_complete_letter_range`]: No longer lints in external macros
+ [#9467](https://github.com/rust-lang/rust-clippy/pull/9467)
+* [`drop_copy`]: No longer lints on idiomatic cases in match arms
+ [#9491](https://github.com/rust-lang/rust-clippy/pull/9491)
+* [`question_mark`]: No longer lints in const context
+ [#9487](https://github.com/rust-lang/rust-clippy/pull/9487)
+* [`collapsible_if`]: Suggestion now work in macros
+ [#9410](https://github.com/rust-lang/rust-clippy/pull/9410)
+* [`std_instead_of_core`]: No longer triggers on unstable modules
+ [#9545](https://github.com/rust-lang/rust-clippy/pull/9545)
+* [`unused_peekable`]: No longer lints, if the peak is done in a closure or function
+ [#9465](https://github.com/rust-lang/rust-clippy/pull/9465)
+* [`useless_attribute`]: No longer lints on `#[allow]` attributes for [`unsafe_removed_from_name`]
+ [#9593](https://github.com/rust-lang/rust-clippy/pull/9593)
+* [`unnecessary_lazy_evaluations`]: No longer suggest switching to early evaluation when type has
+ custom `Drop` implementation
+ [#9551](https://github.com/rust-lang/rust-clippy/pull/9551)
+* [`unnecessary_cast`]: No longer lints on negative hexadecimal literals when cast as floats
+ [#9609](https://github.com/rust-lang/rust-clippy/pull/9609)
+* [`use_self`]: No longer lints in proc macros
+ [#9454](https://github.com/rust-lang/rust-clippy/pull/9454)
+* [`never_loop`]: Now takes `let ... else` statements into consideration.
+ [#9496](https://github.com/rust-lang/rust-clippy/pull/9496)
+* [`default_numeric_fallback`]: Now ignores constants
+ [#9636](https://github.com/rust-lang/rust-clippy/pull/9636)
+* [`uninit_vec`]: No longer lints `Vec::set_len(0)`
+ [#9519](https://github.com/rust-lang/rust-clippy/pull/9519)
+* [`arithmetic_side_effects`]: Now ignores references to integer types
+ [#9507](https://github.com/rust-lang/rust-clippy/pull/9507)
+* [`large_stack_arrays`]: No longer lints inside static items
+ [#9466](https://github.com/rust-lang/rust-clippy/pull/9466)
+* [`ref_option_ref`]: No longer lints if the inner reference is mutable
+ [#9684](https://github.com/rust-lang/rust-clippy/pull/9684)
+* [`ptr_arg`]: No longer lints if the argument is used as an incomplete trait object
+ [#9645](https://github.com/rust-lang/rust-clippy/pull/9645)
+* [`should_implement_trait`]: Now also works for `default` methods
+ [#9546](https://github.com/rust-lang/rust-clippy/pull/9546)
+
+### Suggestion Fixes/Improvements
+
+* [`derivable_impls`]: The suggestion is now machine applicable
+ [#9429](https://github.com/rust-lang/rust-clippy/pull/9429)
+* [`match_single_binding`]: The suggestion now handles scrutinies with side effects better
+ [#9601](https://github.com/rust-lang/rust-clippy/pull/9601)
+* [`zero_prefixed_literal`]: Only suggests using octal numbers, if this is possible
+ [#9652](https://github.com/rust-lang/rust-clippy/pull/9652)
+* [`rc_buffer`]: The suggestion is no longer machine applicable to avoid semantic changes
+ [#9633](https://github.com/rust-lang/rust-clippy/pull/9633)
+* [`print_literal`], [`write_literal`], [`uninlined_format_args`]: The suggestion now ignores
+ comments after the macro call.
+ [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
+* [`expect_fun_call`]:Improved the suggestion for `format!` calls with captured variables
+ [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
+* [`nonstandard_macro_braces`]: The suggestion is now machine applicable and will no longer
+ replace brackets inside the macro argument.
+ [#9499](https://github.com/rust-lang/rust-clippy/pull/9499)
+* [`from_over_into`]: The suggestion is now a machine applicable and contains explanations
+ [#9649](https://github.com/rust-lang/rust-clippy/pull/9649)
+* [`needless_return`]: The automatic suggestion now removes all required semicolons
+ [#9497](https://github.com/rust-lang/rust-clippy/pull/9497)
+* [`to_string_in_format_args`]: The suggestion now keeps parenthesis around values
+ [#9590](https://github.com/rust-lang/rust-clippy/pull/9590)
+* [`manual_assert`]: The suggestion now preserves comments
+ [#9479](https://github.com/rust-lang/rust-clippy/pull/9479)
+* [`redundant_allocation`]: The suggestion applicability is now marked `MaybeIncorrect` to
+ avoid semantic changes
+ [#9634](https://github.com/rust-lang/rust-clippy/pull/9634)
+* [`assertions_on_result_states`]: The suggestion has been corrected, for cases where the
+ `assert!` is not in a statement.
+ [#9453](https://github.com/rust-lang/rust-clippy/pull/9453)
+* [`nonminimal_bool`]: The suggestion no longer expands macros
+ [#9457](https://github.com/rust-lang/rust-clippy/pull/9457)
+* [`collapsible_match`]: Now specifies field names, when a struct is destructed
+ [#9685](https://github.com/rust-lang/rust-clippy/pull/9685)
+* [`unnecessary_cast`]: The suggestion now adds parenthesis for negative numbers
+ [#9577](https://github.com/rust-lang/rust-clippy/pull/9577)
+* [`redundant_closure`]: The suggestion now works for `impl FnMut` arguments
+ [#9556](https://github.com/rust-lang/rust-clippy/pull/9556)
+
+### ICE Fixes
+
+* [`unnecessary_to_owned`]: Avoid ICEs in favor of false negatives if information is missing
+ [#9505](https://github.com/rust-lang/rust-clippy/pull/9505)
+* [`manual_range_contains`]: No longer ICEs on values behind references
+ [#9627](https://github.com/rust-lang/rust-clippy/pull/9627)
+* [`needless_pass_by_value`]: No longer ICEs on unsized `dyn Fn` arguments
+ [#9531](https://github.com/rust-lang/rust-clippy/pull/9531)
+* `*_interior_mutable_const` lints: no longer ICE on const unions containing `!Freeze` types
+ [#9539](https://github.com/rust-lang/rust-clippy/pull/9539)
+
+### Others
+
+* Released `rustc_tools_util` for version information on `Crates.io`. (Further adjustments will
+ not be published as part of this changelog)
## Rust 1.65
-Current stable, released 2022-11-03
+Released 2022-11-03
[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523)
@@ -3875,6 +4045,7 @@ Released 2018-09-13
[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
+[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
@@ -3966,6 +4137,7 @@ Released 2018-09-13
[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
+[`derived_hash_with_manual_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq
[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods
@@ -4032,6 +4204,7 @@ Released 2018-09-13
[`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
@@ -4289,6 +4462,7 @@ Released 2018-09-13
[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
+[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
@@ -4353,6 +4527,8 @@ Released 2018-09-13
[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
+[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block
+[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block
[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
@@ -4372,6 +4548,7 @@ Released 2018-09-13
[`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
[`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
+[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
@@ -4417,6 +4594,7 @@ Released 2018-09-13
[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool
[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char
[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float
+[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn
[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes
[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr
[`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index fe425a2fb..f8cb4b721 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy"
-version = "0.1.67"
+version = "0.1.68"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -23,7 +23,7 @@ path = "src/driver.rs"
[dependencies]
clippy_lints = { path = "clippy_lints" }
semver = "1.0"
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
tempfile = { version = "3.2", optional = true }
termize = "0.1"
@@ -55,7 +55,7 @@ tokio = { version = "1", features = ["io-util"] }
rustc-semver = "1.1"
[build-dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
[features]
deny-warnings = ["clippy_lints/deny-warnings"]
diff --git a/src/tools/clippy/book/src/README.md b/src/tools/clippy/book/src/README.md
index 6248d588a..23867df8e 100644
--- a/src/tools/clippy/book/src/README.md
+++ b/src/tools/clippy/book/src/README.md
@@ -1,6 +1,6 @@
# Clippy
-[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Aauto)
+[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto)
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](https://github.com/rust-lang/rust-clippy#license)
A collection of lints to catch common mistakes and improve your
diff --git a/src/tools/clippy/book/src/installation.md b/src/tools/clippy/book/src/installation.md
index b2a28d0be..cce888b17 100644
--- a/src/tools/clippy/book/src/installation.md
+++ b/src/tools/clippy/book/src/installation.md
@@ -1,6 +1,6 @@
# Installation
-If you're using `rustup` to install and manage you're Rust toolchains, Clippy is
+If you're using `rustup` to install and manage your Rust toolchains, Clippy is
usually **already installed**. In that case you can skip this chapter and go to
the [Usage] chapter.
diff --git a/src/tools/clippy/build.rs b/src/tools/clippy/build.rs
index b5484bec3..b79d09b0d 100644
--- a/src/tools/clippy/build.rs
+++ b/src/tools/clippy/build.rs
@@ -3,17 +3,5 @@ fn main() {
println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap());
// Don't rebuild even if nothing changed
println!("cargo:rerun-if-changed=build.rs");
- // forward git repo hashes we build at
- println!(
- "cargo:rustc-env=GIT_HASH={}",
- rustc_tools_util::get_commit_hash().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=COMMIT_DATE={}",
- rustc_tools_util::get_commit_date().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
- rustc_tools_util::get_channel()
- );
+ rustc_tools_util::setup_version_info!();
}
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 80bb83af4..e70488165 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -5,6 +5,9 @@
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
+// The `rustc_driver` crate seems to be required in order to use the `rust_lexer` crate.
+#[allow(unused_extern_crates)]
+extern crate rustc_driver;
extern crate rustc_lexer;
use std::path::PathBuf;
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index aedff24c1..a9f69b1ba 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.67"
+version = "0.1.68"
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/almost_complete_letter_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
index 52beaf504..42e14b5cd 100644
--- a/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
+++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
@@ -10,8 +10,8 @@ use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
- /// Checks for ranges which almost include the entire range of letters from 'a' to 'z', but
- /// don't because they're a half open range.
+ /// Checks for ranges which almost include the entire range of letters from 'a' to 'z'
+ /// or digits from '0' to '9', but don't because they're a half open range.
///
/// ### Why is this bad?
/// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
@@ -25,21 +25,21 @@ declare_clippy_lint! {
/// let _ = 'a'..='z';
/// ```
#[clippy::version = "1.63.0"]
- pub ALMOST_COMPLETE_LETTER_RANGE,
+ pub ALMOST_COMPLETE_RANGE,
suspicious,
- "almost complete letter range"
+ "almost complete range"
}
-impl_lint_pass!(AlmostCompleteLetterRange => [ALMOST_COMPLETE_LETTER_RANGE]);
+impl_lint_pass!(AlmostCompleteRange => [ALMOST_COMPLETE_RANGE]);
-pub struct AlmostCompleteLetterRange {
+pub struct AlmostCompleteRange {
msrv: Msrv,
}
-impl AlmostCompleteLetterRange {
+impl AlmostCompleteRange {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
-impl EarlyLintPass for AlmostCompleteLetterRange {
+impl EarlyLintPass for AlmostCompleteRange {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
let ctxt = e.span.ctxt();
@@ -87,14 +87,18 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
)
+ | (
+ Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
+ Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
+ )
)
&& !in_external_macro(cx.sess(), span)
{
span_lint_and_then(
cx,
- ALMOST_COMPLETE_LETTER_RANGE,
+ ALMOST_COMPLETE_RANGE,
span,
- "almost complete ascii letter range",
+ "almost complete ascii range",
|diag| {
if let Some((span, sugg)) = sugg {
diag.span_suggestion(
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 0710ac0bb..751c26267 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -472,7 +472,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe
fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) {
// Check for the feature
- if !cx.tcx.sess.features_untracked().lint_reasons {
+ if !cx.tcx.features().lint_reasons {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index 36daceabe..9d98a6bab 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -8,7 +8,7 @@ use rustc_hir::{
Block, Expr, ExprKind, Local, Node, QPath, TyKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
+use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
@@ -30,7 +30,7 @@ declare_clippy_lint! {
/// ```rust
/// let x: Box<String> = Box::default();
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub BOX_DEFAULT,
perf,
"Using Box::new(T::default()) instead of Box::default()"
@@ -59,7 +59,7 @@ impl LateLintPass<'_> for BoxDefault {
if is_plain_default(arg_path) || given_type(cx, expr) {
"Box::default()".into()
} else {
- format!("Box::<{arg_ty}>::default()")
+ with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
},
Applicability::MachineApplicable
);
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
index e862f13e6..27cc5a1c3 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
diag.span_suggestion(
expr.span,
- &format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
+ format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"),
sugg,
rustc_errors::Applicability::HasPlaceholders,
);
@@ -68,7 +68,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
let map = cx.tcx.hir();
if_chain! {
- if let Some(parent_id) = map.find_parent_node(expr.hir_id);
+ if let Some(parent_id) = map.opt_parent_id(expr.hir_id);
if let Some(parent) = map.find(parent_id);
then {
let expr = match parent {
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index c6d505c4a..161e3a698 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -641,7 +641,7 @@ declare_clippy_lint! {
/// ```rust,ignore
/// let _: = 0_u64;
/// ```
- #[clippy::version = "1.64.0"]
+ #[clippy::version = "1.66.0"]
pub CAST_NAN_TO_INT,
suspicious,
"casting a known floating-point NaN into an integer"
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 0e3d93175..f10c35cde 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -525,7 +525,11 @@ fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbo
.iter()
.filter(|&&(_, name)| !name.as_str().starts_with('_'))
.any(|&(_, name)| {
- let mut walker = ContainsName { name, result: false };
+ let mut walker = ContainsName {
+ name,
+ result: false,
+ cx,
+ };
// Scan block
block
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index fe9f4f9ae..799e71e84 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -10,11 +10,11 @@ use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
- /// Checks for usage of dbg!() macro.
+ /// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro.
///
/// ### Why is this bad?
- /// `dbg!` macro is intended as a debugging tool. It
- /// should not be in version control.
+ /// The `dbg!` macro is intended as a debugging tool. It should not be present in released
+ /// software or committed to a version control system.
///
/// ### Example
/// ```rust,ignore
@@ -91,8 +91,8 @@ impl LateLintPass<'_> for DbgMacro {
cx,
DBG_MACRO,
macro_call.span,
- "`dbg!` macro is intended as a debugging tool",
- "ensure to avoid having uses of it in version control",
+ "the `dbg!` macro is intended as a debugging tool",
+ "remove the invocation before committing it to a version control system",
suggestion,
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index e4d76f07d..91ca73633 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -35,7 +35,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
- crate::almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE_INFO,
+ crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
crate::approx_const::APPROX_CONSTANT_INFO,
crate::as_conversions::AS_CONVERSIONS_INFO,
crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
@@ -111,7 +111,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::dereference::NEEDLESS_BORROW_INFO,
crate::dereference::REF_BINDING_TO_REFERENCE_INFO,
crate::derivable_impls::DERIVABLE_IMPLS_INFO,
- crate::derive::DERIVE_HASH_XOR_EQ_INFO,
+ crate::derive::DERIVED_HASH_WITH_MANUAL_EQ_INFO,
crate::derive::DERIVE_ORD_XOR_PARTIAL_ORD_INFO,
crate::derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ_INFO,
crate::derive::EXPL_IMPL_CLONE_ON_COPY_INFO,
@@ -161,6 +161,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
+ crate::fn_null_check::FN_NULL_CHECK_INFO,
crate::format::USELESS_FORMAT_INFO,
crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
@@ -494,6 +495,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO,
crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO,
crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
+ crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
crate::precedence::PRECEDENCE_INFO,
crate::ptr::CMP_NULL_INFO,
crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
@@ -525,6 +527,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::returns::NEEDLESS_RETURN_INFO,
crate::same_name_method::SAME_NAME_METHOD_INFO,
crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
+ crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,
+ crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO,
crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO,
crate::serde_api::SERDE_API_MISUSE_INFO,
crate::shadow::SHADOW_REUSE_INFO,
@@ -533,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
+ crate::size_of_ref::SIZE_OF_REF_INFO,
crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO,
crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO,
@@ -566,6 +571,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO,
crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO,
+ crate::transmute::TRANSMUTE_NULL_TO_FN_INFO,
crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO,
crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO,
crate::transmute::TRANSMUTE_PTR_TO_REF_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 7f937de1d..a04693f46 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -11,6 +11,7 @@ use rustc_hir::def::Res;
use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
@@ -98,9 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
if let ty::Adt(def, ..) = expr_ty.kind();
if !is_from_proc_macro(cx, expr);
then {
- // TODO: Work out a way to put "whatever the imported way of referencing
- // this type in this file" rather than a fully-qualified type.
- let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did()));
+ let replacement = with_forced_trimmed_paths!(format!("{}::default()", cx.tcx.def_path_str(def.did())));
span_lint_and_sugg(
cx,
DEFAULT_TRAIT_ACCESS,
@@ -170,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
// find out if and which field was set by this `consecutive_statement`
if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
// interrupt and cancel lint if assign_rhs references the original binding
- if contains_name(binding_name, assign_rhs) {
+ if contains_name(binding_name, assign_rhs, cx) {
cancel_lint = true;
break;
}
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 38329659e..05f2b92c0 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -969,14 +969,14 @@ fn binding_ty_auto_deref_stability<'tcx>(
precedence: i8,
binder_args: &'tcx List<BoundVariableKind>,
) -> Position {
- let TyKind::Rptr(_, ty) = &ty.kind else {
+ let TyKind::Ref(_, ty) = &ty.kind else {
return Position::Other(precedence);
};
let mut ty = ty;
loop {
break match ty.ty.kind {
- TyKind::Rptr(_, ref ref_ty) => {
+ TyKind::Ref(_, ref ref_ty) => {
ty = ref_ty;
continue;
},
@@ -1244,7 +1244,7 @@ fn is_mixed_projection_predicate<'tcx>(
let mut projection_ty = projection_predicate.projection_ty;
loop {
match projection_ty.self_ty().kind() {
- ty::Projection(inner_projection_ty) => {
+ ty::Alias(ty::Projection, inner_projection_ty) => {
projection_ty = *inner_projection_ty;
}
ty::Param(param_ty) => {
@@ -1330,7 +1330,7 @@ fn replace_types<'tcx>(
&& let Some(term_ty) = projection_predicate.term.ty()
&& let ty::Param(term_param_ty) = term_ty.kind()
{
- let item_def_id = projection_predicate.projection_ty.item_def_id;
+ let item_def_id = projection_predicate.projection_ty.def_id;
let assoc_item = cx.tcx.associated_item(item_def_id);
let projection = cx.tcx
.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
@@ -1390,10 +1390,15 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
continue;
},
ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
- ty::Projection(_) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
- ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => {
- Position::ReborrowStable(precedence).into()
+ ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
+ TyPosition::new_deref_stable_for_result(precedence, ty)
},
+ ty::Infer(_)
+ | ty::Error(_)
+ | ty::Bound(..)
+ | ty::Alias(ty::Opaque, ..)
+ | ty::Placeholder(_)
+ | ty::Dynamic(..) => Position::ReborrowStable(precedence).into(),
ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
Position::ReborrowStable(precedence).into()
},
@@ -1417,7 +1422,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
| ty::Closure(..)
| ty::Never
| ty::Tuple(_)
- | ty::Projection(_) => {
+ | ty::Alias(ty::Projection, _) => {
Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
},
};
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index ae8f6b794..bc18e2e5e 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -1,12 +1,15 @@
use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::indent_of;
use clippy_utils::{is_default_equivalent, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir::{
- def::{DefKind, Res},
- Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
+ def::{CtorKind, CtorOf, DefKind, Res},
+ Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_middle::ty::{AdtDef, DefIdTree};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::sym;
declare_clippy_lint! {
@@ -51,7 +54,18 @@ declare_clippy_lint! {
"manual implementation of the `Default` trait which is equal to a derive"
}
-declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
+pub struct DerivableImpls {
+ msrv: Msrv,
+}
+
+impl DerivableImpls {
+ #[must_use]
+ pub fn new(msrv: Msrv) -> Self {
+ DerivableImpls { msrv }
+ }
+}
+
+impl_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
fn is_path_self(e: &Expr<'_>) -> bool {
if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind {
@@ -61,6 +75,98 @@ fn is_path_self(e: &Expr<'_>) -> bool {
}
}
+fn check_struct<'tcx>(
+ cx: &LateContext<'tcx>,
+ item: &'tcx Item<'_>,
+ self_ty: &Ty<'_>,
+ func_expr: &Expr<'_>,
+ adt_def: AdtDef<'_>,
+) {
+ if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
+ if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
+ for arg in a.args {
+ if !matches!(arg, GenericArg::Lifetime(_)) {
+ return;
+ }
+ }
+ }
+ }
+ let should_emit = match peel_blocks(func_expr).kind {
+ ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
+ ExprKind::Call(callee, args) if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
+ ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
+ _ => false,
+ };
+
+ if should_emit {
+ let struct_span = cx.tcx.def_span(adt_def.did());
+ span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| {
+ diag.span_suggestion_hidden(
+ item.span,
+ "remove the manual implementation...",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ diag.span_suggestion(
+ struct_span.shrink_to_lo(),
+ "...and instead derive it",
+ "#[derive(Default)]\n".to_string(),
+ Applicability::MachineApplicable,
+ );
+ });
+ }
+}
+
+fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Expr<'_>, adt_def: AdtDef<'_>) {
+ if_chain! {
+ if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind;
+ if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res;
+ if let variant_id = cx.tcx.parent(id);
+ if let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id);
+ if variant_def.fields.is_empty();
+ if !variant_def.is_field_list_non_exhaustive();
+
+ then {
+ let enum_span = cx.tcx.def_span(adt_def.did());
+ let indent_enum = indent_of(cx, enum_span).unwrap_or(0);
+ let variant_span = cx.tcx.def_span(variant_def.def_id);
+ let indent_variant = indent_of(cx, variant_span).unwrap_or(0);
+ span_lint_and_then(
+ cx,
+ DERIVABLE_IMPLS,
+ item.span,
+ "this `impl` can be derived",
+ |diag| {
+ diag.span_suggestion_hidden(
+ item.span,
+ "remove the manual implementation...",
+ String::new(),
+ Applicability::MachineApplicable
+ );
+ diag.span_suggestion(
+ enum_span.shrink_to_lo(),
+ "...and instead derive it...",
+ format!(
+ "#[derive(Default)]\n{indent}",
+ indent = " ".repeat(indent_enum),
+ ),
+ Applicability::MachineApplicable
+ );
+ diag.span_suggestion(
+ variant_span.shrink_to_lo(),
+ "...and mark the default variant",
+ format!(
+ "#[default]\n{indent}",
+ indent = " ".repeat(indent_variant),
+ ),
+ Applicability::MachineApplicable
+ );
+ }
+ );
+ }
+ }
+}
+
impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if_chain! {
@@ -83,49 +189,16 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
if !attrs.iter().any(|attr| attr.doc_str().is_some());
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
if !child_attrs.iter().any(|attr| attr.doc_str().is_some());
- if adt_def.is_struct();
- then {
- if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind {
- if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() {
- for arg in a.args {
- if !matches!(arg, GenericArg::Lifetime(_)) {
- return;
- }
- }
- }
- }
- let should_emit = match peel_blocks(func_expr).kind {
- ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
- ExprKind::Call(callee, args)
- if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
- ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
- _ => false,
- };
- if should_emit {
- let struct_span = cx.tcx.def_span(adt_def.did());
- span_lint_and_then(
- cx,
- DERIVABLE_IMPLS,
- item.span,
- "this `impl` can be derived",
- |diag| {
- diag.span_suggestion_hidden(
- item.span,
- "remove the manual implementation...",
- String::new(),
- Applicability::MachineApplicable
- );
- diag.span_suggestion(
- struct_span.shrink_to_lo(),
- "...and instead derive it",
- "#[derive(Default)]\n".to_string(),
- Applicability::MachineApplicable
- );
- }
- );
+ then {
+ if adt_def.is_struct() {
+ check_struct(cx, item, self_ty, func_expr, adt_def);
+ } else if adt_def.is_enum() && self.msrv.meets(msrvs::DEFAULT_ENUM_ATTRIBUTE) {
+ check_enum(cx, item, func_expr, adt_def);
}
}
}
}
+
+ extract_msrv_attr!(LateContext);
}
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 9e596ca81..248d73884 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::{
- self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
- TraitRef, Ty, TyCtxt,
+ self, Binder, BoundConstness, Clause, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind,
+ TraitPredicate, Ty, TyCtxt,
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
@@ -46,7 +46,7 @@ declare_clippy_lint! {
/// }
/// ```
#[clippy::version = "pre 1.29.0"]
- pub DERIVE_HASH_XOR_EQ,
+ pub DERIVED_HASH_WITH_MANUAL_EQ,
correctness,
"deriving `Hash` but implementing `PartialEq` explicitly"
}
@@ -197,7 +197,7 @@ declare_clippy_lint! {
declare_lint_pass!(Derive => [
EXPL_IMPL_CLONE_ON_COPY,
- DERIVE_HASH_XOR_EQ,
+ DERIVED_HASH_WITH_MANUAL_EQ,
DERIVE_ORD_XOR_PARTIAL_ORD,
UNSAFE_DERIVE_DESERIALIZE,
DERIVE_PARTIAL_EQ_WITHOUT_EQ
@@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
}
}
-/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
+/// Implementation of the `DERIVED_HASH_WITH_MANUAL_EQ` lint.
fn check_hash_peq<'tcx>(
cx: &LateContext<'tcx>,
span: Span,
@@ -243,7 +243,7 @@ fn check_hash_peq<'tcx>(
cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
- if peq_is_automatically_derived == hash_is_automatically_derived {
+ if !hash_is_automatically_derived || peq_is_automatically_derived {
return;
}
@@ -251,18 +251,12 @@ fn check_hash_peq<'tcx>(
// Only care about `impl PartialEq<Foo> for Foo`
// For `impl PartialEq<B> for A, input_types is [A, B]
- if trait_ref.substs.type_at(1) == ty {
- let mess = if peq_is_automatically_derived {
- "you are implementing `Hash` explicitly but have derived `PartialEq`"
- } else {
- "you are deriving `Hash` but have implemented `PartialEq` explicitly"
- };
-
+ if trait_ref.subst_identity().substs.type_at(1) == ty {
span_lint_and_then(
cx,
- DERIVE_HASH_XOR_EQ,
+ DERIVED_HASH_WITH_MANUAL_EQ,
span,
- mess,
+ "you are deriving `Hash` but have implemented `PartialEq` explicitly",
|diag| {
if let Some(local_def_id) = impl_id.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
@@ -305,7 +299,7 @@ fn check_ord_partial_ord<'tcx>(
// Only care about `impl PartialOrd<Foo> for Foo`
// For `impl PartialOrd<B> for A, input_types is [A, B]
- if trait_ref.substs.type_at(1) == ty {
+ if trait_ref.subst_identity().substs.type_at(1) == ty {
let mess = if partial_ord_is_automatically_derived {
"you are implementing `Ord` explicitly but have derived `PartialOrd`"
} else {
@@ -366,6 +360,15 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) {
return;
}
+ // `#[repr(packed)]` structs with type/const parameters can't derive `Clone`.
+ // https://github.com/rust-lang/rust-clippy/issues/10188
+ if ty_adt.repr().packed()
+ && ty_subs
+ .iter()
+ .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
+ {
+ return;
+ }
span_lint_and_note(
cx,
@@ -513,10 +516,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
- trait_ref: TraitRef::new(
- eq_trait_id,
- tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
- ),
+ trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
constness: BoundConstness::NotConst,
polarity: ImplPolarity::Positive,
}))))
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
index 68122b4ce..1971cab64 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -47,7 +47,7 @@ declare_clippy_lint! {
/// value: usize,
/// }
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub DISALLOWED_MACROS,
style,
"use of a disallowed macro"
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 4721a7b37..11e1bcdf1 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
let is_copy = is_copy(cx, arg_ty);
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let (lint, msg) = match fn_name {
- sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY),
+ sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => (DROP_REF, DROP_REF_SUMMARY),
sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
diff --git a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
index 08bf80a42..c3a020433 100644
--- a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
@@ -45,7 +45,7 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
span_after_ident,
"remove the brackets",
";",
- Applicability::MachineApplicable);
+ Applicability::Unspecified);
},
);
}
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 1d09adec1..dfb438933 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -131,7 +131,7 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool {
_ => return false,
}
- matches!(map.find(map.get_parent_node(id)), Some(Node::Param(_)))
+ matches!(map.find_parent(id), Some(Node::Param(_)))
}
impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
@@ -156,8 +156,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
let map = &self.cx.tcx.hir();
if is_argument(*map, cmt.hir_id) {
// Skip closure arguments
- let parent_id = map.get_parent_node(cmt.hir_id);
- if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) {
+ let parent_id = map.parent_id(cmt.hir_id);
+ if let Some(Node::Expr(..)) = map.find_parent(parent_id) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
index 9a1058470..2ef547526 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
if_chain! {
if let hir::ItemKind::Impl(impl_) = &item.kind;
if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
- if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.def_id);
+ if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id);
then {
lint_impl_body(cx, item.span, impl_.items);
}
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 0ed301964..f95b628e6 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -324,7 +324,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
let maybe_neg_sugg = |expr, hir_id| {
let sugg = Sugg::hir(cx, expr, "..");
if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
- format!("-{sugg}")
+ format!("-{}", sugg.maybe_par())
} else {
sugg.to_string()
}
diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
new file mode 100644
index 000000000..91c8c340c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
@@ -0,0 +1,106 @@
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
+use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for comparing a function pointer to null.
+ ///
+ /// ### Why is this bad?
+ /// Function pointers are assumed to not be null.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
+ ///
+ /// if (fn_ptr as *const ()).is_null() { ... }
+ /// ```
+ /// Use instead:
+ /// ```rust,ignore
+ /// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */
+ ///
+ /// if fn_ptr.is_none() { ... }
+ /// ```
+ #[clippy::version = "1.67.0"]
+ pub FN_NULL_CHECK,
+ correctness,
+ "`fn()` type assumed to be nullable"
+}
+declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]);
+
+fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
+ span_lint_and_help(
+ cx,
+ FN_NULL_CHECK,
+ expr.span,
+ "function pointer assumed to be nullable, even though it isn't",
+ None,
+ "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value",
+ );
+}
+
+fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
+ && let TyKind::Ptr(_) = cast_ty.kind
+ {
+ cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn()
+ } else {
+ false
+ }
+}
+
+impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ match expr.kind {
+ // Catching:
+ // (fn_ptr as *<const/mut> <ty>).is_null()
+ ExprKind::MethodCall(method_name, receiver, _, _)
+ if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) =>
+ {
+ lint_expr(cx, expr);
+ },
+
+ ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
+ let to_check: &Expr<'_>;
+ if is_fn_ptr_cast(cx, left) {
+ to_check = right;
+ } else if is_fn_ptr_cast(cx, right) {
+ to_check = left;
+ } else {
+ return;
+ }
+
+ match to_check.kind {
+ // Catching:
+ // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
+ ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => {
+ lint_expr(cx, expr);
+ },
+
+ // Catching:
+ // (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
+ ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => {
+ lint_expr(cx, expr);
+ },
+
+ // Catching:
+ // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
+ _ if matches!(
+ constant(cx, cx.typeck_results(), to_check),
+ Some((Constant::RawPtr(0), _))
+ ) =>
+ {
+ lint_expr(cx, expr);
+ },
+
+ _ => {},
+ }
+ },
+ _ => {},
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 658fe2680..04e6949e1 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -2,7 +2,8 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::FormatParamKind::{Implicit, Named, NamedInline, Numbered, Starred};
use clippy_utils::macros::{
- is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, FormatParamUsage,
+ is_assert_macro, is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam,
+ FormatParamUsage,
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
@@ -122,7 +123,7 @@ declare_clippy_lint! {
///
/// If a format string contains a numbered argument that cannot be inlined
/// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub UNINLINED_FORMAT_ARGS,
pedantic,
"using non-inlined variables in `format!` calls"
@@ -290,8 +291,9 @@ fn check_uninlined_args(
if args.format_string.span.from_expansion() {
return;
}
- if call_site.edition() < Edition2021 && is_panic(cx, def_id) {
- // panic! before 2021 edition considers a single string argument as non-format
+ if call_site.edition() < Edition2021 && (is_panic(cx, def_id) || is_assert_macro(cx, def_id)) {
+ // panic!, assert!, and debug_assert! before 2021 edition considers a single string argument as
+ // non-format
return;
}
@@ -380,7 +382,7 @@ fn check_format_in_format_args(
call_site,
&format!("`format!` in `{name}!` args"),
|diag| {
- diag.help(&format!(
+ diag.help(format!(
"combine the `format!(..)` arguments with the outer `{name}!(..)` call"
));
diag.help("or consider changing `format!` to `format_args!`");
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 0634b2798..bd66ace45 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -10,7 +10,7 @@ use rustc_hir::{
TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::{hir::nested_filter::OnlyBodies, ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{kw, sym};
use rustc_span::{Span, Symbol};
@@ -76,8 +76,9 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
&& let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
// `impl Into<target_ty> for self_ty`
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
- && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
+ && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(ty::EarlyBinder::subst_identity)
&& cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
+ && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _))
{
span_lint_and_then(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 91e6ffe64..9dbce3f88 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -63,23 +63,40 @@ declare_clippy_lint! {
/// arguments but are not marked `unsafe`.
///
/// ### Why is this bad?
- /// The function should probably be marked `unsafe`, since
- /// for an arbitrary raw pointer, there is no way of telling for sure if it is
- /// valid.
+ /// The function should almost definitely be marked `unsafe`, since for an
+ /// arbitrary raw pointer, there is no way of telling for sure if it is valid.
+ ///
+ /// In general, this lint should **never be disabled** unless it is definitely a
+ /// false positive (please submit an issue if so) since it breaks Rust's
+ /// soundness guarantees, directly exposing API users to potentially dangerous
+ /// program behavior. This is also true for internal APIs, as it is easy to leak
+ /// unsoundness.
+ ///
+ /// ### Context
+ /// In Rust, an `unsafe {...}` block is used to indicate that the code in that
+ /// section has been verified in some way that the compiler can not. For a
+ /// function that accepts a raw pointer then accesses the pointer's data, this is
+ /// generally impossible as the incoming pointer could point anywhere, valid or
+ /// not. So, the signature should be marked `unsafe fn`: this indicates that the
+ /// function's caller must provide some verification that the arguments it sends
+ /// are valid (and then call the function within an `unsafe` block).
///
/// ### Known problems
/// * It does not check functions recursively so if the pointer is passed to a
/// private non-`unsafe` function which does the dereferencing, the lint won't
- /// trigger.
+ /// trigger (false negative).
/// * It only checks for arguments whose type are raw pointers, not raw pointers
/// got from an argument in some other way (`fn foo(bar: &[*const u8])` or
- /// `some_argument.get_raw_ptr()`).
+ /// `some_argument.get_raw_ptr()`) (false negative).
///
/// ### Example
/// ```rust,ignore
/// pub fn foo(x: *const u8) {
/// println!("{}", unsafe { *x });
/// }
+ ///
+ /// // this call "looks" safe but will segfault or worse!
+ /// // foo(invalid_ptr);
/// ```
///
/// Use instead:
@@ -87,6 +104,12 @@ declare_clippy_lint! {
/// pub unsafe fn foo(x: *const u8) {
/// println!("{}", unsafe { *x });
/// }
+ ///
+ /// // this would cause a compiler error for calling without `unsafe`
+ /// // foo(invalid_ptr);
+ ///
+ /// // sound call if the caller knows the pointer is valid
+ /// unsafe { foo(valid_ptr); }
/// ```
#[clippy::version = "pre 1.29.0"]
pub NOT_UNSAFE_PTR_ARG_DEREF,
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 61934a914..989f83cf8 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Clause, EarlyBinder, Opaque, PredicateKind};
+use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
@@ -62,11 +62,11 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
return;
}
let ret_ty = return_ty(cx, hir_id);
- if let Opaque(id, subst) = *ret_ty.kind() {
- let preds = cx.tcx.explicit_item_bounds(id);
+ if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
+ let preds = cx.tcx.explicit_item_bounds(def_id);
let mut is_future = false;
for &(p, _span) in preds {
- let p = EarlyBinder(p).subst(cx.tcx, subst);
+ let p = EarlyBinder(p).subst(cx.tcx, substs);
if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
is_future = true;
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index bf1351829..6e1934393 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -31,7 +31,7 @@ declare_clippy_lint! {
///
/// u = u.saturating_add(1);
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub IMPLICIT_SATURATING_ADD,
style,
"Perform saturating addition instead of implicitly checking max bound of data type"
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index cf35b1f17..bdeddf44d 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -251,7 +251,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
let map = cx.tcx.hir();
// Checking for slice indexing
- let parent_id = map.get_parent_node(expr.hir_id);
+ let parent_id = map.parent_id(expr.hir_id);
if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind;
if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr);
@@ -259,7 +259,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
if index_value < max_suggested_slice;
// Make sure that this slice index is read only
- let maybe_addrof_id = map.get_parent_node(parent_id);
+ let maybe_addrof_id = map.parent_id(parent_id);
if let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id);
if let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind;
then {
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 4cd7dff4c..eebfb753a 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -1,13 +1,13 @@
//! lint on indexing and slicing operations
use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::higher;
use rustc_ast::ast::RangeLimits;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
/// ### What it does
@@ -82,15 +82,29 @@ declare_clippy_lint! {
"indexing/slicing usage"
}
-declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
+impl_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
+
+#[derive(Copy, Clone)]
+pub struct IndexingSlicing {
+ suppress_restriction_lint_in_const: bool,
+}
+
+impl IndexingSlicing {
+ pub fn new(suppress_restriction_lint_in_const: bool) -> Self {
+ Self {
+ suppress_restriction_lint_in_const,
+ }
+ }
+}
impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+ if self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id) {
return;
}
if let ExprKind::Index(array, index) = &expr.kind {
+ let note = "the suggestion might not be applicable in constant blocks";
let ty = cx.typeck_results().expr_ty(array).peel_refs();
if let Some(range) = higher::Range::hir(index) {
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
@@ -141,7 +155,13 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
(None, None) => return, // [..] is ok.
};
- span_lint_and_help(cx, INDEXING_SLICING, expr.span, "slicing may panic", None, help_msg);
+ span_lint_and_then(cx, INDEXING_SLICING, expr.span, "slicing may panic", |diag| {
+ diag.help(help_msg);
+
+ if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+ diag.note(note);
+ }
+ });
} else {
// Catchall non-range index, i.e., [n] or [n << m]
if let ty::Array(..) = ty.kind() {
@@ -156,14 +176,13 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
}
}
- span_lint_and_help(
- cx,
- INDEXING_SLICING,
- expr.span,
- "indexing may panic",
- None,
- "consider using `.get(n)` or `.get_mut(n)` instead",
- );
+ span_lint_and_then(cx, INDEXING_SLICING, expr.span, "indexing may panic", |diag| {
+ diag.help("consider using `.get(n)` or `.get_mut(n)` instead");
+
+ if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+ diag.note(note);
+ }
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index c5abcc462..e9b2e31a7 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -52,21 +52,19 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
// List of spans to lint. (lint_span, first_span)
let mut lint_spans = Vec::new();
- for (_, impl_ids) in cx
+ let inherent_impls = cx
.tcx
- .crate_inherent_impls(())
- .inherent_impls
- .iter()
- .filter(|(&id, impls)| {
- impls.len() > 1
- // Check for `#[allow]` on the type definition
- && !is_lint_allowed(
- cx,
- MULTIPLE_INHERENT_IMPL,
- cx.tcx.hir().local_def_id_to_hir_id(id),
- )
- })
- {
+ .with_stable_hashing_context(|hcx| cx.tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true));
+
+ for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| {
+ impls.len() > 1
+ // Check for `#[allow]` on the type definition
+ && !is_lint_allowed(
+ cx,
+ MULTIPLE_INHERENT_IMPL,
+ cx.tcx.hir().local_def_id_to_hir_id(id),
+ )
+ }) {
for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
match type_map.entry(cx.tcx.type_of(impl_id)) {
Entry::Vacant(e) => {
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index dd1b23e7d..9f6e89405 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -61,7 +61,7 @@ declare_clippy_lint! {
/// [`Instant::now()`]: std::time::Instant::now;
#[clippy::version = "1.65.0"]
pub UNCHECKED_DURATION_SUBTRACTION,
- suspicious,
+ pedantic,
"finds unchecked subtraction of a 'Duration' from an 'Instant'"
}
diff --git a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
index e0a607f9a..6a4861747 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs
@@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked {
if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
match &arg.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => {
- if let LitKind::ByteStr(bytes) = &lit
+ if let LitKind::ByteStr(bytes, _) = &lit
&& std::str::from_utf8(bytes).is_err()
{
lint(cx, expr.span);
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 76c83ab47..db637dfc0 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -34,12 +34,12 @@ declare_clippy_lint! {
}
pub struct LargeConstArrays {
- maximum_allowed_size: u64,
+ maximum_allowed_size: u128,
}
impl LargeConstArrays {
#[must_use]
- pub fn new(maximum_allowed_size: u64) -> Self {
+ pub fn new(maximum_allowed_size: u128) -> Self {
Self { maximum_allowed_size }
}
}
@@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
- if self.maximum_allowed_size < element_count * element_size;
+ if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size);
then {
let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index b18456ee5..b8d4abdbb 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
);
diag.span_label(
def.variants[variants_size[1].ind].span,
- &if variants_size[1].fields_size.is_empty() {
+ if variants_size[1].fields_size.is_empty() {
"the second-largest variant carries no data at all".to_owned()
} else {
format!(
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index 84dd61a1e..424c0d9e7 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -60,7 +60,7 @@ impl LateLintPass<'_> for LargeIncludeFile {
then {
let len = match &lit.node {
// include_bytes
- LitKind::ByteStr(bstr) => bstr.len(),
+ LitKind::ByteStr(bstr, _) => bstr.len(),
// include_str
LitKind::Str(sym, _) => sym.as_str().len(),
_ => return,
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index 5857d81ab..89ae83d48 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -24,12 +24,12 @@ declare_clippy_lint! {
}
pub struct LargeStackArrays {
- maximum_allowed_size: u64,
+ maximum_allowed_size: u128,
}
impl LargeStackArrays {
#[must_use]
- pub fn new(maximum_allowed_size: u64) -> Self {
+ pub fn new(maximum_allowed_size: u128) -> Self {
Self { maximum_allowed_size }
}
}
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& !cx.tcx.hir().parent_iter(expr.hir_id)
.any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. })))
- && self.maximum_allowed_size < element_count * element_size {
+ && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) {
span_lint_and_help(
cx,
LARGE_STACK_ARRAYS,
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 4c133c06a..3c70c9cf1 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefIdSet;
use rustc_hir::{
def_id::DefId, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, ImplItem, ImplItemKind, ImplicitSelfKind, Item,
- ItemKind, Mutability, Node, TraitItemRef, TyKind,
+ ItemKind, Mutability, Node, TraitItemRef, TyKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@@ -16,6 +16,7 @@ use rustc_span::{
source_map::{Span, Spanned, Symbol},
symbol::sym,
};
+use std::borrow::Cow;
declare_clippy_lint! {
/// ### What it does
@@ -218,7 +219,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
let is_empty = sym!(is_empty);
let is_empty_method_found = current_and_super_traits
- .iter()
+ .items()
.flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty))
.any(|i| {
i.kind == ty::AssocKind::Fn
@@ -360,7 +361,7 @@ fn check_for_is_empty<'tcx>(
db.span_note(span, "`is_empty` defined here");
}
if let Some(self_kind) = self_kind {
- db.note(&output.expected_sig(self_kind));
+ db.note(output.expected_sig(self_kind));
}
});
}
@@ -428,16 +429,23 @@ fn check_len(
fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
let mut applicability = Applicability::MachineApplicable;
+
+ let lit1 = peel_ref_operators(cx, lit1);
+ let mut lit_str = snippet_with_applicability(cx, lit1.span, "_", &mut applicability);
+
+ // Wrap the expression in parentheses if it's a deref expression. Otherwise operator precedence will
+ // cause the code to dereference boolean(won't compile).
+ if let ExprKind::Unary(UnOp::Deref, _) = lit1.kind {
+ lit_str = Cow::from(format!("({lit_str})"));
+ }
+
span_lint_and_sugg(
cx,
COMPARISON_TO_EMPTY,
span,
"comparison to empty slice",
&format!("using `{op}is_empty` is clearer and more explicit"),
- format!(
- "{op}{}.is_empty()",
- snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
- ),
+ format!("{op}{lit_str}.is_empty()"),
applicability,
);
}
@@ -493,7 +501,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
.filter_by_name_unhygienic(is_empty)
.any(|item| is_is_empty(cx, item))
}),
- ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
+ ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id),
ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
ty::Array(..) | ty::Slice(..) | ty::Str => true,
_ => false,
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 7b17d8a15..e93f27bee 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -66,7 +66,7 @@ mod declared_lints;
mod renamed_lints;
// begin lints modules, do not remove this comment, it’s used in `update_lints`
-mod almost_complete_letter_range;
+mod almost_complete_range;
mod approx_const;
mod as_conversions;
mod asm_syntax;
@@ -125,6 +125,7 @@ mod explicit_write;
mod fallible_impl_from;
mod float_literal;
mod floating_point_arithmetic;
+mod fn_null_check;
mod format;
mod format_args;
mod format_impl;
@@ -234,6 +235,7 @@ mod partialeq_ne_impl;
mod partialeq_to_none;
mod pass_by_ref_or_value;
mod pattern_type_mismatch;
+mod permissions_set_readonly_false;
mod precedence;
mod ptr;
mod ptr_offset_with_cast;
@@ -256,12 +258,14 @@ mod return_self_not_must_use;
mod returns;
mod same_name_method;
mod self_named_constructors;
+mod semicolon_block;
mod semicolon_if_nothing_returned;
mod serde_api;
mod shadow;
mod single_char_lifetime_names;
mod single_component_path_imports;
mod size_of_in_element_count;
+mod size_of_ref;
mod slow_vector_initialization;
mod std_instead_of_core;
mod strings;
@@ -333,7 +337,7 @@ pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
Ok(Some(path)) => path,
Ok(None) => return Conf::default(),
Err(error) => {
- sess.struct_err(&format!("error finding Clippy's configuration file: {error}"))
+ sess.struct_err(format!("error finding Clippy's configuration file: {error}"))
.emit();
return Conf::default();
},
@@ -507,9 +511,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
}
let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
+ let arithmetic_side_effects_allowed_binary = conf.arithmetic_side_effects_allowed_binary.clone();
+ let arithmetic_side_effects_allowed_unary = conf.arithmetic_side_effects_allowed_unary.clone();
store.register_late_pass(move |_| {
Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(
- arithmetic_side_effects_allowed.clone(),
+ arithmetic_side_effects_allowed
+ .iter()
+ .flat_map(|el| [[el.clone(), "*".to_string()], ["*".to_string(), el.clone()]])
+ .chain(arithmetic_side_effects_allowed_binary.clone())
+ .collect(),
+ arithmetic_side_effects_allowed
+ .iter()
+ .chain(arithmetic_side_effects_allowed_unary.iter())
+ .cloned()
+ .collect(),
))
});
store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
@@ -538,7 +553,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
- store.register_late_pass(|_| Box::new(misc::MiscLints));
+ store.register_late_pass(|_| Box::<misc::LintPass>::default());
store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
store.register_late_pass(|_| Box::new(mut_mut::MutMut));
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
@@ -561,6 +576,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
let allow_expect_in_tests = conf.allow_expect_in_tests;
let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
+ let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const;
store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
store.register_late_pass(move |_| {
Box::new(methods::Methods::new(
@@ -623,7 +639,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented));
store.register_late_pass(|_| Box::new(strings::StringLitAsBytes));
store.register_late_pass(|_| Box::new(derive::Derive));
- store.register_late_pass(|_| Box::new(derivable_impls::DerivableImpls));
+ store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(msrv())));
store.register_late_pass(|_| Box::new(drop_forget_ref::DropForgetRef));
store.register_late_pass(|_| Box::new(empty_enum::EmptyEnum));
store.register_late_pass(|_| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons));
@@ -682,7 +698,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl));
store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
store.register_late_pass(|_| Box::new(unwrap::Unwrap));
- store.register_late_pass(|_| Box::new(indexing_slicing::IndexingSlicing));
+ store.register_late_pass(move |_| {
+ Box::new(indexing_slicing::IndexingSlicing::new(
+ suppress_restriction_lint_in_const,
+ ))
+ });
store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst));
store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
@@ -748,7 +768,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
store.register_late_pass(|_| Box::new(exit::Exit));
store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome));
- let array_size_threshold = conf.array_size_threshold;
+ let array_size_threshold = u128::from(conf.array_size_threshold);
store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
@@ -859,7 +879,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
- store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv())));
+ store.register_early_pass(move || Box::new(almost_complete_range::AlmostCompleteRange::new(msrv())));
store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
@@ -884,6 +904,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
+ store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
+ store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
+ store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
+ store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
// add lints here, do not remove this comment, it's used in `new_lint`
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
index 14f223481..1953ee8a7 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -77,7 +77,7 @@ pub(super) fn check<'tcx>(
applicability,
);
- diag.note(&format!(
+ diag.note(format!(
"`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
));
},
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 27ba27202..3bca93d80 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
@@ -81,7 +81,7 @@ pub(super) fn check<'tcx>(
let skip = if starts_at_zero {
String::new()
- } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start) {
+ } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, start, cx) {
return;
} else {
format!(".skip({})", snippet(cx, start.span, ".."))
@@ -109,7 +109,7 @@ pub(super) fn check<'tcx>(
if is_len_call(end, indexed) || is_end_eq_array_len(cx, end, limits, indexed_ty) {
String::new()
- } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr) {
+ } else if visitor.indexed_mut.contains(&indexed) && contains_name(indexed, take_expr, cx) {
return;
} else {
match limits {
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index 07edee46f..540656a2c 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -63,7 +63,7 @@ pub(super) fn check<'tcx>(
if let Node::Pat(pat) = node;
if let PatKind::Binding(bind_ann, ..) = pat.kind;
if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut));
- let parent_node = cx.tcx.hir().get_parent_node(hir_id);
+ let parent_node = cx.tcx.hir().parent_id(hir_id);
if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node);
if let Some(init) = parent_let_expr.init;
then {
diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
index f4b47808d..744fd61bd 100644
--- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs
@@ -1,6 +1,7 @@
use super::SINGLE_ELEMENT_LOOP;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, snippet_with_applicability};
+use clippy_utils::visitors::contains_break_or_continue;
use if_chain::if_chain;
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::Mutability;
@@ -67,6 +68,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let ExprKind::Block(block, _) = body.kind;
if !block.stmts.is_empty();
+ if !contains_break_or_continue(body);
then {
let mut applicability = Applicability::MachineApplicable;
let pat_snip = snippet_with_applicability(cx, pat.span, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index b6f4cf7bb..28ee24309 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -25,7 +25,6 @@ pub(super) struct IncrementVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>, // context reference
states: HirIdMap<IncrementVisitorVarState>, // incremented variables
depth: u32, // depth of conditional expressions
- done: bool,
}
impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
@@ -34,7 +33,6 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
cx,
states: HirIdMap::default(),
depth: 0,
- done: false,
}
}
@@ -51,10 +49,6 @@ impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
- if self.done {
- return;
- }
-
// If node is a variable
if let Some(def_id) = path_to_local(expr) {
if let Some(parent) = get_parent_expr(self.cx, expr) {
@@ -95,7 +89,9 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
walk_expr(self, expr);
self.depth -= 1;
} else if let ExprKind::Continue(_) = expr.kind {
- self.done = true;
+ // If we see a `continue` block, then we increment depth so that the IncrementVisitor
+ // state will be set to DontWarn if we see the variable being modified anywhere afterwards.
+ self.depth += 1;
} else {
walk_expr(self, expr);
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
index a63422d2a..d1a1f773f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'
} else {
return;
};
- let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
+ let mutable_static_in_cond = var_visitor.def_ids.items().any(|(_, v)| *v);
let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
has_break_or_return: false,
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index b8ed9b9ec..4277455a3 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -2,7 +2,7 @@ use crate::rustc_lint::LintContext;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{peel_blocks_with_stmt, span_extract_comment, sugg};
+use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
@@ -47,6 +47,10 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
if cx.tcx.item_name(macro_call.def_id) == sym::panic;
if !cx.tcx.sess.source_map().is_multiline(cond.span);
if let Some(format_args) = FormatArgsExpn::find_nested(cx, then, macro_call.expn);
+ // Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just
+ // shuffles the condition around.
+ // Should this have a config value?
+ if !is_else_clause(cx.tcx, expr);
then {
let mut applicability = Applicability::MachineApplicable;
let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index 075ecbe7e..63212beaa 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
let help = format!("make the function `async` and {ret_sugg}");
diag.span_suggestion(
header_span,
- &help,
+ help,
format!("async {}{ret_snip}", &header_snip[..ret_pos]),
Applicability::MachineApplicable
);
@@ -152,7 +152,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
let input_lifetimes: Vec<LifetimeName> = inputs
.iter()
.filter_map(|ty| {
- if let TyKind::Rptr(lt, _) = ty.kind {
+ if let TyKind::Ref(lt, _) = ty.kind {
Some(lt.res)
} else {
None
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index 5ab049d8d..d9ef7dffa 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -1,11 +1,12 @@
use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::{diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, source::snippet};
+use clippy_utils::{diagnostics::span_lint_and_sugg, higher, in_constant, macros::root_macro_call, source::snippet};
+use rustc_ast::ast::RangeLimits;
use rustc_ast::LitKind::{Byte, Char};
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd};
+use rustc_hir::{BorrowKind, Expr, ExprKind, PatKind, RangeEnd};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{def_id::DefId, sym};
+use rustc_span::{def_id::DefId, sym, Span};
declare_clippy_lint! {
/// ### What it does
@@ -23,6 +24,10 @@ declare_clippy_lint! {
/// assert!(matches!(b'X', b'A'..=b'Z'));
/// assert!(matches!('2', '0'..='9'));
/// assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+ ///
+ /// ('0'..='9').contains(&'0');
+ /// ('a'..='z').contains(&'a');
+ /// ('A'..='Z').contains(&'A');
/// }
/// ```
/// Use instead:
@@ -32,6 +37,10 @@ declare_clippy_lint! {
/// assert!(b'X'.is_ascii_uppercase());
/// assert!('2'.is_ascii_digit());
/// assert!('x'.is_ascii_alphabetic());
+ ///
+ /// '0'.is_ascii_digit();
+ /// 'a'.is_ascii_lowercase();
+ /// 'A'.is_ascii_uppercase();
/// }
/// ```
#[clippy::version = "1.66.0"]
@@ -75,40 +84,21 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
return;
}
- let Some(macro_call) = root_macro_call(expr.span) else { return };
-
- if is_matches_macro(cx, macro_call.def_id) {
+ if let Some(macro_call) = root_macro_call(expr.span)
+ && is_matches_macro(cx, macro_call.def_id) {
if let ExprKind::Match(recv, [arm, ..], _) = expr.kind {
let range = check_pat(&arm.pat.kind);
-
- if let Some(sugg) = match range {
- CharRange::UpperChar => Some("is_ascii_uppercase"),
- CharRange::LowerChar => Some("is_ascii_lowercase"),
- CharRange::FullChar => Some("is_ascii_alphabetic"),
- CharRange::Digit => Some("is_ascii_digit"),
- CharRange::Otherwise => None,
- } {
- let default_snip = "..";
- // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
- // macro span, so we check applicability manually by comparing `recv` is not default.
- let recv = snippet(cx, recv.span, default_snip);
-
- let applicability = if recv == default_snip {
- Applicability::HasPlaceholders
- } else {
- Applicability::MachineApplicable
- };
-
- span_lint_and_sugg(
- cx,
- MANUAL_IS_ASCII_CHECK,
- macro_call.span,
- "manual check for common ascii range",
- "try",
- format!("{recv}.{sugg}()"),
- applicability,
- );
- }
+ check_is_ascii(cx, macro_call.span, recv, &range);
+ }
+ } else if let ExprKind::MethodCall(path, receiver, [arg], ..) = expr.kind
+ && path.ident.name == sym!(contains)
+ && let Some(higher::Range { start: Some(start), end: Some(end), limits: RangeLimits::Closed })
+ = higher::Range::hir(receiver) {
+ let range = check_range(start, end);
+ if let ExprKind::AddrOf(BorrowKind::Ref, _, e) = arg.kind {
+ check_is_ascii(cx, expr.span, e, &range);
+ } else {
+ check_is_ascii(cx, expr.span, arg, &range);
}
}
}
@@ -116,6 +106,37 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
extract_msrv_attr!(LateContext);
}
+fn check_is_ascii(cx: &LateContext<'_>, span: Span, recv: &Expr<'_>, range: &CharRange) {
+ if let Some(sugg) = match range {
+ CharRange::UpperChar => Some("is_ascii_uppercase"),
+ CharRange::LowerChar => Some("is_ascii_lowercase"),
+ CharRange::FullChar => Some("is_ascii_alphabetic"),
+ CharRange::Digit => Some("is_ascii_digit"),
+ CharRange::Otherwise => None,
+ } {
+ let default_snip = "..";
+ // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
+ // macro span, so we check applicability manually by comparing `recv` is not default.
+ let recv = snippet(cx, recv.span, default_snip);
+
+ let applicability = if recv == default_snip {
+ Applicability::HasPlaceholders
+ } else {
+ Applicability::MachineApplicable
+ };
+
+ span_lint_and_sugg(
+ cx,
+ MANUAL_IS_ASCII_CHECK,
+ span,
+ "manual check for common ascii range",
+ "try",
+ format!("{recv}.{sugg}()"),
+ applicability,
+ );
+ }
+}
+
fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
match pat_kind {
PatKind::Or(pats) => {
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 874d36ca9..9c6f8b43c 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -151,7 +151,12 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
} else {
format!("{{ {sn_else} }}")
};
- let sugg = format!("let {sn_pat} = {sn_expr} else {else_bl};");
+ let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
+ format!("({sn_pat})")
+ } else {
+ sn_pat.into_owned()
+ };
+ let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
diag.span_suggestion(span, "consider writing", sugg, app);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
index 8d447c371..38f41d077 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
&& let Some(hir_id) = path_to_local(expr3)
&& let Some(Node::Pat(_)) = cx.tcx.hir().find(hir_id) {
// Apply only to params or locals with annotated types
- match cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+ match cx.tcx.hir().find_parent(hir_id) {
Some(Node::Param(..)) => (),
Some(Node::Local(local)) => {
let Some(ty) = local.ty else { return };
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index c1e6c8248..72cdb9c17 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -70,7 +70,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain {
&& seg.args.is_none()
&& let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind
&& let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
- && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) {
+ && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id)
+ {
check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv);
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index de166b976..c795c1d9a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
let test_span = expr.span.until(then.span);
span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| {
- diag.span_note(test_span, &format!("the {kind_word} was tested here"));
+ diag.span_note(test_span, format!("the {kind_word} was tested here"));
multispan_sugg(
diag,
&format!("try using the `strip_{kind_word}` method"),
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
index d521a529e..f6bf0e7aa 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
@@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::contains_unsafe_block;
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
-use rustc_hir::LangItem::OptionSome;
+use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind};
use rustc_lint::LateContext;
use rustc_span::{sym, SyntaxContext};
@@ -25,15 +25,13 @@ fn get_cond_expr<'tcx>(
if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr);
if let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind;
if let PatKind::Binding(_,target, ..) = pat.kind;
- if let (then_visitor, else_visitor)
- = (is_some_expr(cx, target, ctxt, then_expr),
- is_some_expr(cx, target, ctxt, else_expr));
- if then_visitor != else_visitor; // check that one expr resolves to `Some(x)`, the other to `None`
+ if is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr)
+ || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr); // check that one expr resolves to `Some(x)`, the other to `None`
then {
return Some(SomeExpr {
expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()),
needs_unsafe_block: contains_unsafe_block(cx, expr),
- needs_negated: !then_visitor // if the `then_expr` resolves to `None`, need to negate the cond
+ needs_negated: is_none_expr(cx, then_expr) // if the `then_expr` resolves to `None`, need to negate the cond
})
}
};
@@ -74,6 +72,13 @@ fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr:
false
}
+fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) {
+ return is_res_lang_ctor(cx, path_res(cx, inner_expr), OptionNone);
+ };
+ false
+}
+
// given the closure: `|<pattern>| <expr>`
// returns `|&<pattern>| <expr>`
fn add_ampersand_if_copy(body_str: String, has_copy_trait: bool) -> String {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 168c1e4d2..158e6caa4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -282,7 +282,7 @@ impl<'a> NormalizedPat<'a> {
// TODO: Handle negative integers. They're currently treated as a wild match.
ExprKind::Lit(lit) => match lit.node {
LitKind::Str(sym, _) => Self::LitStr(sym),
- LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes),
+ LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
LitKind::Byte(val) => Self::LitInt(val.into()),
LitKind::Char(val) => Self::LitInt(val.into()),
LitKind::Int(val, _) => Self::LitInt(val),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index 1bf8d4e96..065a5c726 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -31,19 +31,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
};
// Do we need to add ';' to suggestion ?
- match match_body.kind {
- ExprKind::Block(block, _) => {
- // macro + expr_ty(body) == ()
- if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() {
- snippet_body.push(';');
- }
- },
- _ => {
- // expr_ty(body) == ()
- if cx.typeck_results().expr_ty(match_body).is_unit() {
- snippet_body.push(';');
- }
- },
+ if let ExprKind::Block(block, _) = match_body.kind {
+ // macro + expr_ty(body) == ()
+ if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() {
+ snippet_body.push(';');
+ }
}
let mut applicability = Applicability::MaybeIncorrect;
@@ -148,8 +140,8 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<AssignmentExpr> {
let map = &cx.tcx.hir();
- if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id)) {
- return match map.find(map.get_parent_node(parent_arm_expr.hir_id)) {
+ if let Some(Node::Expr(parent_arm_expr)) = map.find_parent(ex.hir_id) {
+ return match map.find_parent(parent_arm_expr.hir_id) {
Some(Node::Local(parent_let_expr)) => Some(AssignmentExpr::Local {
span: parent_let_expr.span,
pat_span: parent_let_expr.pat.span(),
@@ -191,8 +183,7 @@ fn sugg_with_curlies<'a>(
// If the parent is already an arm, and the body is another match statement,
// we need curly braces around suggestion
- let parent_node_id = cx.tcx.hir().get_parent_node(match_expr.hir_id);
- if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) {
+ if let Node::Arm(arm) = &cx.tcx.hir().get_parent(match_expr.hir_id) {
if let ExprKind::Match(..) = arm.body.kind {
cbrace_end = format!("\n{indent}}}");
// Fix body indent due to the match
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
index 7f8d12483..59de8c038 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
@@ -30,7 +30,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
let mut has_non_wild = false;
for arm in arms {
match peel_hir_pat_refs(arm.pat).0.kind {
- PatKind::Wild => wildcard_span = Some(arm.pat.span),
+ PatKind::Wild if arm.guard.is_none() => wildcard_span = Some(arm.pat.span),
PatKind::Binding(_, _, ident, None) => {
wildcard_span = Some(arm.pat.span);
wildcard_ident = Some(ident);
diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index d226c0bba..0b3bf2274 100644
--- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -1,7 +1,10 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{indent_of, reindent_multiline};
use clippy_utils::ty::is_type_lang_item;
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
+use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::LateContext;
use rustc_span::{source_map::Spanned, Span};
@@ -15,6 +18,15 @@ pub(super) fn check<'tcx>(
recv: &'tcx Expr<'_>,
arg: &'tcx Expr<'_>,
) {
+ if let ExprKind::MethodCall(path_segment, ..) = recv.kind {
+ if matches!(
+ path_segment.ident.name.as_str(),
+ "to_lowercase" | "to_uppercase" | "to_ascii_lowercase" | "to_ascii_uppercase"
+ ) {
+ return;
+ }
+ }
+
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
@@ -28,13 +40,37 @@ pub(super) fn check<'tcx>(
let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs();
if recv_ty.is_str() || is_type_lang_item(cx, recv_ty, LangItem::String);
then {
- span_lint_and_help(
+ span_lint_and_then(
cx,
CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
- call_span,
+ recv.span.to(call_span),
"case-sensitive file extension comparison",
- None,
- "consider using a case-insensitive comparison instead",
+ |diag| {
+ diag.help("consider using a case-insensitive comparison instead");
+ if let Some(mut recv_source) = snippet_opt(cx, recv.span) {
+
+ if !cx.typeck_results().expr_ty(recv).is_ref() {
+ recv_source = format!("&{recv_source}");
+ }
+
+ let suggestion_source = reindent_multiline(
+ format!(
+ "std::path::Path::new({})
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case(\"{}\"))",
+ recv_source, ext_str.strip_prefix('.').unwrap()).into(),
+ true,
+ Some(indent_of(cx, call_span).unwrap_or(0) + 4)
+ );
+
+ diag.span_suggestion(
+ recv.span.to(call_span),
+ "use std::path::Path",
+ suggestion_source,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 7c7938dd2..3795c0ec2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -6,7 +6,7 @@ use clippy_utils::ty::is_copy;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath};
use rustc_lint::LateContext;
-use rustc_middle::ty::{self, adjustment::Adjust};
+use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths};
use rustc_span::symbol::{sym, Symbol};
use super::CLONE_DOUBLE_REF;
@@ -47,10 +47,10 @@ pub(super) fn check(
cx,
CLONE_DOUBLE_REF,
expr.span,
- &format!(
+ &with_forced_trimmed_paths!(format!(
"using `clone` on a double-reference; \
this will copy the reference of type `{ty}` instead of cloning the inner type"
- ),
+ )),
|diag| {
if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
let mut ty = innermost;
@@ -61,11 +61,11 @@ pub(super) fn check(
}
let refs = "&".repeat(n + 1);
let derefs = "*".repeat(n);
- let explicit = format!("<{refs}{ty}>::clone({snip})");
+ let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})"));
diag.span_suggestion(
expr.span,
"try dereferencing it",
- format!("{refs}({derefs}{}).clone()", snip.deref()),
+ with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())),
Applicability::MaybeIncorrect,
);
diag.span_suggestion(
@@ -129,7 +129,9 @@ pub(super) fn check(
cx,
CLONE_ON_COPY,
expr.span,
- &format!("using `clone` on type `{ty}` which implements the `Copy` trait"),
+ &with_forced_trimmed_paths!(format!(
+ "using `clone` on type `{ty}` which implements the `Copy` trait"
+ )),
help,
sugg,
app,
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index f888c58a7..fc80f2eea 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -30,12 +30,12 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
match closure_expr.kind {
hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
if_chain! {
- if ident.name == method_name;
- if let hir::ExprKind::Path(path) = &receiver.kind;
- if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
- then {
- return arg_id == *local
- }
+ if ident.name == method_name;
+ if let hir::ExprKind::Path(path) = &receiver.kind;
+ if let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id);
+ then {
+ return arg_id == *local
+ }
}
false
},
@@ -92,92 +92,92 @@ pub(super) fn check(
}
if_chain! {
- if is_trait_method(cx, map_recv, sym::Iterator);
-
- // filter(|x| ...is_some())...
- if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
- let filter_body = cx.tcx.hir().body(filter_body_id);
- if let [filter_param] = filter_body.params;
- // optional ref pattern: `filter(|&x| ..)`
- let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
- (ref_pat, true)
- } else {
- (filter_param.pat, false)
+ if is_trait_method(cx, map_recv, sym::Iterator);
+
+ // filter(|x| ...is_some())...
+ if let ExprKind::Closure(&Closure { body: filter_body_id, .. }) = filter_arg.kind;
+ let filter_body = cx.tcx.hir().body(filter_body_id);
+ if let [filter_param] = filter_body.params;
+ // optional ref pattern: `filter(|&x| ..)`
+ let (filter_pat, is_filter_param_ref) = if let PatKind::Ref(ref_pat, _) = filter_param.pat.kind {
+ (ref_pat, true)
+ } else {
+ (filter_param.pat, false)
+ };
+ // closure ends with is_some() or is_ok()
+ if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
+ if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
+ if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
+ if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
+ Some(false)
+ } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
+ Some(true)
+ } else {
+ None
+ };
+ if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
+
+ // ...map(|x| ...unwrap())
+ if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
+ let map_body = cx.tcx.hir().body(map_body_id);
+ if let [map_param] = map_body.params;
+ if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
+ // closure ends with expect() or unwrap()
+ if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
+ if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
+
+ // .filter(..).map(|y| f(y).copied().unwrap())
+ // ~~~~
+ let map_arg_peeled = match map_arg.kind {
+ ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
+ original_arg
+ },
+ _ => map_arg,
+ };
+
+ // .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
+ let simple_equal = path_to_local_id(filter_arg, filter_param_id)
+ && path_to_local_id(map_arg_peeled, map_param_id);
+
+ let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
+ // in `filter(|x| ..)`, replace `*x` with `x`
+ let a_path = if_chain! {
+ if !is_filter_param_ref;
+ if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
+ then { expr_path } else { a }
};
- // closure ends with is_some() or is_ok()
- if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind;
- if let ExprKind::MethodCall(path, filter_arg, [], _) = filter_body.value.kind;
- if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).peel_refs().ty_adt_def();
- if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did()) {
- Some(false)
- } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did()) {
- Some(true)
+ // let the filter closure arg and the map closure arg be equal
+ path_to_local_id(a_path, filter_param_id)
+ && path_to_local_id(b, map_param_id)
+ && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
+ };
+
+ if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
+ then {
+ let span = filter_span.with_hi(expr.span.hi());
+ let (filter_name, lint) = if is_find {
+ ("find", MANUAL_FIND_MAP)
} else {
- None
- };
- if path.ident.name.as_str() == if is_result { "is_ok" } else { "is_some" };
-
- // ...map(|x| ...unwrap())
- if let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind;
- let map_body = cx.tcx.hir().body(map_body_id);
- if let [map_param] = map_body.params;
- if let PatKind::Binding(_, map_param_id, map_param_ident, None) = map_param.pat.kind;
- // closure ends with expect() or unwrap()
- if let ExprKind::MethodCall(seg, map_arg, ..) = map_body.value.kind;
- if matches!(seg.ident.name, sym::expect | sym::unwrap | sym::unwrap_or);
-
- // .filter(..).map(|y| f(y).copied().unwrap())
- // ~~~~
- let map_arg_peeled = match map_arg.kind {
- ExprKind::MethodCall(method, original_arg, [], _) if acceptable_methods(method) => {
- original_arg
- },
- _ => map_arg,
+ ("filter", MANUAL_FILTER_MAP)
};
+ let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
+ let (to_opt, deref) = if is_result {
+ (".ok()", String::new())
+ } else {
+ let derefs = cx.typeck_results()
+ .expr_adjustments(map_arg)
+ .iter()
+ .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
+ .count();
- // .filter(|x| x.is_some()).map(|y| y[.acceptable_method()].unwrap())
- let simple_equal = path_to_local_id(filter_arg, filter_param_id)
- && path_to_local_id(map_arg_peeled, map_param_id);
-
- let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
- // in `filter(|x| ..)`, replace `*x` with `x`
- let a_path = if_chain! {
- if !is_filter_param_ref;
- if let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind;
- then { expr_path } else { a }
- };
- // let the filter closure arg and the map closure arg be equal
- path_to_local_id(a_path, filter_param_id)
- && path_to_local_id(b, map_param_id)
- && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
+ ("", "*".repeat(derefs))
};
-
- if simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg_peeled);
- then {
- let span = filter_span.with_hi(expr.span.hi());
- let (filter_name, lint) = if is_find {
- ("find", MANUAL_FIND_MAP)
- } else {
- ("filter", MANUAL_FILTER_MAP)
- };
- let msg = format!("`{filter_name}(..).map(..)` can be simplified as `{filter_name}_map(..)`");
- let (to_opt, deref) = if is_result {
- (".ok()", String::new())
- } else {
- let derefs = cx.typeck_results()
- .expr_adjustments(map_arg)
- .iter()
- .filter(|adj| matches!(adj.kind, Adjust::Deref(_)))
- .count();
-
- ("", "*".repeat(derefs))
- };
- let sugg = format!(
- "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
- snippet(cx, map_arg.span, ".."),
- );
- span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
- }
+ let sugg = format!(
+ "{filter_name}_map(|{map_param_ident}| {deref}{}{to_opt})",
+ snippet(cx, map_arg.span, ".."),
+ );
+ span_lint_and_sugg(cx, lint, span, &msg, "try", sugg, Applicability::MachineApplicable);
+ }
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index 429cdc191..06ecbce4e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::peel_mid_ty_refs;
+use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
use clippy_utils::{is_diag_item_method, is_diag_trait_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
@@ -19,6 +19,8 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
let (input_type, ref_count) = peel_mid_ty_refs(input_type);
if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()));
if return_type == input_type;
+ if let Some(clone_trait) = cx.tcx.lang_items().clone_trait();
+ if implements_trait(cx, return_type, clone_trait, &[]);
then {
let mut app = Applicability::MachineApplicable;
let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
index d8c821bc9..424482859 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
@@ -36,7 +36,7 @@ pub fn check(
expr.span,
&format!("calling `to_string` on `{arg_ty}`"),
|diag| {
- diag.help(&format!(
+ diag.help(format!(
"`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`"
));
let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 2244ebfb1..c87f5daab 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::is_local_used;
-use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
+use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty;
use rustc_span::sym;
@@ -30,9 +30,9 @@ pub(super) fn check<'tcx>(
if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
- let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
- (key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
- (PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
+ let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
+ (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
+ (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
_ => return,
};
@@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
if let [local_ident] = path.segments;
- if local_ident.ident.as_str() == binded_ident.as_str();
+ if local_ident.ident.as_str() == bound_ident.as_str();
then {
span_lint_and_sugg(
@@ -60,13 +60,23 @@ pub(super) fn check<'tcx>(
applicability,
);
} else {
+ let ref_annotation = if annotation.0 == ByRef::Yes {
+ "ref "
+ } else {
+ ""
+ };
+ let mut_annotation = if annotation.1 == Mutability::Mut {
+ "mut "
+ } else {
+ ""
+ };
span_lint_and_sugg(
cx,
ITER_KV_MAP,
expr.span,
&format!("iterating on a map's {replacement_kind}s"),
"try",
- format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
+ format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
index beb772100..279175e20 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs
@@ -29,7 +29,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
application = Applicability::Unspecified;
diag.span_help(
pat.span,
- &format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")),
+ format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index d2913680c..77be61b47 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -3059,7 +3059,7 @@ declare_clippy_lint! {
/// let map: HashMap<u32, u32> = HashMap::new();
/// let values = map.values().collect::<Vec<_>>();
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub ITER_KV_MAP,
complexity,
"iterating on map using `iter` when `keys` or `values` would do"
@@ -3672,7 +3672,10 @@ impl Methods {
no_effect_replace::check(cx, expr, arg1, arg2);
// Check for repeated `str::replace` calls to perform `collapsible_str_replace` lint
- if name == "replace" && let Some(("replace", ..)) = method_call(recv) {
+ if self.msrv.meets(msrvs::PATTERN_TRAIT_CHAR_ARRAY)
+ && name == "replace"
+ && let Some(("replace", ..)) = method_call(recv)
+ {
collapsible_str_replace::check(cx, expr, arg1, arg2);
}
},
@@ -3983,7 +3986,7 @@ impl OutType {
(Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true,
(Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true,
(Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true,
- (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)),
+ (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)),
_ => false,
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index b088e642e..f4d3ef3b7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -151,7 +151,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty:
&& let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
&& let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
- cx.tcx.mk_projection(into_iter_item_proj.item_def_id, into_iter_item_proj.substs)
+ cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs)
)
{
iter_item_ty == into_iter_item_ty
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 910ee1485..4c6328481 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, ")));
}
- diag.multipart_suggestion(&format!("use `{suggest}` instead"), suggestion, applicability);
+ diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability);
});
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index 7e3bed1e4..660b7049c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_trait_def_id, match_def_path, paths};
+use clippy_utils::{get_trait_def_id, is_expr_used_or_unified, match_def_path, paths};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
@@ -19,6 +19,10 @@ pub(super) fn check<'tcx>(
// Get receiver type
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+ if is_expr_used_or_unified(cx.tcx, expr) {
+ return;
+ }
+
if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) &&
implements_trait(cx, ty, seek_trait_id, &[]) &&
let ExprKind::Call(func, args1) = arg.kind &&
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 3c01ce1fe..d00708e82 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -167,7 +167,7 @@ fn check_manual_split_once_indirect(
};
diag.span_suggestion_verbose(
local.span,
- &format!("try `{r}split_once`"),
+ format!("try `{r}split_once`"),
format!("let ({lhs}, {rhs}) = {self_snip}.{r}split_once({pat_snip}){unwrap};"),
app,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
index 15c1c618c..fe88fa41f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
@@ -5,7 +5,7 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, print::with_forced_trimmed_paths};
use rustc_span::sym;
use super::SUSPICIOUS_TO_OWNED;
@@ -24,7 +24,9 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
cx,
SUSPICIOUS_TO_OWNED,
expr.span,
- &format!("this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"),
+ &with_forced_trimmed_paths!(format!(
+ "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
+ )),
"consider using, depending on intent",
format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
app,
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index 0e73459ad..47e2e7441 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -62,7 +62,7 @@ pub(super) fn check<'tcx>(
span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
diag.span_suggestion(
span,
- &format!("use `{simplify_using}(..)` instead"),
+ format!("use `{simplify_using}(..)` instead"),
format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 516dee20f..9f4beb92b 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -9,12 +9,14 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_expr, in_constant, is_integer_literal, iter_input_pats, last_path_segment, SpanlessEq};
+use clippy_utils::{
+ get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+};
declare_clippy_lint! {
/// ### What it does
@@ -120,14 +122,28 @@ declare_clippy_lint! {
"using `0 as *{const, mut} T`"
}
-declare_lint_pass!(MiscLints => [
+pub struct LintPass {
+ std_or_core: &'static str,
+}
+impl Default for LintPass {
+ fn default() -> Self {
+ Self { std_or_core: "std" }
+ }
+}
+impl_lint_pass!(LintPass => [
TOPLEVEL_REF_ARG,
USED_UNDERSCORE_BINDING,
SHORT_CIRCUIT_STATEMENT,
ZERO_PTR,
]);
-impl<'tcx> LateLintPass<'tcx> for MiscLints {
+impl<'tcx> LateLintPass<'tcx> for LintPass {
+ fn check_crate(&mut self, cx: &LateContext<'_>) {
+ if is_no_std_crate(cx) {
+ self.std_or_core = "core";
+ }
+ }
+
fn check_fn(
&mut self,
cx: &LateContext<'tcx>,
@@ -231,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Cast(e, ty) = expr.kind {
- check_cast(cx, expr.span, e, ty);
+ self.check_cast(cx, expr.span, e, ty);
return;
}
if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) {
@@ -310,26 +326,28 @@ fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool {
}
}
-fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
- if_chain! {
- if let TyKind::Ptr(ref mut_ty) = ty.kind;
- if is_integer_literal(e, 0);
- if !in_constant(cx, e.hir_id);
- then {
- let (msg, sugg_fn) = match mut_ty.mutbl {
- Mutability::Mut => ("`0 as *mut _` detected", "std::ptr::null_mut"),
- Mutability::Not => ("`0 as *const _` detected", "std::ptr::null"),
- };
+impl LintPass {
+ fn check_cast(&self, cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
+ if_chain! {
+ if let TyKind::Ptr(ref mut_ty) = ty.kind;
+ if is_integer_literal(e, 0);
+ if !in_constant(cx, e.hir_id);
+ then {
+ let (msg, sugg_fn) = match mut_ty.mutbl {
+ Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"),
+ Mutability::Not => ("`0 as *const _` detected", "ptr::null"),
+ };
- let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
- (format!("{sugg_fn}()"), Applicability::MachineApplicable)
- } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
- (format!("{sugg_fn}::<{mut_ty_snip}>()"), Applicability::MachineApplicable)
- } else {
- // `MaybeIncorrect` as type inference may not work with the suggested code
- (format!("{sugg_fn}()"), Applicability::MaybeIncorrect)
- };
- span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
+ let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
+ (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MachineApplicable)
+ } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
+ (format!("{}::{sugg_fn}::<{mut_ty_snip}>()", self.std_or_core), Applicability::MachineApplicable)
+ } else {
+ // `MaybeIncorrect` as type inference may not work with the suggested code
+ (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MaybeIncorrect)
+ };
+ span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
+ }
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 758ce47cf..5a4595481 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -155,7 +155,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
let container_id = assoc_item.container_id(cx.tcx);
let trait_def_id = match assoc_item.container {
TraitContainer => Some(container_id),
- ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.def_id),
+ ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
};
if let Some(trait_def_id) = trait_def_id {
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
index 68af8a672..3371b4cce 100644
--- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -80,19 +80,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
}
}
- for assoc in provided.values() {
- let source_map = cx.tcx.sess.source_map();
- let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id));
+ cx.tcx.with_stable_hashing_context(|hcx| {
+ for assoc in provided.values_sorted(&hcx, true) {
+ let source_map = cx.tcx.sess.source_map();
+ let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id));
- span_lint_and_help(
- cx,
- MISSING_TRAIT_METHODS,
- source_map.guess_head_span(item.span),
- &format!("missing trait method provided by default: `{}`", assoc.name),
- Some(definition_span),
- "implement the method",
- );
- }
+ span_lint_and_help(
+ cx,
+ MISSING_TRAIT_METHODS,
+ source_map.guess_head_span(item.span),
+ &format!("missing trait method provided by default: `{}`", assoc.name),
+ Some(definition_span),
+ "implement the method",
+ );
+ }
+ })
}
}
}
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 321fa4b7f..f0be7771b 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
@@ -186,7 +186,7 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
let map = &vis.cx.tcx.hir();
let mut cur_id = vis.write_expr.hir_id;
loop {
- let parent_id = map.get_parent_node(cur_id);
+ let parent_id = map.parent_id(cur_id);
if parent_id == cur_id {
break;
}
diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs
index bc90e131b..64d8333a0 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
return;
}
- if let hir::TyKind::Rptr(
+ if let hir::TyKind::Ref(
_,
hir::MutTy {
ty: pty,
@@ -94,7 +94,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
},
) = ty.kind
{
- if let hir::TyKind::Rptr(
+ if let hir::TyKind::Ref(
_,
hir::MutTy {
mutbl: hir::Mutability::Mut,
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index 09cb53331..dc866ab63 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -1,6 +1,6 @@
//! Checks for uses of mutex where an atomic value could be used
//!
-//! This lint is **warn** by default
+//! This lint is **allow** by default
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_type_diagnostic_item;
@@ -20,6 +20,10 @@ declare_clippy_lint! {
/// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and
/// faster.
///
+ /// On the other hand, `Mutex`es are, in general, easier to
+ /// verify correctness. An atomic does not behave the same as
+ /// an equivalent mutex. See [this issue](https://github.com/rust-lang/rust-clippy/issues/4295)'s commentary for more details.
+ ///
/// ### Known problems
/// This lint cannot detect if the mutex is actually used
/// for waiting before a critical section.
@@ -39,8 +43,8 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "pre 1.29.0"]
pub MUTEX_ATOMIC,
- nursery,
- "using a mutex where an atomic value could be used instead"
+ restriction,
+ "using a mutex where an atomic value could be used instead."
}
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
index f2ffac85b..5457eeec4 100644
--- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
@@ -124,7 +124,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
}
},
- TyKind::Rptr(lifetime, mut_ty) => {
+ TyKind::Ref(lifetime, mut_ty) => {
if_chain! {
if let TyKind::Path(None, path) = &mut_ty.ty.kind;
if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind;
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index 67debe7e0..5a9387b34 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -284,7 +284,7 @@ fn check<'tcx>(
diag.span_suggestion(
assign.lhs_span,
- &format!("declare `{binding_name}` here"),
+ format!("declare `{binding_name}` here"),
let_snippet,
Applicability::MachineApplicable,
);
@@ -304,7 +304,7 @@ fn check<'tcx>(
diag.span_suggestion_verbose(
usage.stmt.span.shrink_to_lo(),
- &format!("declare `{binding_name}` here"),
+ format!("declare `{binding_name}` here"),
format!("{let_snippet} = "),
applicability,
);
@@ -335,7 +335,7 @@ fn check<'tcx>(
diag.span_suggestion_verbose(
usage.stmt.span.shrink_to_lo(),
- &format!("declare `{binding_name}` here"),
+ format!("declare `{binding_name}` here"),
format!("{let_snippet} = "),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 2f0b7ce16..8c9d4c5cf 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -24,7 +24,7 @@ use rustc_span::symbol::kw;
use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
-use rustc_trait_selection::traits::misc::can_type_implement_copy;
+use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
use std::borrow::Cow;
declare_clippy_lint! {
@@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
}
// Exclude non-inherent impls
- if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+ if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
if matches!(
item.kind,
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
@@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
let sugg = |diag: &mut Diagnostic| {
if let ty::Adt(def, ..) = ty.kind() {
if let Some(span) = cx.tcx.hir().span_if_local(def.did()) {
- if can_type_implement_copy(
+ if type_allowed_to_implement_copy(
cx.tcx,
cx.param_env,
ty,
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 2a3bd4ee6..07fd321d6 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -366,7 +366,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
let mut dereferenced_expr = expr;
let mut needs_check_adjustment = true;
loop {
- let parent_id = cx.tcx.hir().get_parent_node(cur_expr.hir_id);
+ let parent_id = cx.tcx.hir().parent_id(cur_expr.hir_id);
if parent_id == cur_expr.hir_id {
break;
}
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 714c0ff22..839c3a381 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
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
if send_trait == trait_id;
if hir_impl.polarity == ImplPolarity::Positive;
if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
- if let self_ty = ty_trait_ref.self_ty();
+ if let self_ty = ty_trait_ref.subst_identity().self_ty();
if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
then {
let mut non_send_fields = Vec::new();
diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
index ae0a41db9..7376ab0c8 100644
--- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs
+++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
@@ -125,7 +125,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
if is_string { "string" } else { "byte string" }
),
|diag| {
- diag.help(&format!(
+ diag.help(format!(
"octal escapes are not supported, `\\0` is always a null {}",
if is_string { "character" } else { "byte" }
));
@@ -139,7 +139,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
// suggestion 2: unambiguous null byte
diag.span_suggestion(
span,
- &format!(
+ format!(
"if the null {} is intended, disambiguate using",
if is_string { "character" } else { "byte" }
),
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 7722a476d..7b1d974f2 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -244,7 +244,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
})) => {
#[allow(trivial_casts)]
if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into())
- && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
+ && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(|t| t.subst_identity())
&& let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id
{
(
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index 20b82d81a..cff82b875 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -2,28 +2,29 @@ use super::ARITHMETIC_SIDE_EFFECTS;
use clippy_utils::{
consts::{constant, constant_simple},
diagnostics::span_lint,
- peel_hir_expr_refs,
+ peel_hir_expr_refs, peel_hir_expr_unary,
};
use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::impl_lint_pass;
use rustc_span::source_map::{Span, Spanned};
-const HARD_CODED_ALLOWED: &[&str] = &[
- "&str",
- "f32",
- "f64",
- "std::num::Saturating",
- "std::num::Wrapping",
- "std::string::String",
+const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
+ ["f32", "f32"],
+ ["f64", "f64"],
+ ["std::num::Saturating", "std::num::Saturating"],
+ ["std::num::Wrapping", "std::num::Wrapping"],
+ ["std::string::String", "&str"],
];
+const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
#[derive(Debug)]
pub struct ArithmeticSideEffects {
- allowed: FxHashSet<String>,
+ allowed_binary: FxHashMap<String, FxHashSet<String>>,
+ allowed_unary: FxHashSet<String>,
// Used to check whether expressions are constants, such as in enum discriminants and consts
const_span: Option<Span>,
expr_span: Option<Span>,
@@ -33,19 +34,55 @@ impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]);
impl ArithmeticSideEffects {
#[must_use]
- pub fn new(mut allowed: FxHashSet<String>) -> Self {
- allowed.extend(HARD_CODED_ALLOWED.iter().copied().map(String::from));
+ pub fn new(user_allowed_binary: Vec<[String; 2]>, user_allowed_unary: Vec<String>) -> Self {
+ let mut allowed_binary: FxHashMap<String, FxHashSet<String>> = <_>::default();
+ for [lhs, rhs] in user_allowed_binary.into_iter().chain(
+ HARD_CODED_ALLOWED_BINARY
+ .iter()
+ .copied()
+ .map(|[lhs, rhs]| [lhs.to_string(), rhs.to_string()]),
+ ) {
+ allowed_binary.entry(lhs).or_default().insert(rhs);
+ }
+ let allowed_unary = user_allowed_unary
+ .into_iter()
+ .chain(HARD_CODED_ALLOWED_UNARY.iter().copied().map(String::from))
+ .collect();
Self {
- allowed,
+ allowed_binary,
+ allowed_unary,
const_span: None,
expr_span: None,
}
}
- /// Checks if the given `expr` has any of the inner `allowed` elements.
- fn is_allowed_ty(&self, ty: Ty<'_>) -> bool {
- self.allowed
- .contains(ty.to_string().split('<').next().unwrap_or_default())
+ /// Checks if the lhs and the rhs types of a binary operation like "addition" or
+ /// "multiplication" are present in the inner set of allowed types.
+ fn has_allowed_binary(&self, lhs_ty: Ty<'_>, rhs_ty: Ty<'_>) -> bool {
+ let lhs_ty_string = lhs_ty.to_string();
+ let lhs_ty_string_elem = lhs_ty_string.split('<').next().unwrap_or_default();
+ let rhs_ty_string = rhs_ty.to_string();
+ let rhs_ty_string_elem = rhs_ty_string.split('<').next().unwrap_or_default();
+ if let Some(rhs_from_specific) = self.allowed_binary.get(lhs_ty_string_elem)
+ && {
+ let rhs_has_allowed_ty = rhs_from_specific.contains(rhs_ty_string_elem);
+ rhs_has_allowed_ty || rhs_from_specific.contains("*")
+ }
+ {
+ true
+ } else if let Some(rhs_from_glob) = self.allowed_binary.get("*") {
+ rhs_from_glob.contains(rhs_ty_string_elem)
+ } else {
+ false
+ }
+ }
+
+ /// Checks if the type of an unary operation like "negation" is present in the inner set of
+ /// allowed types.
+ fn has_allowed_unary(&self, ty: Ty<'_>) -> bool {
+ let ty_string = ty.to_string();
+ let ty_string_elem = ty_string.split('<').next().unwrap_or_default();
+ self.allowed_unary.contains(ty_string_elem)
}
// For example, 8i32 or &i64::MAX.
@@ -61,8 +98,11 @@ impl ArithmeticSideEffects {
}
/// If `expr` is not a literal integer like `1`, returns `None`.
+ ///
+ /// Returns the absolute value of the expression, if this is an integer literal.
fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
- if let hir::ExprKind::Lit(ref lit) = expr.kind && let ast::LitKind::Int(n, _) = lit.node {
+ let actual = peel_hir_expr_unary(expr).0;
+ if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
Some(n)
}
else {
@@ -86,19 +126,18 @@ impl ArithmeticSideEffects {
if !matches!(
op.node,
hir::BinOpKind::Add
- | hir::BinOpKind::Sub
- | hir::BinOpKind::Mul
| hir::BinOpKind::Div
+ | hir::BinOpKind::Mul
| hir::BinOpKind::Rem
| hir::BinOpKind::Shl
| hir::BinOpKind::Shr
+ | hir::BinOpKind::Sub
) {
return;
};
let lhs_ty = cx.typeck_results().expr_ty(lhs);
let rhs_ty = cx.typeck_results().expr_ty(rhs);
- let lhs_and_rhs_have_the_same_ty = lhs_ty == rhs_ty;
- if lhs_and_rhs_have_the_same_ty && self.is_allowed_ty(lhs_ty) && self.is_allowed_ty(rhs_ty) {
+ if self.has_allowed_binary(lhs_ty, rhs_ty) {
return;
}
let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
@@ -137,7 +176,7 @@ impl ArithmeticSideEffects {
return;
}
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
- if self.is_allowed_ty(ty) {
+ if self.has_allowed_unary(ty) {
return;
}
let actual_un_expr = peel_hir_expr_refs(un_expr).0;
diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
index b48d6c4e2..14a12da86 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -1,7 +1,7 @@
use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{clip, unsext};
+use clippy_utils::{clip, peel_hir_expr_refs, unsext};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
use rustc_lint::LateContext;
@@ -20,20 +20,76 @@ pub(crate) fn check<'tcx>(
if !is_allowed(cx, op, left, right) {
match op {
BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
- check_op(cx, left, 0, expr.span, right.span, needs_parenthesis(cx, expr, right));
- check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ left,
+ 0,
+ expr.span,
+ peel_hir_expr_refs(right).0.span,
+ needs_parenthesis(cx, expr, right),
+ );
+ check_op(
+ cx,
+ right,
+ 0,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
- check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ right,
+ 0,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
BinOpKind::Mul => {
- check_op(cx, left, 1, expr.span, right.span, needs_parenthesis(cx, expr, right));
- check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ left,
+ 1,
+ expr.span,
+ peel_hir_expr_refs(right).0.span,
+ needs_parenthesis(cx, expr, right),
+ );
+ check_op(
+ cx,
+ right,
+ 1,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
- BinOpKind::Div => check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded),
+ BinOpKind::Div => check_op(
+ cx,
+ right,
+ 1,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ ),
BinOpKind::BitAnd => {
- check_op(cx, left, -1, expr.span, right.span, needs_parenthesis(cx, expr, right));
- check_op(cx, right, -1, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ left,
+ -1,
+ expr.span,
+ peel_hir_expr_refs(right).0.span,
+ needs_parenthesis(cx, expr, right),
+ );
+ check_op(
+ cx,
+ right,
+ -1,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
_ => (),
diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
index ae805147f..015f6c14e 100644
--- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
@@ -50,7 +50,7 @@ fn lint_misrefactored_assign_op(
let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r));
diag.span_suggestion(
expr.span,
- &format!(
+ format!(
"did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with",
op.as_str()
),
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index b8a20d5eb..eba230da6 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -90,9 +90,6 @@ declare_clippy_lint! {
/// use rust_decimal::Decimal;
/// let _n = Decimal::MAX + Decimal::MAX;
/// ```
- ///
- /// ### Allowed types
- /// Custom allowed types can be specified through the "arithmetic-side-effects-allowed" filter.
#[clippy::version = "1.64.0"]
pub ARITHMETIC_SIDE_EFFECTS,
restriction,
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index f9fd36456..2d21aaa4f 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -184,16 +184,16 @@ impl<'tcx> PassByRefOrValue {
if is_copy(cx, ty)
&& let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes())
&& size <= self.ref_min_size
- && let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind
+ && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind
{
if let Some(typeck) = cx.maybe_typeck_results() {
// Don't lint if an unsafe pointer is created.
// TODO: Limit the check only to unsafe pointers to the argument (or part of the argument)
// which escape the current function.
- if typeck.node_types().iter().any(|(_, &ty)| ty.is_unsafe_ptr())
+ if typeck.node_types().items().any(|(_, &ty)| ty.is_unsafe_ptr())
|| typeck
.adjustments()
- .iter()
+ .items()
.flat_map(|(_, a)| a)
.any(|a| matches!(a.kind, Adjust::Pointer(PointerCast::UnsafeFnPointer)))
{
@@ -299,7 +299,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
}
// Exclude non-inherent impls
- if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+ if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
if matches!(
item.kind,
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
new file mode 100644
index 000000000..e7095ec19
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs
@@ -0,0 +1,52 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::paths;
+use clippy_utils::ty::match_type;
+use rustc_ast::ast::LitKind;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`.
+ ///
+ /// ### Why is this bad?
+ /// On Unix platforms this results in the file being world writable,
+ /// equivalent to `chmod a+w <file>`.
+ /// ### Example
+ /// ```rust
+ /// use std::fs::File;
+ /// let f = File::create("foo.txt").unwrap();
+ /// let metadata = f.metadata().unwrap();
+ /// let mut permissions = metadata.permissions();
+ /// permissions.set_readonly(false);
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub PERMISSIONS_SET_READONLY_FALSE,
+ suspicious,
+ "Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`"
+}
+declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALSE]);
+
+impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind
+ && match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS)
+ && path.ident.name == sym!(set_readonly)
+ && let ExprKind::Lit(lit) = &arg.kind
+ && LitKind::Bool(false) == lit.node
+ {
+ span_lint_and_then(
+ cx,
+ PERMISSIONS_SET_READONLY_FALSE,
+ expr.span,
+ "call to `set_readonly` with argument `false`",
+ |diag| {
+ diag.note("on Unix platforms this results in the file being world writable");
+ diag.help("you can set the desired permissions using `PermissionsExt`. For more information, see\n\
+ https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html");
+ }
+ );
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index e395ff54c..262953042 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -421,7 +421,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
if let ty::Ref(_, ty, mutability) = *ty.kind();
if let ty::Adt(adt, substs) = *ty.kind();
- if let TyKind::Rptr(lt, ref ty) = hir_ty.kind;
+ if let TyKind::Ref(lt, ref ty) = hir_ty.kind;
if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind;
// Check that the name as typed matches the actual name of the type.
@@ -503,14 +503,14 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&'tcx Body<'_>>) {
if let FnRetTy::Return(ty) = sig.decl.output
- && let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty)
+ && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty)
{
let out_region = cx.tcx.named_region(out.hir_id);
let args: Option<Vec<_>> = sig
.decl
.inputs
.iter()
- .filter_map(get_rptr_lm)
+ .filter_map(get_ref_lm)
.filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
.map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
.collect();
@@ -704,8 +704,8 @@ fn matches_preds<'tcx>(
})
}
-fn get_rptr_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
- if let TyKind::Rptr(lt, ref m) = ty.kind {
+fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
+ if let TyKind::Ref(lt, ref m) = ty.kind {
Some((lt, m.mutbl, ty.span))
} else {
None
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 0a1b9d173..fc655fe2d 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -103,7 +103,7 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
/// Checks for range expressions `x..y` where both `x` and `y`
- /// are constant and `x` is greater or equal to `y`.
+ /// are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop.
///
/// ### Why is this bad?
/// Empty ranges yield no values so iterating them is a no-op.
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index d612d249c..c2a8db7df 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -84,7 +84,11 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
if let ItemKind::Use(path, _) = item.kind {
- if path.res.iter().all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _))) {
+ if path
+ .res
+ .iter()
+ .all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _)))
+ {
return false;
}
} else if let ItemKind::Macro(..) = item.kind {
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 3aa2490bc..44bf824aa 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -59,14 +59,14 @@ impl RedundantStaticLifetimes {
}
},
// This is what we are looking for !
- TyKind::Rptr(ref optional_lifetime, ref borrow_type) => {
+ TyKind::Ref(ref optional_lifetime, ref borrow_type) => {
// Match the 'static lifetime
if let Some(lifetime) = *optional_lifetime {
match borrow_type.ty.kind {
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
if lifetime.ident.name == rustc_span::symbol::kw::StaticLifetime {
let snip = snippet(cx, borrow_type.ty.span, "<type>");
- let sugg = format!("&{snip}");
+ let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str());
span_lint_and_then(
cx,
REDUNDANT_STATIC_LIFETIMES,
diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
index f21b3ea6c..448a32b77 100644
--- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
@@ -39,7 +39,7 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]);
impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
if_chain! {
- if let TyKind::Rptr(_, ref mut_ty) = ty.kind;
+ if let TyKind::Ref(_, ref mut_ty) = ty.kind;
if mut_ty.mutbl == Mutability::Not;
if let TyKind::Path(ref qpath) = &mut_ty.ty.kind;
let last = last_path_segment(qpath);
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
GenericArg::Type(inner_ty) => Some(inner_ty),
_ => None,
});
- if let TyKind::Rptr(_, ref inner_mut_ty) = inner_ty.kind;
+ if let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind;
if inner_mut_ty.mutbl == Mutability::Not;
then {
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 8e214218f..9f487dedb 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -2,12 +2,14 @@
#[rustfmt::skip]
pub static RENAMED_LINTS: &[(&str, &str)] = &[
+ ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"),
("clippy::blacklisted_name", "clippy::disallowed_names"),
("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"),
("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"),
("clippy::box_vec", "clippy::box_collection"),
("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
+ ("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"),
("clippy::disallowed_method", "clippy::disallowed_methods"),
("clippy::disallowed_type", "clippy::disallowed_types"),
("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 81143d779..bbbd9e498 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -6,7 +6,7 @@ use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind};
+use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, LangItem, MatchSource, PatKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind;
@@ -207,19 +207,28 @@ fn check_final_expr<'tcx>(
match &peeled_drop_expr.kind {
// simple return is always "bad"
ExprKind::Ret(ref inner) => {
- if cx.tcx.hir().attrs(expr.hir_id).is_empty() {
- let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
- if !borrows {
- // check if expr return nothing
- let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
- extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
- } else {
- peeled_drop_expr.span
- };
-
- emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
- }
+ // if desugar of `do yeet`, don't lint
+ if let Some(inner_expr) = inner
+ && let ExprKind::Call(path_expr, _) = inner_expr.kind
+ && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
+ {
+ return;
+ }
+ if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
+ return;
}
+ let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
+ if borrows {
+ return;
+ }
+ // check if expr return nothing
+ let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
+ extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
+ } else {
+ peeled_drop_expr.span
+ };
+
+ emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
},
ExprKind::If(_, then, else_clause_opt) => {
check_block_return(cx, &then.kind, semi_spans.clone());
@@ -286,7 +295,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
{
ControlFlow::Break(())
} else {
- ControlFlow::Continue(Descend::from(!expr.span.from_expansion()))
+ ControlFlow::Continue(Descend::from(!e.span.from_expansion()))
}
})
.is_some()
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index caab5851b..17763128c 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|diag| {
diag.span_note(
trait_method_span,
- &format!("existing `{method_name}` defined here"),
+ format!("existing `{method_name}` defined here"),
);
},
);
@@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
// iterate on trait_spans?
diag.span_note(
trait_spans[0],
- &format!("existing `{method_name}` defined here"),
+ format!("existing `{method_name}` defined here"),
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
new file mode 100644
index 000000000..8f1d1490e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -0,0 +1,137 @@
+use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Suggests moving the semicolon after a block to the inside of the block, after its last
+ /// expression.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine
+ /// and this lint suggests inside the block.
+ /// Take a look at `semicolon_outside_block` for the other alternative.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x) };
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x); }
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub SEMICOLON_INSIDE_BLOCK,
+ restriction,
+ "add a semicolon inside the block"
+}
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Suggests moving the semicolon from a block's final expression outside of the block.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine
+ /// and this lint suggests outside the block.
+ /// Take a look at `semicolon_inside_block` for the other alternative.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x); }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x) };
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub SEMICOLON_OUTSIDE_BLOCK,
+ restriction,
+ "add a semicolon outside the block"
+}
+declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
+
+impl LateLintPass<'_> for SemicolonBlock {
+ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+ match stmt.kind {
+ StmtKind::Expr(Expr {
+ kind: ExprKind::Block(block, _),
+ ..
+ }) if !block.span.from_expansion() => {
+ let Block {
+ expr: None,
+ stmts: [.., stmt],
+ ..
+ } = block else { return };
+ let &Stmt {
+ kind: StmtKind::Semi(expr),
+ span,
+ ..
+ } = stmt else { return };
+ semicolon_outside_block(cx, block, expr, span);
+ },
+ StmtKind::Semi(Expr {
+ kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _),
+ ..
+ }) if !block.span.from_expansion() => semicolon_inside_block(cx, block, tail, stmt.span),
+ _ => (),
+ }
+ }
+}
+
+fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
+ let insert_span = tail.span.source_callsite().shrink_to_hi();
+ let remove_span = semi_span.with_lo(block.span.hi());
+
+ span_lint_and_then(
+ cx,
+ SEMICOLON_INSIDE_BLOCK,
+ semi_span,
+ "consider moving the `;` inside the block for consistent formatting",
+ |diag| {
+ multispan_sugg_with_applicability(
+ diag,
+ "put the `;` here",
+ Applicability::MachineApplicable,
+ [(remove_span, String::new()), (insert_span, ";".to_owned())],
+ );
+ },
+ );
+}
+
+fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) {
+ let insert_span = block.span.with_lo(block.span.hi());
+ // account for macro calls
+ let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span);
+ let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi());
+
+ span_lint_and_then(
+ cx,
+ SEMICOLON_OUTSIDE_BLOCK,
+ block.span,
+ "consider moving the `;` outside the block for consistent formatting",
+ |diag| {
+ multispan_sugg_with_applicability(
+ diag,
+ "put the `;` here",
+ Applicability::MachineApplicable,
+ [(remove_span, String::new()), (insert_span, ";".to_owned())],
+ );
+ },
+ );
+}
diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs
new file mode 100644
index 000000000..3fcdb4288
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs
@@ -0,0 +1,73 @@
+use clippy_utils::{diagnostics::span_lint_and_help, path_def_id, ty::peel_mid_ty_refs};
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Checks for calls to `std::mem::size_of_val()` where the argument is
+ /// a reference to a reference.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// Calling `size_of_val()` with a reference to a reference as the argument
+ /// yields the size of the reference-type, not the size of the value behind
+ /// the reference.
+ ///
+ /// ### Example
+ /// ```rust
+ /// struct Foo {
+ /// buffer: [u8],
+ /// }
+ ///
+ /// impl Foo {
+ /// fn size(&self) -> usize {
+ /// // Note that `&self` as an argument is a `&&Foo`: Because `self`
+ /// // is already a reference, `&self` is a double-reference.
+ /// // The return value of `size_of_val()` therefor is the
+ /// // size of the reference-type, not the size of `self`.
+ /// std::mem::size_of_val(&self)
+ /// }
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// struct Foo {
+ /// buffer: [u8],
+ /// }
+ ///
+ /// impl Foo {
+ /// fn size(&self) -> usize {
+ /// // Correct
+ /// std::mem::size_of_val(self)
+ /// }
+ /// }
+ /// ```
+ #[clippy::version = "1.67.0"]
+ pub SIZE_OF_REF,
+ suspicious,
+ "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended"
+}
+declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]);
+
+impl LateLintPass<'_> for SizeOfRef {
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
+ if let ExprKind::Call(path, [arg]) = expr.kind
+ && let Some(def_id) = path_def_id(cx, path)
+ && cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id)
+ && let arg_ty = cx.typeck_results().expr_ty(arg)
+ && peel_mid_ty_refs(arg_ty).1 > 1
+ {
+ span_lint_and_help(
+ cx,
+ SIZE_OF_REF,
+ expr.span,
+ "argument to `std::mem::size_of_val()` is a reference to a reference",
+ None,
+ "dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type",
+ );
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index f4705481d..bc18cad6d 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -1,12 +1,12 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{get_expr_use_or_unification_node, peel_blocks, SpanlessEq};
use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths};
-use clippy_utils::{peel_blocks, SpanlessEq};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
-use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
+use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
@@ -249,6 +249,7 @@ const MAX_LENGTH_BYTE_STRING_LIT: usize = 32;
declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]);
impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
+ #[expect(clippy::too_many_lines)]
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
use rustc_ast::LitKind;
@@ -316,18 +317,27 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
&& lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
&& !receiver.span.from_expansion()
{
- span_lint_and_sugg(
- cx,
- STRING_LIT_AS_BYTES,
- e.span,
- "calling `as_bytes()` on a string literal",
- "consider using a byte string literal instead",
- format!(
- "b{}",
- snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
- ),
- applicability,
- );
+ if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e)
+ && let Node::Expr(parent) = parent
+ && let ExprKind::Match(scrutinee, ..) = parent.kind
+ && scrutinee.hir_id == id
+ {
+ // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces
+ // `&[u8]`. This change would prevent matching with different sized slices.
+ } else {
+ span_lint_and_sugg(
+ cx,
+ STRING_LIT_AS_BYTES,
+ e.span,
+ "calling `as_bytes()` on a string literal",
+ "consider using a byte string literal instead",
+ format!(
+ "b{}",
+ snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
+ ),
+ applicability,
+ );
+ }
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index c374529d1..17e9cc5f6 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -132,7 +132,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
applicability,
);
if !is_xor_based {
- diag.note(&format!("or maybe you should use `{sugg}::mem::replace`?"));
+ diag.note(format!("or maybe you should use `{sugg}::mem::replace`?"));
}
},
);
@@ -214,7 +214,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
Applicability::MaybeIncorrect,
);
diag.note(
- &format!("or maybe you should use `{sugg}::mem::replace`?")
+ format!("or maybe you should use `{sugg}::mem::replace`?")
);
}
});
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 83e651aba..691d759d7 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -3,6 +3,7 @@ mod transmute_float_to_int;
mod transmute_int_to_bool;
mod transmute_int_to_char;
mod transmute_int_to_float;
+mod transmute_null_to_fn;
mod transmute_num_to_bytes;
mod transmute_ptr_to_ptr;
mod transmute_ptr_to_ref;
@@ -409,6 +410,34 @@ declare_clippy_lint! {
"transmutes from a null pointer to a reference, which is undefined behavior"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for null function pointer creation through transmute.
+ ///
+ /// ### Why is this bad?
+ /// Creating a null function pointer is undefined behavior.
+ ///
+ /// More info: https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization
+ ///
+ /// ### Known problems
+ /// Not all cases can be detected at the moment of this writing.
+ /// For example, variables which hold a null pointer and are then fed to a `transmute`
+ /// call, aren't detectable yet.
+ ///
+ /// ### Example
+ /// ```rust
+ /// let null_fn: fn() = unsafe { std::mem::transmute( std::ptr::null::<()>() ) };
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let null_fn: Option<fn()> = None;
+ /// ```
+ #[clippy::version = "1.67.0"]
+ pub TRANSMUTE_NULL_TO_FN,
+ correctness,
+ "transmute results in a null function pointer, which is undefined behavior"
+}
+
pub struct Transmute {
msrv: Msrv,
}
@@ -428,6 +457,7 @@ impl_lint_pass!(Transmute => [
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
TRANSMUTE_UNDEFINED_REPR,
TRANSMUTING_NULL,
+ TRANSMUTE_NULL_TO_FN,
]);
impl Transmute {
#[must_use]
@@ -461,6 +491,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
let linted = wrong_transmute::check(cx, e, from_ty, to_ty)
| crosspointer_transmute::check(cx, e, from_ty, to_ty)
| transmuting_null::check(cx, e, arg, to_ty)
+ | transmute_null_to_fn::check(cx, e, arg, to_ty)
| transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv)
| transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
new file mode 100644
index 000000000..e75d7f6bf
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -0,0 +1,64 @@
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
+use rustc_span::symbol::sym;
+
+use super::TRANSMUTE_NULL_TO_FN;
+
+fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
+ span_lint_and_then(
+ cx,
+ TRANSMUTE_NULL_TO_FN,
+ expr.span,
+ "transmuting a known null pointer into a function pointer",
+ |diag| {
+ diag.span_label(expr.span, "this transmute results in undefined behavior");
+ diag.help(
+ "try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value"
+ );
+ },
+ );
+}
+
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, to_ty: Ty<'tcx>) -> bool {
+ if !to_ty.is_fn() {
+ return false;
+ }
+
+ match arg.kind {
+ // Catching:
+ // transmute over constants that resolve to `null`.
+ ExprKind::Path(ref _qpath)
+ if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) =>
+ {
+ lint_expr(cx, expr);
+ true
+ },
+
+ // Catching:
+ // `std::mem::transmute(0 as *const i32)`
+ ExprKind::Cast(inner_expr, _cast_ty) if is_integer_literal(inner_expr, 0) => {
+ lint_expr(cx, expr);
+ true
+ },
+
+ // Catching:
+ // `std::mem::transmute(std::ptr::null::<i32>())`
+ ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => {
+ lint_expr(cx, expr);
+ true
+ },
+
+ _ => {
+ // FIXME:
+ // Also catch transmutations of variables which are known nulls.
+ // To do this, MIR const propagation seems to be the better tool.
+ // Whenever MIR const prop routines are more developed, this will
+ // become available. As of this writing (25/03/19) it is not yet.
+ false
+ },
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index 3dde4eee6..54ac04df1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -71,7 +71,7 @@ pub(super) fn check<'tcx>(
/// Gets the type `Bar` in `…::transmute<Foo, &Bar>`.
fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> {
if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)?
- && let TyKind::Rptr(_, ty) = &ty.kind
+ && let TyKind::Ref(_, ty) = &ty.kind
{
Some(ty.ty)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 34642f4b1..af0242348 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -77,7 +77,7 @@ pub(super) fn check<'tcx>(
&format!("transmute from `{from_ty_orig}` which has an undefined layout"),
|diag| {
if from_ty_orig.peel_refs() != from_ty.peel_refs() {
- diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
+ diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
}
},
);
@@ -91,7 +91,7 @@ pub(super) fn check<'tcx>(
&format!("transmute to `{to_ty_orig}` which has an undefined layout"),
|diag| {
if to_ty_orig.peel_refs() != to_ty.peel_refs() {
- diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
+ diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
}
},
);
@@ -119,16 +119,16 @@ pub(super) fn check<'tcx>(
),
|diag| {
if let Some(same_adt_did) = same_adt_did {
- diag.note(&format!(
+ diag.note(format!(
"two instances of the same generic type (`{}`) may have different layouts",
cx.tcx.item_name(same_adt_did)
));
} else {
if from_ty_orig.peel_refs() != from_ty {
- diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
+ diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
}
if to_ty_orig.peel_refs() != to_ty {
- diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
+ diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
}
}
},
@@ -146,7 +146,7 @@ pub(super) fn check<'tcx>(
&format!("transmute from `{from_ty_orig}` which has an undefined layout"),
|diag| {
if from_ty_orig.peel_refs() != from_ty {
- diag.note(&format!("the contained type `{from_ty}` has an undefined layout"));
+ diag.note(format!("the contained type `{from_ty}` has an undefined layout"));
}
},
);
@@ -163,7 +163,7 @@ pub(super) fn check<'tcx>(
&format!("transmute into `{to_ty_orig}` which has an undefined layout"),
|diag| {
if to_ty_orig.peel_refs() != to_ty {
- diag.note(&format!("the contained type `{to_ty}` has an undefined layout"));
+ diag.note(format!("the contained type `{to_ty}` has an undefined layout"));
}
},
);
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 6b444922a..b79d4e915 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(
&format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
|diag| {
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
- let sugg = arg.as_ty(&to_ty.to_string()).to_string();
+ let sugg = arg.as_ty(to_ty.to_string()).to_string();
diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
}
},
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index 19ce5ae72..1e407fc41 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -18,8 +18,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
// Catching transmute over constants that resolve to `null`.
let mut const_eval_context = constant_context(cx, cx.typeck_results());
if let ExprKind::Path(ref _qpath) = arg.kind &&
- let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg) &&
- x == 0
+ let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg)
{
span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
return true;
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index f919bbd5a..871c3fadb 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -61,7 +61,7 @@ pub(super) fn check<'tcx>(
"transmute from an integer to a pointer",
|diag| {
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
- diag.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()), Applicability::Unspecified);
+ diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified);
}
},
);
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 20978e81d..229478b7c 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -127,7 +127,7 @@ declare_clippy_lint! {
/// `Vec` or a `VecDeque` (formerly called `RingBuf`).
///
/// ### Why is this bad?
- /// Gankro says:
+ /// Gankra says:
///
/// > The TL;DR of `LinkedList` is that it's built on a massive amount of
/// pointers and indirection.
@@ -539,7 +539,7 @@ impl Types {
QPath::LangItem(..) => {},
}
},
- TyKind::Rptr(lt, ref mut_ty) => {
+ TyKind::Ref(lt, ref mut_ty) => {
context.is_nested_call = true;
if !borrowed_box::check(cx, hir_ty, lt, mut_ty) {
self.check_ty(cx, mut_ty.ty, context);
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index fae5385ff..f9b9a66b5 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
&format!("usage of `{outer_sym}<{generic_snippet}>`"),
|diag| {
diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability);
- diag.note(&format!(
+ diag.note(format!(
"`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap"
));
},
@@ -78,7 +78,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
format!("{outer_sym}<{generic_snippet}>"),
applicability,
);
- diag.note(&format!(
+ diag.note(format!(
"`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
));
},
@@ -91,10 +91,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
hir_ty.span,
&format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
|diag| {
- diag.note(&format!(
+ diag.note(format!(
"`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
));
- diag.help(&format!(
+ diag.help(format!(
"consider using just `{outer_sym}<{generic_snippet}>` or `{inner_sym}<{generic_snippet}>`"
));
},
diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
index 5ca4023aa..0aa50c99c 100644
--- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
@@ -44,7 +44,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
let (add_score, sub_nest) = match ty.kind {
// _, &x and *x have only small overhead; don't mess with nesting level
- TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0),
+ TyKind::Infer | TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0),
// the "normal" components of a type: named types, arrays/tuples
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1),
diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs
index 0fa75f8f0..7f43b7841 100644
--- a/src/tools/clippy/clippy_lints/src/types/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/types/utils.rs
@@ -13,7 +13,7 @@ pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>)
GenericArg::Type(ty) => Some(ty),
_ => None,
});
- if let TyKind::Rptr(..) = ty.kind;
+ if let TyKind::Ref(..) = ty.kind;
then {
return Some(ty.span);
}
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
index f6d3fb00f..dd120599c 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
return;
}
let map = &cx.tcx.hir();
- let opt_parent_node = map.find(map.get_parent_node(expr.hir_id));
+ let opt_parent_node = map.find_parent(expr.hir_id);
if_chain! {
if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node;
if is_questionmark_desugar_marked_call(parent_expr);
@@ -129,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
if arg_snippets_without_empty_blocks.is_empty() {
db.multipart_suggestion(
- &format!("use {singular}unit literal{plural} instead"),
+ format!("use {singular}unit literal{plural} instead"),
args_to_recover
.iter()
.map(|arg| (arg.span, "()".to_string()))
@@ -142,7 +142,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
let it_or_them = if plural { "them" } else { "it" };
db.span_suggestion(
expr.span,
- &format!(
+ format!(
"{or}move the expression{empty_or_s} in front of the call and replace {it_or_them} with the unit literal `()`"
),
sugg,
@@ -192,7 +192,7 @@ fn fmt_stmts_and_call(
let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
// expr is not in a block statement or result expression position, wrap in a block
- let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id));
+ let parent_node = cx.tcx.hir().find_parent(call_expr.hir_id);
if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
let block_indent = call_expr_indent + 4;
stmts_and_call_snippet =
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 60b46854b..84ec0d0fb 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
}
// Abort if the method is implementing a trait or of it a trait method.
- if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+ if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
if matches!(
item.kind,
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 42bccc721..f864c5203 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -1,9 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::visitors::is_local_used;
use if_chain::if_chain;
-use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
+use rustc_hir::{Body, Impl, ImplItem, ImplItemKind, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use std::ops::ControlFlow;
declare_clippy_lint! {
/// ### What it does
@@ -57,6 +59,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let parent_item = cx.tcx.hir().expect_item(parent);
let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
+ let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
+ clippy_utils::visitors::for_each_expr(body.value, |e| {
+ if let Some(macro_call) = root_macro_call_first_node(cx, e) {
+ if cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
+ }
+ } else {
+ ControlFlow::Continue(())
+ }
+ })
+ .is_some()
+ };
if_chain! {
if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
if assoc_item.fn_has_self_parameter;
@@ -65,6 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
let body = cx.tcx.hir().body(*body_id);
if let [self_param, ..] = body.params;
if !is_local_used(cx, body, self_param.pat.hir_id);
+ if !contains_todo(cx, body);
then {
span_lint_and_help(
cx,
@@ -72,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
self_param.span,
"unused `self` argument",
None,
- "consider refactoring to a associated function",
+ "consider refactoring to an associated function",
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 4c755d812..6ae9d9d63 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
then {
// `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be
// `Self`.
- let self_ty = impl_trait_ref.self_ty();
+ let self_ty = impl_trait_ref.subst_identity().self_ty();
// `trait_method_sig` is the signature of the function, how it is declared in the
// trait, not in the impl of the trait.
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 3743d5d97..a95e7b613 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
-use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
+use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
+use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
+use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -81,16 +81,24 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
}
}
if is_trait_method(cx, e, sym::IntoIterator) && name.ident.name == sym::into_iter {
- if let Some(parent_expr) = get_parent_expr(cx, e) {
- if let ExprKind::MethodCall(parent_name, ..) = parent_expr.kind {
- if parent_name.ident.name != sym::into_iter {
- return;
- }
- }
+ if get_parent_expr(cx, e).is_some() &&
+ let Some(id) = path_to_local(recv) &&
+ let Node::Pat(pat) = cx.tcx.hir().get(id) &&
+ let PatKind::Binding(ann, ..) = pat.kind &&
+ ann != BindingAnnotation::MUT
+ {
+ // Do not remove .into_iter() applied to a non-mutable local variable used in
+ // a larger expression context as it would differ in mutability.
+ return;
}
+
let a = cx.typeck_results().expr_ty(e);
let b = cx.typeck_results().expr_ty(recv);
- if same_type_and_consts(a, b) {
+
+ // If the types are identical then .into_iter() can be removed, unless the type
+ // implements Copy, in which case .into_iter() returns a copy of the receiver and
+ // cannot be safely omitted.
+ if same_type_and_consts(a, b) && !is_copy(cx, b) {
let sugg = snippet(cx, recv.span, "<expr>").into_owned();
span_lint_and_sugg(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 0c052d86e..bd7daf077 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -299,7 +299,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
};
kind!("Float(_, {float_ty})");
},
- LitKind::ByteStr(ref vec) => {
+ LitKind::ByteStr(ref vec, _) => {
bind!(self, vec);
kind!("ByteStr(ref {vec})");
chain!(self, "let [{:?}] = **{vec}", vec.value);
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index b6dc8cd7a..3e7d0028c 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -205,10 +205,49 @@ macro_rules! define_Conf {
}
define_Conf! {
- /// Lint: Arithmetic.
+ /// Lint: ARITHMETIC_SIDE_EFFECTS.
///
- /// Suppress checking of the passed type names.
+ /// Suppress checking of the passed type names in all types of operations.
+ ///
+ /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
+ /// ```
+ ///
+ /// #### Noteworthy
+ ///
+ /// A type, say `SomeType`, listed in this configuration has the same behavior of `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
(arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
+ /// Lint: ARITHMETIC_SIDE_EFFECTS.
+ ///
+ /// Suppress checking of the passed type pair names in binary operations like addition or
+ /// multiplication.
+ ///
+ /// Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
+ /// of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
+ ///
+ /// Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
+ /// `["AnotherType", "SomeType"]`.
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
+ /// ```
+ (arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default()),
+ /// Lint: ARITHMETIC_SIDE_EFFECTS.
+ ///
+ /// Suppress checking of the passed type names in unary operations like "negation" (`-`).
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
+ /// ```
+ (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
@@ -406,6 +445,14 @@ define_Conf! {
///
/// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
(allow_mixed_uninlined_format_args: bool = true),
+ /// Lint: INDEXING_SLICING
+ ///
+ /// Whether to suppress a restriction lint in constant code. In same
+ /// cases the restructured operation might not be unavoidable, as the
+ /// suggested counterparts are unavailable in constant code. This
+ /// configuration will cause restriction lints to trigger even
+ /// if no suggestion can be made.
+ (suppress_restriction_lint_in_const: bool = false),
}
/// Search for the configuration file.
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 680935f23..9afe02c1e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -7,7 +7,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::Item;
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, FloatTy};
+use rustc_middle::ty::{self, fast_reject::SimplifiedType, FloatTy};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol;
@@ -73,10 +73,10 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
let lang_items = cx.tcx.lang_items();
// This list isn't complete, but good enough for our current list of paths.
let incoherent_impls = [
- SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32),
- SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64),
- SimplifiedTypeGen::SliceSimplifiedType,
- SimplifiedTypeGen::StrSimplifiedType,
+ SimplifiedType::FloatSimplifiedType(FloatTy::F32),
+ SimplifiedType::FloatSimplifiedType(FloatTy::F64),
+ SimplifiedType::SliceSimplifiedType,
+ SimplifiedType::StrSimplifiedType,
]
.iter()
.flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 786d9608c..4c3b1b131 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -257,7 +257,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
}
pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
- if let TyKind::Rptr(
+ if let TyKind::Ref(
_,
MutTy {
ty: inner,
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 857abe77e..c4d8c28f0 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -558,8 +558,8 @@ impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
- "* `{}`: `{}`: {} (defaults to `{}`)",
- self.name, self.config_type, self.doc, self.default
+ "* `{}`: `{}`(defaults to `{}`): {}",
+ self.name, self.config_type, self.default, self.doc
)
}
}
@@ -1058,7 +1058,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -
fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
let map = cx.tcx.hir();
- match map.find(map.get_parent_node(hir_id)) {
+ match map.find_parent(hir_id) {
Some(hir::Node::Local(local)) => Some(local),
Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id),
_ => None,
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 393988dba..714436363 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -219,7 +219,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
match peel_hir_expr_refs(expr).0.kind {
ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
Res::Local(hir_id) => {
- let parent_id = cx.tcx.hir().get_parent_node(hir_id);
+ let parent_id = cx.tcx.hir().parent_id(hir_id);
if let Some(Node::Local(Local { init: Some(init), .. })) = cx.tcx.hir().find(parent_id) {
path_to_matched_type(cx, init)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 6b321765b..df3350388 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -377,7 +377,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c
// print!("\n"), write!(f, "\n")
diag.multipart_suggestion(
- &format!("use `{name}ln!` instead"),
+ format!("use `{name}ln!` instead"),
vec![(name_span, format!("{name}ln")), (format_string_span, String::new())],
Applicability::MachineApplicable,
);
@@ -388,7 +388,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c
let newline_span = format_string_span.with_lo(hi - BytePos(3)).with_hi(hi - BytePos(1));
diag.multipart_suggestion(
- &format!("use `{name}ln!` instead"),
+ format!("use `{name}ln!` instead"),
vec![(name_span, format!("{name}ln")), (newline_span, String::new())],
Applicability::MachineApplicable,
);
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index fb9f4740e..ac6a566b9 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.67"
+version = "0.1.68"
edition = "2021"
publish = false
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 49e5f283d..9d0263e93 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -625,7 +625,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
(Slice(l), Slice(r)) => eq_ty(l, r),
(Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value),
(Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty),
- (Rptr(ll, l), Rptr(rl, r)) => {
+ (Ref(ll, l), Ref(rl, r)) => {
both(ll, rl, |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty)
},
(BareFn(l), BareFn(r)) => {
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index c6bf98b7b..43f0df145 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -69,7 +69,9 @@ fn lit_search_pat(lit: &LitKind) -> (Pat, Pat) {
LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")),
LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")),
LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")),
- LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")),
+ LitKind::ByteStr(_, StrStyle::Cooked) => (Pat::Str("b\""), Pat::Str("\"")),
+ LitKind::ByteStr(_, StrStyle::Raw(0)) => (Pat::Str("br\""), Pat::Str("\"")),
+ LitKind::ByteStr(_, StrStyle::Raw(_)) => (Pat::Str("br#\""), Pat::Str("#")),
LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")),
LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")),
LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")),
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 315aea9aa..a67bd8d46 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -210,7 +210,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
match *lit {
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
LitKind::Byte(b) => Constant::Int(u128::from(b)),
- LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)),
+ LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
LitKind::Char(c) => Constant::Char(c),
LitKind::Int(n, _) => Constant::Int(n),
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
@@ -620,12 +620,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
int.try_into().expect("invalid f64 bit representation"),
))),
- ty::RawPtr(type_and_mut) => {
- if let ty::Uint(_) = type_and_mut.ty.kind() {
- return Some(Constant::RawPtr(int.assert_bits(int.size())));
- }
- None
- },
+ ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
// FIXME: implement other conversions.
_ => None,
}
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 16b160b6f..812f6fe71 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -17,7 +17,7 @@ use std::env;
fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
- diag.help(&format!(
+ diag.help(format!(
"for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
&option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
// extract just major + minor version and ignore patch versions
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 07fb6af91..2bbe1a19b 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -430,7 +430,7 @@ impl HirEqInterExpr<'_, '_, '_> {
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
(TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
- (TyKind::Rptr(_, l_rmut), TyKind::Rptr(_, r_rmut)) => {
+ (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
},
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
@@ -950,7 +950,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_ty(mut_ty.ty);
mut_ty.mutbl.hash(&mut self.s);
},
- TyKind::Rptr(lifetime, ref mut_ty) => {
+ TyKind::Ref(lifetime, ref mut_ty) => {
self.hash_lifetime(lifetime);
self.hash_ty(mut_ty.ty);
mut_ty.mutbl.hash(&mut self.s);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 90192f46c..7a4a9036d 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -22,6 +22,9 @@ extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr;
extern crate rustc_data_structures;
+// The `rustc_driver` crate seems to be required in order to use the `rust_ast` crate.
+#[allow(unused_extern_crates)]
+extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_hir;
extern crate rustc_hir_typeck;
@@ -97,7 +100,7 @@ use rustc_middle::hir::place::PlaceBase;
use rustc_middle::ty as rustc_ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{
+use rustc_middle::ty::fast_reject::SimplifiedType::{
ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
};
@@ -116,6 +119,8 @@ use crate::consts::{constant, Constant};
use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
use crate::visitors::for_each_expr;
+use rustc_middle::hir::nested_filter;
+
#[macro_export]
macro_rules! extract_msrv_attr {
($context:ident) => {
@@ -174,7 +179,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
if_chain! {
if let Some(Node::Pat(pat)) = hir.find(hir_id);
if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..));
- let parent = hir.get_parent_node(hir_id);
+ let parent = hir.parent_id(hir_id);
if let Some(Node::Local(local)) = hir.find(parent);
then {
return local.init;
@@ -196,7 +201,7 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
let parent_id = cx.tcx.hir().get_parent_item(id).def_id;
match cx.tcx.hir().get_by_def_id(parent_id) {
Node::Item(&Item {
- kind: ItemKind::Const(..) | ItemKind::Static(..),
+ kind: ItemKind::Const(..) | ItemKind::Static(..) | ItemKind::Enum(..),
..
})
| Node::TraitItem(&TraitItem {
@@ -1253,22 +1258,33 @@ pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
}
}
-pub struct ContainsName {
+pub struct ContainsName<'a, 'tcx> {
+ pub cx: &'a LateContext<'tcx>,
pub name: Symbol,
pub result: bool,
}
-impl<'tcx> Visitor<'tcx> for ContainsName {
+impl<'a, 'tcx> Visitor<'tcx> for ContainsName<'a, 'tcx> {
+ type NestedFilter = nested_filter::OnlyBodies;
+
fn visit_name(&mut self, name: Symbol) {
if self.name == name {
self.result = true;
}
}
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
}
/// Checks if an `Expr` contains a certain name.
-pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
- let mut cn = ContainsName { name, result: false };
+pub fn contains_name<'tcx>(name: Symbol, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
+ let mut cn = ContainsName {
+ name,
+ result: false,
+ cx,
+ };
cn.visit_expr(expr);
cn.result
}
@@ -1287,7 +1303,7 @@ pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
/// Gets the parent node, if any.
pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
- tcx.hir().parent_iter(id).next().map(|(_, node)| node)
+ tcx.hir().find_parent(id)
}
/// Gets the parent expression, if any –- this is useful to constrain a lint.
@@ -1304,6 +1320,7 @@ pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId)
}
}
+/// Gets the enclosing block, if any.
pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Block<'tcx>> {
let map = &cx.tcx.hir();
let enclosing_node = map
@@ -2075,7 +2092,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
/// }
/// ```
pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
- if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) {
+ if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
} else {
false
@@ -2244,6 +2261,18 @@ pub fn peel_n_hir_expr_refs<'a>(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'
(e, count - remaining)
}
+/// Peels off all unary operators of an expression. Returns the underlying expression and the number
+/// of operators removed.
+pub fn peel_hir_expr_unary<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
+ let mut count: usize = 0;
+ let mut curr_expr = expr;
+ while let ExprKind::Unary(_, local_expr) = curr_expr.kind {
+ count = count.wrapping_add(1);
+ curr_expr = local_expr;
+ }
+ (curr_expr, count)
+}
+
/// Peels off all references on the expression. Returns the underlying expression and the number of
/// references removed.
pub fn peel_hir_expr_refs<'a>(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
@@ -2264,7 +2293,7 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize)
let mut count = 0;
loop {
match &ty.kind {
- TyKind::Rptr(_, ref_ty) => {
+ TyKind::Ref(_, ref_ty) => {
ty = ref_ty.ty;
count += 1;
},
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index d13b34a66..77c5f1155 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -208,6 +208,12 @@ pub fn is_panic(cx: &LateContext<'_>, def_id: DefId) -> bool {
)
}
+/// Is `def_id` of `assert!` or `debug_assert!`
+pub fn is_assert_macro(cx: &LateContext<'_>, def_id: DefId) -> bool {
+ let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return false };
+ matches!(name, sym::assert_macro | sym::debug_assert_macro)
+}
+
pub enum PanicExpn<'a> {
/// No arguments - `panic!()`
Empty,
diff --git a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs b/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs
deleted file mode 100644
index d262b335d..000000000
--- a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use rustc_index::bit_set::BitSet;
-use rustc_middle::mir;
-use rustc_mir_dataflow::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis};
-
-/// Determines liveness of each local purely based on `StorageLive`/`Dead`.
-#[derive(Copy, Clone)]
-pub(super) struct MaybeStorageLive;
-
-impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive {
- type Domain = BitSet<mir::Local>;
- const NAME: &'static str = "maybe_storage_live";
-
- fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
- // bottom = dead
- BitSet::new_empty(body.local_decls.len())
- }
-
- fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) {
- for arg in body.args_iter() {
- state.insert(arg);
- }
- }
-}
-
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
- type Idx = mir::Local;
-
- fn statement_effect(&self, trans: &mut impl GenKill<Self::Idx>, stmt: &mir::Statement<'tcx>, _: mir::Location) {
- match stmt.kind {
- mir::StatementKind::StorageLive(l) => trans.gen(l),
- mir::StatementKind::StorageDead(l) => trans.kill(l),
- _ => (),
- }
- }
-
- fn terminator_effect(
- &self,
- _trans: &mut impl GenKill<Self::Idx>,
- _terminator: &mir::Terminator<'tcx>,
- _loc: mir::Location,
- ) {
- }
-
- fn call_return_effect(
- &self,
- _trans: &mut impl GenKill<Self::Idx>,
- _block: mir::BasicBlock,
- _return_places: CallReturnPlaces<'_, 'tcx>,
- ) {
- // Nothing to do when a call returns successfully
- }
-}
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
index 818e603f6..26c0015e8 100644
--- a/src/tools/clippy/clippy_utils/src/mir/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -5,8 +5,6 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::TyCtxt;
-mod maybe_storage_live;
-
mod possible_borrower;
pub use possible_borrower::PossibleBorrowerMap;
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 25717bf3d..9adae7733 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -1,14 +1,12 @@
-use super::{
- maybe_storage_live::MaybeStorageLive, possible_origin::PossibleOriginVisitor,
- transitive_relation::TransitiveRelation,
-};
+use super::{possible_origin::PossibleOriginVisitor, transitive_relation::TransitiveRelation};
use crate::ty::is_copy;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_lint::LateContext;
use rustc_middle::mir::{self, visit::Visitor as _, Mutability};
use rustc_middle::ty::{self, visit::TypeVisitor};
-use rustc_mir_dataflow::{Analysis, ResultsCursor};
+use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor};
+use std::borrow::Cow;
use std::ops::ControlFlow;
/// Collects the possible borrowers of each local.
@@ -39,7 +37,7 @@ impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
fn into_map(
self,
cx: &'a LateContext<'tcx>,
- maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>,
+ maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
) -> PossibleBorrowerMap<'b, 'tcx> {
let mut map = FxHashMap::default();
for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
@@ -170,7 +168,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
pub struct PossibleBorrowerMap<'b, 'tcx> {
/// Mapping `Local -> its possible borrowers`
pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
- maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>,
+ maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>,
// Caches to avoid allocation of `BitSet` on every query
pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
}
@@ -182,7 +180,7 @@ impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
vis.visit_body(mir);
vis.into_map(cx)
};
- let maybe_storage_live_result = MaybeStorageLive
+ let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
.into_engine(cx.tcx, mir)
.pass_name("redundant_clone")
.iterate_to_fixpoint()
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 12a512f78..dbf9f3b62 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -20,8 +20,9 @@ macro_rules! msrv_aliases {
// names may refer to stabilized feature flags or library items
msrv_aliases! {
1,65,0 { LET_ELSE }
- 1,62,0 { BOOL_THEN_SOME }
- 1,58,0 { FORMAT_ARGS_CAPTURE }
+ 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
+ 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
+ 1,55,0 { SEEK_REWIND }
1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
@@ -45,7 +46,6 @@ msrv_aliases! {
1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
1,16,0 { STR_REPEAT }
- 1,55,0 { SEEK_REWIND }
}
fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 6417f0f3c..95eebab75 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -20,7 +20,6 @@ pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
-pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"];
pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
@@ -48,7 +47,6 @@ pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
#[cfg(feature = "internal")]
pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
-pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"];
pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
#[cfg(feature = "internal")]
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 480e8e55c..e5d7da682 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -82,7 +82,7 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
ty::Ref(_, _, hir::Mutability::Mut) => {
return Err((span, "mutable references in const fn are unstable".into()));
},
- ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+ ty::Alias(ty::Opaque, ..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
ty::FnPtr(..) => {
return Err((span, "function pointers in const fn are unstable".into()));
},
@@ -301,11 +301,7 @@ fn check_terminator<'tcx>(
check_operand(tcx, value, span, body)
},
- TerminatorKind::SwitchInt {
- discr,
- switch_ty: _,
- targets: _,
- } => check_operand(tcx, discr, span, body),
+ TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index b66604f33..e7879bb19 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -185,7 +185,6 @@ impl<'a> Sugg<'a> {
) -> Self {
use rustc_ast::ast::RangeLimits;
- #[expect(clippy::match_wildcard_for_single_variants)]
match expr.kind {
_ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
ast::ExprKind::AddrOf(..)
@@ -813,9 +812,9 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
let closure_body = cx.tcx.hir().body(body);
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
// a type annotation is present if param `kind` is different from `TyKind::Infer`
- let closure_arg_is_type_annotated_double_ref = if let TyKind::Rptr(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind
+ let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind
{
- matches!(ty.kind, TyKind::Rptr(_, MutTy { .. }))
+ matches!(ty.kind, TyKind::Ref(_, MutTy { .. }))
} else {
false
};
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 05c6eb7f2..99fba4fe7 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -16,8 +16,8 @@ use rustc_infer::infer::{
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::ty::{
- self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
- ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+ self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate,
+ PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
VariantDef, VariantDiscr,
};
use rustc_middle::ty::{GenericArg, GenericArgKind};
@@ -30,7 +30,7 @@ use std::iter;
use crate::{match_def_path, path_res, paths};
-// Checks if the given type implements copy.
+/// Checks if the given type implements copy.
pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
}
@@ -85,7 +85,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
return true;
}
- if let ty::Opaque(def_id, _) = *inner_ty.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() {
if !seen.insert(def_id) {
return false;
}
@@ -266,7 +266,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
is_must_use_ty(cx, *ty)
},
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
- ty::Opaque(def_id, _) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
@@ -496,7 +496,7 @@ pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bo
/// Returns the base type for HIR references and pointers.
pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
match ty.kind {
- TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty),
+ TyKind::Ptr(ref mut_ty) | TyKind::Ref(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty),
_ => ty,
}
}
@@ -647,7 +647,9 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
},
ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
- ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+ sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id).subst(cx.tcx, substs), cx.tcx.opt_parent(def_id))
+ },
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
ty::Dynamic(bounds, _, _) => {
let lang_items = cx.tcx.lang_items();
@@ -666,7 +668,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
_ => None,
}
},
- ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
+ ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
_ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
},
@@ -701,8 +703,7 @@ fn sig_from_bounds<'tcx>(
inputs = Some(i);
},
PredicateKind::Clause(ty::Clause::Projection(p))
- if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
- && p.projection_ty.self_ty() == ty =>
+ if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty =>
{
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
@@ -717,14 +718,14 @@ fn sig_from_bounds<'tcx>(
inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id))
}
-fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
+fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
let mut inputs = None;
let mut output = None;
let lang_items = cx.tcx.lang_items();
for (pred, _) in cx
.tcx
- .bound_explicit_item_bounds(ty.item_def_id)
+ .bound_explicit_item_bounds(ty.def_id)
.subst_iter_copied(cx.tcx, ty.substs)
{
match pred.kind().skip_binder() {
@@ -742,7 +743,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
inputs = Some(i);
},
PredicateKind::Clause(ty::Clause::Projection(p))
- if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
+ if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
{
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
@@ -996,13 +997,13 @@ pub fn make_projection<'tcx>(
container_id: DefId,
assoc_ty: Symbol,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
-) -> Option<ProjectionTy<'tcx>> {
+) -> Option<AliasTy<'tcx>> {
fn helper<'tcx>(
tcx: TyCtxt<'tcx>,
container_id: DefId,
assoc_ty: Symbol,
substs: SubstsRef<'tcx>,
- ) -> Option<ProjectionTy<'tcx>> {
+ ) -> Option<AliasTy<'tcx>> {
let Some(assoc_item) = tcx
.associated_items(container_id)
.find_by_name_and_kind(tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, container_id)
@@ -1055,10 +1056,7 @@ pub fn make_projection<'tcx>(
}
}
- Some(ProjectionTy {
- substs,
- item_def_id: assoc_item.def_id,
- })
+ Some(tcx.mk_alias_ty(assoc_item.def_id, substs))
}
helper(
tcx,
@@ -1081,7 +1079,7 @@ pub fn make_normalized_projection<'tcx>(
assoc_ty: Symbol,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
) -> Option<Ty<'tcx>> {
- fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'tcx>) -> Option<Ty<'tcx>> {
+ fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
#[cfg(debug_assertions)]
if let Some((i, subst)) = ty
.substs
@@ -1097,7 +1095,7 @@ pub fn make_normalized_projection<'tcx>(
);
return None;
}
- match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.item_def_id, ty.substs)) {
+ match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) {
Ok(ty) => Some(ty),
Err(e) => {
debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 863fb60fc..14c01a60b 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -724,3 +724,14 @@ pub fn for_each_local_assignment<'tcx, B>(
ControlFlow::Continue(())
}
}
+
+pub fn contains_break_or_continue(expr: &Expr<'_>) -> bool {
+ for_each_expr(expr, |e| {
+ if matches!(e.kind, ExprKind::Break(..) | ExprKind::Continue(..)) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
+ }
+ })
+ .is_some()
+}
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 082570f1f..c01e1062c 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "declare_clippy_lint"
-version = "0.1.67"
+version = "0.1.68"
edition = "2021"
publish = false
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 19fee38db..40a6f4709 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-12-01"
+channel = "nightly-2023-01-12"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/rustc_tools_util/CHANGELOG.md b/src/tools/clippy/rustc_tools_util/CHANGELOG.md
new file mode 100644
index 000000000..1b351da2e
--- /dev/null
+++ b/src/tools/clippy/rustc_tools_util/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Changelog
+
+## Version 0.3.0
+
+* Added `setup_version_info!();` macro for automated scripts.
+* `get_version_info!()` no longer requires the user to import `rustc_tools_util::VersionInfo` and `std::env`
diff --git a/src/tools/clippy/rustc_tools_util/Cargo.toml b/src/tools/clippy/rustc_tools_util/Cargo.toml
index 89c3d6aaa..877049ae7 100644
--- a/src/tools/clippy/rustc_tools_util/Cargo.toml
+++ b/src/tools/clippy/rustc_tools_util/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rustc_tools_util"
-version = "0.2.1"
+version = "0.3.0"
description = "small helper to generate version information for git packages"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
diff --git a/src/tools/clippy/rustc_tools_util/README.md b/src/tools/clippy/rustc_tools_util/README.md
index e947f9c7e..eefc661f9 100644
--- a/src/tools/clippy/rustc_tools_util/README.md
+++ b/src/tools/clippy/rustc_tools_util/README.md
@@ -13,43 +13,39 @@ build = "build.rs"
List rustc_tools_util as regular AND build dependency.
````toml
[dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
[build-dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
````
In `build.rs`, generate the data in your `main()`
-````rust
+
+```rust
fn main() {
- println!(
- "cargo:rustc-env=GIT_HASH={}",
- rustc_tools_util::get_commit_hash().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=COMMIT_DATE={}",
- rustc_tools_util::get_commit_date().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
- rustc_tools_util::get_channel().unwrap_or_default()
- );
+ rustc_tools_util::setup_version_info!();
}
-
-````
+```
Use the version information in your main.rs
-````rust
-use rustc_tools_util::*;
+```rust
fn show_version() {
let version_info = rustc_tools_util::get_version_info!();
println!("{}", version_info);
}
-````
+```
+
This gives the following output in clippy:
-`clippy 0.0.212 (a416c5e 2018-12-14)`
+`clippy 0.1.66 (a28f3c8 2022-11-20)`
+
+## Repository
+
+This project is part of the rust-lang/rust-clippy repository. The source code
+can be found under `./rustc_tools_util/`.
+The changelog for `rustc_tools_util` is available under:
+[`rustc_tools_util/CHANGELOG.md`](https://github.com/rust-lang/rust-clippy/blob/master/rustc_tools_util/CHANGELOG.md)
## License
diff --git a/src/tools/clippy/rustc_tools_util/src/lib.rs b/src/tools/clippy/rustc_tools_util/src/lib.rs
index 01d25c531..4c1d8c373 100644
--- a/src/tools/clippy/rustc_tools_util/src/lib.rs
+++ b/src/tools/clippy/rustc_tools_util/src/lib.rs
@@ -1,20 +1,20 @@
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-use std::env;
-
+/// This macro creates the version string during compilation from the
+/// current environment
#[macro_export]
macro_rules! get_version_info {
() => {{
- let major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
- let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
- let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
- let crate_name = String::from(env!("CARGO_PKG_NAME"));
+ let major = std::env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
+ let minor = std::env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
+ let patch = std::env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
+ let crate_name = String::from(std::env!("CARGO_PKG_NAME"));
- let host_compiler = option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
- let commit_hash = option_env!("GIT_HASH").map(str::to_string);
- let commit_date = option_env!("COMMIT_DATE").map(str::to_string);
+ let host_compiler = std::option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
+ let commit_hash = std::option_env!("GIT_HASH").map(str::to_string);
+ let commit_date = std::option_env!("COMMIT_DATE").map(str::to_string);
- VersionInfo {
+ $crate::VersionInfo {
major,
minor,
patch,
@@ -26,6 +26,24 @@ macro_rules! get_version_info {
}};
}
+/// This macro can be used in `build.rs` to automatically set the needed
+/// environment values, namely `GIT_HASH`, `COMMIT_DATE` and
+/// `RUSTC_RELEASE_CHANNEL`
+#[macro_export]
+macro_rules! setup_version_info {
+ () => {{
+ println!(
+ "cargo:rustc-env=GIT_HASH={}",
+ $crate::get_commit_hash().unwrap_or_default()
+ );
+ println!(
+ "cargo:rustc-env=COMMIT_DATE={}",
+ $crate::get_commit_date().unwrap_or_default()
+ );
+ println!("cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", $crate::get_channel());
+ }};
+}
+
// some code taken and adapted from RLS and cargo
pub struct VersionInfo {
pub major: u8,
@@ -101,7 +119,7 @@ pub fn get_commit_date() -> Option<String> {
#[must_use]
pub fn get_channel() -> String {
- match env::var("CFG_RELEASE_CHANNEL") {
+ match std::env::var("CFG_RELEASE_CHANNEL") {
Ok(channel) => channel,
Err(_) => {
// if that failed, try to ask rustc -V, do some parsing and find out
@@ -136,8 +154,8 @@ mod test {
fn test_struct_local() {
let vi = get_version_info!();
assert_eq!(vi.major, 0);
- assert_eq!(vi.minor, 2);
- assert_eq!(vi.patch, 1);
+ assert_eq!(vi.minor, 3);
+ assert_eq!(vi.patch, 0);
assert_eq!(vi.crate_name, "rustc_tools_util");
// hard to make positive tests for these since they will always change
assert!(vi.commit_hash.is_none());
@@ -147,7 +165,7 @@ mod test {
#[test]
fn test_display_local() {
let vi = get_version_info!();
- assert_eq!(vi.to_string(), "rustc_tools_util 0.2.1");
+ assert_eq!(vi.to_string(), "rustc_tools_util 0.3.0");
}
#[test]
@@ -156,7 +174,7 @@ mod test {
let s = format!("{vi:?}");
assert_eq!(
s,
- "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 1 }"
+ "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 3, patch: 0 }"
);
}
}
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9ec4df8e6..d521e8d88 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -19,7 +19,6 @@ extern crate rustc_span;
use rustc_interface::interface;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::Symbol;
-use rustc_tools_util::VersionInfo;
use std::borrow::Cow;
use std::env;
@@ -257,11 +256,14 @@ pub fn main() {
LazyLock::force(&ICE_HOOK);
exit(rustc_driver::catch_with_exit_code(move || {
let mut orig_args: Vec<String> = env::args().collect();
+ let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some();
let sys_root_env = std::env::var("SYSROOT").ok();
let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
if let Some(sys_root) = sys_root_env {
- args.extend(vec!["--sysroot".into(), sys_root]);
+ if !has_sysroot_arg {
+ args.extend(vec!["--sysroot".into(), sys_root]);
+ }
};
};
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index d418d2daa..7a78b3262 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -2,7 +2,6 @@
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
-use rustc_tools_util::VersionInfo;
use std::env;
use std::path::PathBuf;
use std::process::{self, Command};
diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs
index 818ff70b3..a771d8b87 100644
--- a/src/tools/clippy/tests/integration.rs
+++ b/src/tools/clippy/tests/integration.rs
@@ -1,3 +1,12 @@
+//! This test is meant to only be run in CI. To run it locally use:
+//!
+//! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
+//!
+//! You can use a different `INTEGRATION` value to test different repositories.
+//!
+//! This test will clone the specified repository and run Clippy on it. The test succeeds, if
+//! Clippy doesn't produce an ICE. Lint warnings are ignored by this test.
+
#![cfg(feature = "integration")]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index 2a240cc24..3ca45404e 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -7,14 +7,6 @@ LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
= help: convert all references to use `sym::Deref`
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
-error: hardcoded path to a diagnostic item
- --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
- |
-LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: convert all references to use `sym::deref_method`
-
error: hardcoded path to a language item
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
@@ -23,5 +15,13 @@ LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]
|
= help: convert all references to use `LangItem::DerefMut`
+error: hardcoded path to a diagnostic item
+ --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+ |
+LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: convert all references to use `sym::deref_method`
+
error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
index e8a023ab1..fb5b1b193 100644
--- a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
+++ b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.rs
@@ -2,32 +2,117 @@
use core::ops::{Add, Neg};
-#[derive(Clone, Copy)]
-struct Point {
- x: i32,
- y: i32,
+macro_rules! create {
+ ($name:ident) => {
+ #[allow(clippy::arithmetic_side_effects)]
+ #[derive(Clone, Copy)]
+ struct $name;
+
+ impl Add<$name> for $name {
+ type Output = $name;
+ fn add(self, other: $name) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<i32> for $name {
+ type Output = $name;
+ fn add(self, other: i32) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<$name> for i32 {
+ type Output = $name;
+ fn add(self, other: $name) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<i64> for $name {
+ type Output = $name;
+ fn add(self, other: i64) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<$name> for i64 {
+ type Output = $name;
+ fn add(self, other: $name) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Neg for $name {
+ type Output = $name;
+ fn neg(self) -> Self::Output {
+ todo!()
+ }
+ }
+ };
}
-impl Add for Point {
- type Output = Self;
+create!(Foo);
+create!(Bar);
+create!(Baz);
+create!(OutOfNames);
- fn add(self, other: Self) -> Self {
- todo!()
- }
+fn lhs_and_rhs_are_equal() {
+ // is explicitly on the list
+ let _ = OutOfNames + OutOfNames;
+ // is explicitly on the list
+ let _ = Foo + Foo;
+ // is implicitly on the list
+ let _ = Bar + Bar;
+ // not on the list
+ let _ = Baz + Baz;
}
-impl Neg for Point {
- type Output = Self;
+fn lhs_is_different() {
+ // is explicitly on the list
+ let _ = 1i32 + OutOfNames;
+ // is explicitly on the list
+ let _ = 1i32 + Foo;
+ // is implicitly on the list
+ let _ = 1i32 + Bar;
+ // not on the list
+ let _ = 1i32 + Baz;
- fn neg(self) -> Self::Output {
- todo!()
- }
+ // not on the list
+ let _ = 1i64 + Foo;
+ // is implicitly on the list
+ let _ = 1i64 + Bar;
+ // not on the list
+ let _ = 1i64 + Baz;
}
-fn main() {
- let _ = Point { x: 1, y: 0 } + Point { x: 2, y: 3 };
+fn rhs_is_different() {
+ // is explicitly on the list
+ let _ = OutOfNames + 1i32;
+ // is explicitly on the list
+ let _ = Foo + 1i32;
+ // is implicitly on the list
+ let _ = Bar + 1i32;
+ // not on the list
+ let _ = Baz + 1i32;
+
+ // not on the list
+ let _ = Foo + 1i64;
+ // is implicitly on the list
+ let _ = Bar + 1i64;
+ // not on the list
+ let _ = Baz + 1i64;
+}
- let point: Point = Point { x: 1, y: 0 };
- let _ = point + point;
- let _ = -point;
+fn unary() {
+ // is explicitly on the list
+ let _ = -OutOfNames;
+ // is explicitly on the list
+ let _ = -Foo;
+ // not on the list
+ let _ = -Bar;
+ // not on the list
+ let _ = -Baz;
}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr
new file mode 100644
index 000000000..ad89534aa
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/arithmetic_side_effects_allowed.stderr
@@ -0,0 +1,58 @@
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:68:13
+ |
+LL | let _ = Baz + Baz;
+ | ^^^^^^^^^
+ |
+ = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:79:13
+ |
+LL | let _ = 1i32 + Baz;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:82:13
+ |
+LL | let _ = 1i64 + Foo;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:86:13
+ |
+LL | let _ = 1i64 + Baz;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:97:13
+ |
+LL | let _ = Baz + 1i32;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:100:13
+ |
+LL | let _ = Foo + 1i64;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:104:13
+ |
+LL | let _ = Baz + 1i64;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:113:13
+ |
+LL | let _ = -Bar;
+ | ^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:115:13
+ |
+LL | let _ = -Baz;
+ | ^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/clippy.toml b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/clippy.toml
index e736256f2..89cbea7ec 100644
--- a/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/arithmetic_side_effects_allowed/clippy.toml
@@ -1 +1,11 @@
-arithmetic-side-effects-allowed = ["Point"]
+arithmetic-side-effects-allowed = [
+ "OutOfNames"
+]
+arithmetic-side-effects-allowed-binary = [
+ ["Foo", "Foo"],
+ ["Foo", "i32"],
+ ["i32", "Foo"],
+ ["Bar", "*"],
+ ["*", "Bar"],
+]
+arithmetic-side-effects-allowed-unary = ["Foo"]
diff --git a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
index 46efb86dc..859383a71 100644
--- a/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui-toml/dbg_macro/dbg_macro.stderr
@@ -1,99 +1,99 @@
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:5:22
|
LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::dbg-macro` implied by `-D warnings`
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | if let Some(n) = n.checked_sub(4) { n } else { n }
| ~~~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:9:8
|
LL | if dbg!(n <= 1) {
| ^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | if n <= 1 {
| ~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:10:9
|
LL | dbg!(1)
| ^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 1
|
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:12:9
|
LL | dbg!(n * factorial(n - 1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | n * factorial(n - 1)
|
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:17:5
|
LL | dbg!(42);
| ^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 42;
| ~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:18:5
|
LL | dbg!(dbg!(dbg!(42)));
| ^^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | dbg!(dbg!(42));
| ~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:19:14
|
LL | foo(3) + dbg!(factorial(4));
| ^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | foo(3) + factorial(4);
| ~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:20:5
|
LL | dbg!(1, 2, dbg!(3, 4));
| ^^^^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | (1, 2, dbg!(3, 4));
| ~~~~~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:21:5
|
LL | dbg!(1, 2, 3, 4, 5);
| ^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | (1, 2, 3, 4, 5);
| ~~~~~~~~~~~~~~~
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml
new file mode 100644
index 000000000..1b9384d7e
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/clippy.toml
@@ -0,0 +1 @@
+suppress-restriction-lint-in-const = true
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
new file mode 100644
index 000000000..5a2df9f6c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs
@@ -0,0 +1,60 @@
+#![feature(inline_const)]
+#![warn(clippy::indexing_slicing)]
+// We also check the out_of_bounds_indexing lint here, because it lints similar things and
+// we want to avoid false positives.
+#![warn(clippy::out_of_bounds_indexing)]
+#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
+
+const ARR: [i32; 2] = [1, 2];
+const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+
+const fn idx() -> usize {
+ 1
+}
+const fn idx4() -> usize {
+ 4
+}
+
+fn main() {
+ let x = [1, 2, 3, 4];
+ let index: usize = 1;
+ x[index];
+ x[4]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+ x[1 << 3]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+
+ x[0]; // Ok, should not produce stderr.
+ x[3]; // Ok, should not produce stderr.
+ x[const { idx() }]; // Ok, should not produce stderr.
+ x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+ const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+ const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+
+ let y = &x;
+ y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
+ y[4]; // Ok, rustc will handle references too.
+
+ let v = vec![0; 5];
+ v[0];
+ v[10];
+ v[1 << 3];
+
+ const N: usize = 15; // Out of bounds
+ const M: usize = 3; // In bounds
+ x[N]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+ x[M]; // Ok, should not produce stderr.
+ v[N];
+ v[M];
+}
+
+/// An opaque integer representation
+pub struct Integer<'a> {
+ /// The underlying data
+ value: &'a [u8],
+}
+impl<'a> Integer<'a> {
+ // Check whether `self` holds a negative number or not
+ pub const fn is_negative(&self) -> bool {
+ self.value[0] & 0b1000_0000 != 0
+ }
+}
diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
new file mode 100644
index 000000000..bc178b7e1
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr
@@ -0,0 +1,70 @@
+error[E0080]: evaluation of `main::{constant#3}` failed
+ --> $DIR/test.rs:31:14
+ |
+LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+ | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+note: erroneous constant used
+ --> $DIR/test.rs:31:5
+ |
+LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: indexing may panic
+ --> $DIR/test.rs:22:5
+ |
+LL | x[index];
+ | ^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+ --> $DIR/test.rs:38:5
+ |
+LL | v[0];
+ | ^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:39:5
+ |
+LL | v[10];
+ | ^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:40:5
+ |
+LL | v[1 << 3];
+ | ^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:46:5
+ |
+LL | v[N];
+ | ^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:47:5
+ |
+LL | v[M];
+ | ^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/test.rs:10:24
+ |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+ | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 01a5e962c..a22c6a5a0 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -6,6 +6,8 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
allow-unwrap-in-tests
allowed-scripts
arithmetic-side-effects-allowed
+ arithmetic-side-effects-allowed-binary
+ arithmetic-side-effects-allowed-unary
array-size-threshold
avoid-breaking-exported-api
await-holding-invalid-types
@@ -35,6 +37,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
pass-by-value-size-limit
single-char-binding-names-threshold
standard-macro-braces
+ suppress-restriction-lint-in-const
third-party
too-large-for-stack
too-many-arguments-threshold
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr b/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr
deleted file mode 100644
index 9abf6d6c5..000000000
--- a/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr
+++ /dev/null
@@ -1,113 +0,0 @@
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:29:17
- |
-LL | let _ = ('a') ..'z';
- | ^^^^^^--^^^
- | |
- | help: use an inclusive range: `..=`
- |
- = note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:30:17
- |
-LL | let _ = 'A' .. ('Z');
- | ^^^^--^^^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:36:13
- |
-LL | let _ = (b'a')..(b'z');
- | ^^^^^^--^^^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:37:13
- |
-LL | let _ = b'A'..b'Z';
- | ^^^^--^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:42:13
- |
-LL | let _ = a!()..'z';
- | ^^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:45:9
- |
-LL | b'a'..b'z' if true => 1,
- | ^^^^--^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:46:9
- |
-LL | b'A'..b'Z' if true => 2,
- | ^^^^--^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:53:9
- |
-LL | 'a'..'z' if true => 1,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:54:9
- |
-LL | 'A'..'Z' if true => 2,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:22:17
- |
-LL | let _ = 'a'..'z';
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-...
-LL | b!();
- | ---- in this macro invocation
- |
- = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:67:9
- |
-LL | 'a'..'z' => 1,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `...`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:74:13
- |
-LL | let _ = 'a'..'z';
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:76:9
- |
-LL | 'a'..'z' => 1,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: aborting due to 13 previous errors
-
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed b/src/tools/clippy/tests/ui/almost_complete_range.fixed
index adcbd4d51..6046addf7 100644
--- a/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed
+++ b/src/tools/clippy/tests/ui/almost_complete_range.fixed
@@ -4,9 +4,10 @@
#![feature(exclusive_range_pattern)]
#![feature(stmt_expr_attributes)]
-#![warn(clippy::almost_complete_letter_range)]
+#![warn(clippy::almost_complete_range)]
#![allow(ellipsis_inclusive_range_patterns)]
#![allow(clippy::needless_parens_on_range_literals)]
+#![allow(clippy::double_parens)]
#[macro_use]
extern crate macro_rules;
@@ -16,10 +17,22 @@ macro_rules! a {
'a'
};
}
+macro_rules! A {
+ () => {
+ 'A'
+ };
+}
+macro_rules! zero {
+ () => {
+ '0'
+ };
+}
macro_rules! b {
() => {
let _ = 'a'..='z';
+ let _ = 'A'..='Z';
+ let _ = '0'..='9';
};
}
@@ -28,36 +41,46 @@ fn main() {
{
let _ = ('a') ..='z';
let _ = 'A' ..= ('Z');
+ let _ = ((('0'))) ..= ('9');
}
let _ = 'b'..'z';
let _ = 'B'..'Z';
+ let _ = '1'..'9';
let _ = (b'a')..=(b'z');
let _ = b'A'..=b'Z';
+ let _ = b'0'..=b'9';
let _ = b'b'..b'z';
let _ = b'B'..b'Z';
+ let _ = b'1'..b'9';
let _ = a!()..='z';
+ let _ = A!()..='Z';
+ let _ = zero!()..='9';
let _ = match 0u8 {
b'a'..=b'z' if true => 1,
b'A'..=b'Z' if true => 2,
- b'b'..b'z' => 3,
- b'B'..b'Z' => 4,
- _ => 5,
+ b'0'..=b'9' if true => 3,
+ b'b'..b'z' => 4,
+ b'B'..b'Z' => 5,
+ b'1'..b'9' => 6,
+ _ => 7,
};
let _ = match 'x' {
'a'..='z' if true => 1,
'A'..='Z' if true => 2,
- 'b'..'z' => 3,
- 'B'..'Z' => 4,
- _ => 5,
+ '0'..='9' if true => 3,
+ 'b'..'z' => 4,
+ 'B'..'Z' => 5,
+ '1'..'9' => 6,
+ _ => 7,
};
- almost_complete_letter_range!();
+ almost_complete_range!();
b!();
}
@@ -65,15 +88,21 @@ fn main() {
fn _under_msrv() {
let _ = match 'a' {
'a'...'z' => 1,
- _ => 2,
+ 'A'...'Z' => 2,
+ '0'...'9' => 3,
+ _ => 4,
};
}
#[clippy::msrv = "1.26"]
fn _meets_msrv() {
let _ = 'a'..='z';
+ let _ = 'A'..='Z';
+ let _ = '0'..='9';
let _ = match 'a' {
'a'..='z' => 1,
- _ => 2,
+ 'A'..='Z' => 1,
+ '0'..='9' => 3,
+ _ => 4,
};
}
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.rs b/src/tools/clippy/tests/ui/almost_complete_range.rs
index 9979316ec..ae7e07ab8 100644
--- a/src/tools/clippy/tests/ui/almost_complete_letter_range.rs
+++ b/src/tools/clippy/tests/ui/almost_complete_range.rs
@@ -4,9 +4,10 @@
#![feature(exclusive_range_pattern)]
#![feature(stmt_expr_attributes)]
-#![warn(clippy::almost_complete_letter_range)]
+#![warn(clippy::almost_complete_range)]
#![allow(ellipsis_inclusive_range_patterns)]
#![allow(clippy::needless_parens_on_range_literals)]
+#![allow(clippy::double_parens)]
#[macro_use]
extern crate macro_rules;
@@ -16,10 +17,22 @@ macro_rules! a {
'a'
};
}
+macro_rules! A {
+ () => {
+ 'A'
+ };
+}
+macro_rules! zero {
+ () => {
+ '0'
+ };
+}
macro_rules! b {
() => {
let _ = 'a'..'z';
+ let _ = 'A'..'Z';
+ let _ = '0'..'9';
};
}
@@ -28,36 +41,46 @@ fn main() {
{
let _ = ('a') ..'z';
let _ = 'A' .. ('Z');
+ let _ = ((('0'))) .. ('9');
}
let _ = 'b'..'z';
let _ = 'B'..'Z';
+ let _ = '1'..'9';
let _ = (b'a')..(b'z');
let _ = b'A'..b'Z';
+ let _ = b'0'..b'9';
let _ = b'b'..b'z';
let _ = b'B'..b'Z';
+ let _ = b'1'..b'9';
let _ = a!()..'z';
+ let _ = A!()..'Z';
+ let _ = zero!()..'9';
let _ = match 0u8 {
b'a'..b'z' if true => 1,
b'A'..b'Z' if true => 2,
- b'b'..b'z' => 3,
- b'B'..b'Z' => 4,
- _ => 5,
+ b'0'..b'9' if true => 3,
+ b'b'..b'z' => 4,
+ b'B'..b'Z' => 5,
+ b'1'..b'9' => 6,
+ _ => 7,
};
let _ = match 'x' {
'a'..'z' if true => 1,
'A'..'Z' if true => 2,
- 'b'..'z' => 3,
- 'B'..'Z' => 4,
- _ => 5,
+ '0'..'9' if true => 3,
+ 'b'..'z' => 4,
+ 'B'..'Z' => 5,
+ '1'..'9' => 6,
+ _ => 7,
};
- almost_complete_letter_range!();
+ almost_complete_range!();
b!();
}
@@ -65,15 +88,21 @@ fn main() {
fn _under_msrv() {
let _ = match 'a' {
'a'..'z' => 1,
- _ => 2,
+ 'A'..'Z' => 2,
+ '0'..'9' => 3,
+ _ => 4,
};
}
#[clippy::msrv = "1.26"]
fn _meets_msrv() {
let _ = 'a'..'z';
+ let _ = 'A'..'Z';
+ let _ = '0'..'9';
let _ = match 'a' {
'a'..'z' => 1,
- _ => 2,
+ 'A'..'Z' => 1,
+ '0'..'9' => 3,
+ _ => 4,
};
}
diff --git a/src/tools/clippy/tests/ui/almost_complete_range.stderr b/src/tools/clippy/tests/ui/almost_complete_range.stderr
new file mode 100644
index 000000000..a7a532878
--- /dev/null
+++ b/src/tools/clippy/tests/ui/almost_complete_range.stderr
@@ -0,0 +1,235 @@
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:42:17
+ |
+LL | let _ = ('a') ..'z';
+ | ^^^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+ |
+ = note: `-D clippy::almost-complete-range` implied by `-D warnings`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:43:17
+ |
+LL | let _ = 'A' .. ('Z');
+ | ^^^^--^^^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:44:17
+ |
+LL | let _ = ((('0'))) .. ('9');
+ | ^^^^^^^^^^--^^^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:51:13
+ |
+LL | let _ = (b'a')..(b'z');
+ | ^^^^^^--^^^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:52:13
+ |
+LL | let _ = b'A'..b'Z';
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:53:13
+ |
+LL | let _ = b'0'..b'9';
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:59:13
+ |
+LL | let _ = a!()..'z';
+ | ^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:60:13
+ |
+LL | let _ = A!()..'Z';
+ | ^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:61:13
+ |
+LL | let _ = zero!()..'9';
+ | ^^^^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:64:9
+ |
+LL | b'a'..b'z' if true => 1,
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:65:9
+ |
+LL | b'A'..b'Z' if true => 2,
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:66:9
+ |
+LL | b'0'..b'9' if true => 3,
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:74:9
+ |
+LL | 'a'..'z' if true => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:75:9
+ |
+LL | 'A'..'Z' if true => 2,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:76:9
+ |
+LL | '0'..'9' if true => 3,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:33:17
+ |
+LL | let _ = 'a'..'z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:34:17
+ |
+LL | let _ = 'A'..'Z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:35:17
+ |
+LL | let _ = '0'..'9';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:90:9
+ |
+LL | 'a'..'z' => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `...`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:91:9
+ |
+LL | 'A'..'Z' => 2,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `...`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:92:9
+ |
+LL | '0'..'9' => 3,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `...`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:99:13
+ |
+LL | let _ = 'a'..'z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:100:13
+ |
+LL | let _ = 'A'..'Z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:101:13
+ |
+LL | let _ = '0'..'9';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:103:9
+ |
+LL | 'a'..'z' => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:104:9
+ |
+LL | 'A'..'Z' => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:105:9
+ |
+LL | '0'..'9' => 3,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: aborting due to 27 previous errors
+
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index b5ed8988a..918cf81c6 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -2,6 +2,7 @@
clippy::assign_op_pattern,
clippy::erasing_op,
clippy::identity_op,
+ clippy::no_effect,
clippy::op_ref,
clippy::unnecessary_owned_empty_strings,
arithmetic_overflow,
@@ -12,31 +13,95 @@
use core::num::{Saturating, Wrapping};
+#[derive(Clone, Copy)]
pub struct Custom;
macro_rules! impl_arith {
- ( $( $_trait:ident, $ty:ty, $method:ident; )* ) => {
+ ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
$(
- impl core::ops::$_trait<$ty> for Custom {
- type Output = Self;
- fn $method(self, _: $ty) -> Self::Output { Self }
+ impl core::ops::$_trait<$lhs> for $rhs {
+ type Output = Custom;
+ fn $method(self, _: $lhs) -> Self::Output { todo!() }
+ }
+ )*
+ }
+}
+
+macro_rules! impl_assign_arith {
+ ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => {
+ $(
+ impl core::ops::$_trait<$lhs> for $rhs {
+ fn $method(&mut self, _: $lhs) {}
}
)*
}
}
impl_arith!(
- Add, i32, add;
- Div, i32, div;
- Mul, i32, mul;
- Sub, i32, sub;
-
- Add, f64, add;
- Div, f64, div;
- Mul, f64, mul;
- Sub, f64, sub;
+ Add, Custom, Custom, add;
+ Div, Custom, Custom, div;
+ Mul, Custom, Custom, mul;
+ Rem, Custom, Custom, rem;
+ Sub, Custom, Custom, sub;
+
+ Add, Custom, &Custom, add;
+ Div, Custom, &Custom, div;
+ Mul, Custom, &Custom, mul;
+ Rem, Custom, &Custom, rem;
+ Sub, Custom, &Custom, sub;
+
+ Add, &Custom, Custom, add;
+ Div, &Custom, Custom, div;
+ Mul, &Custom, Custom, mul;
+ Rem, &Custom, Custom, rem;
+ Sub, &Custom, Custom, sub;
+
+ Add, &Custom, &Custom, add;
+ Div, &Custom, &Custom, div;
+ Mul, &Custom, &Custom, mul;
+ Rem, &Custom, &Custom, rem;
+ Sub, &Custom, &Custom, sub;
+);
+
+impl_assign_arith!(
+ AddAssign, Custom, Custom, add_assign;
+ DivAssign, Custom, Custom, div_assign;
+ MulAssign, Custom, Custom, mul_assign;
+ RemAssign, Custom, Custom, rem_assign;
+ SubAssign, Custom, Custom, sub_assign;
+
+ AddAssign, Custom, &Custom, add_assign;
+ DivAssign, Custom, &Custom, div_assign;
+ MulAssign, Custom, &Custom, mul_assign;
+ RemAssign, Custom, &Custom, rem_assign;
+ SubAssign, Custom, &Custom, sub_assign;
+
+ AddAssign, &Custom, Custom, add_assign;
+ DivAssign, &Custom, Custom, div_assign;
+ MulAssign, &Custom, Custom, mul_assign;
+ RemAssign, &Custom, Custom, rem_assign;
+ SubAssign, &Custom, Custom, sub_assign;
+
+ AddAssign, &Custom, &Custom, add_assign;
+ DivAssign, &Custom, &Custom, div_assign;
+ MulAssign, &Custom, &Custom, mul_assign;
+ RemAssign, &Custom, &Custom, rem_assign;
+ SubAssign, &Custom, &Custom, sub_assign;
);
+impl core::ops::Neg for Custom {
+ type Output = Custom;
+ fn neg(self) -> Self::Output {
+ todo!()
+ }
+}
+impl core::ops::Neg for &Custom {
+ type Output = Custom;
+ fn neg(self) -> Self::Output {
+ todo!()
+ }
+}
+
pub fn association_with_structures_should_not_trigger_the_lint() {
enum Foo {
Bar = -2,
@@ -125,6 +190,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n *= &0;
_n *= 1;
_n *= &1;
+ _n += -0;
+ _n += &-0;
+ _n -= -0;
+ _n -= &-0;
+ _n /= -99;
+ _n /= &-99;
+ _n %= -99;
+ _n %= &-99;
+ _n *= -0;
+ _n *= &-0;
+ _n *= -1;
+ _n *= &-1;
// Binary
_n = _n + 0;
@@ -158,8 +235,9 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n = -&i32::MIN;
}
-pub fn runtime_ops() {
+pub fn unknown_ops_or_runtime_ops_that_can_overflow() {
let mut _n = i32::MAX;
+ let mut _custom = Custom;
// Assign
_n += 1;
@@ -172,6 +250,36 @@ pub fn runtime_ops() {
_n %= &0;
_n *= 2;
_n *= &2;
+ _n += -1;
+ _n += &-1;
+ _n -= -1;
+ _n -= &-1;
+ _n /= -0;
+ _n /= &-0;
+ _n %= -0;
+ _n %= &-0;
+ _n *= -2;
+ _n *= &-2;
+ _custom += Custom;
+ _custom += &Custom;
+ _custom -= Custom;
+ _custom -= &Custom;
+ _custom /= Custom;
+ _custom /= &Custom;
+ _custom %= Custom;
+ _custom %= &Custom;
+ _custom *= Custom;
+ _custom *= &Custom;
+ _custom += -Custom;
+ _custom += &-Custom;
+ _custom -= -Custom;
+ _custom -= &-Custom;
+ _custom /= -Custom;
+ _custom /= &-Custom;
+ _custom %= -Custom;
+ _custom %= &-Custom;
+ _custom *= -Custom;
+ _custom *= &-Custom;
// Binary
_n = _n + 1;
@@ -193,36 +301,73 @@ pub fn runtime_ops() {
_n = 23 + &85;
_n = &23 + 85;
_n = &23 + &85;
-
- // Custom
- let _ = Custom + 0;
- let _ = Custom + 1;
- let _ = Custom + 2;
- let _ = Custom + 0.0;
- let _ = Custom + 1.0;
- let _ = Custom + 2.0;
- let _ = Custom - 0;
- let _ = Custom - 1;
- let _ = Custom - 2;
- let _ = Custom - 0.0;
- let _ = Custom - 1.0;
- let _ = Custom - 2.0;
- let _ = Custom / 0;
- let _ = Custom / 1;
- let _ = Custom / 2;
- let _ = Custom / 0.0;
- let _ = Custom / 1.0;
- let _ = Custom / 2.0;
- let _ = Custom * 0;
- let _ = Custom * 1;
- let _ = Custom * 2;
- let _ = Custom * 0.0;
- let _ = Custom * 1.0;
- let _ = Custom * 2.0;
+ _custom = _custom + _custom;
+ _custom = _custom + &_custom;
+ _custom = Custom + _custom;
+ _custom = &Custom + _custom;
+ _custom = _custom - Custom;
+ _custom = _custom - &Custom;
+ _custom = Custom - _custom;
+ _custom = &Custom - _custom;
+ _custom = _custom / Custom;
+ _custom = _custom / &Custom;
+ _custom = _custom % Custom;
+ _custom = _custom % &Custom;
+ _custom = _custom * Custom;
+ _custom = _custom * &Custom;
+ _custom = Custom * _custom;
+ _custom = &Custom * _custom;
+ _custom = Custom + &Custom;
+ _custom = &Custom + Custom;
+ _custom = &Custom + &Custom;
// Unary
_n = -_n;
_n = -&_n;
+ _custom = -_custom;
+ _custom = -&_custom;
+}
+
+// Copied and pasted from the `integer_arithmetic` lint for comparison.
+pub fn integer_arithmetic() {
+ let mut i = 1i32;
+ let mut var1 = 0i32;
+ let mut var2 = -1i32;
+
+ 1 + i;
+ i * 2;
+ 1 % i / 2;
+ i - 2 + 2 - i;
+ -i;
+ i >> 1;
+ i << 1;
+
+ -1;
+ -(-1);
+
+ i & 1;
+ i | 1;
+ i ^ 1;
+
+ i += 1;
+ i -= 1;
+ i *= 2;
+ i /= 2;
+ i /= 0;
+ i /= -1;
+ i /= var1;
+ i /= var2;
+ i %= 2;
+ i %= 0;
+ i %= -1;
+ i %= var1;
+ i %= var2;
+ i <<= 3;
+ i >>= 2;
+
+ i |= 1;
+ i &= 1;
+ i ^= i;
}
fn main() {}
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 0259a0824..5e349f6b4 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,352 +1,598 @@
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:78:13
- |
-LL | let _ = String::new() + "";
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
-
-error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:86:27
- |
-LL | let inferred_string = string + "";
- | ^^^^^^^^^^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:90:13
- |
-LL | let _ = inferred_string + "";
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:165:5
+ --> $DIR/arithmetic_side_effects.rs:243:5
|
LL | _n += 1;
| ^^^^^^^
+ |
+ = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:166:5
+ --> $DIR/arithmetic_side_effects.rs:244:5
|
LL | _n += &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:167:5
+ --> $DIR/arithmetic_side_effects.rs:245:5
|
LL | _n -= 1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:168:5
+ --> $DIR/arithmetic_side_effects.rs:246:5
|
LL | _n -= &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:169:5
+ --> $DIR/arithmetic_side_effects.rs:247:5
|
LL | _n /= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:170:5
+ --> $DIR/arithmetic_side_effects.rs:248:5
|
LL | _n /= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:171:5
+ --> $DIR/arithmetic_side_effects.rs:249:5
|
LL | _n %= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:172:5
+ --> $DIR/arithmetic_side_effects.rs:250:5
|
LL | _n %= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:173:5
+ --> $DIR/arithmetic_side_effects.rs:251:5
|
LL | _n *= 2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:174:5
+ --> $DIR/arithmetic_side_effects.rs:252:5
|
LL | _n *= &2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:177:10
+ --> $DIR/arithmetic_side_effects.rs:253:5
+ |
+LL | _n += -1;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:254:5
+ |
+LL | _n += &-1;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:255:5
+ |
+LL | _n -= -1;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:256:5
+ |
+LL | _n -= &-1;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:257:5
+ |
+LL | _n /= -0;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:258:5
+ |
+LL | _n /= &-0;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:259:5
+ |
+LL | _n %= -0;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:260:5
+ |
+LL | _n %= &-0;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:261:5
+ |
+LL | _n *= -2;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:262:5
+ |
+LL | _n *= &-2;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:263:5
+ |
+LL | _custom += Custom;
+ | ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:264:5
+ |
+LL | _custom += &Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:265:5
+ |
+LL | _custom -= Custom;
+ | ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:266:5
+ |
+LL | _custom -= &Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:267:5
+ |
+LL | _custom /= Custom;
+ | ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:268:5
+ |
+LL | _custom /= &Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:269:5
+ |
+LL | _custom %= Custom;
+ | ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:270:5
+ |
+LL | _custom %= &Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:271:5
+ |
+LL | _custom *= Custom;
+ | ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:272:5
+ |
+LL | _custom *= &Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:273:5
+ |
+LL | _custom += -Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:274:5
+ |
+LL | _custom += &-Custom;
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:275:5
+ |
+LL | _custom -= -Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:276:5
+ |
+LL | _custom -= &-Custom;
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:277:5
+ |
+LL | _custom /= -Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:278:5
+ |
+LL | _custom /= &-Custom;
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:279:5
+ |
+LL | _custom %= -Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:280:5
+ |
+LL | _custom %= &-Custom;
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:281:5
+ |
+LL | _custom *= -Custom;
+ | ^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:282:5
+ |
+LL | _custom *= &-Custom;
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:285:10
|
LL | _n = _n + 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:178:10
+ --> $DIR/arithmetic_side_effects.rs:286:10
|
LL | _n = _n + &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:179:10
+ --> $DIR/arithmetic_side_effects.rs:287:10
|
LL | _n = 1 + _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:180:10
+ --> $DIR/arithmetic_side_effects.rs:288:10
|
LL | _n = &1 + _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:181:10
+ --> $DIR/arithmetic_side_effects.rs:289:10
|
LL | _n = _n - 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:182:10
+ --> $DIR/arithmetic_side_effects.rs:290:10
|
LL | _n = _n - &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:183:10
+ --> $DIR/arithmetic_side_effects.rs:291:10
|
LL | _n = 1 - _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:184:10
+ --> $DIR/arithmetic_side_effects.rs:292:10
|
LL | _n = &1 - _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:185:10
+ --> $DIR/arithmetic_side_effects.rs:293:10
|
LL | _n = _n / 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:186:10
+ --> $DIR/arithmetic_side_effects.rs:294:10
|
LL | _n = _n / &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:187:10
+ --> $DIR/arithmetic_side_effects.rs:295:10
|
LL | _n = _n % 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:188:10
+ --> $DIR/arithmetic_side_effects.rs:296:10
|
LL | _n = _n % &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:189:10
+ --> $DIR/arithmetic_side_effects.rs:297:10
|
LL | _n = _n * 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:190:10
+ --> $DIR/arithmetic_side_effects.rs:298:10
|
LL | _n = _n * &2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:191:10
+ --> $DIR/arithmetic_side_effects.rs:299:10
|
LL | _n = 2 * _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:192:10
+ --> $DIR/arithmetic_side_effects.rs:300:10
|
LL | _n = &2 * _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:193:10
+ --> $DIR/arithmetic_side_effects.rs:301:10
|
LL | _n = 23 + &85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:194:10
+ --> $DIR/arithmetic_side_effects.rs:302:10
|
LL | _n = &23 + 85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:195:10
+ --> $DIR/arithmetic_side_effects.rs:303:10
|
LL | _n = &23 + &85;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:198:13
+ --> $DIR/arithmetic_side_effects.rs:304:15
+ |
+LL | _custom = _custom + _custom;
+ | ^^^^^^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:305:15
|
-LL | let _ = Custom + 0;
- | ^^^^^^^^^^
+LL | _custom = _custom + &_custom;
+ | ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:199:13
+ --> $DIR/arithmetic_side_effects.rs:306:15
|
-LL | let _ = Custom + 1;
- | ^^^^^^^^^^
+LL | _custom = Custom + _custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:200:13
+ --> $DIR/arithmetic_side_effects.rs:307:15
|
-LL | let _ = Custom + 2;
- | ^^^^^^^^^^
+LL | _custom = &Custom + _custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:201:13
+ --> $DIR/arithmetic_side_effects.rs:308:15
|
-LL | let _ = Custom + 0.0;
- | ^^^^^^^^^^^^
+LL | _custom = _custom - Custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:202:13
+ --> $DIR/arithmetic_side_effects.rs:309:15
|
-LL | let _ = Custom + 1.0;
- | ^^^^^^^^^^^^
+LL | _custom = _custom - &Custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:203:13
+ --> $DIR/arithmetic_side_effects.rs:310:15
|
-LL | let _ = Custom + 2.0;
- | ^^^^^^^^^^^^
+LL | _custom = Custom - _custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:204:13
+ --> $DIR/arithmetic_side_effects.rs:311:15
|
-LL | let _ = Custom - 0;
- | ^^^^^^^^^^
+LL | _custom = &Custom - _custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:205:13
+ --> $DIR/arithmetic_side_effects.rs:312:15
|
-LL | let _ = Custom - 1;
- | ^^^^^^^^^^
+LL | _custom = _custom / Custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:206:13
+ --> $DIR/arithmetic_side_effects.rs:313:15
|
-LL | let _ = Custom - 2;
- | ^^^^^^^^^^
+LL | _custom = _custom / &Custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:207:13
+ --> $DIR/arithmetic_side_effects.rs:314:15
|
-LL | let _ = Custom - 0.0;
- | ^^^^^^^^^^^^
+LL | _custom = _custom % Custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:208:13
+ --> $DIR/arithmetic_side_effects.rs:315:15
|
-LL | let _ = Custom - 1.0;
- | ^^^^^^^^^^^^
+LL | _custom = _custom % &Custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:209:13
+ --> $DIR/arithmetic_side_effects.rs:316:15
|
-LL | let _ = Custom - 2.0;
- | ^^^^^^^^^^^^
+LL | _custom = _custom * Custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:210:13
+ --> $DIR/arithmetic_side_effects.rs:317:15
|
-LL | let _ = Custom / 0;
- | ^^^^^^^^^^
+LL | _custom = _custom * &Custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:211:13
+ --> $DIR/arithmetic_side_effects.rs:318:15
|
-LL | let _ = Custom / 1;
- | ^^^^^^^^^^
+LL | _custom = Custom * _custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:212:13
+ --> $DIR/arithmetic_side_effects.rs:319:15
|
-LL | let _ = Custom / 2;
- | ^^^^^^^^^^
+LL | _custom = &Custom * _custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:213:13
+ --> $DIR/arithmetic_side_effects.rs:320:15
|
-LL | let _ = Custom / 0.0;
- | ^^^^^^^^^^^^
+LL | _custom = Custom + &Custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:214:13
+ --> $DIR/arithmetic_side_effects.rs:321:15
|
-LL | let _ = Custom / 1.0;
- | ^^^^^^^^^^^^
+LL | _custom = &Custom + Custom;
+ | ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:215:13
+ --> $DIR/arithmetic_side_effects.rs:322:15
|
-LL | let _ = Custom / 2.0;
- | ^^^^^^^^^^^^
+LL | _custom = &Custom + &Custom;
+ | ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:216:13
+ --> $DIR/arithmetic_side_effects.rs:325:10
|
-LL | let _ = Custom * 0;
- | ^^^^^^^^^^
+LL | _n = -_n;
+ | ^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:217:13
+ --> $DIR/arithmetic_side_effects.rs:326:10
|
-LL | let _ = Custom * 1;
- | ^^^^^^^^^^
+LL | _n = -&_n;
+ | ^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:218:13
+ --> $DIR/arithmetic_side_effects.rs:327:15
|
-LL | let _ = Custom * 2;
- | ^^^^^^^^^^
+LL | _custom = -_custom;
+ | ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:219:13
+ --> $DIR/arithmetic_side_effects.rs:328:15
|
-LL | let _ = Custom * 0.0;
- | ^^^^^^^^^^^^
+LL | _custom = -&_custom;
+ | ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:220:13
+ --> $DIR/arithmetic_side_effects.rs:337:5
|
-LL | let _ = Custom * 1.0;
- | ^^^^^^^^^^^^
+LL | 1 + i;
+ | ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:221:13
+ --> $DIR/arithmetic_side_effects.rs:338:5
|
-LL | let _ = Custom * 2.0;
- | ^^^^^^^^^^^^
+LL | i * 2;
+ | ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:224:10
+ --> $DIR/arithmetic_side_effects.rs:340:5
|
-LL | _n = -_n;
- | ^^^
+LL | i - 2 + 2 - i;
+ | ^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:225:10
+ --> $DIR/arithmetic_side_effects.rs:341:5
|
-LL | _n = -&_n;
- | ^^^^
+LL | -i;
+ | ^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:342:5
+ |
+LL | i >> 1;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:343:5
+ |
+LL | i << 1;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:352:5
+ |
+LL | i += 1;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:353:5
+ |
+LL | i -= 1;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:354:5
+ |
+LL | i *= 2;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:356:5
+ |
+LL | i /= 0;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:358:5
+ |
+LL | i /= var1;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:359:5
+ |
+LL | i /= var2;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:361:5
+ |
+LL | i %= 0;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:363:5
+ |
+LL | i %= var1;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:364:5
+ |
+LL | i %= var2;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:365:5
+ |
+LL | i <<= 3;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:366:5
+ |
+LL | i >>= 2;
+ | ^^^^^^^
-error: aborting due to 58 previous errors
+error: aborting due to 99 previous errors
diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr
index 92ba35929..22ce1c6f6 100644
--- a/src/tools/clippy/tests/ui/async_yields_async.stderr
+++ b/src/tools/clippy/tests/ui/async_yields_async.stderr
@@ -3,8 +3,7 @@ error: an async construct yields a type which is itself awaitable
|
LL | let _h = async {
| _____________________-
-LL | | async {
- | | _________^
+LL | |/ async {
LL | || 3
LL | || }
| ||_________^ awaitable value not awaited
@@ -37,8 +36,7 @@ error: an async construct yields a type which is itself awaitable
|
LL | let _j = async || {
| ________________________-
-LL | | async {
- | | _________^
+LL | |/ async {
LL | || 3
LL | || }
| ||_________^ awaitable value not awaited
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index ef3ca9aea..1e5f20e8c 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -142,8 +142,10 @@ macro_rules! equatable_if_let {
}
#[macro_export]
-macro_rules! almost_complete_letter_range {
+macro_rules! almost_complete_range {
() => {
let _ = 'a'..'z';
+ let _ = 'A'..'Z';
+ let _ = '0'..'9';
};
}
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index 911fa856a..7e9f074fd 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -21,16 +21,16 @@ macro_rules! outer {
fn main() {
let _string: Box<String> = Box::default();
let _byte = Box::<u8>::default();
- let _vec = Box::<std::vec::Vec<u8>>::default();
+ let _vec = Box::<Vec<u8>>::default();
let _impl = Box::<ImplementsDefault>::default();
let _impl2 = Box::<ImplementsDefault>::default();
let _impl3: Box<ImplementsDefault> = Box::default();
let _own = Box::new(OwnDefault::default()); // should not lint
- let _in_macro = outer!(Box::<std::string::String>::default());
- let _string_default = outer!(Box::<std::string::String>::default());
+ let _in_macro = outer!(Box::<String>::default());
+ let _string_default = outer!(Box::<String>::default());
let _vec2: Box<Vec<ImplementsDefault>> = Box::default();
let _vec3: Box<Vec<bool>> = Box::default();
- let _vec4: Box<_> = Box::<std::vec::Vec<bool>>::default();
+ let _vec4: Box<_> = Box::<Vec<bool>>::default();
let _more = ret_ty_fn();
call_ty_fn(Box::default());
}
@@ -54,4 +54,14 @@ impl Read for ImplementsDefault {
fn issue_9621_dyn_trait() {
let _: Box<dyn Read> = Box::<ImplementsDefault>::default();
+ issue_10089();
+}
+
+fn issue_10089() {
+ let _closure = || {
+ #[derive(Default)]
+ struct WeirdPathed;
+
+ let _ = Box::<WeirdPathed>::default();
+ };
}
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 20019c2ee..5c8d0b835 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -54,4 +54,14 @@ impl Read for ImplementsDefault {
fn issue_9621_dyn_trait() {
let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
+ issue_10089();
+}
+
+fn issue_10089() {
+ let _closure = || {
+ #[derive(Default)]
+ struct WeirdPathed;
+
+ let _ = Box::new(WeirdPathed::default());
+ };
}
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index 5ea410331..249eb340f 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -16,7 +16,7 @@ error: `Box::new(_)` of default value
--> $DIR/box_default.rs:24:16
|
LL | let _vec = Box::new(Vec::<u8>::new());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<u8>>::default()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<u8>>::default()`
error: `Box::new(_)` of default value
--> $DIR/box_default.rs:25:17
@@ -40,13 +40,13 @@ error: `Box::new(_)` of default value
--> $DIR/box_default.rs:29:28
|
LL | let _in_macro = outer!(Box::new(String::new()));
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
error: `Box::new(_)` of default value
--> $DIR/box_default.rs:30:34
|
LL | let _string_default = outer!(Box::new(String::from("")));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<String>::default()`
error: `Box::new(_)` of default value
--> $DIR/box_default.rs:31:46
@@ -64,7 +64,7 @@ error: `Box::new(_)` of default value
--> $DIR/box_default.rs:33:25
|
LL | let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<bool>>::default()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Vec<bool>>::default()`
error: `Box::new(_)` of default value
--> $DIR/box_default.rs:35:16
@@ -84,5 +84,11 @@ error: `Box::new(_)` of default value
LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
-error: aborting due to 14 previous errors
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:65:17
+ |
+LL | let _ = Box::new(WeirdPathed::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
+
+error: aborting due to 15 previous errors
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
new file mode 100644
index 000000000..5fbaa64db
--- /dev/null
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
@@ -0,0 +1,67 @@
+// run-rustfix
+#![warn(clippy::case_sensitive_file_extension_comparisons)]
+
+use std::string::String;
+
+struct TestStruct;
+
+impl TestStruct {
+ fn ends_with(self, _arg: &str) {}
+}
+
+#[allow(dead_code)]
+fn is_rust_file(filename: &str) -> bool {
+ std::path::Path::new(filename)
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
+}
+
+fn main() {
+ // std::string::String and &str should trigger the lint failure with .ext12
+ let _ = std::path::Path::new(&String::new())
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+ let _ = std::path::Path::new("str")
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+
+ // The fixup should preserve the indentation level
+ {
+ let _ = std::path::Path::new("str")
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+ }
+
+ // The test struct should not trigger the lint failure with .ext12
+ TestStruct {}.ends_with(".ext12");
+
+ // std::string::String and &str should trigger the lint failure with .EXT12
+ let _ = std::path::Path::new(&String::new())
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+ let _ = std::path::Path::new("str")
+ .extension()
+ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+
+ // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
+ let _ = String::new().to_lowercase().ends_with(".EXT12");
+ let _ = String::new().to_uppercase().ends_with(".EXT12");
+
+ // The test struct should not trigger the lint failure with .EXT12
+ TestStruct {}.ends_with(".EXT12");
+
+ // Should not trigger the lint failure with .eXT12
+ let _ = String::new().ends_with(".eXT12");
+ let _ = "str".ends_with(".eXT12");
+ TestStruct {}.ends_with(".eXT12");
+
+ // Should not trigger the lint failure with .EXT123 (too long)
+ let _ = String::new().ends_with(".EXT123");
+ let _ = "str".ends_with(".EXT123");
+ TestStruct {}.ends_with(".EXT123");
+
+ // Shouldn't fail if it doesn't start with a dot
+ let _ = String::new().ends_with("a.ext");
+ let _ = "str".ends_with("a.extA");
+ TestStruct {}.ends_with("a.ext");
+}
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
index 6f0485b52..3c0d4821f 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
@@ -1,3 +1,4 @@
+// run-rustfix
#![warn(clippy::case_sensitive_file_extension_comparisons)]
use std::string::String;
@@ -5,9 +6,10 @@ use std::string::String;
struct TestStruct;
impl TestStruct {
- fn ends_with(self, arg: &str) {}
+ fn ends_with(self, _arg: &str) {}
}
+#[allow(dead_code)]
fn is_rust_file(filename: &str) -> bool {
filename.ends_with(".rs")
}
@@ -17,6 +19,11 @@ fn main() {
let _ = String::new().ends_with(".ext12");
let _ = "str".ends_with(".ext12");
+ // The fixup should preserve the indentation level
+ {
+ let _ = "str".ends_with(".ext12");
+ }
+
// The test struct should not trigger the lint failure with .ext12
TestStruct {}.ends_with(".ext12");
@@ -24,6 +31,10 @@ fn main() {
let _ = String::new().ends_with(".EXT12");
let _ = "str".ends_with(".EXT12");
+ // Should not trigger the lint failure because of the calls to to_lowercase and to_uppercase
+ let _ = String::new().to_lowercase().ends_with(".EXT12");
+ let _ = String::new().to_uppercase().ends_with(".EXT12");
+
// The test struct should not trigger the lint failure with .EXT12
TestStruct {}.ends_with(".EXT12");
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
index a28dd8bd5..44c8e3fdf 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
@@ -1,43 +1,87 @@
error: case-sensitive file extension comparison
- --> $DIR/case_sensitive_file_extension_comparisons.rs:12:14
+ --> $DIR/case_sensitive_file_extension_comparisons.rs:14:5
|
LL | filename.ends_with(".rs")
- | ^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using a case-insensitive comparison instead
= note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings`
+help: use std::path::Path
+ |
+LL ~ std::path::Path::new(filename)
+LL + .extension()
+LL + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
+ |
error: case-sensitive file extension comparison
- --> $DIR/case_sensitive_file_extension_comparisons.rs:17:27
+ --> $DIR/case_sensitive_file_extension_comparisons.rs:19:13
|
LL | let _ = String::new().ends_with(".ext12");
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+ |
+LL ~ let _ = std::path::Path::new(&String::new())
+LL + .extension()
+LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+ |
error: case-sensitive file extension comparison
- --> $DIR/case_sensitive_file_extension_comparisons.rs:18:19
+ --> $DIR/case_sensitive_file_extension_comparisons.rs:20:13
|
LL | let _ = "str".ends_with(".ext12");
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+ |
+LL ~ let _ = std::path::Path::new("str")
+LL + .extension()
+LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+ |
error: case-sensitive file extension comparison
- --> $DIR/case_sensitive_file_extension_comparisons.rs:24:27
+ --> $DIR/case_sensitive_file_extension_comparisons.rs:24:17
+ |
+LL | let _ = "str".ends_with(".ext12");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+ |
+LL ~ let _ = std::path::Path::new("str")
+LL + .extension()
+LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12"));
+ |
+
+error: case-sensitive file extension comparison
+ --> $DIR/case_sensitive_file_extension_comparisons.rs:31:13
|
LL | let _ = String::new().ends_with(".EXT12");
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+ |
+LL ~ let _ = std::path::Path::new(&String::new())
+LL + .extension()
+LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+ |
error: case-sensitive file extension comparison
- --> $DIR/case_sensitive_file_extension_comparisons.rs:25:19
+ --> $DIR/case_sensitive_file_extension_comparisons.rs:32:13
|
LL | let _ = "str".ends_with(".EXT12");
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider using a case-insensitive comparison instead
+help: use std::path::Path
+ |
+LL ~ let _ = std::path::Path::new("str")
+LL + .extension()
+LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12"));
+ |
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
index 72a708b40..925cbf253 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.fixed
@@ -45,3 +45,9 @@ mod cast_lossless_in_impl {
}
}
}
+
+#[derive(PartialEq, Debug)]
+#[repr(i64)]
+enum Test {
+ A = u32::MAX as i64 + 1,
+}
diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.rs b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
index 34bb47181..c82bd9108 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_integer.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_integer.rs
@@ -45,3 +45,9 @@ mod cast_lossless_in_impl {
}
}
}
+
+#[derive(PartialEq, Debug)]
+#[repr(i64)]
+enum Test {
+ A = u32::MAX as i64 + 1,
+}
diff --git a/src/tools/clippy/tests/ui/clone_on_copy.stderr b/src/tools/clippy/tests/ui/clone_on_copy.stderr
index 42ae22777..862234d20 100644
--- a/src/tools/clippy/tests/ui/clone_on_copy.stderr
+++ b/src/tools/clippy/tests/ui/clone_on_copy.stderr
@@ -48,7 +48,7 @@ error: using `clone` on type `i32` which implements the `Copy` trait
LL | vec.push(42.clone());
| ^^^^^^^^^^ help: try removing the `clone` call: `42`
-error: using `clone` on type `std::option::Option<i32>` which implements the `Copy` trait
+error: using `clone` on type `Option<i32>` which implements the `Copy` trait
--> $DIR/clone_on_copy.rs:77:17
|
LL | let value = opt.clone()?; // operator precedence needed (*opt)?
diff --git a/src/tools/clippy/tests/ui/collapsible_str_replace.fixed b/src/tools/clippy/tests/ui/collapsible_str_replace.fixed
index 49fc9a962..9792ae9ed 100644
--- a/src/tools/clippy/tests/ui/collapsible_str_replace.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_str_replace.fixed
@@ -1,5 +1,6 @@
// run-rustfix
+#![allow(unused)]
#![warn(clippy::collapsible_str_replace)]
fn get_filter() -> char {
@@ -71,3 +72,13 @@ fn main() {
.replace('u', iter.next().unwrap())
.replace('s', iter.next().unwrap());
}
+
+#[clippy::msrv = "1.57"]
+fn msrv_1_57() {
+ let _ = "".replace('a', "1.57").replace('b', "1.57");
+}
+
+#[clippy::msrv = "1.58"]
+fn msrv_1_58() {
+ let _ = "".replace(['a', 'b'], "1.58");
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_str_replace.rs b/src/tools/clippy/tests/ui/collapsible_str_replace.rs
index e3e25c414..baee185b7 100644
--- a/src/tools/clippy/tests/ui/collapsible_str_replace.rs
+++ b/src/tools/clippy/tests/ui/collapsible_str_replace.rs
@@ -1,5 +1,6 @@
// run-rustfix
+#![allow(unused)]
#![warn(clippy::collapsible_str_replace)]
fn get_filter() -> char {
@@ -74,3 +75,13 @@ fn main() {
.replace('u', iter.next().unwrap())
.replace('s', iter.next().unwrap());
}
+
+#[clippy::msrv = "1.57"]
+fn msrv_1_57() {
+ let _ = "".replace('a', "1.57").replace('b', "1.57");
+}
+
+#[clippy::msrv = "1.58"]
+fn msrv_1_58() {
+ let _ = "".replace('a', "1.58").replace('b', "1.58");
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_str_replace.stderr b/src/tools/clippy/tests/ui/collapsible_str_replace.stderr
index 8e3daf3b8..223358cf5 100644
--- a/src/tools/clippy/tests/ui/collapsible_str_replace.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_str_replace.stderr
@@ -1,5 +1,5 @@
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:19:27
+ --> $DIR/collapsible_str_replace.rs:20:27
|
LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")`
@@ -7,19 +7,19 @@ LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l");
= note: `-D clippy::collapsible-str-replace` implied by `-D warnings`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:21:27
+ --> $DIR/collapsible_str_replace.rs:22:27
|
LL | let _ = "hesuo worpd".replace('s', l).replace('u', l);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], l)`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:23:27
+ --> $DIR/collapsible_str_replace.rs:24:27
|
LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:26:10
+ --> $DIR/collapsible_str_replace.rs:27:10
|
LL | .replace('s', "l")
| __________^
@@ -29,58 +29,64 @@ LL | | .replace('d', "l");
| |__________________________^ help: replace with: `replace(['s', 'u', 'p', 'd'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:31:27
+ --> $DIR/collapsible_str_replace.rs:32:27
|
LL | let _ = "hesuo world".replace(s, "l").replace('u', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:33:27
+ --> $DIR/collapsible_str_replace.rs:34:27
|
LL | let _ = "hesuo worpd".replace(s, "l").replace('u', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:35:27
+ --> $DIR/collapsible_str_replace.rs:36:27
|
LL | let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:37:27
+ --> $DIR/collapsible_str_replace.rs:38:27
|
LL | let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace(p, "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, p], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:39:27
+ --> $DIR/collapsible_str_replace.rs:40:27
|
LL | let _ = "hesuo worlp".replace('s', "l").replace('u', "l").replace('p', "d");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:41:45
+ --> $DIR/collapsible_str_replace.rs:42:45
|
LL | let _ = "hesuo worpd".replace('s', "x").replace('u', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['u', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:44:47
+ --> $DIR/collapsible_str_replace.rs:45:47
|
LL | let _ = "hesudo worpd".replace("su", "l").replace('d', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['d', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:46:28
+ --> $DIR/collapsible_str_replace.rs:47:28
|
LL | let _ = "hesudo worpd".replace(d, "l").replace('p', "l").replace("su", "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([d, 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:48:27
+ --> $DIR/collapsible_str_replace.rs:49:27
|
LL | let _ = "hesuo world".replace(get_filter(), "l").replace('s', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([get_filter(), 's'], "l")`
-error: aborting due to 13 previous errors
+error: used consecutive `str::replace` call
+ --> $DIR/collapsible_str_replace.rs:86:16
+ |
+LL | let _ = "".replace('a', "1.58").replace('b', "1.58");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['a', 'b'], "1.58")`
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
index 638e4a548..efdd56dd4 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
@@ -17,9 +17,12 @@ error[E0412]: cannot find type `VAL` in this scope
--> $DIR/ice-6252.rs:10:63
|
LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
- | - ^^^ not found in this scope
- | |
- | help: you might be missing a type parameter: `, VAL`
+ | ^^^ not found in this scope
+ |
+help: you might be missing a type parameter
+ |
+LL | impl<N, M, VAL> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
+ | +++++
error[E0046]: not all trait items implemented, missing: `VAL`
--> $DIR/ice-6252.rs:10:1
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6254.rs b/src/tools/clippy/tests/ui/crashes/ice-6254.rs
index a2a60a169..8af608903 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6254.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6254.rs
@@ -1,4 +1,4 @@
-// originally from ./src/test/ui/pattern/usefulness/consts-opaque.rs
+// originally from ./tests/ui/pattern/usefulness/consts-opaque.rs
// panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())',
// compiler/rustc_mir_build/src/thir/pattern/_match.rs:2030:5
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6255.rs b/src/tools/clippy/tests/ui/crashes/ice-6255.rs
index bd4a81d98..ccde6aa2b 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6255.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6255.rs
@@ -1,4 +1,4 @@
-// originally from rustc ./src/test/ui/macros/issue-78325-inconsistent-resolution.rs
+// originally from rustc ./tests/ui/macros/issue-78325-inconsistent-resolution.rs
// inconsistent resolution for a macro
macro_rules! define_other_core {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.rs b/src/tools/clippy/tests/ui/crashes/ice-6256.rs
index 67308263d..f9ee3e058 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6256.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6256.rs
@@ -1,4 +1,4 @@
-// originally from rustc ./src/test/ui/regions/issue-78262.rs
+// originally from rustc ./tests/ui/regions/issue-78262.rs
// ICE: to get the signature of a closure, use substs.as_closure().sig() not fn_sig()
#![allow(clippy::upper_case_acronyms)]
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index e6a65b46d..ddb5f1342 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -1,143 +1,143 @@
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:5:22
|
LL | if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::dbg-macro` implied by `-D warnings`
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | if let Some(n) = n.checked_sub(4) { n } else { n }
| ~~~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:9:8
|
LL | if dbg!(n <= 1) {
| ^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | if n <= 1 {
| ~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:10:9
|
LL | dbg!(1)
| ^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 1
|
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:12:9
|
LL | dbg!(n * factorial(n - 1))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | n * factorial(n - 1)
|
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:17:5
|
LL | dbg!(42);
| ^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 42;
| ~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:18:5
|
LL | dbg!(dbg!(dbg!(42)));
| ^^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | dbg!(dbg!(42));
| ~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:19:14
|
LL | foo(3) + dbg!(factorial(4));
| ^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | foo(3) + factorial(4);
| ~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:20:5
|
LL | dbg!(1, 2, dbg!(3, 4));
| ^^^^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | (1, 2, dbg!(3, 4));
| ~~~~~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:21:5
|
LL | dbg!(1, 2, 3, 4, 5);
| ^^^^^^^^^^^^^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | (1, 2, 3, 4, 5);
| ~~~~~~~~~~~~~~~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:41:9
|
LL | dbg!(2);
| ^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 2;
| ~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:47:5
|
LL | dbg!(1);
| ^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 1;
| ~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:52:5
|
LL | dbg!(1);
| ^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 1;
| ~
-error: `dbg!` macro is intended as a debugging tool
+error: the `dbg!` macro is intended as a debugging tool
--> $DIR/dbg_macro.rs:58:9
|
LL | dbg!(1);
| ^^^^^^^
|
-help: ensure to avoid having uses of it in version control
+help: remove the invocation before committing it to a version control system
|
LL | 1;
| ~
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index a7da8f89a..1af77d1a2 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -15,7 +15,7 @@ pub trait Copy {}
pub unsafe trait Freeze {}
#[lang = "start"]
-fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
0
}
diff --git a/src/tools/clippy/tests/ui/default_trait_access.fixed b/src/tools/clippy/tests/ui/default_trait_access.fixed
index eedd43619..5640599d4 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.fixed
+++ b/src/tools/clippy/tests/ui/default_trait_access.fixed
@@ -12,17 +12,17 @@ use std::default::Default as D2;
use std::string;
fn main() {
- let s1: String = std::string::String::default();
+ let s1: String = String::default();
let s2 = String::default();
- let s3: String = std::string::String::default();
+ let s3: String = String::default();
- let s4: String = std::string::String::default();
+ let s4: String = String::default();
let s5 = string::String::default();
- let s6: String = std::string::String::default();
+ let s6: String = String::default();
let s7 = std::string::String::default();
diff --git a/src/tools/clippy/tests/ui/default_trait_access.stderr b/src/tools/clippy/tests/ui/default_trait_access.stderr
index 49b2dde3f..e4f73c08d 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.stderr
+++ b/src/tools/clippy/tests/ui/default_trait_access.stderr
@@ -1,8 +1,8 @@
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
--> $DIR/default_trait_access.rs:15:22
|
LL | let s1: String = Default::default();
- | ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+ | ^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
|
note: the lint level is defined here
--> $DIR/default_trait_access.rs:3:9
@@ -10,23 +10,23 @@ note: the lint level is defined here
LL | #![deny(clippy::default_trait_access)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
--> $DIR/default_trait_access.rs:19:22
|
LL | let s3: String = D2::default();
- | ^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+ | ^^^^^^^^^^^^^ help: try: `String::default()`
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
--> $DIR/default_trait_access.rs:21:22
|
LL | let s4: String = std::default::Default::default();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
-error: calling `std::string::String::default()` is more clear than this expression
+error: calling `String::default()` is more clear than this expression
--> $DIR/default_trait_access.rs:25:22
|
LL | let s6: String = default::Default::default();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `String::default()`
error: calling `GenericDerivedDefault::default()` is more clear than this expression
--> $DIR/default_trait_access.rs:35:46
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
index 7dcdfb093..ee8456f5d 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.fixed
+++ b/src/tools/clippy/tests/ui/derivable_impls.fixed
@@ -210,4 +210,25 @@ impl Default for IntOrString {
}
}
+#[derive(Default)]
+pub enum SimpleEnum {
+ Foo,
+ #[default]
+ Bar,
+}
+
+
+
+pub enum NonExhaustiveEnum {
+ Foo,
+ #[non_exhaustive]
+ Bar,
+}
+
+impl Default for NonExhaustiveEnum {
+ fn default() -> Self {
+ NonExhaustiveEnum::Bar
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index 625cbcdde..14af419bc 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -244,4 +244,27 @@ impl Default for IntOrString {
}
}
+pub enum SimpleEnum {
+ Foo,
+ Bar,
+}
+
+impl Default for SimpleEnum {
+ fn default() -> Self {
+ SimpleEnum::Bar
+ }
+}
+
+pub enum NonExhaustiveEnum {
+ Foo,
+ #[non_exhaustive]
+ Bar,
+}
+
+impl Default for NonExhaustiveEnum {
+ fn default() -> Self {
+ NonExhaustiveEnum::Bar
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
index c1db5a58b..81963c3be 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.stderr
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -113,5 +113,26 @@ help: ...and instead derive it
LL | #[derive(Default)]
|
-error: aborting due to 7 previous errors
+error: this `impl` can be derived
+ --> $DIR/derivable_impls.rs:252:1
+ |
+LL | / impl Default for SimpleEnum {
+LL | | fn default() -> Self {
+LL | | SimpleEnum::Bar
+LL | | }
+LL | | }
+ | |_^
+ |
+ = help: remove the manual implementation...
+help: ...and instead derive it...
+ |
+LL | #[derive(Default)]
+ |
+help: ...and mark the default variant
+ |
+LL ~ #[default]
+LL ~ Bar,
+ |
+
+error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/tests/ui/derive.rs b/src/tools/clippy/tests/ui/derive.rs
index b276c384c..6e0ce55f5 100644
--- a/src/tools/clippy/tests/ui/derive.rs
+++ b/src/tools/clippy/tests/ui/derive.rs
@@ -86,4 +86,15 @@ impl<T: Clone, U> Clone for GenericRef<'_, T, U> {
}
}
+// https://github.com/rust-lang/rust-clippy/issues/10188
+#[repr(packed)]
+#[derive(Copy)]
+struct Packed<T>(T);
+
+impl<T: Copy> Clone for Packed<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr b/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
deleted file mode 100644
index 16c923978..000000000
--- a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
+++ /dev/null
@@ -1,59 +0,0 @@
-error: you are deriving `Hash` but have implemented `PartialEq` explicitly
- --> $DIR/derive_hash_xor_eq.rs:12:10
- |
-LL | #[derive(Hash)]
- | ^^^^
- |
-note: `PartialEq` implemented here
- --> $DIR/derive_hash_xor_eq.rs:15:1
- |
-LL | impl PartialEq for Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^
- = note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
- = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: you are deriving `Hash` but have implemented `PartialEq` explicitly
- --> $DIR/derive_hash_xor_eq.rs:21:10
- |
-LL | #[derive(Hash)]
- | ^^^^
- |
-note: `PartialEq` implemented here
- --> $DIR/derive_hash_xor_eq.rs:24:1
- |
-LL | impl PartialEq<Baz> for Baz {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: you are implementing `Hash` explicitly but have derived `PartialEq`
- --> $DIR/derive_hash_xor_eq.rs:33:1
- |
-LL | / impl std::hash::Hash for Bah {
-LL | | fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
-LL | | }
- | |_^
- |
-note: `PartialEq` implemented here
- --> $DIR/derive_hash_xor_eq.rs:30:10
- |
-LL | #[derive(PartialEq)]
- | ^^^^^^^^^
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: you are implementing `Hash` explicitly but have derived `PartialEq`
- --> $DIR/derive_hash_xor_eq.rs:51:5
- |
-LL | / impl Hash for Foo3 {
-LL | | fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
-LL | | }
- | |_____^
- |
-note: `PartialEq` implemented here
- --> $DIR/derive_hash_xor_eq.rs:48:14
- |
-LL | #[derive(PartialEq)]
- | ^^^^^^^^^
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/derive_hash_xor_eq.rs b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs
index 813ddc566..8ad09a8de 100644
--- a/src/tools/clippy/tests/ui/derive_hash_xor_eq.rs
+++ b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.rs
@@ -27,6 +27,8 @@ impl PartialEq<Baz> for Baz {
}
}
+// Implementing `Hash` with a derived `PartialEq` is fine. See #2627
+
#[derive(PartialEq)]
struct Bah;
@@ -34,23 +36,4 @@ impl std::hash::Hash for Bah {
fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
}
-#[derive(PartialEq)]
-struct Foo2;
-
-trait Hash {}
-
-// We don't want to lint on user-defined traits called `Hash`
-impl Hash for Foo2 {}
-
-mod use_hash {
- use std::hash::{Hash, Hasher};
-
- #[derive(PartialEq)]
- struct Foo3;
-
- impl Hash for Foo3 {
- fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
- }
-}
-
fn main() {}
diff --git a/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
new file mode 100644
index 000000000..230940f25
--- /dev/null
+++ b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr
@@ -0,0 +1,29 @@
+error: you are deriving `Hash` but have implemented `PartialEq` explicitly
+ --> $DIR/derived_hash_with_manual_eq.rs:12:10
+ |
+LL | #[derive(Hash)]
+ | ^^^^
+ |
+note: `PartialEq` implemented here
+ --> $DIR/derived_hash_with_manual_eq.rs:15:1
+ |
+LL | impl PartialEq for Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
+ = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: you are deriving `Hash` but have implemented `PartialEq` explicitly
+ --> $DIR/derived_hash_with_manual_eq.rs:21:10
+ |
+LL | #[derive(Hash)]
+ | ^^^^
+ |
+note: `PartialEq` implemented here
+ --> $DIR/derived_hash_with_manual_eq.rs:24:1
+ |
+LL | impl PartialEq<Baz> for Baz {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/drop_ref.rs b/src/tools/clippy/tests/ui/drop_ref.rs
index 7de0b0bbd..10044e65f 100644
--- a/src/tools/clippy/tests/ui/drop_ref.rs
+++ b/src/tools/clippy/tests/ui/drop_ref.rs
@@ -72,3 +72,26 @@ fn test_owl_result_2() -> Result<u8, ()> {
produce_half_owl_ok().map(drop)?;
Ok(1)
}
+
+#[allow(unused)]
+#[allow(clippy::unit_cmp)]
+fn issue10122(x: u8) {
+ // This is a function which returns a reference and has a side-effect, which means
+ // that calling drop() on the function is considered an idiomatic way of achieving the side-effect
+ // in a match arm.
+ fn println_and<T>(t: &T) -> &T {
+ println!("foo");
+ t
+ }
+
+ match x {
+ 0 => drop(println_and(&12)), // Don't lint (copy type), we only care about side-effects
+ 1 => drop(println_and(&String::new())), // Don't lint (no copy type), we only care about side-effects
+ 2 => {
+ drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+ },
+ 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+ 4 => drop(&2), // Lint, not a fn/method call
+ _ => (),
+ }
+}
diff --git a/src/tools/clippy/tests/ui/drop_ref.stderr b/src/tools/clippy/tests/ui/drop_ref.stderr
index 4743cf79b..293b9f6de 100644
--- a/src/tools/clippy/tests/ui/drop_ref.stderr
+++ b/src/tools/clippy/tests/ui/drop_ref.stderr
@@ -107,5 +107,41 @@ note: argument has type `&SomeStruct`
LL | std::mem::drop(&SomeStruct);
| ^^^^^^^^^^^
-error: aborting due to 9 previous errors
+error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
+ --> $DIR/drop_ref.rs:91:13
+ |
+LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: argument has type `&i32`
+ --> $DIR/drop_ref.rs:91:18
+ |
+LL | drop(println_and(&13)); // Lint, even if we only care about the side-effect, it's already in a block
+ | ^^^^^^^^^^^^^^^^
+
+error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
+ --> $DIR/drop_ref.rs:93:14
+ |
+LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: argument has type `&i32`
+ --> $DIR/drop_ref.rs:93:19
+ |
+LL | 3 if drop(println_and(&14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+ | ^^^^^^^^^^^^^^^^
+
+error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
+ --> $DIR/drop_ref.rs:94:14
+ |
+LL | 4 => drop(&2), // Lint, not a fn/method call
+ | ^^^^^^^^
+ |
+note: argument has type `&i32`
+ --> $DIR/drop_ref.rs:94:19
+ |
+LL | 4 => drop(&2), // Lint, not a fn/method call
+ | ^^
+
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.rs b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
index 6eddc01e2..46565a97f 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.rs
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
@@ -189,3 +189,33 @@ mod issue_7920 {
}
}
}
+
+mod issue_10058 {
+ pub fn test() {
+ // should not lint since we are increasing counter potentially more than once in the loop
+ let values = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1];
+ let mut counter = 0;
+ for value in values {
+ counter += 1;
+
+ if value == 0 {
+ continue;
+ }
+
+ counter += 1;
+ }
+ }
+
+ pub fn test2() {
+ // should not lint since we are increasing counter potentially more than once in the loop
+ let values = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1];
+ let mut counter = 0;
+ for value in values {
+ counter += 1;
+
+ if value != 0 {
+ counter += 1;
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 7367910ea..1f989bb12 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -247,3 +247,24 @@ mod issue6312 {
}
}
}
+
+struct Collection {
+ items: Vec<i32>,
+ len: usize,
+}
+
+impl Default for Collection {
+ fn default() -> Self {
+ Self {
+ items: vec![1, 2, 3],
+ len: 0,
+ }
+ }
+}
+
+#[allow(clippy::redundant_closure_call)]
+fn issue10136() {
+ let mut c = Collection::default();
+ // don't lint, since c.items was used to calculate this value
+ c.len = (|| c.items.len())();
+}
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.fixed b/src/tools/clippy/tests/ui/floating_point_powi.fixed
index 884d05fed..8ffd4cc51 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_powi.fixed
@@ -14,6 +14,15 @@ fn main() {
let _ = (y as f32).mul_add(y as f32, x);
let _ = x.mul_add(x, y).sqrt();
let _ = y.mul_add(y, x).sqrt();
+
+ let _ = (x - 1.0).mul_add(x - 1.0, -y);
+ let _ = (x - 1.0).mul_add(x - 1.0, -y) + 3.0;
+ let _ = (x - 1.0).mul_add(x - 1.0, -(y + 3.0));
+ let _ = (y + 1.0).mul_add(-(y + 1.0), x);
+ let _ = (3.0 * y).mul_add(-(3.0 * y), x);
+ let _ = (y + 1.0 + x).mul_add(-(y + 1.0 + x), x);
+ let _ = (y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x);
+
// Cases where the lint shouldn't be applied
let _ = x.powi(2);
let _ = x.powi(1 + 1);
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.rs b/src/tools/clippy/tests/ui/floating_point_powi.rs
index e6a1c8953..9ae3455a1 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.rs
+++ b/src/tools/clippy/tests/ui/floating_point_powi.rs
@@ -14,6 +14,15 @@ fn main() {
let _ = x + (y as f32).powi(2);
let _ = (x.powi(2) + y).sqrt();
let _ = (x + y.powi(2)).sqrt();
+
+ let _ = (x - 1.0).powi(2) - y;
+ let _ = (x - 1.0).powi(2) - y + 3.0;
+ let _ = (x - 1.0).powi(2) - (y + 3.0);
+ let _ = x - (y + 1.0).powi(2);
+ let _ = x - (3.0 * y).powi(2);
+ let _ = x - (y + 1.0 + x).powi(2);
+ let _ = x - (y + 1.0 + 2.0).powi(2);
+
// Cases where the lint shouldn't be applied
let _ = x.powi(2);
let _ = x.powi(1 + 1);
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.stderr b/src/tools/clippy/tests/ui/floating_point_powi.stderr
index 5df0de1fe..fdf6d0880 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_powi.stderr
@@ -42,5 +42,47 @@ error: multiply and add expressions can be calculated more efficiently and accur
LL | let _ = (x + y.powi(2)).sqrt();
| ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
-error: aborting due to 7 previous errors
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:18:13
+ |
+LL | let _ = (x - 1.0).powi(2) - y;
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:19:13
+ |
+LL | let _ = (x - 1.0).powi(2) - y + 3.0;
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:20:13
+ |
+LL | let _ = (x - 1.0).powi(2) - (y + 3.0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -(y + 3.0))`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:21:13
+ |
+LL | let _ = x - (y + 1.0).powi(2);
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0).mul_add(-(y + 1.0), x)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:22:13
+ |
+LL | let _ = x - (3.0 * y).powi(2);
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(3.0 * y).mul_add(-(3.0 * y), x)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:23:13
+ |
+LL | let _ = x - (y + 1.0 + x).powi(2);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + x).mul_add(-(y + 1.0 + x), x)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:24:13
+ |
+LL | let _ = x - (y + 1.0 + 2.0).powi(2);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x)`
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs
new file mode 100644
index 000000000..df5bc8420
--- /dev/null
+++ b/src/tools/clippy/tests/ui/fn_null_check.rs
@@ -0,0 +1,21 @@
+#![allow(unused)]
+#![warn(clippy::fn_null_check)]
+#![allow(clippy::cmp_null)]
+#![allow(clippy::ptr_eq)]
+#![allow(clippy::zero_ptr)]
+
+pub const ZPTR: *const () = 0 as *const _;
+pub const NOT_ZPTR: *const () = 1 as *const _;
+
+fn main() {
+ let fn_ptr = main;
+
+ if (fn_ptr as *mut ()).is_null() {}
+ if (fn_ptr as *const u8).is_null() {}
+ if (fn_ptr as *const ()) == std::ptr::null() {}
+ if (fn_ptr as *const ()) == (0 as *const ()) {}
+ if (fn_ptr as *const ()) == ZPTR {}
+
+ // no lint
+ if (fn_ptr as *const ()) == NOT_ZPTR {}
+}
diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr
new file mode 100644
index 000000000..660dd3239
--- /dev/null
+++ b/src/tools/clippy/tests/ui/fn_null_check.stderr
@@ -0,0 +1,43 @@
+error: function pointer assumed to be nullable, even though it isn't
+ --> $DIR/fn_null_check.rs:13:8
+ |
+LL | if (fn_ptr as *mut ()).is_null() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
+ = note: `-D clippy::fn-null-check` implied by `-D warnings`
+
+error: function pointer assumed to be nullable, even though it isn't
+ --> $DIR/fn_null_check.rs:14:8
+ |
+LL | if (fn_ptr as *const u8).is_null() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
+
+error: function pointer assumed to be nullable, even though it isn't
+ --> $DIR/fn_null_check.rs:15:8
+ |
+LL | if (fn_ptr as *const ()) == std::ptr::null() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
+
+error: function pointer assumed to be nullable, even though it isn't
+ --> $DIR/fn_null_check.rs:16:8
+ |
+LL | if (fn_ptr as *const ()) == (0 as *const ()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
+
+error: function pointer assumed to be nullable, even though it isn't
+ --> $DIR/fn_null_check.rs:17:8
+ |
+LL | if (fn_ptr as *const ()) == ZPTR {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed
index 125c9a69c..72d635c2c 100644
--- a/src/tools/clippy/tests/ui/from_over_into.fixed
+++ b/src/tools/clippy/tests/ui/from_over_into.fixed
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(type_alias_impl_trait)]
#![warn(clippy::from_over_into)]
#![allow(unused)]
@@ -81,4 +82,10 @@ fn msrv_1_41() {
}
}
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+ fn into(self) -> Opaque {}
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
index 5aa127bfa..965f4d5d7 100644
--- a/src/tools/clippy/tests/ui/from_over_into.rs
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(type_alias_impl_trait)]
#![warn(clippy::from_over_into)]
#![allow(unused)]
@@ -81,4 +82,10 @@ fn msrv_1_41() {
}
}
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+ fn into(self) -> Opaque {}
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
index a1764a5ea..3c4d011d6 100644
--- a/src/tools/clippy/tests/ui/from_over_into.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -1,5 +1,5 @@
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:9:1
+ --> $DIR/from_over_into.rs:10:1
|
LL | impl Into<StringWrapper> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL ~ StringWrapper(val)
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:17:1
+ --> $DIR/from_over_into.rs:18:1
|
LL | impl Into<SelfType> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL ~ SelfType(String::new())
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:32:1
+ --> $DIR/from_over_into.rs:33:1
|
LL | impl Into<SelfKeywords> for X {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL ~ let _: X = val;
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:44:1
+ --> $DIR/from_over_into.rs:45:1
|
LL | impl core::convert::Into<bool> for crate::ExplicitPaths {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ LL ~ val.0
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:77:5
+ --> $DIR/from_over_into.rs:78:5
|
LL | impl<T> Into<FromOverInto<T>> for Vec<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index e7b9a78c5..cac69ef42 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -65,7 +65,7 @@ fn main() {
42;
1;
42;
- &x;
+ x;
x;
let mut a = A(String::new());
@@ -112,6 +112,10 @@ fn main() {
2 * { a };
(({ a } + 4));
1;
+
+ // Issue #9904
+ let x = 0i32;
+ let _: i32 = x;
}
pub fn decide(a: bool, b: bool) -> u32 {
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index 9a435cdbb..33201aad4 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -112,6 +112,10 @@ fn main() {
2 * (0 + { a });
1 * ({ a } + 4);
1 * 1;
+
+ // Issue #9904
+ let x = 0i32;
+ let _: i32 = &x + 0;
}
pub fn decide(a: bool, b: bool) -> u32 {
diff --git a/src/tools/clippy/tests/ui/identity_op.stderr b/src/tools/clippy/tests/ui/identity_op.stderr
index 1a104a20b..3ba557d18 100644
--- a/src/tools/clippy/tests/ui/identity_op.stderr
+++ b/src/tools/clippy/tests/ui/identity_op.stderr
@@ -70,7 +70,7 @@ error: this operation has no effect
--> $DIR/identity_op.rs:68:5
|
LL | &x >> 0;
- | ^^^^^^^ help: consider reducing it to: `&x`
+ | ^^^^^^^ help: consider reducing it to: `x`
error: this operation has no effect
--> $DIR/identity_op.rs:69:5
@@ -229,10 +229,16 @@ LL | 1 * 1;
| ^^^^^ help: consider reducing it to: `1`
error: this operation has no effect
- --> $DIR/identity_op.rs:118:5
+ --> $DIR/identity_op.rs:118:18
+ |
+LL | let _: i32 = &x + 0;
+ | ^^^^^^ help: consider reducing it to: `x`
+
+error: this operation has no effect
+ --> $DIR/identity_op.rs:122:5
|
LL | 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })`
-error: aborting due to 39 previous errors
+error: aborting due to 40 previous errors
diff --git a/src/tools/clippy/tests/ui/implicit_clone.fixed b/src/tools/clippy/tests/ui/implicit_clone.fixed
index 33770fc2a..51b1afbe5 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.fixed
+++ b/src/tools/clippy/tests/ui/implicit_clone.fixed
@@ -115,4 +115,14 @@ fn main() {
let pathbuf_ref = &pathbuf_ref;
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
let _ = (**pathbuf_ref).clone();
+
+ struct NoClone;
+ impl ToOwned for NoClone {
+ type Owned = Self;
+ fn to_owned(&self) -> Self {
+ NoClone
+ }
+ }
+ let no_clone = &NoClone;
+ let _ = no_clone.to_owned();
}
diff --git a/src/tools/clippy/tests/ui/implicit_clone.rs b/src/tools/clippy/tests/ui/implicit_clone.rs
index fc896525b..8a9027433 100644
--- a/src/tools/clippy/tests/ui/implicit_clone.rs
+++ b/src/tools/clippy/tests/ui/implicit_clone.rs
@@ -115,4 +115,14 @@ fn main() {
let pathbuf_ref = &pathbuf_ref;
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
let _ = pathbuf_ref.to_path_buf();
+
+ struct NoClone;
+ impl ToOwned for NoClone {
+ type Owned = Self;
+ fn to_owned(&self) -> Self {
+ NoClone
+ }
+ }
+ let no_clone = &NoClone;
+ let _ = no_clone.to_owned();
}
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
index 4476e0eb9..26abc9edb 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
@@ -6,7 +6,7 @@
#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
const ARR: [i32; 2] = [1, 2];
-const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr.
+const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
const fn idx() -> usize {
@@ -27,8 +27,8 @@ fn main() {
x[3]; // Ok, should not produce stderr.
x[const { idx() }]; // Ok, should not produce stderr.
x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
- const { &ARR[idx()] }; // Ok, should not produce stderr.
- const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+ const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
let y = &x;
y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
index d8b6e3f12..8fd77913a 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
@@ -1,13 +1,32 @@
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:9:20
+ |
+LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ | ^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
+ = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:10:24
+ |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+ | ^^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
+
error[E0080]: evaluation of `main::{constant#3}` failed
--> $DIR/indexing_slicing_index.rs:31:14
|
-LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
note: erroneous constant used
--> $DIR/indexing_slicing_index.rs:31:5
|
-LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
| ^^^^^^^^^^^^^^^^^^^^^^
error: indexing may panic
@@ -17,7 +36,24 @@ LL | x[index];
| ^^^^^^^^
|
= help: consider using `.get(n)` or `.get_mut(n)` instead
- = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:30:14
+ |
+LL | const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ | ^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
+
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:31:14
+ |
+LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ | ^^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
error: indexing may panic
--> $DIR/indexing_slicing_index.rs:38:5
@@ -65,6 +101,6 @@ error[E0080]: evaluation of constant value failed
LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
-error: aborting due to 8 previous errors
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0080`.
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.fixed b/src/tools/clippy/tests/ui/iter_kv_map.fixed
index 83fee0408..f2a4c284c 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.fixed
+++ b/src/tools/clippy/tests/ui/iter_kv_map.fixed
@@ -1,14 +1,15 @@
// run-rustfix
#![warn(clippy::iter_kv_map)]
-#![allow(clippy::redundant_clone)]
-#![allow(clippy::suspicious_map)]
-#![allow(clippy::map_identity)]
+#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
use std::collections::{BTreeMap, HashMap};
fn main() {
let get_key = |(key, _val)| key;
+ fn ref_acceptor(v: &u32) -> u32 {
+ *v
+ }
let map: HashMap<u32, u32> = HashMap::new();
@@ -36,6 +37,20 @@ fn main() {
let _ = map.keys().map(|key| key * 9).count();
let _ = map.values().map(|value| value * 17).count();
+ // Preserve the ref in the fix.
+ let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
+
+ // Preserve the mut in the fix.
+ let _ = map
+ .clone().into_values().map(|mut val| {
+ val += 2;
+ val
+ })
+ .count();
+
+ // Don't let a mut interfere.
+ let _ = map.clone().into_values().count();
+
let map: BTreeMap<u32, u32> = BTreeMap::new();
let _ = map.keys().collect::<Vec<_>>();
@@ -61,4 +76,18 @@ fn main() {
// Lint
let _ = map.keys().map(|key| key * 9).count();
let _ = map.values().map(|value| value * 17).count();
+
+ // Preserve the ref in the fix.
+ let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
+
+ // Preserve the mut in the fix.
+ let _ = map
+ .clone().into_values().map(|mut val| {
+ val += 2;
+ val
+ })
+ .count();
+
+ // Don't let a mut interfere.
+ let _ = map.clone().into_values().count();
}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.rs b/src/tools/clippy/tests/ui/iter_kv_map.rs
index 7a1f1fb01..ad6564df4 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.rs
+++ b/src/tools/clippy/tests/ui/iter_kv_map.rs
@@ -1,14 +1,15 @@
// run-rustfix
#![warn(clippy::iter_kv_map)]
-#![allow(clippy::redundant_clone)]
-#![allow(clippy::suspicious_map)]
-#![allow(clippy::map_identity)]
+#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
use std::collections::{BTreeMap, HashMap};
fn main() {
let get_key = |(key, _val)| key;
+ fn ref_acceptor(v: &u32) -> u32 {
+ *v
+ }
let map: HashMap<u32, u32> = HashMap::new();
@@ -36,6 +37,22 @@ fn main() {
let _ = map.iter().map(|(key, _value)| key * 9).count();
let _ = map.iter().map(|(_key, value)| value * 17).count();
+ // Preserve the ref in the fix.
+ let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+
+ // Preserve the mut in the fix.
+ let _ = map
+ .clone()
+ .into_iter()
+ .map(|(_, mut val)| {
+ val += 2;
+ val
+ })
+ .count();
+
+ // Don't let a mut interfere.
+ let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+
let map: BTreeMap<u32, u32> = BTreeMap::new();
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
@@ -61,4 +78,20 @@ fn main() {
// Lint
let _ = map.iter().map(|(key, _value)| key * 9).count();
let _ = map.iter().map(|(_key, value)| value * 17).count();
+
+ // Preserve the ref in the fix.
+ let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+
+ // Preserve the mut in the fix.
+ let _ = map
+ .clone()
+ .into_iter()
+ .map(|(_, mut val)| {
+ val += 2;
+ val
+ })
+ .count();
+
+ // Don't let a mut interfere.
+ let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.stderr b/src/tools/clippy/tests/ui/iter_kv_map.stderr
index 9b9b04c97..e00da223b 100644
--- a/src/tools/clippy/tests/ui/iter_kv_map.stderr
+++ b/src/tools/clippy/tests/ui/iter_kv_map.stderr
@@ -1,5 +1,5 @@
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:15:13
+ --> $DIR/iter_kv_map.rs:16:13
|
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
@@ -7,130 +7,198 @@ LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
= note: `-D clippy::iter-kv-map` implied by `-D warnings`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:16:13
+ --> $DIR/iter_kv_map.rs:17:13
|
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:17:13
+ --> $DIR/iter_kv_map.rs:18:13
|
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:19:13
+ --> $DIR/iter_kv_map.rs:20:13
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:20:13
+ --> $DIR/iter_kv_map.rs:21:13
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:22:13
+ --> $DIR/iter_kv_map.rs:23:13
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:23:13
+ --> $DIR/iter_kv_map.rs:24:13
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:25:13
+ --> $DIR/iter_kv_map.rs:26:13
|
LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:26:13
+ --> $DIR/iter_kv_map.rs:27:13
|
LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:36:13
+ --> $DIR/iter_kv_map.rs:37:13
|
LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:37:13
+ --> $DIR/iter_kv_map.rs:38:13
|
LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
-error: iterating on a map's keys
+error: iterating on a map's values
--> $DIR/iter_kv_map.rs:41:13
|
+LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:44:13
+ |
+LL | let _ = map
+ | _____________^
+LL | | .clone()
+LL | | .into_iter()
+LL | | .map(|(_, mut val)| {
+LL | | val += 2;
+LL | | val
+LL | | })
+ | |__________^
+ |
+help: try
+ |
+LL ~ let _ = map
+LL + .clone().into_values().map(|mut val| {
+LL + val += 2;
+LL + val
+LL + })
+ |
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:54:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:58:13
+ |
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:42:13
+ --> $DIR/iter_kv_map.rs:59:13
|
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:43:13
+ --> $DIR/iter_kv_map.rs:60:13
|
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:45:13
+ --> $DIR/iter_kv_map.rs:62:13
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:46:13
+ --> $DIR/iter_kv_map.rs:63:13
|
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:48:13
+ --> $DIR/iter_kv_map.rs:65:13
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:49:13
+ --> $DIR/iter_kv_map.rs:66:13
|
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:51:13
+ --> $DIR/iter_kv_map.rs:68:13
|
LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:52:13
+ --> $DIR/iter_kv_map.rs:69:13
|
LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
error: iterating on a map's keys
- --> $DIR/iter_kv_map.rs:62:13
+ --> $DIR/iter_kv_map.rs:79:13
|
LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
error: iterating on a map's values
- --> $DIR/iter_kv_map.rs:63:13
+ --> $DIR/iter_kv_map.rs:80:13
|
LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
-error: aborting due to 22 previous errors
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:83:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:86:13
+ |
+LL | let _ = map
+ | _____________^
+LL | | .clone()
+LL | | .into_iter()
+LL | | .map(|(_, mut val)| {
+LL | | val += 2;
+LL | | val
+LL | | })
+ | |__________^
+ |
+help: try
+ |
+LL ~ let _ = map
+LL + .clone().into_values().map(|mut val| {
+LL + val += 2;
+LL + val
+LL + })
+ |
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:96:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: aborting due to 28 previous errors
diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.rs b/src/tools/clippy/tests/ui/large_stack_arrays.rs
index 6790765f8..99787ffd3 100644
--- a/src/tools/clippy/tests/ui/large_stack_arrays.rs
+++ b/src/tools/clippy/tests/ui/large_stack_arrays.rs
@@ -24,6 +24,7 @@ fn main() {
[S { data: [0; 32] }; 5000],
[Some(""); 20_000_000],
[E::T(0); 5000],
+ [0u8; usize::MAX],
);
let good = (
diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.stderr b/src/tools/clippy/tests/ui/large_stack_arrays.stderr
index c7bf941ad..24e900949 100644
--- a/src/tools/clippy/tests/ui/large_stack_arrays.stderr
+++ b/src/tools/clippy/tests/ui/large_stack_arrays.stderr
@@ -31,5 +31,13 @@ LL | [E::T(0); 5000],
|
= help: consider allocating on the heap with `vec![E::T(0); 5000].into_boxed_slice()`
-error: aborting due to 4 previous errors
+error: allocating a local array larger than 512000 bytes
+ --> $DIR/large_stack_arrays.rs:27:9
+ |
+LL | [0u8; usize::MAX],
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: consider allocating on the heap with `vec![0u8; usize::MAX].into_boxed_slice()`
+
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/len_zero.fixed b/src/tools/clippy/tests/ui/len_zero.fixed
index 1f3b8ac99..c1c0b5ae4 100644
--- a/src/tools/clippy/tests/ui/len_zero.fixed
+++ b/src/tools/clippy/tests/ui/len_zero.fixed
@@ -3,6 +3,9 @@
#![warn(clippy::len_zero)]
#![allow(dead_code, unused, clippy::len_without_is_empty)]
+extern crate core;
+use core::ops::Deref;
+
pub struct One;
struct Wither;
@@ -56,6 +59,26 @@ impl WithIsEmpty for Wither {
}
}
+struct DerefToDerefToString;
+
+impl Deref for DerefToDerefToString {
+ type Target = DerefToString;
+
+ fn deref(&self) -> &Self::Target {
+ &DerefToString {}
+ }
+}
+
+struct DerefToString;
+
+impl Deref for DerefToString {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "Hello, world!"
+ }
+}
+
fn main() {
let x = [1, 2];
if x.is_empty() {
@@ -64,6 +87,23 @@ fn main() {
if "".is_empty() {}
+ let s = "Hello, world!";
+ let s1 = &s;
+ let s2 = &s1;
+ let s3 = &s2;
+ let s4 = &s3;
+ let s5 = &s4;
+ let s6 = &s5;
+ println!("{}", s1.is_empty());
+ println!("{}", s2.is_empty());
+ println!("{}", s3.is_empty());
+ println!("{}", s4.is_empty());
+ println!("{}", s5.is_empty());
+ println!("{}", (s6).is_empty());
+
+ let d2s = DerefToDerefToString {};
+ println!("{}", (**d2s).is_empty());
+
let y = One;
if y.len() == 0 {
// No error; `One` does not have `.is_empty()`.
diff --git a/src/tools/clippy/tests/ui/len_zero.rs b/src/tools/clippy/tests/ui/len_zero.rs
index dc21de000..cc2eb05b6 100644
--- a/src/tools/clippy/tests/ui/len_zero.rs
+++ b/src/tools/clippy/tests/ui/len_zero.rs
@@ -3,6 +3,9 @@
#![warn(clippy::len_zero)]
#![allow(dead_code, unused, clippy::len_without_is_empty)]
+extern crate core;
+use core::ops::Deref;
+
pub struct One;
struct Wither;
@@ -56,6 +59,26 @@ impl WithIsEmpty for Wither {
}
}
+struct DerefToDerefToString;
+
+impl Deref for DerefToDerefToString {
+ type Target = DerefToString;
+
+ fn deref(&self) -> &Self::Target {
+ &DerefToString {}
+ }
+}
+
+struct DerefToString;
+
+impl Deref for DerefToString {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "Hello, world!"
+ }
+}
+
fn main() {
let x = [1, 2];
if x.len() == 0 {
@@ -64,6 +87,23 @@ fn main() {
if "".len() == 0 {}
+ let s = "Hello, world!";
+ let s1 = &s;
+ let s2 = &s1;
+ let s3 = &s2;
+ let s4 = &s3;
+ let s5 = &s4;
+ let s6 = &s5;
+ println!("{}", *s1 == "");
+ println!("{}", **s2 == "");
+ println!("{}", ***s3 == "");
+ println!("{}", ****s4 == "");
+ println!("{}", *****s5 == "");
+ println!("{}", ******(s6) == "");
+
+ let d2s = DerefToDerefToString {};
+ println!("{}", &**d2s == "");
+
let y = One;
if y.len() == 0 {
// No error; `One` does not have `.is_empty()`.
diff --git a/src/tools/clippy/tests/ui/len_zero.stderr b/src/tools/clippy/tests/ui/len_zero.stderr
index 6c71f1bee..b6f137802 100644
--- a/src/tools/clippy/tests/ui/len_zero.stderr
+++ b/src/tools/clippy/tests/ui/len_zero.stderr
@@ -1,5 +1,5 @@
error: length comparison to zero
- --> $DIR/len_zero.rs:61:8
+ --> $DIR/len_zero.rs:84:8
|
LL | if x.len() == 0 {
| ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()`
@@ -7,82 +7,126 @@ LL | if x.len() == 0 {
= note: `-D clippy::len-zero` implied by `-D warnings`
error: length comparison to zero
- --> $DIR/len_zero.rs:65:8
+ --> $DIR/len_zero.rs:88:8
|
LL | if "".len() == 0 {}
| ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()`
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:97:20
+ |
+LL | println!("{}", *s1 == "");
+ | ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s1.is_empty()`
+ |
+ = note: `-D clippy::comparison-to-empty` implied by `-D warnings`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:98:20
+ |
+LL | println!("{}", **s2 == "");
+ | ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s2.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:99:20
+ |
+LL | println!("{}", ***s3 == "");
+ | ^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s3.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:100:20
+ |
+LL | println!("{}", ****s4 == "");
+ | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s4.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:101:20
+ |
+LL | println!("{}", *****s5 == "");
+ | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s5.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:102:20
+ |
+LL | println!("{}", ******(s6) == "");
+ | ^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(s6).is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:105:20
+ |
+LL | println!("{}", &**d2s == "");
+ | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(**d2s).is_empty()`
+
error: length comparison to zero
- --> $DIR/len_zero.rs:80:8
+ --> $DIR/len_zero.rs:120:8
|
LL | if has_is_empty.len() == 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:83:8
+ --> $DIR/len_zero.rs:123:8
|
LL | if has_is_empty.len() != 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:86:8
+ --> $DIR/len_zero.rs:126:8
|
LL | if has_is_empty.len() > 0 {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:89:8
+ --> $DIR/len_zero.rs:129:8
|
LL | if has_is_empty.len() < 1 {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:92:8
+ --> $DIR/len_zero.rs:132:8
|
LL | if has_is_empty.len() >= 1 {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:103:8
+ --> $DIR/len_zero.rs:143:8
|
LL | if 0 == has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:106:8
+ --> $DIR/len_zero.rs:146:8
|
LL | if 0 != has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:109:8
+ --> $DIR/len_zero.rs:149:8
|
LL | if 0 < has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:112:8
+ --> $DIR/len_zero.rs:152:8
|
LL | if 1 <= has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:115:8
+ --> $DIR/len_zero.rs:155:8
|
LL | if 1 > has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:129:8
+ --> $DIR/len_zero.rs:169:8
|
LL | if with_is_empty.len() == 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:142:8
+ --> $DIR/len_zero.rs:182:8
|
LL | if b.len() != 0 {}
| ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()`
-error: aborting due to 14 previous errors
+error: aborting due to 21 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index c9a819ba5..638320dd6 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -62,6 +62,11 @@ fn main() {
panic!("panic5");
}
assert!(!a.is_empty(), "with expansion {}", one!());
+ if a.is_empty() {
+ let _ = 0;
+ } else if a.len() == 1 {
+ panic!("panic6");
+ }
}
fn issue7730(a: u8) {
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
index 2f62de51c..8c7e919bf 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
@@ -50,6 +50,11 @@ fn main() {
assert!(!(b.is_empty() || a.is_empty()), "panic4");
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
assert!(!a.is_empty(), "with expansion {}", one!());
+ if a.is_empty() {
+ let _ = 0;
+ } else if a.len() == 1 {
+ panic!("panic6");
+ }
}
fn issue7730(a: u8) {
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
index 237638ee1..3555ac292 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
@@ -65,7 +65,7 @@ LL | | }
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:73:5
+ --> $DIR/manual_assert.rs:78:5
|
LL | / if a > 2 {
LL | | // comment
diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs
index 6a4cc2468..f037c5b84 100644
--- a/src/tools/clippy/tests/ui/manual_assert.rs
+++ b/src/tools/clippy/tests/ui/manual_assert.rs
@@ -66,6 +66,11 @@ fn main() {
if a.is_empty() {
panic!("with expansion {}", one!())
}
+ if a.is_empty() {
+ let _ = 0;
+ } else if a.len() == 1 {
+ panic!("panic6");
+ }
}
fn issue7730(a: u8) {
diff --git a/src/tools/clippy/tests/ui/manual_filter.fixed b/src/tools/clippy/tests/ui/manual_filter.fixed
index 3553291b8..ef6780dc9 100644
--- a/src/tools/clippy/tests/ui/manual_filter.fixed
+++ b/src/tools/clippy/tests/ui/manual_filter.fixed
@@ -116,4 +116,45 @@ fn main() {
},
None => None,
};
+
+ match Some(20) {
+ // Don't Lint, because `Some(3*x)` is not `None`
+ None => None,
+ Some(x) => {
+ if x > 0 {
+ Some(3 * x)
+ } else {
+ Some(x)
+ }
+ },
+ };
+
+ // Don't lint: https://github.com/rust-lang/rust-clippy/issues/10088
+ let result = if let Some(a) = maybe_some() {
+ if let Some(b) = maybe_some() {
+ Some(a + b)
+ } else {
+ Some(a)
+ }
+ } else {
+ None
+ };
+
+ let allowed_integers = vec![3, 4, 5, 6];
+ // Don't lint, since there's a side effect in the else branch
+ match Some(21) {
+ Some(x) => {
+ if allowed_integers.contains(&x) {
+ Some(x)
+ } else {
+ println!("Invalid integer: {x:?}");
+ None
+ }
+ },
+ None => None,
+ };
+}
+
+fn maybe_some() -> Option<u32> {
+ Some(0)
}
diff --git a/src/tools/clippy/tests/ui/manual_filter.rs b/src/tools/clippy/tests/ui/manual_filter.rs
index aa9f90f75..ea0ce8317 100644
--- a/src/tools/clippy/tests/ui/manual_filter.rs
+++ b/src/tools/clippy/tests/ui/manual_filter.rs
@@ -240,4 +240,45 @@ fn main() {
},
None => None,
};
+
+ match Some(20) {
+ // Don't Lint, because `Some(3*x)` is not `None`
+ None => None,
+ Some(x) => {
+ if x > 0 {
+ Some(3 * x)
+ } else {
+ Some(x)
+ }
+ },
+ };
+
+ // Don't lint: https://github.com/rust-lang/rust-clippy/issues/10088
+ let result = if let Some(a) = maybe_some() {
+ if let Some(b) = maybe_some() {
+ Some(a + b)
+ } else {
+ Some(a)
+ }
+ } else {
+ None
+ };
+
+ let allowed_integers = vec![3, 4, 5, 6];
+ // Don't lint, since there's a side effect in the else branch
+ match Some(21) {
+ Some(x) => {
+ if allowed_integers.contains(&x) {
+ Some(x)
+ } else {
+ println!("Invalid integer: {x:?}");
+ None
+ }
+ },
+ None => None,
+ };
+}
+
+fn maybe_some() -> Option<u32> {
+ Some(0)
}
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
index 231ba83b1..5b2b44c2f 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.fixed
@@ -15,6 +15,19 @@ fn main() {
assert!('x'.is_ascii_alphabetic());
assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+
+ b'0'.is_ascii_digit();
+ b'a'.is_ascii_lowercase();
+ b'A'.is_ascii_uppercase();
+
+ '0'.is_ascii_digit();
+ 'a'.is_ascii_lowercase();
+ 'A'.is_ascii_uppercase();
+
+ let cool_letter = &'g';
+ cool_letter.is_ascii_digit();
+ cool_letter.is_ascii_lowercase();
+ cool_letter.is_ascii_uppercase();
}
#[clippy::msrv = "1.23"]
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
index 39ee6151c..c9433f33a 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.rs
@@ -15,6 +15,19 @@ fn main() {
assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+
+ (b'0'..=b'9').contains(&b'0');
+ (b'a'..=b'z').contains(&b'a');
+ (b'A'..=b'Z').contains(&b'A');
+
+ ('0'..='9').contains(&'0');
+ ('a'..='z').contains(&'a');
+ ('A'..='Z').contains(&'A');
+
+ let cool_letter = &'g';
+ ('0'..='9').contains(cool_letter);
+ ('a'..='z').contains(cool_letter);
+ ('A'..='Z').contains(cool_letter);
}
#[clippy::msrv = "1.23"]
diff --git a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
index 397cbe05c..ee6018850 100644
--- a/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
+++ b/src/tools/clippy/tests/ui/manual_is_ascii_check.stderr
@@ -43,28 +43,82 @@ LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:29:13
+ --> $DIR/manual_is_ascii_check.rs:19:5
+ |
+LL | (b'0'..=b'9').contains(&b'0');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'0'.is_ascii_digit()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:20:5
+ |
+LL | (b'a'..=b'z').contains(&b'a');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'a'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:21:5
+ |
+LL | (b'A'..=b'Z').contains(&b'A');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'A'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:23:5
+ |
+LL | ('0'..='9').contains(&'0');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'0'.is_ascii_digit()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:24:5
+ |
+LL | ('a'..='z').contains(&'a');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'a'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:25:5
+ |
+LL | ('A'..='Z').contains(&'A');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'A'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:28:5
+ |
+LL | ('0'..='9').contains(cool_letter);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:29:5
+ |
+LL | ('a'..='z').contains(cool_letter);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:30:5
+ |
+LL | ('A'..='Z').contains(cool_letter);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:42:13
|
LL | assert!(matches!(b'1', b'0'..=b'9'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:30:13
+ --> $DIR/manual_is_ascii_check.rs:43:13
|
LL | assert!(matches!('X', 'A'..='Z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:31:13
+ --> $DIR/manual_is_ascii_check.rs:44:13
|
LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:41:23
+ --> $DIR/manual_is_ascii_check.rs:54:23
|
LL | const FOO: bool = matches!('x', '0'..='9');
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
-error: aborting due to 11 previous errors
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs
index 93c86ca24..28caed9d7 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs
@@ -64,6 +64,13 @@ fn fire() {
Ok(v) => v,
Err(()) => return,
};
+
+ let f = Variant::Bar(1);
+
+ let _value = match f {
+ Variant::Bar(_) | Variant::Baz(_) => (),
+ _ => return,
+ };
}
fn not_fire() {
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 38be5ac54..cd5e9a9ac 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -25,7 +25,7 @@ LL | / let v = match h() {
LL | | (Some(_), Some(_)) | (None, None) => continue,
LL | | (Some(v), None) | (None, Some(v)) => v,
LL | | };
- | |__________^ help: consider writing: `let (Some(v), None) | (None, Some(v)) = h() else { continue };`
+ | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };`
error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:49:9
@@ -34,7 +34,7 @@ LL | / let v = match build_enum() {
LL | | _ => continue,
LL | | Variant::Bar(v) | Variant::Baz(v) => v,
LL | | };
- | |__________^ help: consider writing: `let Variant::Bar(v) | Variant::Baz(v) = build_enum() else { continue };`
+ | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };`
error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:57:5
@@ -54,5 +54,14 @@ LL | | Err(()) => return,
LL | | };
| |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };`
-error: aborting due to 6 previous errors
+error: this could be rewritten as `let...else`
+ --> $DIR/manual_let_else_match.rs:70:5
+ |
+LL | / let _value = match f {
+LL | | Variant::Bar(_) | Variant::Baz(_) => (),
+LL | | _ => return,
+LL | | };
+ | |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };`
+
+error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed
index e5ae3cf3e..8f25fea67 100644
--- a/src/tools/clippy/tests/ui/manual_retain.fixed
+++ b/src/tools/clippy/tests/ui/manual_retain.fixed
@@ -1,6 +1,6 @@
// run-rustfix
#![warn(clippy::manual_retain)]
-#![allow(unused)]
+#![allow(unused, clippy::redundant_clone)]
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::BinaryHeap;
diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs
index 1021f15ed..e6b3995a6 100644
--- a/src/tools/clippy/tests/ui/manual_retain.rs
+++ b/src/tools/clippy/tests/ui/manual_retain.rs
@@ -1,6 +1,6 @@
// run-rustfix
#![warn(clippy::manual_retain)]
-#![allow(unused)]
+#![allow(unused, clippy::redundant_clone)]
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::BinaryHeap;
diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed
index a6e315e47..6cfb6661a 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding.fixed
@@ -133,3 +133,16 @@ fn issue_9575() {
println!("Needs curlies");
};
}
+
+#[allow(dead_code)]
+fn issue_9725(r: Option<u32>) {
+ let x = r;
+ match x {
+ Some(_) => {
+ println!("Some");
+ },
+ None => {
+ println!("None");
+ },
+ };
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs
index cecbd703e..f188aeb5f 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding.rs
@@ -148,3 +148,17 @@ fn issue_9575() {
_ => println!("Needs curlies"),
};
}
+
+#[allow(dead_code)]
+fn issue_9725(r: Option<u32>) {
+ match r {
+ x => match x {
+ Some(_) => {
+ println!("Some");
+ },
+ None => {
+ println!("None");
+ },
+ },
+ };
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr
index 2b9ec7ee7..e960d64ad 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.stderr
+++ b/src/tools/clippy/tests/ui/match_single_binding.stderr
@@ -213,5 +213,30 @@ LL + println!("Needs curlies");
LL ~ };
|
-error: aborting due to 14 previous errors
+error: this match could be written as a `let` statement
+ --> $DIR/match_single_binding.rs:154:5
+ |
+LL | / match r {
+LL | | x => match x {
+LL | | Some(_) => {
+LL | | println!("Some");
+... |
+LL | | },
+LL | | };
+ | |_____^
+ |
+help: consider using a `let` statement
+ |
+LL ~ let x = r;
+LL + match x {
+LL + Some(_) => {
+LL + println!("Some");
+LL + },
+LL + None => {
+LL + println!("None");
+LL + },
+LL ~ };
+ |
+
+error: aborting due to 15 previous errors
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
index e675c183e..fc252cdd3 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
@@ -132,3 +132,25 @@ fn main() {
}
}
}
+
+mod issue9993 {
+ enum Foo {
+ A(bool),
+ B,
+ }
+
+ fn test() {
+ let _ = match Foo::A(true) {
+ _ if false => 0,
+ Foo::A(true) => 1,
+ Foo::A(false) => 2,
+ Foo::B => 3,
+ };
+
+ let _ = match Foo::B {
+ _ if false => 0,
+ Foo::A(_) => 1,
+ Foo::B => 2,
+ };
+ }
+}
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
index 38c3ffc00..9a5c849e6 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs
@@ -132,3 +132,25 @@ fn main() {
}
}
}
+
+mod issue9993 {
+ enum Foo {
+ A(bool),
+ B,
+ }
+
+ fn test() {
+ let _ = match Foo::A(true) {
+ _ if false => 0,
+ Foo::A(true) => 1,
+ Foo::A(false) => 2,
+ Foo::B => 3,
+ };
+
+ let _ = match Foo::B {
+ _ if false => 0,
+ Foo::A(_) => 1,
+ _ => 2,
+ };
+ }
+}
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
index 34538dea8..6fa313dc9 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
@@ -48,5 +48,11 @@ error: wildcard matches only a single variant and will also match any future add
LL | _ => (),
| ^ help: try this: `Color::Blue`
-error: aborting due to 8 previous errors
+error: wildcard matches only a single variant and will also match any future added variants
+ --> $DIR/match_wildcard_for_single_variants.rs:153:13
+ |
+LL | _ => 2,
+ | ^ help: try this: `Foo::B`
+
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
index 1bd75c806..f11330a89 100644
--- a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
+++ b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.fixed
@@ -2,7 +2,7 @@
// edition:2018
#![warn(clippy::needless_parens_on_range_literals)]
-#![allow(clippy::almost_complete_letter_range)]
+#![allow(clippy::almost_complete_range)]
fn main() {
let _ = 'a'..='z';
diff --git a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
index 7abb8a1ad..671c0009e 100644
--- a/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
+++ b/src/tools/clippy/tests/ui/needless_parens_on_range_literals.rs
@@ -2,7 +2,7 @@
// edition:2018
#![warn(clippy::needless_parens_on_range_literals)]
-#![allow(clippy::almost_complete_letter_range)]
+#![allow(clippy::almost_complete_range)]
fn main() {
let _ = ('a')..=('z');
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 4386aaec4..ab1c0e590 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -1,6 +1,7 @@
// run-rustfix
#![feature(lint_reasons)]
+#![feature(yeet_expr)]
#![allow(unused)]
#![allow(
clippy::if_same_then_else,
@@ -272,4 +273,18 @@ mod issue9416 {
}
}
+fn issue9947() -> Result<(), String> {
+ do yeet "hello";
+}
+
+// without anyhow, but triggers the same bug I believe
+#[expect(clippy::useless_format)]
+fn issue10051() -> Result<String, String> {
+ if true {
+ Ok(format!("ok!"))
+ } else {
+ Err(format!("err!"))
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 666dc54b7..abed338bb 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -1,6 +1,7 @@
// run-rustfix
#![feature(lint_reasons)]
+#![feature(yeet_expr)]
#![allow(unused)]
#![allow(
clippy::if_same_then_else,
@@ -282,4 +283,18 @@ mod issue9416 {
}
}
+fn issue9947() -> Result<(), String> {
+ do yeet "hello";
+}
+
+// without anyhow, but triggers the same bug I believe
+#[expect(clippy::useless_format)]
+fn issue10051() -> Result<String, String> {
+ if true {
+ return Ok(format!("ok!"));
+ } else {
+ return Err(format!("err!"));
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index a8b5d86cd..52eabf6e1 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -1,5 +1,5 @@
error: unneeded `return` statement
- --> $DIR/needless_return.rs:26:5
+ --> $DIR/needless_return.rs:27:5
|
LL | return true;
| ^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:30:5
+ --> $DIR/needless_return.rs:31:5
|
LL | return true;
| ^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:35:9
+ --> $DIR/needless_return.rs:36:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:37:9
+ --> $DIR/needless_return.rs:38:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:43:17
+ --> $DIR/needless_return.rs:44:17
|
LL | true => return false,
| ^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL | true => return false,
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:45:13
+ --> $DIR/needless_return.rs:46:13
|
LL | return true;
| ^^^^^^^^^^^
@@ -48,7 +48,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:52:9
+ --> $DIR/needless_return.rs:53:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -56,7 +56,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:54:16
+ --> $DIR/needless_return.rs:55:16
|
LL | let _ = || return true;
| ^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL | let _ = || return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:58:5
+ --> $DIR/needless_return.rs:59:5
|
LL | return the_answer!();
| ^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL | return the_answer!();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:61:21
+ --> $DIR/needless_return.rs:62:21
|
LL | fn test_void_fun() {
| _____________________^
@@ -82,7 +82,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:66:11
+ --> $DIR/needless_return.rs:67:11
|
LL | if b {
| ___________^
@@ -92,7 +92,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:68:13
+ --> $DIR/needless_return.rs:69:13
|
LL | } else {
| _____________^
@@ -102,7 +102,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:76:14
+ --> $DIR/needless_return.rs:77:14
|
LL | _ => return,
| ^^^^^^
@@ -110,7 +110,7 @@ LL | _ => return,
= help: replace `return` with a unit value
error: unneeded `return` statement
- --> $DIR/needless_return.rs:84:24
+ --> $DIR/needless_return.rs:85:24
|
LL | let _ = 42;
| ________________________^
@@ -120,7 +120,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:87:14
+ --> $DIR/needless_return.rs:88:14
|
LL | _ => return,
| ^^^^^^
@@ -128,7 +128,7 @@ LL | _ => return,
= help: replace `return` with a unit value
error: unneeded `return` statement
- --> $DIR/needless_return.rs:100:9
+ --> $DIR/needless_return.rs:101:9
|
LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,7 +136,7 @@ LL | return String::from("test");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:102:9
+ --> $DIR/needless_return.rs:103:9
|
LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +144,7 @@ LL | return String::new();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:124:32
+ --> $DIR/needless_return.rs:125:32
|
LL | bar.unwrap_or_else(|_| return)
| ^^^^^^
@@ -152,7 +152,7 @@ LL | bar.unwrap_or_else(|_| return)
= help: replace `return` with an empty block
error: unneeded `return` statement
- --> $DIR/needless_return.rs:128:21
+ --> $DIR/needless_return.rs:129:21
|
LL | let _ = || {
| _____________________^
@@ -162,7 +162,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:131:20
+ --> $DIR/needless_return.rs:132:20
|
LL | let _ = || return;
| ^^^^^^
@@ -170,7 +170,7 @@ LL | let _ = || return;
= help: replace `return` with an empty block
error: unneeded `return` statement
- --> $DIR/needless_return.rs:137:32
+ --> $DIR/needless_return.rs:138:32
|
LL | res.unwrap_or_else(|_| return Foo)
| ^^^^^^^^^^
@@ -178,7 +178,7 @@ LL | res.unwrap_or_else(|_| return Foo)
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:146:5
+ --> $DIR/needless_return.rs:147:5
|
LL | return true;
| ^^^^^^^^^^^
@@ -186,7 +186,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:150:5
+ --> $DIR/needless_return.rs:151:5
|
LL | return true;
| ^^^^^^^^^^^
@@ -194,7 +194,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:155:9
+ --> $DIR/needless_return.rs:156:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -202,7 +202,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:157:9
+ --> $DIR/needless_return.rs:158:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -210,7 +210,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:163:17
+ --> $DIR/needless_return.rs:164:17
|
LL | true => return false,
| ^^^^^^^^^^^^
@@ -218,7 +218,7 @@ LL | true => return false,
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:165:13
+ --> $DIR/needless_return.rs:166:13
|
LL | return true;
| ^^^^^^^^^^^
@@ -226,7 +226,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:172:9
+ --> $DIR/needless_return.rs:173:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -234,7 +234,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:174:16
+ --> $DIR/needless_return.rs:175:16
|
LL | let _ = || return true;
| ^^^^^^^^^^^
@@ -242,7 +242,7 @@ LL | let _ = || return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:178:5
+ --> $DIR/needless_return.rs:179:5
|
LL | return the_answer!();
| ^^^^^^^^^^^^^^^^^^^^
@@ -250,7 +250,7 @@ LL | return the_answer!();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:181:33
+ --> $DIR/needless_return.rs:182:33
|
LL | async fn async_test_void_fun() {
| _________________________________^
@@ -260,7 +260,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:186:11
+ --> $DIR/needless_return.rs:187:11
|
LL | if b {
| ___________^
@@ -270,7 +270,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:188:13
+ --> $DIR/needless_return.rs:189:13
|
LL | } else {
| _____________^
@@ -280,7 +280,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:196:14
+ --> $DIR/needless_return.rs:197:14
|
LL | _ => return,
| ^^^^^^
@@ -288,7 +288,7 @@ LL | _ => return,
= help: replace `return` with a unit value
error: unneeded `return` statement
- --> $DIR/needless_return.rs:209:9
+ --> $DIR/needless_return.rs:210:9
|
LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -296,7 +296,7 @@ LL | return String::from("test");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:211:9
+ --> $DIR/needless_return.rs:212:9
|
LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^
@@ -304,7 +304,7 @@ LL | return String::new();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:227:5
+ --> $DIR/needless_return.rs:228:5
|
LL | return format!("Hello {}", "world!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -312,7 +312,7 @@ LL | return format!("Hello {}", "world!");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:238:9
+ --> $DIR/needless_return.rs:239:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -320,7 +320,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:240:9
+ --> $DIR/needless_return.rs:241:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -328,7 +328,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:247:13
+ --> $DIR/needless_return.rs:248:13
|
LL | return 10;
| ^^^^^^^^^
@@ -336,7 +336,7 @@ LL | return 10;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:250:13
+ --> $DIR/needless_return.rs:251:13
|
LL | return 100;
| ^^^^^^^^^^
@@ -344,7 +344,7 @@ LL | return 100;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:258:9
+ --> $DIR/needless_return.rs:259:9
|
LL | return 0;
| ^^^^^^^^
@@ -352,7 +352,7 @@ LL | return 0;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:265:13
+ --> $DIR/needless_return.rs:266:13
|
LL | return *(x as *const isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -360,7 +360,7 @@ LL | return *(x as *const isize);
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:267:13
+ --> $DIR/needless_return.rs:268:13
|
LL | return !*(x as *const isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -368,7 +368,7 @@ LL | return !*(x as *const isize);
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:274:20
+ --> $DIR/needless_return.rs:275:20
|
LL | let _ = 42;
| ____________________^
@@ -379,12 +379,28 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:281:20
+ --> $DIR/needless_return.rs:282:20
|
LL | let _ = 42; return;
| ^^^^^^^
|
= help: remove `return`
-error: aborting due to 46 previous errors
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:294:9
+ |
+LL | return Ok(format!("ok!"));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:296:9
+ |
+LL | return Err(format!("err!"));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: aborting due to 48 previous errors
diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs b/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs
new file mode 100644
index 000000000..28c00d100
--- /dev/null
+++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs
@@ -0,0 +1,29 @@
+#![allow(unused)]
+#![warn(clippy::permissions_set_readonly_false)]
+
+use std::fs::File;
+
+struct A;
+
+impl A {
+ pub fn set_readonly(&mut self, b: bool) {}
+}
+
+fn set_readonly(b: bool) {}
+
+fn main() {
+ let f = File::create("foo.txt").unwrap();
+ let metadata = f.metadata().unwrap();
+ let mut permissions = metadata.permissions();
+ // lint here
+ permissions.set_readonly(false);
+ // no lint
+ permissions.set_readonly(true);
+
+ let mut a = A;
+ // no lint here - a is not of type std::fs::Permissions
+ a.set_readonly(false);
+
+ // no lint here - plain function
+ set_readonly(false);
+}
diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr
new file mode 100644
index 000000000..e7a8ee6cb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr
@@ -0,0 +1,13 @@
+error: call to `set_readonly` with argument `false`
+ --> $DIR/permissions_set_readonly_false.rs:19:5
+ |
+LL | permissions.set_readonly(false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: on Unix platforms this results in the file being world writable
+ = help: you can set the desired permissions using `PermissionsExt`. For more information, see
+ https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html
+ = note: `-D clippy::permissions-set-readonly-false` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
index 4c5846fe8..bca777a89 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
@@ -39,8 +39,14 @@ static STATIC_VAR_TUPLE: &(u8, u8) = &(1, 2); // ERROR Consider removing 'static
static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static.
+static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0];
+
fn main() {
let false_positive: &'static str = "test";
+
+ unsafe {
+ STATIC_MUT_SLICE[0] = 0;
+ }
}
trait Bar {
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
index 64a66be1a..afe764481 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
@@ -39,8 +39,14 @@ static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing
static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
+static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
+
fn main() {
let false_positive: &'static str = "test";
+
+ unsafe {
+ STATIC_MUT_SLICE[0] = 0;
+ }
}
trait Bar {
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
index 0938ebf78..b2cbd2d9d 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
@@ -97,10 +97,16 @@ LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removin
| -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:65:16
+ --> $DIR/redundant_static_lifetimes.rs:42:31
+ |
+LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
+ | -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]`
+
+error: statics have by default a `'static` lifetime
+ --> $DIR/redundant_static_lifetimes.rs:71:16
|
LL | static V: &'static u8 = &17;
| -^^^^^^^--- help: consider removing `'static`: `&u8`
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 689928f04..5076f6133 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -4,11 +4,13 @@
// run-rustfix
+#![allow(clippy::almost_complete_range)]
#![allow(clippy::disallowed_names)]
#![allow(clippy::blocks_in_if_conditions)]
#![allow(clippy::box_collection)]
#![allow(clippy::redundant_static_lifetimes)]
#![allow(clippy::cognitive_complexity)]
+#![allow(clippy::derived_hash_with_manual_eq)]
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
@@ -37,12 +39,14 @@
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
+#![warn(clippy::almost_complete_range)]
#![warn(clippy::disallowed_names)]
#![warn(clippy::blocks_in_if_conditions)]
#![warn(clippy::blocks_in_if_conditions)]
#![warn(clippy::box_collection)]
#![warn(clippy::redundant_static_lifetimes)]
#![warn(clippy::cognitive_complexity)]
+#![warn(clippy::derived_hash_with_manual_eq)]
#![warn(clippy::disallowed_methods)]
#![warn(clippy::disallowed_types)]
#![warn(clippy::mixed_read_write_in_expression)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index b74aa650f..64bc1ca71 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -4,11 +4,13 @@
// run-rustfix
+#![allow(clippy::almost_complete_range)]
#![allow(clippy::disallowed_names)]
#![allow(clippy::blocks_in_if_conditions)]
#![allow(clippy::box_collection)]
#![allow(clippy::redundant_static_lifetimes)]
#![allow(clippy::cognitive_complexity)]
+#![allow(clippy::derived_hash_with_manual_eq)]
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
@@ -37,12 +39,14 @@
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
+#![warn(clippy::almost_complete_letter_range)]
#![warn(clippy::blacklisted_name)]
#![warn(clippy::block_in_if_condition_expr)]
#![warn(clippy::block_in_if_condition_stmt)]
#![warn(clippy::box_vec)]
#![warn(clippy::const_static_lifetime)]
#![warn(clippy::cyclomatic_complexity)]
+#![warn(clippy::derive_hash_xor_eq)]
#![warn(clippy::disallowed_method)]
#![warn(clippy::disallowed_type)]
#![warn(clippy::eval_order_dependence)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 622a32c59..27a026329 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,244 +1,256 @@
+error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
+ --> $DIR/rename.rs:42:9
+ |
+LL | #![warn(clippy::almost_complete_letter_range)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
+ |
+ = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
- --> $DIR/rename.rs:40:9
+ --> $DIR/rename.rs:43:9
|
LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
- |
- = note: `-D renamed-and-removed-lints` implied by `-D warnings`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:41:9
+ --> $DIR/rename.rs:44:9
|
LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:42:9
+ --> $DIR/rename.rs:45:9
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
- --> $DIR/rename.rs:43:9
+ --> $DIR/rename.rs:46:9
|
LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
- --> $DIR/rename.rs:44:9
+ --> $DIR/rename.rs:47:9
|
LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
- --> $DIR/rename.rs:45:9
+ --> $DIR/rename.rs:48:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
+error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
+ --> $DIR/rename.rs:49:9
+ |
+LL | #![warn(clippy::derive_hash_xor_eq)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
+
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
- --> $DIR/rename.rs:46:9
+ --> $DIR/rename.rs:50:9
|
LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
- --> $DIR/rename.rs:47:9
+ --> $DIR/rename.rs:51:9
|
LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
- --> $DIR/rename.rs:48:9
+ --> $DIR/rename.rs:52:9
|
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
- --> $DIR/rename.rs:49:9
+ --> $DIR/rename.rs:53:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
- --> $DIR/rename.rs:50:9
+ --> $DIR/rename.rs:54:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
- --> $DIR/rename.rs:51:9
+ --> $DIR/rename.rs:55:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> $DIR/rename.rs:52:9
+ --> $DIR/rename.rs:56:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
- --> $DIR/rename.rs:53:9
+ --> $DIR/rename.rs:57:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:54:9
+ --> $DIR/rename.rs:58:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:55:9
+ --> $DIR/rename.rs:59:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:56:9
+ --> $DIR/rename.rs:60:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:57:9
+ --> $DIR/rename.rs:61:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
- --> $DIR/rename.rs:58:9
+ --> $DIR/rename.rs:62:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:59:9
+ --> $DIR/rename.rs:63:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:60:9
+ --> $DIR/rename.rs:64:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:61:9
+ --> $DIR/rename.rs:65:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
- --> $DIR/rename.rs:62:9
+ --> $DIR/rename.rs:66:9
|
LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
- --> $DIR/rename.rs:63:9
+ --> $DIR/rename.rs:67:9
|
LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
- --> $DIR/rename.rs:64:9
+ --> $DIR/rename.rs:68:9
|
LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
- --> $DIR/rename.rs:65:9
+ --> $DIR/rename.rs:69:9
|
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
- --> $DIR/rename.rs:66:9
+ --> $DIR/rename.rs:70:9
|
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:67:9
+ --> $DIR/rename.rs:71:9
|
LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:68:9
+ --> $DIR/rename.rs:72:9
|
LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:69:9
+ --> $DIR/rename.rs:73:9
|
LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> $DIR/rename.rs:70:9
+ --> $DIR/rename.rs:74:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> $DIR/rename.rs:71:9
+ --> $DIR/rename.rs:75:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> $DIR/rename.rs:72:9
+ --> $DIR/rename.rs:76:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
- --> $DIR/rename.rs:73:9
+ --> $DIR/rename.rs:77:9
|
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> $DIR/rename.rs:74:9
+ --> $DIR/rename.rs:78:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> $DIR/rename.rs:75:9
+ --> $DIR/rename.rs:79:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
- --> $DIR/rename.rs:76:9
+ --> $DIR/rename.rs:80:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
- --> $DIR/rename.rs:77:9
+ --> $DIR/rename.rs:81:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> $DIR/rename.rs:78:9
+ --> $DIR/rename.rs:82:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> $DIR/rename.rs:79:9
+ --> $DIR/rename.rs:83:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
-error: aborting due to 40 previous errors
+error: aborting due to 42 previous errors
diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr
index 2e1eb8eb1..d0e534f63 100644
--- a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr
@@ -19,10 +19,7 @@ LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value)
error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()`
--> $DIR/result_map_unit_fn_unfixable.rs:29:5
|
-LL | x.field.map(|value| {
- | ______^
- | | _____|
- | ||
+LL | // x.field.map(|value| {
LL | || do_nothing(value);
LL | || do_nothing(value)
LL | || });
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
index 9d0d1124c..713cff604 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -70,6 +70,12 @@ fn seek_to_end<T: Seek>(t: &mut T) {
t.seek(SeekFrom::End(0));
}
+// This should NOT trigger clippy warning because
+// expr is used here
+fn seek_to_start_in_let<T: Seek>(t: &mut T) {
+ let a = t.seek(SeekFrom::Start(0)).unwrap();
+}
+
fn main() {
let mut f = OpenOptions::new()
.write(true)
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
index c5bc57cc3..467003a1a 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -70,6 +70,12 @@ fn seek_to_end<T: Seek>(t: &mut T) {
t.seek(SeekFrom::End(0));
}
+// This should NOT trigger clippy warning because
+// expr is used here
+fn seek_to_start_in_let<T: Seek>(t: &mut T) {
+ let a = t.seek(SeekFrom::Start(0)).unwrap();
+}
+
fn main() {
let mut f = OpenOptions::new()
.write(true)
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
index 6cce02535..342ec00fe 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
@@ -13,7 +13,7 @@ LL | t.seek(SeekFrom::Start(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
error: used `seek` to go to the start of the stream
- --> $DIR/seek_to_start_instead_of_rewind.rs:128:7
+ --> $DIR/seek_to_start_instead_of_rewind.rs:134:7
|
LL | f.seek(SeekFrom::Start(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.fixed b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
new file mode 100644
index 000000000..42e97e1ca
--- /dev/null
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()); }
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.rs b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
new file mode 100644
index 000000000..f40848f70
--- /dev/null
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.stderr b/src/tools/clippy/tests/ui/semicolon_inside_block.stderr
new file mode 100644
index 000000000..48d3690e2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.stderr
@@ -0,0 +1,54 @@
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:39:5
+ |
+LL | { unit_fn_block() };
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::semicolon-inside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL - { unit_fn_block() };
+LL + { unit_fn_block(); }
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:40:5
+ |
+LL | unsafe { unit_fn_block() };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - unsafe { unit_fn_block() };
+LL + unsafe { unit_fn_block(); }
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:48:5
+ |
+LL | / {
+LL | | unit_fn_block();
+LL | | unit_fn_block()
+LL | | };
+ | |______^
+ |
+help: put the `;` here
+ |
+LL ~ unit_fn_block();
+LL ~ }
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:61:5
+ |
+LL | { m!(()) };
+ | ^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - { m!(()) };
+LL + { m!(()); }
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.fixed b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed
new file mode 100644
index 000000000..091eaa751
--- /dev/null
+++ b/src/tools/clippy/tests/ui/semicolon_outside_block.fixed
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()) };
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.rs b/src/tools/clippy/tests/ui/semicolon_outside_block.rs
new file mode 100644
index 000000000..7ce46431f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/semicolon_outside_block.rs
@@ -0,0 +1,85 @@
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_outside_block.stderr b/src/tools/clippy/tests/ui/semicolon_outside_block.stderr
new file mode 100644
index 000000000..dcc102e60
--- /dev/null
+++ b/src/tools/clippy/tests/ui/semicolon_outside_block.stderr
@@ -0,0 +1,54 @@
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:42:5
+ |
+LL | { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::semicolon-outside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL - { unit_fn_block(); }
+LL + { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:43:5
+ |
+LL | unsafe { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - unsafe { unit_fn_block(); }
+LL + unsafe { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:52:5
+ |
+LL | / {
+LL | | unit_fn_block();
+LL | | unit_fn_block();
+LL | | }
+ | |_____^
+ |
+help: put the `;` here
+ |
+LL ~ unit_fn_block()
+LL ~ };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:62:5
+ |
+LL | { m!(()); }
+ | ^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - { m!(()); }
+LL + { m!(()) };
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/single_element_loop.fixed b/src/tools/clippy/tests/ui/single_element_loop.fixed
index 63d31ff83..a0dcc0172 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.fixed
+++ b/src/tools/clippy/tests/ui/single_element_loop.fixed
@@ -33,4 +33,31 @@ fn main() {
let item = 0..5;
dbg!(item);
}
+
+ // should not lint (issue #10018)
+ for e in [42] {
+ if e > 0 {
+ continue;
+ }
+ }
+
+ // should not lint (issue #10018)
+ for e in [42] {
+ if e > 0 {
+ break;
+ }
+ }
+
+ // should lint (issue #10018)
+ {
+ let _ = 42;
+ let _f = |n: u32| {
+ for i in 0..n {
+ if i > 10 {
+ dbg!(i);
+ break;
+ }
+ }
+ };
+ }
}
diff --git a/src/tools/clippy/tests/ui/single_element_loop.rs b/src/tools/clippy/tests/ui/single_element_loop.rs
index 2cda5a329..bc014035c 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.rs
+++ b/src/tools/clippy/tests/ui/single_element_loop.rs
@@ -27,4 +27,30 @@ fn main() {
for item in [0..5].into_iter() {
dbg!(item);
}
+
+ // should not lint (issue #10018)
+ for e in [42] {
+ if e > 0 {
+ continue;
+ }
+ }
+
+ // should not lint (issue #10018)
+ for e in [42] {
+ if e > 0 {
+ break;
+ }
+ }
+
+ // should lint (issue #10018)
+ for _ in [42] {
+ let _f = |n: u32| {
+ for i in 0..n {
+ if i > 10 {
+ dbg!(i);
+ break;
+ }
+ }
+ };
+ }
}
diff --git a/src/tools/clippy/tests/ui/single_element_loop.stderr b/src/tools/clippy/tests/ui/single_element_loop.stderr
index 0aeb8da1a..14437a597 100644
--- a/src/tools/clippy/tests/ui/single_element_loop.stderr
+++ b/src/tools/clippy/tests/ui/single_element_loop.stderr
@@ -95,5 +95,32 @@ LL + dbg!(item);
LL + }
|
-error: aborting due to 6 previous errors
+error: for loop over a single element
+ --> $DIR/single_element_loop.rs:46:5
+ |
+LL | / for _ in [42] {
+LL | | let _f = |n: u32| {
+LL | | for i in 0..n {
+LL | | if i > 10 {
+... |
+LL | | };
+LL | | }
+ | |_____^
+ |
+help: try
+ |
+LL ~ {
+LL + let _ = 42;
+LL + let _f = |n: u32| {
+LL + for i in 0..n {
+LL + if i > 10 {
+LL + dbg!(i);
+LL + break;
+LL + }
+LL + }
+LL + };
+LL + }
+ |
+
+error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/size_of_ref.rs b/src/tools/clippy/tests/ui/size_of_ref.rs
new file mode 100644
index 000000000..1e83ab829
--- /dev/null
+++ b/src/tools/clippy/tests/ui/size_of_ref.rs
@@ -0,0 +1,27 @@
+#![allow(unused)]
+#![warn(clippy::size_of_ref)]
+
+use std::mem::size_of_val;
+
+fn main() {
+ let x = 5;
+ let y = &x;
+
+ size_of_val(&x); // no lint
+ size_of_val(y); // no lint
+
+ size_of_val(&&x);
+ size_of_val(&y);
+}
+
+struct S {
+ field: u32,
+ data: Vec<u8>,
+}
+
+impl S {
+ /// Get size of object including `self`, in bytes.
+ pub fn size(&self) -> usize {
+ std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity())
+ }
+}
diff --git a/src/tools/clippy/tests/ui/size_of_ref.stderr b/src/tools/clippy/tests/ui/size_of_ref.stderr
new file mode 100644
index 000000000..d4c13ac32
--- /dev/null
+++ b/src/tools/clippy/tests/ui/size_of_ref.stderr
@@ -0,0 +1,27 @@
+error: argument to `std::mem::size_of_val()` is a reference to a reference
+ --> $DIR/size_of_ref.rs:13:5
+ |
+LL | size_of_val(&&x);
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type
+ = note: `-D clippy::size-of-ref` implied by `-D warnings`
+
+error: argument to `std::mem::size_of_val()` is a reference to a reference
+ --> $DIR/size_of_ref.rs:14:5
+ |
+LL | size_of_val(&y);
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type
+
+error: argument to `std::mem::size_of_val()` is a reference to a reference
+ --> $DIR/size_of_ref.rs:25:9
+ |
+LL | std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
index df2256e4f..506187fc1 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.fixed
@@ -25,6 +25,12 @@ fn str_lit_as_bytes() {
let includestr = include_bytes!("string_lit_as_bytes.rs");
let _ = b"string with newline\t\n";
+
+ let _ = match "x".as_bytes() {
+ b"xx" => 0,
+ [b'x', ..] => 1,
+ _ => 2,
+ };
}
fn main() {}
diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
index c6bf8f732..2c339f1dd 100644
--- a/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
+++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.rs
@@ -25,6 +25,12 @@ fn str_lit_as_bytes() {
let includestr = include_str!("string_lit_as_bytes.rs").as_bytes();
let _ = "string with newline\t\n".as_bytes();
+
+ let _ = match "x".as_bytes() {
+ b"xx" => 0,
+ [b'x', ..] => 1,
+ _ => 2,
+ };
}
fn main() {}
diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
index ae1aec34d..dec3f50d6 100644
--- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
@@ -1,4 +1,4 @@
-error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
+error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
--> $DIR/suspicious_to_owned.rs:16:13
|
LL | let _ = cow.to_owned();
@@ -6,19 +6,19 @@ LL | let _ = cow.to_owned();
|
= note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
-error: this `to_owned` call clones the std::borrow::Cow<'_, [char; 3]> itself and does not cause the std::borrow::Cow<'_, [char; 3]> contents to become owned
+error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
--> $DIR/suspicious_to_owned.rs:26:13
|
LL | let _ = cow.to_owned();
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
-error: this `to_owned` call clones the std::borrow::Cow<'_, std::vec::Vec<char>> itself and does not cause the std::borrow::Cow<'_, std::vec::Vec<char>> contents to become owned
+error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
--> $DIR/suspicious_to_owned.rs:36:13
|
LL | let _ = cow.to_owned();
| ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
-error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
+error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
--> $DIR/suspicious_to_owned.rs:46:13
|
LL | let _ = cow.to_owned();
diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs
new file mode 100644
index 000000000..b3ea3d903
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs
@@ -0,0 +1,28 @@
+#![allow(dead_code)]
+#![warn(clippy::transmute_null_to_fn)]
+#![allow(clippy::zero_ptr)]
+
+// Easy to lint because these only span one line.
+fn one_liners() {
+ unsafe {
+ let _: fn() = std::mem::transmute(0 as *const ());
+ let _: fn() = std::mem::transmute(std::ptr::null::<()>());
+ }
+}
+
+pub const ZPTR: *const usize = 0 as *const _;
+pub const NOT_ZPTR: *const usize = 1 as *const _;
+
+fn transmute_const() {
+ unsafe {
+ // Should raise a lint.
+ let _: fn() = std::mem::transmute(ZPTR);
+ // Should NOT raise a lint.
+ let _: fn() = std::mem::transmute(NOT_ZPTR);
+ }
+}
+
+fn main() {
+ one_liners();
+ transmute_const();
+}
diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr
new file mode 100644
index 000000000..f0c65497d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr
@@ -0,0 +1,27 @@
+error: transmuting a known null pointer into a function pointer
+ --> $DIR/transmute_null_to_fn.rs:8:23
+ |
+LL | let _: fn() = std::mem::transmute(0 as *const ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
+ = note: `-D clippy::transmute-null-to-fn` implied by `-D warnings`
+
+error: transmuting a known null pointer into a function pointer
+ --> $DIR/transmute_null_to_fn.rs:9:23
+ |
+LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
+
+error: transmuting a known null pointer into a function pointer
+ --> $DIR/transmute_null_to_fn.rs:19:23
+ |
+LL | let _: fn() = std::mem::transmute(ZPTR);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior
+ |
+ = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
index 96cc08779..52b5343c3 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
@@ -26,4 +26,7 @@ fn main() {
panic!("p4 {var}");
}
}
+
+ assert!(var == 1, "p5 {}", var);
+ debug_assert!(var == 1, "p6 {}", var);
}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
index faf8ca4d3..ee72065e2 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
@@ -26,4 +26,7 @@ fn main() {
panic!("p4 {var}");
}
}
+
+ assert!(var == 1, "p5 {var}");
+ debug_assert!(var == 1, "p6 {var}");
}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr
index 0f09c45f4..fc7b12508 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr
@@ -47,5 +47,29 @@ LL - panic!("p3 {var}", var = var);
LL + panic!("p3 {var}");
|
-error: aborting due to 4 previous errors
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:30:5
+ |
+LL | assert!(var == 1, "p5 {}", var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - assert!(var == 1, "p5 {}", var);
+LL + assert!(var == 1, "p5 {var}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:31:5
+ |
+LL | debug_assert!(var == 1, "p6 {}", var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - debug_assert!(var == 1, "p6 {}", var);
+LL + debug_assert!(var == 1, "p6 {var}");
+ |
+
+error: aborting due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs b/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
index 6421c5bbe..b4a0a0f49 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
@@ -26,4 +26,7 @@ fn main() {
panic!("p4 {var}");
}
}
+
+ assert!(var == 1, "p5 {}", var);
+ debug_assert!(var == 1, "p6 {}", var);
}
diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.stderr b/src/tools/clippy/tests/ui/unnecessary_clone.stderr
index 94cc7777a..6022d9fa4 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clone.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_clone.stderr
@@ -38,13 +38,13 @@ LL | t.clone();
|
= note: `-D clippy::clone-on-copy` implied by `-D warnings`
-error: using `clone` on type `std::option::Option<T>` which implements the `Copy` trait
+error: using `clone` on type `Option<T>` which implements the `Copy` trait
--> $DIR/unnecessary_clone.rs:42:5
|
LL | Some(t).clone();
| ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)`
-error: using `clone` on a double-reference; this will copy the reference of type `&std::vec::Vec<i32>` instead of cloning the inner type
+error: using `clone` on a double-reference; this will copy the reference of type `&Vec<i32>` instead of cloning the inner type
--> $DIR/unnecessary_clone.rs:48:22
|
LL | let z: &Vec<_> = y.clone();
@@ -57,10 +57,10 @@ LL | let z: &Vec<_> = &(*y).clone();
| ~~~~~~~~~~~~~
help: or try being explicit if you are sure, that you want to clone a reference
|
-LL | let z: &Vec<_> = <&std::vec::Vec<i32>>::clone(y);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | let z: &Vec<_> = <&Vec<i32>>::clone(y);
+ | ~~~~~~~~~~~~~~~~~~~~~
-error: using `clone` on type `many_derefs::E` which implements the `Copy` trait
+error: using `clone` on type `E` which implements the `Copy` trait
--> $DIR/unnecessary_clone.rs:84:20
|
LL | let _: E = a.clone();
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
index ddeda795f..345f6d604 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
@@ -454,3 +454,23 @@ mod issue_9771b {
Key(v.to_vec())
}
}
+
+// This is a watered down version of the code in: https://github.com/oxigraph/rio
+// The ICE is triggered by the call to `to_owned` on this line:
+// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
+mod issue_10021 {
+ #![allow(unused)]
+
+ pub struct Iri<T>(T);
+
+ impl<T: AsRef<str>> Iri<T> {
+ pub fn parse(iri: T) -> Result<Self, ()> {
+ unimplemented!()
+ }
+ }
+
+ pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
+ let base_iri = Iri::parse(url.to_owned())?;
+ Ok(())
+ }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
index 95d257673..7eb53df39 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
@@ -454,3 +454,23 @@ mod issue_9771b {
Key(v.to_vec())
}
}
+
+// This is a watered down version of the code in: https://github.com/oxigraph/rio
+// The ICE is triggered by the call to `to_owned` on this line:
+// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
+mod issue_10021 {
+ #![allow(unused)]
+
+ pub struct Iri<T>(T);
+
+ impl<T: AsRef<str>> Iri<T> {
+ pub fn parse(iri: T) -> Result<Self, ()> {
+ unimplemented!()
+ }
+ }
+
+ pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
+ let base_iri = Iri::parse(url.to_owned())?;
+ Ok(())
+ }
+}
diff --git a/src/tools/clippy/tests/ui/unused_self.rs b/src/tools/clippy/tests/ui/unused_self.rs
index 92e8e1dba..55bd56071 100644
--- a/src/tools/clippy/tests/ui/unused_self.rs
+++ b/src/tools/clippy/tests/ui/unused_self.rs
@@ -60,6 +60,16 @@ mod unused_self_allow {
// shouldn't trigger for public methods
pub fn unused_self_move(self) {}
}
+
+ pub struct E;
+
+ impl E {
+ // shouldn't trigger if body contains todo!()
+ pub fn unused_self_todo(self) {
+ let x = 42;
+ todo!()
+ }
+ }
}
pub use unused_self_allow::D;
diff --git a/src/tools/clippy/tests/ui/unused_self.stderr b/src/tools/clippy/tests/ui/unused_self.stderr
index 23186122a..919f9b6ef 100644
--- a/src/tools/clippy/tests/ui/unused_self.stderr
+++ b/src/tools/clippy/tests/ui/unused_self.stderr
@@ -4,7 +4,7 @@ error: unused `self` argument
LL | fn unused_self_move(self) {}
| ^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
= note: `-D clippy::unused-self` implied by `-D warnings`
error: unused `self` argument
@@ -13,7 +13,7 @@ error: unused `self` argument
LL | fn unused_self_ref(&self) {}
| ^^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:13:32
@@ -21,7 +21,7 @@ error: unused `self` argument
LL | fn unused_self_mut_ref(&mut self) {}
| ^^^^^^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:14:32
@@ -29,7 +29,7 @@ error: unused `self` argument
LL | fn unused_self_pin_ref(self: Pin<&Self>) {}
| ^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:15:36
@@ -37,7 +37,7 @@ error: unused `self` argument
LL | fn unused_self_pin_mut_ref(self: Pin<&mut Self>) {}
| ^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:16:35
@@ -45,7 +45,7 @@ error: unused `self` argument
LL | fn unused_self_pin_nested(self: Pin<Arc<Self>>) {}
| ^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:17:28
@@ -53,7 +53,7 @@ error: unused `self` argument
LL | fn unused_self_box(self: Box<Self>) {}
| ^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:18:40
@@ -61,7 +61,7 @@ error: unused `self` argument
LL | fn unused_with_other_used_args(&self, x: u8, y: u8) -> u8 {
| ^^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: unused `self` argument
--> $DIR/unused_self.rs:21:37
@@ -69,7 +69,7 @@ error: unused `self` argument
LL | fn unused_self_class_method(&self) {
| ^^^^^
|
- = help: consider refactoring to a associated function
+ = help: consider refactoring to an associated function
error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 70ff08f36..94b206d8e 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -33,12 +33,71 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
Ok(())
}
-fn test_issue_5833() -> Result<(), ()> {
+fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
let text = "foo\r\nbar\n\nbaz\n";
let lines = text.lines();
if Some("ok") == lines.into_iter().next() {}
+}
- Ok(())
+fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() {
+ let text = "foo\r\nbar\n\nbaz\n";
+ let mut lines = text.lines();
+ if Some("ok") == lines.next() {}
+}
+
+fn lint_into_iter_on_expr_implementing_iterator() {
+ let text = "foo\r\nbar\n\nbaz\n";
+ let mut lines = text.lines();
+ if Some("ok") == lines.next() {}
+}
+
+fn lint_into_iter_on_expr_implementing_iterator_2() {
+ let text = "foo\r\nbar\n\nbaz\n";
+ if Some("ok") == text.lines().next() {}
+}
+
+#[allow(const_item_mutation)]
+fn lint_into_iter_on_const_implementing_iterator() {
+ const NUMBERS: std::ops::Range<i32> = 0..10;
+ let _ = NUMBERS.next();
+}
+
+fn lint_into_iter_on_const_implementing_iterator_2() {
+ const NUMBERS: std::ops::Range<i32> = 0..10;
+ let mut n = NUMBERS;
+ n.next();
+}
+
+#[derive(Clone, Copy)]
+struct CopiableCounter {
+ counter: u32,
+}
+
+impl Iterator for CopiableCounter {
+ type Item = u32;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.counter = self.counter.wrapping_add(1);
+ Some(self.counter)
+ }
+}
+
+fn dont_lint_into_iter_on_copy_iter() {
+ let mut c = CopiableCounter { counter: 0 };
+ assert_eq!(c.into_iter().next(), Some(1));
+ assert_eq!(c.into_iter().next(), Some(1));
+ assert_eq!(c.next(), Some(1));
+ assert_eq!(c.next(), Some(2));
+}
+
+fn dont_lint_into_iter_on_static_copy_iter() {
+ static mut C: CopiableCounter = CopiableCounter { counter: 0 };
+ unsafe {
+ assert_eq!(C.into_iter().next(), Some(1));
+ assert_eq!(C.into_iter().next(), Some(1));
+ assert_eq!(C.next(), Some(1));
+ assert_eq!(C.next(), Some(2));
+ }
}
fn main() {
@@ -46,7 +105,15 @@ fn main() {
test_generic2::<i32, i32>(10i32);
test_questionmark().unwrap();
test_issue_3913().unwrap();
- test_issue_5833().unwrap();
+
+ dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
+ lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
+ lint_into_iter_on_expr_implementing_iterator();
+ lint_into_iter_on_expr_implementing_iterator_2();
+ lint_into_iter_on_const_implementing_iterator();
+ lint_into_iter_on_const_implementing_iterator_2();
+ dont_lint_into_iter_on_copy_iter();
+ dont_lint_into_iter_on_static_copy_iter();
let _: String = "foo".into();
let _: String = From::from("foo");
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index f2444a8f4..c7ae92794 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -33,12 +33,71 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
Ok(())
}
-fn test_issue_5833() -> Result<(), ()> {
+fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
let text = "foo\r\nbar\n\nbaz\n";
let lines = text.lines();
if Some("ok") == lines.into_iter().next() {}
+}
- Ok(())
+fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() {
+ let text = "foo\r\nbar\n\nbaz\n";
+ let mut lines = text.lines();
+ if Some("ok") == lines.into_iter().next() {}
+}
+
+fn lint_into_iter_on_expr_implementing_iterator() {
+ let text = "foo\r\nbar\n\nbaz\n";
+ let mut lines = text.lines().into_iter();
+ if Some("ok") == lines.next() {}
+}
+
+fn lint_into_iter_on_expr_implementing_iterator_2() {
+ let text = "foo\r\nbar\n\nbaz\n";
+ if Some("ok") == text.lines().into_iter().next() {}
+}
+
+#[allow(const_item_mutation)]
+fn lint_into_iter_on_const_implementing_iterator() {
+ const NUMBERS: std::ops::Range<i32> = 0..10;
+ let _ = NUMBERS.into_iter().next();
+}
+
+fn lint_into_iter_on_const_implementing_iterator_2() {
+ const NUMBERS: std::ops::Range<i32> = 0..10;
+ let mut n = NUMBERS.into_iter();
+ n.next();
+}
+
+#[derive(Clone, Copy)]
+struct CopiableCounter {
+ counter: u32,
+}
+
+impl Iterator for CopiableCounter {
+ type Item = u32;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.counter = self.counter.wrapping_add(1);
+ Some(self.counter)
+ }
+}
+
+fn dont_lint_into_iter_on_copy_iter() {
+ let mut c = CopiableCounter { counter: 0 };
+ assert_eq!(c.into_iter().next(), Some(1));
+ assert_eq!(c.into_iter().next(), Some(1));
+ assert_eq!(c.next(), Some(1));
+ assert_eq!(c.next(), Some(2));
+}
+
+fn dont_lint_into_iter_on_static_copy_iter() {
+ static mut C: CopiableCounter = CopiableCounter { counter: 0 };
+ unsafe {
+ assert_eq!(C.into_iter().next(), Some(1));
+ assert_eq!(C.into_iter().next(), Some(1));
+ assert_eq!(C.next(), Some(1));
+ assert_eq!(C.next(), Some(2));
+ }
}
fn main() {
@@ -46,7 +105,15 @@ fn main() {
test_generic2::<i32, i32>(10i32);
test_questionmark().unwrap();
test_issue_3913().unwrap();
- test_issue_5833().unwrap();
+
+ dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
+ lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
+ lint_into_iter_on_expr_implementing_iterator();
+ lint_into_iter_on_expr_implementing_iterator_2();
+ lint_into_iter_on_const_implementing_iterator();
+ lint_into_iter_on_const_implementing_iterator_2();
+ dont_lint_into_iter_on_copy_iter();
+ dont_lint_into_iter_on_static_copy_iter();
let _: String = "foo".into();
let _: String = From::from("foo");
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index 65ee3807f..be067c684 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -22,71 +22,101 @@ error: useless conversion to the same type: `i32`
LL | let _: i32 = 0i32.into();
| ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
+error: useless conversion to the same type: `std::str::Lines<'_>`
+ --> $DIR/useless_conversion.rs:45:22
+ |
+LL | if Some("ok") == lines.into_iter().next() {}
+ | ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
+
+error: useless conversion to the same type: `std::str::Lines<'_>`
+ --> $DIR/useless_conversion.rs:50:21
+ |
+LL | let mut lines = text.lines().into_iter();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
+
+error: useless conversion to the same type: `std::str::Lines<'_>`
+ --> $DIR/useless_conversion.rs:56:22
+ |
+LL | if Some("ok") == text.lines().into_iter().next() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
+
+error: useless conversion to the same type: `std::ops::Range<i32>`
+ --> $DIR/useless_conversion.rs:62:13
+ |
+LL | let _ = NUMBERS.into_iter().next();
+ | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
+
+error: useless conversion to the same type: `std::ops::Range<i32>`
+ --> $DIR/useless_conversion.rs:67:17
+ |
+LL | let mut n = NUMBERS.into_iter();
+ | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
+
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:61:21
+ --> $DIR/useless_conversion.rs:128:21
|
LL | let _: String = "foo".to_string().into();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:62:21
+ --> $DIR/useless_conversion.rs:129:21
|
LL | let _: String = From::from("foo".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:63:13
+ --> $DIR/useless_conversion.rs:130:13
|
LL | let _ = String::from("foo".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:64:13
+ --> $DIR/useless_conversion.rs:131:13
|
LL | let _ = String::from(format!("A: {:04}", 123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
error: useless conversion to the same type: `std::str::Lines<'_>`
- --> $DIR/useless_conversion.rs:65:13
+ --> $DIR/useless_conversion.rs:132:13
|
LL | let _ = "".lines().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
error: useless conversion to the same type: `std::vec::IntoIter<i32>`
- --> $DIR/useless_conversion.rs:66:13
+ --> $DIR/useless_conversion.rs:133:13
|
LL | let _ = vec![1, 2, 3].into_iter().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
error: useless conversion to the same type: `std::string::String`
- --> $DIR/useless_conversion.rs:67:21
+ --> $DIR/useless_conversion.rs:134:21
|
LL | let _: String = format!("Hello {}", "world").into();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
error: useless conversion to the same type: `i32`
- --> $DIR/useless_conversion.rs:72:13
+ --> $DIR/useless_conversion.rs:139:13
|
LL | let _ = i32::from(a + b) * 3;
| ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
error: useless conversion to the same type: `Foo<'a'>`
- --> $DIR/useless_conversion.rs:78:23
+ --> $DIR/useless_conversion.rs:145:23
|
LL | let _: Foo<'a'> = s2.into();
| ^^^^^^^^^ help: consider removing `.into()`: `s2`
error: useless conversion to the same type: `Foo<'a'>`
- --> $DIR/useless_conversion.rs:80:13
+ --> $DIR/useless_conversion.rs:147:13
|
LL | let _ = Foo::<'a'>::from(s3);
| ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
- --> $DIR/useless_conversion.rs:82:13
+ --> $DIR/useless_conversion.rs:149:13
|
LL | let _ = vec![s4, s4, s4].into_iter().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
-error: aborting due to 14 previous errors
+error: aborting due to 19 previous errors
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed
index ef55f1c31..0baec6f0b 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed
@@ -5,7 +5,6 @@
// the 2015 edition here is needed because edition 2018 changed the module system
// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
// no longer detects some of the cases starting with Rust 2018.
-// FIXME: We should likely add another edition 2021 test case for this lint
#![warn(clippy::wildcard_imports)]
#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs
index b81285142..db591d56a 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.rs
+++ b/src/tools/clippy/tests/ui/wildcard_imports.rs
@@ -5,7 +5,6 @@
// the 2015 edition here is needed because edition 2018 changed the module system
// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
// no longer detects some of the cases starting with Rust 2018.
-// FIXME: We should likely add another edition 2021 test case for this lint
#![warn(clippy::wildcard_imports)]
#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr
index 626c1754f..6b469cdfc 100644
--- a/src/tools/clippy/tests/ui/wildcard_imports.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr
@@ -1,5 +1,5 @@
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:16:5
+ --> $DIR/wildcard_imports.rs:15:5
|
LL | use crate::fn_mod::*;
| ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
@@ -7,85 +7,85 @@ LL | use crate::fn_mod::*;
= note: `-D clippy::wildcard-imports` implied by `-D warnings`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:17:5
+ --> $DIR/wildcard_imports.rs:16:5
|
LL | use crate::mod_mod::*;
| ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:18:5
+ --> $DIR/wildcard_imports.rs:17:5
|
LL | use crate::multi_fn_mod::*;
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:20:5
+ --> $DIR/wildcard_imports.rs:19:5
|
LL | use crate::struct_mod::*;
| ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:24:5
+ --> $DIR/wildcard_imports.rs:23:5
|
LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:25:5
+ --> $DIR/wildcard_imports.rs:24:5
|
LL | use wildcard_imports_helper::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:96:13
+ --> $DIR/wildcard_imports.rs:95:13
|
LL | use crate::fn_mod::*;
| ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:102:75
+ --> $DIR/wildcard_imports.rs:101:75
|
LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
| ^ help: try: `inner_extern_foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:103:13
+ --> $DIR/wildcard_imports.rs:102:13
|
LL | use wildcard_imports_helper::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:114:20
+ --> $DIR/wildcard_imports.rs:113:20
|
LL | use self::{inner::*, inner2::*};
| ^^^^^^^^ help: try: `inner::inner_foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:114:30
+ --> $DIR/wildcard_imports.rs:113:30
|
LL | use self::{inner::*, inner2::*};
| ^^^^^^^^^ help: try: `inner2::inner_bar`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:121:13
+ --> $DIR/wildcard_imports.rs:120:13
|
LL | use wildcard_imports_helper::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:150:9
+ --> $DIR/wildcard_imports.rs:149:9
|
LL | use crate::in_fn_test::*;
| ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:159:9
+ --> $DIR/wildcard_imports.rs:158:9
|
LL | use crate:: in_fn_test:: * ;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:160:9
+ --> $DIR/wildcard_imports.rs:159:9
|
LL | use crate:: fn_mod::
| _________^
@@ -93,37 +93,37 @@ LL | | *;
| |_________^ help: try: `crate:: fn_mod::foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:171:13
+ --> $DIR/wildcard_imports.rs:170:13
|
LL | use super::*;
| ^^^^^^^^ help: try: `super::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:206:17
+ --> $DIR/wildcard_imports.rs:205:17
|
LL | use super::*;
| ^^^^^^^^ help: try: `super::insidefoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:214:13
+ --> $DIR/wildcard_imports.rs:213:13
|
LL | use super_imports::*;
| ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:223:17
+ --> $DIR/wildcard_imports.rs:222:17
|
LL | use super::super::*;
| ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:232:13
+ --> $DIR/wildcard_imports.rs:231:13
|
LL | use super::super::super_imports::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:240:13
+ --> $DIR/wildcard_imports.rs:239:13
|
LL | use super::*;
| ^^^^^^^^ help: try: `super::foofoo`
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
new file mode 100644
index 000000000..6d534a10e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed
@@ -0,0 +1,240 @@
+// revisions: edition2018 edition2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
+// run-rustfix
+// aux-build:wildcard_imports_helper.rs
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+#![warn(unused_imports)]
+
+extern crate wildcard_imports_helper;
+
+use crate::fn_mod::foo;
+use crate::mod_mod::inner_mod;
+use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod};
+use crate::struct_mod::{A, inner_struct_mod};
+
+#[allow(unused_imports)]
+use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar;
+use wildcard_imports_helper::prelude::v1::*;
+use wildcard_imports_helper::{ExternA, extern_foo};
+
+use std::io::prelude::*;
+
+struct ReadFoo;
+
+impl Read for ReadFoo {
+ fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
+ Ok(0)
+ }
+}
+
+mod fn_mod {
+ pub fn foo() {}
+}
+
+mod mod_mod {
+ pub mod inner_mod {
+ pub fn foo() {}
+ }
+}
+
+mod multi_fn_mod {
+ pub fn multi_foo() {}
+ pub fn multi_bar() {}
+ pub fn multi_baz() {}
+ pub mod multi_inner_mod {
+ pub fn foo() {}
+ }
+}
+
+mod struct_mod {
+ pub struct A;
+ pub struct B;
+ pub mod inner_struct_mod {
+ pub struct C;
+ }
+
+ #[macro_export]
+ macro_rules! double_struct_import_test {
+ () => {
+ let _ = A;
+ };
+ }
+}
+
+fn main() {
+ foo();
+ multi_foo();
+ multi_bar();
+ multi_inner_mod::foo();
+ inner_mod::foo();
+ extern_foo();
+ inner_extern_bar();
+
+ let _ = A;
+ let _ = inner_struct_mod::C;
+ let _ = ExternA;
+ let _ = PreludeModAnywhere;
+
+ double_struct_import_test!();
+ double_struct_import_test!();
+}
+
+mod in_fn_test {
+ pub use self::inner_exported::*;
+ #[allow(unused_imports)]
+ pub(crate) use self::inner_exported2::*;
+
+ fn test_intern() {
+ use crate::fn_mod::foo;
+
+ foo();
+ }
+
+ fn test_extern() {
+ use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo};
+ use wildcard_imports_helper::{ExternA, extern_foo};
+
+ inner_for_self_import::inner_extern_foo();
+ inner_extern_foo();
+
+ extern_foo();
+
+ let _ = ExternA;
+ }
+
+ fn test_inner_nested() {
+ use self::{inner::inner_foo, inner2::inner_bar};
+
+ inner_foo();
+ inner_bar();
+ }
+
+ fn test_extern_reexported() {
+ use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported};
+
+ extern_exported();
+ let _ = ExternExportedStruct;
+ let _ = ExternExportedEnum::A;
+ }
+
+ mod inner_exported {
+ pub fn exported() {}
+ pub struct ExportedStruct;
+ pub enum ExportedEnum {
+ A,
+ }
+ }
+
+ mod inner_exported2 {
+ pub(crate) fn exported2() {}
+ }
+
+ mod inner {
+ pub fn inner_foo() {}
+ }
+
+ mod inner2 {
+ pub fn inner_bar() {}
+ }
+}
+
+fn test_reexported() {
+ use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported};
+
+ exported();
+ let _ = ExportedStruct;
+ let _ = ExportedEnum::A;
+}
+
+#[rustfmt::skip]
+fn test_weird_formatting() {
+ use crate:: in_fn_test::exported;
+ use crate:: fn_mod::foo;
+
+ exported();
+ foo();
+}
+
+mod super_imports {
+ fn foofoo() {}
+
+ mod should_be_replaced {
+ use super::foofoo;
+
+ fn with_super() {
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass {
+ use super::*;
+
+ fn with_super() {
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass_inside_function {
+ fn with_super_inside_function() {
+ use super::*;
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass_further_inside {
+ fn insidefoo() {}
+ mod inner {
+ use super::*;
+ fn with_super() {
+ let _ = insidefoo();
+ }
+ }
+ }
+
+ mod should_be_replaced_further_inside {
+ fn insidefoo() {}
+ mod inner {
+ use super::insidefoo;
+ fn with_super() {
+ let _ = insidefoo();
+ }
+ }
+ }
+
+ mod use_explicit_should_be_replaced {
+ use crate::super_imports::foofoo;
+
+ fn with_explicit() {
+ let _ = foofoo();
+ }
+ }
+
+ mod use_double_super_should_be_replaced {
+ mod inner {
+ use super::super::foofoo;
+
+ fn with_double_super() {
+ let _ = foofoo();
+ }
+ }
+ }
+
+ mod use_super_explicit_should_be_replaced {
+ use super::super::super_imports::foofoo;
+
+ fn with_super_explicit() {
+ let _ = foofoo();
+ }
+ }
+
+ mod attestation_should_be_replaced {
+ use super::foofoo;
+
+ fn with_explicit() {
+ let _ = foofoo();
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr
new file mode 100644
index 000000000..acca9f651
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr
@@ -0,0 +1,132 @@
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:13:5
+ |
+LL | use crate::fn_mod::*;
+ | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
+ |
+ = note: `-D clippy::wildcard-imports` implied by `-D warnings`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:14:5
+ |
+LL | use crate::mod_mod::*;
+ | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:15:5
+ |
+LL | use crate::multi_fn_mod::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:16:5
+ |
+LL | use crate::struct_mod::*;
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:19:5
+ |
+LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:21:5
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:91:13
+ |
+LL | use crate::fn_mod::*;
+ | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:97:75
+ |
+LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
+ | ^ help: try: `inner_extern_foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:98:13
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:109:20
+ |
+LL | use self::{inner::*, inner2::*};
+ | ^^^^^^^^ help: try: `inner::inner_foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:109:30
+ |
+LL | use self::{inner::*, inner2::*};
+ | ^^^^^^^^^ help: try: `inner2::inner_bar`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:116:13
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:145:9
+ |
+LL | use crate::in_fn_test::*;
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:154:9
+ |
+LL | use crate:: in_fn_test:: * ;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:155:9
+ |
+LL | use crate:: fn_mod::
+ | _________^
+LL | | *;
+ | |_________^ help: try: `crate:: fn_mod::foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:166:13
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:201:17
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::insidefoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:209:13
+ |
+LL | use crate::super_imports::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:218:17
+ |
+LL | use super::super::*;
+ | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:227:13
+ |
+LL | use super::super::super_imports::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:235:13
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::foofoo`
+
+error: aborting due to 21 previous errors
+
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
new file mode 100644
index 000000000..6d534a10e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed
@@ -0,0 +1,240 @@
+// revisions: edition2018 edition2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
+// run-rustfix
+// aux-build:wildcard_imports_helper.rs
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+#![warn(unused_imports)]
+
+extern crate wildcard_imports_helper;
+
+use crate::fn_mod::foo;
+use crate::mod_mod::inner_mod;
+use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod};
+use crate::struct_mod::{A, inner_struct_mod};
+
+#[allow(unused_imports)]
+use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar;
+use wildcard_imports_helper::prelude::v1::*;
+use wildcard_imports_helper::{ExternA, extern_foo};
+
+use std::io::prelude::*;
+
+struct ReadFoo;
+
+impl Read for ReadFoo {
+ fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
+ Ok(0)
+ }
+}
+
+mod fn_mod {
+ pub fn foo() {}
+}
+
+mod mod_mod {
+ pub mod inner_mod {
+ pub fn foo() {}
+ }
+}
+
+mod multi_fn_mod {
+ pub fn multi_foo() {}
+ pub fn multi_bar() {}
+ pub fn multi_baz() {}
+ pub mod multi_inner_mod {
+ pub fn foo() {}
+ }
+}
+
+mod struct_mod {
+ pub struct A;
+ pub struct B;
+ pub mod inner_struct_mod {
+ pub struct C;
+ }
+
+ #[macro_export]
+ macro_rules! double_struct_import_test {
+ () => {
+ let _ = A;
+ };
+ }
+}
+
+fn main() {
+ foo();
+ multi_foo();
+ multi_bar();
+ multi_inner_mod::foo();
+ inner_mod::foo();
+ extern_foo();
+ inner_extern_bar();
+
+ let _ = A;
+ let _ = inner_struct_mod::C;
+ let _ = ExternA;
+ let _ = PreludeModAnywhere;
+
+ double_struct_import_test!();
+ double_struct_import_test!();
+}
+
+mod in_fn_test {
+ pub use self::inner_exported::*;
+ #[allow(unused_imports)]
+ pub(crate) use self::inner_exported2::*;
+
+ fn test_intern() {
+ use crate::fn_mod::foo;
+
+ foo();
+ }
+
+ fn test_extern() {
+ use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo};
+ use wildcard_imports_helper::{ExternA, extern_foo};
+
+ inner_for_self_import::inner_extern_foo();
+ inner_extern_foo();
+
+ extern_foo();
+
+ let _ = ExternA;
+ }
+
+ fn test_inner_nested() {
+ use self::{inner::inner_foo, inner2::inner_bar};
+
+ inner_foo();
+ inner_bar();
+ }
+
+ fn test_extern_reexported() {
+ use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported};
+
+ extern_exported();
+ let _ = ExternExportedStruct;
+ let _ = ExternExportedEnum::A;
+ }
+
+ mod inner_exported {
+ pub fn exported() {}
+ pub struct ExportedStruct;
+ pub enum ExportedEnum {
+ A,
+ }
+ }
+
+ mod inner_exported2 {
+ pub(crate) fn exported2() {}
+ }
+
+ mod inner {
+ pub fn inner_foo() {}
+ }
+
+ mod inner2 {
+ pub fn inner_bar() {}
+ }
+}
+
+fn test_reexported() {
+ use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported};
+
+ exported();
+ let _ = ExportedStruct;
+ let _ = ExportedEnum::A;
+}
+
+#[rustfmt::skip]
+fn test_weird_formatting() {
+ use crate:: in_fn_test::exported;
+ use crate:: fn_mod::foo;
+
+ exported();
+ foo();
+}
+
+mod super_imports {
+ fn foofoo() {}
+
+ mod should_be_replaced {
+ use super::foofoo;
+
+ fn with_super() {
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass {
+ use super::*;
+
+ fn with_super() {
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass_inside_function {
+ fn with_super_inside_function() {
+ use super::*;
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass_further_inside {
+ fn insidefoo() {}
+ mod inner {
+ use super::*;
+ fn with_super() {
+ let _ = insidefoo();
+ }
+ }
+ }
+
+ mod should_be_replaced_further_inside {
+ fn insidefoo() {}
+ mod inner {
+ use super::insidefoo;
+ fn with_super() {
+ let _ = insidefoo();
+ }
+ }
+ }
+
+ mod use_explicit_should_be_replaced {
+ use crate::super_imports::foofoo;
+
+ fn with_explicit() {
+ let _ = foofoo();
+ }
+ }
+
+ mod use_double_super_should_be_replaced {
+ mod inner {
+ use super::super::foofoo;
+
+ fn with_double_super() {
+ let _ = foofoo();
+ }
+ }
+ }
+
+ mod use_super_explicit_should_be_replaced {
+ use super::super::super_imports::foofoo;
+
+ fn with_super_explicit() {
+ let _ = foofoo();
+ }
+ }
+
+ mod attestation_should_be_replaced {
+ use super::foofoo;
+
+ fn with_explicit() {
+ let _ = foofoo();
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr
new file mode 100644
index 000000000..acca9f651
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr
@@ -0,0 +1,132 @@
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:13:5
+ |
+LL | use crate::fn_mod::*;
+ | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
+ |
+ = note: `-D clippy::wildcard-imports` implied by `-D warnings`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:14:5
+ |
+LL | use crate::mod_mod::*;
+ | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:15:5
+ |
+LL | use crate::multi_fn_mod::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:16:5
+ |
+LL | use crate::struct_mod::*;
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:19:5
+ |
+LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:21:5
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:91:13
+ |
+LL | use crate::fn_mod::*;
+ | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:97:75
+ |
+LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
+ | ^ help: try: `inner_extern_foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:98:13
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:109:20
+ |
+LL | use self::{inner::*, inner2::*};
+ | ^^^^^^^^ help: try: `inner::inner_foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:109:30
+ |
+LL | use self::{inner::*, inner2::*};
+ | ^^^^^^^^^ help: try: `inner2::inner_bar`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:116:13
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:145:9
+ |
+LL | use crate::in_fn_test::*;
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:154:9
+ |
+LL | use crate:: in_fn_test:: * ;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:155:9
+ |
+LL | use crate:: fn_mod::
+ | _________^
+LL | | *;
+ | |_________^ help: try: `crate:: fn_mod::foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:166:13
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:201:17
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::insidefoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:209:13
+ |
+LL | use crate::super_imports::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:218:17
+ |
+LL | use super::super::*;
+ | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:227:13
+ |
+LL | use super::super::super_imports::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:235:13
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::foofoo`
+
+error: aborting due to 21 previous errors
+
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
new file mode 100644
index 000000000..b5ed58e68
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs
@@ -0,0 +1,241 @@
+// revisions: edition2018 edition2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
+// run-rustfix
+// aux-build:wildcard_imports_helper.rs
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+#![warn(unused_imports)]
+
+extern crate wildcard_imports_helper;
+
+use crate::fn_mod::*;
+use crate::mod_mod::*;
+use crate::multi_fn_mod::*;
+use crate::struct_mod::*;
+
+#[allow(unused_imports)]
+use wildcard_imports_helper::inner::inner_for_self_import::*;
+use wildcard_imports_helper::prelude::v1::*;
+use wildcard_imports_helper::*;
+
+use std::io::prelude::*;
+
+struct ReadFoo;
+
+impl Read for ReadFoo {
+ fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
+ Ok(0)
+ }
+}
+
+mod fn_mod {
+ pub fn foo() {}
+}
+
+mod mod_mod {
+ pub mod inner_mod {
+ pub fn foo() {}
+ }
+}
+
+mod multi_fn_mod {
+ pub fn multi_foo() {}
+ pub fn multi_bar() {}
+ pub fn multi_baz() {}
+ pub mod multi_inner_mod {
+ pub fn foo() {}
+ }
+}
+
+mod struct_mod {
+ pub struct A;
+ pub struct B;
+ pub mod inner_struct_mod {
+ pub struct C;
+ }
+
+ #[macro_export]
+ macro_rules! double_struct_import_test {
+ () => {
+ let _ = A;
+ };
+ }
+}
+
+fn main() {
+ foo();
+ multi_foo();
+ multi_bar();
+ multi_inner_mod::foo();
+ inner_mod::foo();
+ extern_foo();
+ inner_extern_bar();
+
+ let _ = A;
+ let _ = inner_struct_mod::C;
+ let _ = ExternA;
+ let _ = PreludeModAnywhere;
+
+ double_struct_import_test!();
+ double_struct_import_test!();
+}
+
+mod in_fn_test {
+ pub use self::inner_exported::*;
+ #[allow(unused_imports)]
+ pub(crate) use self::inner_exported2::*;
+
+ fn test_intern() {
+ use crate::fn_mod::*;
+
+ foo();
+ }
+
+ fn test_extern() {
+ use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
+ use wildcard_imports_helper::*;
+
+ inner_for_self_import::inner_extern_foo();
+ inner_extern_foo();
+
+ extern_foo();
+
+ let _ = ExternA;
+ }
+
+ fn test_inner_nested() {
+ use self::{inner::*, inner2::*};
+
+ inner_foo();
+ inner_bar();
+ }
+
+ fn test_extern_reexported() {
+ use wildcard_imports_helper::*;
+
+ extern_exported();
+ let _ = ExternExportedStruct;
+ let _ = ExternExportedEnum::A;
+ }
+
+ mod inner_exported {
+ pub fn exported() {}
+ pub struct ExportedStruct;
+ pub enum ExportedEnum {
+ A,
+ }
+ }
+
+ mod inner_exported2 {
+ pub(crate) fn exported2() {}
+ }
+
+ mod inner {
+ pub fn inner_foo() {}
+ }
+
+ mod inner2 {
+ pub fn inner_bar() {}
+ }
+}
+
+fn test_reexported() {
+ use crate::in_fn_test::*;
+
+ exported();
+ let _ = ExportedStruct;
+ let _ = ExportedEnum::A;
+}
+
+#[rustfmt::skip]
+fn test_weird_formatting() {
+ use crate:: in_fn_test:: * ;
+ use crate:: fn_mod::
+ *;
+
+ exported();
+ foo();
+}
+
+mod super_imports {
+ fn foofoo() {}
+
+ mod should_be_replaced {
+ use super::*;
+
+ fn with_super() {
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass {
+ use super::*;
+
+ fn with_super() {
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass_inside_function {
+ fn with_super_inside_function() {
+ use super::*;
+ let _ = foofoo();
+ }
+ }
+
+ mod test_should_pass_further_inside {
+ fn insidefoo() {}
+ mod inner {
+ use super::*;
+ fn with_super() {
+ let _ = insidefoo();
+ }
+ }
+ }
+
+ mod should_be_replaced_further_inside {
+ fn insidefoo() {}
+ mod inner {
+ use super::*;
+ fn with_super() {
+ let _ = insidefoo();
+ }
+ }
+ }
+
+ mod use_explicit_should_be_replaced {
+ use crate::super_imports::*;
+
+ fn with_explicit() {
+ let _ = foofoo();
+ }
+ }
+
+ mod use_double_super_should_be_replaced {
+ mod inner {
+ use super::super::*;
+
+ fn with_double_super() {
+ let _ = foofoo();
+ }
+ }
+ }
+
+ mod use_super_explicit_should_be_replaced {
+ use super::super::super_imports::*;
+
+ fn with_super_explicit() {
+ let _ = foofoo();
+ }
+ }
+
+ mod attestation_should_be_replaced {
+ use super::*;
+
+ fn with_explicit() {
+ let _ = foofoo();
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr
new file mode 100644
index 000000000..92f6d3153
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr
@@ -0,0 +1,132 @@
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:9:5
+ |
+LL | use crate::fn_mod::*;
+ | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
+ |
+ = note: `-D clippy::wildcard-imports` implied by `-D warnings`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:10:5
+ |
+LL | use crate::mod_mod::*;
+ | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:11:5
+ |
+LL | use crate::multi_fn_mod::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:12:5
+ |
+LL | use crate::struct_mod::*;
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:15:5
+ |
+LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:17:5
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:87:13
+ |
+LL | use crate::fn_mod::*;
+ | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:93:75
+ |
+LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
+ | ^ help: try: `inner_extern_foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:94:13
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:105:20
+ |
+LL | use self::{inner::*, inner2::*};
+ | ^^^^^^^^ help: try: `inner::inner_foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:105:30
+ |
+LL | use self::{inner::*, inner2::*};
+ | ^^^^^^^^^ help: try: `inner2::inner_bar`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:112:13
+ |
+LL | use wildcard_imports_helper::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:141:9
+ |
+LL | use crate::in_fn_test::*;
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:150:9
+ |
+LL | use crate:: in_fn_test:: * ;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:151:9
+ |
+LL | use crate:: fn_mod::
+ | _________^
+LL | | *;
+ | |_________^ help: try: `crate:: fn_mod::foo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:162:13
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:197:17
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::insidefoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:205:13
+ |
+LL | use crate::super_imports::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:214:17
+ |
+LL | use super::super::*;
+ | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:223:13
+ |
+LL | use super::super::super_imports::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
+
+error: usage of wildcard import
+ --> $DIR/wildcard_imports_2021.rs:231:13
+ |
+LL | use super::*;
+ | ^^^^^^^^ help: try: `super::foofoo`
+
+error: aborting due to 21 previous errors
+
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed
new file mode 100644
index 000000000..8906c7769
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed
@@ -0,0 +1,21 @@
+// run-rustfix
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![deny(clippy::zero_ptr)]
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _ = core::ptr::null::<usize>();
+ let _ = core::ptr::null_mut::<f64>();
+ let _: *const u8 = core::ptr::null();
+ 0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.rs b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs
new file mode 100644
index 000000000..379c1b18d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs
@@ -0,0 +1,21 @@
+// run-rustfix
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![deny(clippy::zero_ptr)]
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _ = 0 as *const usize;
+ let _ = 0 as *mut f64;
+ let _: *const u8 = 0 as *const _;
+ 0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr b/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr
new file mode 100644
index 000000000..d92bb4a65
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr
@@ -0,0 +1,26 @@
+error: `0 as *const _` detected
+ --> $DIR/zero_ptr_no_std.rs:9:13
+ |
+LL | let _ = 0 as *const usize;
+ | ^^^^^^^^^^^^^^^^^ help: try: `core::ptr::null::<usize>()`
+ |
+note: the lint level is defined here
+ --> $DIR/zero_ptr_no_std.rs:5:9
+ |
+LL | #![deny(clippy::zero_ptr)]
+ | ^^^^^^^^^^^^^^^^
+
+error: `0 as *mut _` detected
+ --> $DIR/zero_ptr_no_std.rs:10:13
+ |
+LL | let _ = 0 as *mut f64;
+ | ^^^^^^^^^^^^^ help: try: `core::ptr::null_mut::<f64>()`
+
+error: `0 as *const _` detected
+ --> $DIR/zero_ptr_no_std.rs:11:24
+ |
+LL | let _: *const u8 = 0 as *const _;
+ | ^^^^^^^^^^^^^ help: try: `core::ptr::null()`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index 7a85386a3..c721e9969 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -2,7 +2,6 @@
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(clippy::single_match_else)]
-use rustc_tools_util::VersionInfo;
use std::fs;
#[test]
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index acb476ee6..6f50ef932 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -1,7 +1,7 @@
[relabel]
allow-unauthenticated = [
"A-*", "C-*", "E-*", "I-*", "L-*", "P-*", "S-*", "T-*",
- "good-first-issue"
+ "good-first-issue", "beta-nominated"
]
# Allows shortcuts like `@rustbot ready`