summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2024-09-24 11:58:04 +0200
committerPhilipp Krones <hello@philkrones.com>2024-09-24 11:58:04 +0200
commitae1c19146776bec5275c71e64f26f02ecd2893b7 (patch)
treefd7272e3195c9c46e491eff35ed4e08a1df42058
parent4cadeda932d5c261a9a0b1bbd25c4486e4e0a4c6 (diff)
parent7901289135257ca0fbed3a5522526f95b0f5edba (diff)
Merge commit '7901289135257ca0fbed3a5522526f95b0f5edba' into clippy-subtree-update
-rw-r--r--src/tools/clippy/.github/deploy.sh9
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml4
-rw-r--r--src/tools/clippy/CHANGELOG.md65
-rw-r--r--src/tools/clippy/Cargo.toml11
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md1
-rw-r--r--src/tools/clippy/clippy_config/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs5
-rw-r--r--src/tools/clippy/clippy_config/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_config/src/msrvs.rs6
-rw-r--r--src/tools/clippy/clippy_config/src/types.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/fmt.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/serve.rs3
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs30
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/absolute_paths.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/almost_complete_range.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/assigning_clones.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/inline_always.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs97
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/byte_char_slices.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cfg_not_test.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/collection_is_never_read.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/comparison_chain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs73
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs342
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/mod.rs93
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_nesting.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/fallible_impl_from.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/format_push_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_hasher.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs359
-rw-r--r--src/tools/clippy/clippy_lints/src/incompatible_msrv.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/ineffective_open_options.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/items_after_test_module.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_bits.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_div_ceil.rs158
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_hash_one.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs142
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs186
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_range_patterns.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.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_string_new.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_filter.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_utils.rs8
-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_str_case_mismatch.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/drain_collect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/err_expect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_filter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_flatten.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_identity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs63
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_first_then_check.rs56
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs66
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/min_ident_chars.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs186
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_assert_message.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_for_each.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_expressive_names.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs143
-rw-r--r--src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.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/absurd_extreme_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_unimplemented.rs78
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs88
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs106
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_else.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_field_names.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_locals.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/string_patterns.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/to_digit_is_some.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs34
-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/unsound_collection_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/box_collection.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/type_complexity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/uninhabited_references.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/uninit_vec.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_async.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_peekable.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_trait_names.rs94
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_unit.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs4
-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/unnecessary_def_path.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/vec_init_then_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/visibility.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/zombie_processes.rs334
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs15
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs87
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/ptr.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs81
-rw-r--r--src/tools/clippy/clippy_utils/src/str_utils.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs38
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs15
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs4
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/declare_clippy_lint/src/lib.rs17
-rw-r--r--src/tools/clippy/lintcheck/src/driver.rs2
-rw-r--r--src/tools/clippy/lintcheck/src/recursive.rs2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs4
-rw-r--r--src/tools/clippy/tests/compile-test.rs20
-rw-r--r--src/tools/clippy/tests/config-metadata.rs2
-rw-r--r--src/tools/clippy/tests/dogfood.rs49
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed4
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs4
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_names_append/disallowed_names.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/panic/panic.rs5
-rw-r--r--src/tools/clippy/tests/ui-toml/panic/panic.stderr10
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.fixed7
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.rs7
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_without_reason.rs1
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr4
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs1
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr246
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax_not_x86.rs3
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax_x86.rs4
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax_x86.stderr70
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/external_item.rs7
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs4
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macros.rs2
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast_alignment.rs8
-rw-r--r--src/tools/clippy/tests/ui/cmp_owned/without_suggestion.rs4
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.fixed5
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.rs5
-rw-r--r--src/tools/clippy/tests/ui/collapsible_else_if.stderr16
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.fixed8
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.rs8
-rw-r--r--src/tools/clippy/tests/ui/comparison_to_empty.stderr26
-rw-r--r--src/tools/clippy/tests/ui/crashes/associated-constant-ice.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/cc_seme.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-11230.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1588.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-1969.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2499.rs6
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2594.rs1
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2727.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2760.rs8
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2862.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2865.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3151.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3462.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3747.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-3969.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6251.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-700.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7410.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice_exact_size.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/if_same_then_else.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/inherent_impl.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/issue-825.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/match_same_arms_const.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/returns.rs2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs2
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs2
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--src/tools/clippy/tests/ui/diverging_sub_expression.rs6
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.fixed47
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.rs43
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.stderr56
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed9
-rw-r--r--src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr27
-rw-r--r--src/tools/clippy/tests/ui/duplicate_underscore_argument.rs1
-rw-r--r--src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr2
-rw-r--r--src/tools/clippy/tests/ui/duplicated_attributes.rs4
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed135
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed144
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs147
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr176
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/outer_attribute.1.fixed108
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/outer_attribute.2.fixed111
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/outer_attribute.rs119
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr116
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs132
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr37
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs120
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr54
-rw-r--r--src/tools/clippy/tests/ui/empty_loop_no_std.rs2
-rw-r--r--src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs2
-rw-r--r--src/tools/clippy/tests/ui/exit1.rs2
-rw-r--r--src/tools/clippy/tests/ui/exit2.rs2
-rw-r--r--src/tools/clippy/tests/ui/exit3.rs2
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.fixed2
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.rs2
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.stderr30
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs2
-rw-r--r--src/tools/clippy/tests/ui/format_args.fixed2
-rw-r--r--src/tools/clippy/tests/ui/format_args.rs2
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.fixed4
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.rs4
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.stderr8
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.fixed15
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.rs15
-rw-r--r--src/tools/clippy/tests/ui/ignored_unit_patterns.stderr18
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.fixed13
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.rs13
-rw-r--r--src/tools/clippy/tests/ui/incompatible_msrv.rs2
-rw-r--r--src/tools/clippy/tests/ui/legacy_numeric_constants.fixed4
-rw-r--r--src/tools/clippy/tests/ui/legacy_numeric_constants.rs4
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.fixed2
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.rs2
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports_expect.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs35
-rw-r--r--src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr75
-rw-r--r--src/tools/clippy/tests/ui/manual_arithmetic_check.fixed24
-rw-r--r--src/tools/clippy/tests/ui/manual_arithmetic_check.rs24
-rw-r--r--src/tools/clippy/tests/ui/manual_arithmetic_check.stderr29
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil.fixed30
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil.rs30
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil.stderr35
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil_with_feature.fixed25
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil_with_feature.rs25
-rw-r--r--src/tools/clippy/tests/ui/manual_div_ceil_with_feature.stderr47
-rw-r--r--src/tools/clippy/tests/ui/manual_is_power_of_two.fixed20
-rw-r--r--src/tools/clippy/tests/ui/manual_is_power_of_two.rs20
-rw-r--r--src/tools/clippy/tests/ui/manual_is_power_of_two.stderr41
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs24
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr22
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_struct.rs50
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr64
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.fixed8
-rw-r--r--src/tools/clippy/tests/ui/manual_range_patterns.rs8
-rw-r--r--src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.stderr32
-rw-r--r--src/tools/clippy/tests/ui/mixed_attributes_style.rs3
-rw-r--r--src/tools/clippy/tests/ui/mixed_attributes_style.stderr3
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed2
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs2
-rw-r--r--src/tools/clippy/tests/ui/mut_key.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_value.rs12
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_value.stderr18
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed4
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs4
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr14
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed2
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.rs2
-rw-r--r--src/tools/clippy/tests/ui/non_zero_suggestions.fixed65
-rw-r--r--src/tools/clippy/tests/ui/non_zero_suggestions.rs65
-rw-r--r--src/tools/clippy/tests/ui/non_zero_suggestions.stderr41
-rw-r--r--src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.rs23
-rw-r--r--src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.stderr23
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn.rs9
-rw-r--r--src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs33
-rw-r--r--src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr34
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.rs22
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.stderr14
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.fixed17
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.rs17
-rw-r--r--src/tools/clippy/tests/ui/ptr_cast_constness.stderr42
-rw-r--r--src/tools/clippy/tests/ui/result_large_err.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_call_fn.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_match.fixed26
-rw-r--r--src/tools/clippy/tests/ui/single_match.rs44
-rw-r--r--src/tools/clippy/tests/ui/single_match.stderr67
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.fixed4
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.rs10
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.stderr14
-rw-r--r--src/tools/clippy/tests/ui/string_slice.rs6
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.fixed1
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.rs1
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr4
-rw-r--r--src/tools/clippy/tests/ui/suspicious_to_owned.rs2
-rw-r--r--src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed1
-rw-r--r--src/tools/clippy/tests/ui/tabs_in_doc_comments.rs1
-rw-r--r--src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr16
-rw-r--r--src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs10
-rw-r--r--src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr28
-rw-r--r--src/tools/clippy/tests/ui/transmute_32bit.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_64bit.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_collection.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_undefined_repr.rs2
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.rs32
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.stderr24
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_first_then_check.fixed22
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_first_then_check.rs22
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_first_then_check.stderr47
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_min_or_max.fixed29
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_min_or_max.rs29
-rw-r--r--src/tools/clippy/tests/ui/unsafe_removed_from_name.rs2
-rw-r--r--src/tools/clippy/tests/ui/unused_trait_names.fixed286
-rw-r--r--src/tools/clippy/tests/ui/unused_trait_names.rs286
-rw-r--r--src/tools/clippy/tests/ui/unused_trait_names.stderr73
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.stderr24
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_items.rs63
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_items.stderr112
-rw-r--r--src/tools/clippy/tests/ui/zombie_processes.rs138
-rw-r--r--src/tools/clippy/tests/ui/zombie_processes.stderr64
-rw-r--r--src/tools/clippy/tests/ui/zombie_processes_fixable.fixed26
-rw-r--r--src/tools/clippy/tests/ui/zombie_processes_fixable.rs26
-rw-r--r--src/tools/clippy/tests/ui/zombie_processes_fixable.stderr40
-rw-r--r--src/tools/clippy/triagebot.toml1
-rw-r--r--src/tools/clippy/util/gh-pages/versions.html121
-rwxr-xr-xsrc/tools/clippy/util/versions.py41
566 files changed, 7437 insertions, 2571 deletions
diff --git a/src/tools/clippy/.github/deploy.sh b/src/tools/clippy/.github/deploy.sh
index d937661c0f8..5b4b4be4e36 100644
--- a/src/tools/clippy/.github/deploy.sh
+++ b/src/tools/clippy/.github/deploy.sh
@@ -25,16 +25,15 @@ if [[ $BETA = "true" ]]; then
fi
# Generate version index that is shown as root index page
-cp util/gh-pages/versions.html out/index.html
-
-echo "Making the versions.json file"
-python3 ./util/versions.py out
+python3 ./util/versions.py ./util/gh-pages/versions.html out
# Now let's go have some fun with the cloned repo
cd out
git config user.name "GHA CI"
git config user.email "gha@ci.invalid"
+git status
+
if [[ -n $TAG_NAME ]]; then
# track files, so that the following check works
git add --intent-to-add "$TAG_NAME"
@@ -46,8 +45,6 @@ if [[ -n $TAG_NAME ]]; then
git add "$TAG_NAME"
# Update the symlink
git add stable
- # Update versions file
- git add versions.json
git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
elif [[ $BETA = "true" ]]; then
if git diff --exit-code --quiet -- beta/; then
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 2aa13313fa5..026771e6fcf 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -162,7 +162,7 @@ jobs:
find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf
- name: Upload Binaries
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: binaries
path: target/debug
@@ -202,7 +202,7 @@ jobs:
# Download
- name: Download target dir
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v4
with:
name: binaries
path: target/debug
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 9bc4ad9698d..41a86e8ce51 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,7 +6,61 @@ document.
## Unreleased / Beta / In Rust Nightly
-[c9139bd5...master](https://github.com/rust-lang/rust-clippy/compare/c9139bd5...master)
+[b794b8e0...master](https://github.com/rust-lang/rust-clippy/compare/b794b8e0...master)
+
+## Rust 1.81
+
+Current stable, released 2024-09-05
+
+### New Lints
+
+* Added [`cfg_not_test`] to `restriction`
+ [#11293](https://github.com/rust-lang/rust-clippy/pull/11293)
+* Added [`byte_char_slices`] to `style`
+ [#10155](https://github.com/rust-lang/rust-clippy/pull/10155)
+* Added [`set_contains_or_insert`] to `nursery`
+ [#12873](https://github.com/rust-lang/rust-clippy/pull/12873)
+* Added [`manual_rotate`] to `style`
+ [#12983](https://github.com/rust-lang/rust-clippy/pull/12983)
+* Added [`unnecessary_min_or_max`] to `complexity`
+ [#12368](https://github.com/rust-lang/rust-clippy/pull/12368)
+* Added [`manual_inspect`] to `complexity`
+ [#12287](https://github.com/rust-lang/rust-clippy/pull/12287)
+* Added [`field_scoped_visibility_modifiers`] to `restriction`
+ [#12893](https://github.com/rust-lang/rust-clippy/pull/12893)
+* Added [`manual_pattern_char_comparison`] to `style`
+ [#12849](https://github.com/rust-lang/rust-clippy/pull/12849)
+* Added [`needless_maybe_sized`] to `suspicious`
+ [#10632](https://github.com/rust-lang/rust-clippy/pull/10632)
+* Added [`needless_character_iteration`] to `suspicious`
+ [#12815](https://github.com/rust-lang/rust-clippy/pull/12815)
+
+### Moves and Deprecations
+
+* [`allow_attributes`], [`allow_attributes_without_reason`]: Now work on stable
+ [rust#120924](https://github.com/rust-lang/rust/pull/120924)
+* Renamed `overflow_check_conditional` to [`panicking_overflow_checks`]
+ [#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
+* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now deny-by-default)
+ [#12944](https://github.com/rust-lang/rust-clippy/pull/12944)
+* Renamed `thread_local_initializer_can_be_made_const` to [`missing_const_for_thread_local`]
+ [#12974](https://github.com/rust-lang/rust-clippy/pull/12974)
+* Deprecated [`maybe_misused_cfg`] and [`mismatched_target_os`] as they are now caught by cargo
+ and rustc
+ [#12875](https://github.com/rust-lang/rust-clippy/pull/12875)
+
+### Enhancements
+
+* [`significant_drop_in_scrutinee`]: Now also checks scrutinies of `while let` and `for let`
+ expressions
+ [#12870](https://github.com/rust-lang/rust-clippy/pull/12870)
+* [`std_instead_of_core`]: Now respects the `msrv` configuration
+ [#13168](https://github.com/rust-lang/rust-clippy/pull/13168)
+
+### ICE Fixes
+
+* [`suboptimal_flops`]: No longer crashes on custom `.log()` functions
+ [#12884](https://github.com/rust-lang/rust-clippy/pull/12884)
## Rust 1.80
@@ -5500,6 +5554,7 @@ Released 2018-09-13
[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
+[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub
[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
@@ -5559,6 +5614,7 @@ Released 2018-09-13
[`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits
[`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals
[`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp
+[`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil
[`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter
[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
@@ -5570,6 +5626,7 @@ Released 2018-09-13
[`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
[`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
[`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite
+[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two
[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and
[`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
[`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
@@ -5716,6 +5773,7 @@ Released 2018-09-13
[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
+[`non_zero_suggestions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_zero_suggestions
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options
[`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces
@@ -5757,6 +5815,7 @@ Released 2018-09-13
[`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push
[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
+[`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointers_in_nomem_asm_block
[`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters
[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
@@ -5962,6 +6021,7 @@ Released 2018-09-13
[`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
[`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map
+[`unnecessary_first_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_first_then_check
[`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold
[`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_get_then_check
[`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join
@@ -6003,6 +6063,7 @@ Released 2018-09-13
[`unused_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_result_ok
[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
+[`unused_trait_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
@@ -6013,6 +6074,7 @@ Released 2018-09-13
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
[`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self
[`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding
+[`used_underscore_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_items
[`useless_asref`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_asref
[`useless_attribute`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_attribute
[`useless_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
@@ -6047,6 +6109,7 @@ Released 2018-09-13
[`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects
[`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values
[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
+[`zombie_processes`]: https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes
[`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
<!-- end autogenerated links to lint list -->
<!-- begin autogenerated links to configuration documentation -->
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index b48b881097f..ddc27179ef2 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy"
-version = "0.1.82"
+version = "0.1.83"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -31,7 +31,7 @@ anstream = "0.6.0"
[dev-dependencies]
cargo_metadata = "0.18.1"
-ui_test = "0.25"
+ui_test = "0.26.4"
regex = "1.5.5"
serde = { version = "1.0.145", features = ["derive"] }
serde_json = "1.0.122"
@@ -67,3 +67,10 @@ harness = false
[[test]]
name = "dogfood"
harness = false
+
+# quine-mc_cluskey makes up a significant part of the runtime in dogfood
+# due to the number of conditions in the clippy_lints crate
+# and enabling optimizations for that specific dependency helps a bit
+# without increasing total build times.
+[profile.dev.package.quine-mc_cluskey]
+opt-level = 3
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 78348797588..91159bc79c5 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -727,6 +727,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
+* [`unused_trait_names`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_trait_names)
* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index 5c4e0761dbc..9da7112345d 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy_config"
-version = "0.1.82"
+version = "0.1.83"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index a6f1b958bfb..757620341cc 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -1,6 +1,6 @@
+use crate::ClippyConfiguration;
use crate::msrvs::Msrv;
use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
-use crate::ClippyConfiguration;
use rustc_errors::Applicability;
use rustc_session::Session;
use rustc_span::edit_distance::edit_distance;
@@ -563,6 +563,7 @@ define_Conf! {
uninlined_format_args,
unnecessary_lazy_evaluations,
unnested_or_patterns,
+ unused_trait_names,
use_self,
)]
msrv: Msrv = Msrv::empty(),
@@ -864,7 +865,7 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) {
cmp::max(1, terminal_width / (SEPARATOR_WIDTH + max_field_width))
});
- let rows = (fields.len() + (columns - 1)) / columns;
+ let rows = fields.len().div_ceil(columns);
let column_widths = (0..columns)
.map(|column| {
diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs
index ac838cc81d2..c63d98a0a13 100644
--- a/src/tools/clippy/clippy_config/src/lib.rs
+++ b/src/tools/clippy/clippy_config/src/lib.rs
@@ -26,5 +26,5 @@ mod metadata;
pub mod msrvs;
pub mod types;
-pub use conf::{get_configuration_metadata, lookup_conf_file, Conf};
+pub use conf::{Conf, get_configuration_metadata, lookup_conf_file};
pub use metadata::ClippyConfiguration;
diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs
index a2b4b6e256f..e30df3d3234 100644
--- a/src/tools/clippy/clippy_config/src/msrvs.rs
+++ b/src/tools/clippy/clippy_config/src/msrvs.rs
@@ -1,7 +1,7 @@
use rustc_ast::Attribute;
use rustc_attr::parse_version;
use rustc_session::{RustcVersion, Session};
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
use serde::Deserialize;
use std::fmt;
@@ -23,6 +23,7 @@ msrv_aliases! {
1,80,0 { BOX_INTO_ITER}
1,77,0 { C_STR_LITERALS }
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
+ 1,73,0 { MANUAL_DIV_CEIL }
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
1,68,0 { PATH_MAIN_SEPARATOR_STR }
@@ -38,7 +39,7 @@ msrv_aliases! {
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
1,50,0 { BOOL_THEN, CLAMP }
- 1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN }
+ 1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN, SATURATING_SUB_CONST }
1,46,0 { CONST_IF_MATCH }
1,45,0 { STR_STRIP_PREFIX }
1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS }
@@ -50,6 +51,7 @@ msrv_aliases! {
1,36,0 { ITERATOR_COPIED }
1,35,0 { OPTION_COPIED, RANGE_CONTAINS }
1,34,0 { TRY_FROM }
+ 1,33,0 { UNDERSCORE_IMPORTS }
1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
1,29,0 { ITER_FLATTEN }
1,28,0 { FROM_BOOL }
diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs
index d47e34bb5bc..bab63911182 100644
--- a/src/tools/clippy/clippy_config/src/types.rs
+++ b/src/tools/clippy/clippy_config/src/types.rs
@@ -1,5 +1,5 @@
use serde::de::{self, Deserializer, Visitor};
-use serde::{ser, Deserialize, Serialize};
+use serde::{Deserialize, Serialize, ser};
use std::fmt;
#[derive(Debug, Deserialize)]
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 5fc4365c6e7..8c61c35533c 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -1,6 +1,6 @@
use crate::clippy_project_root;
use itertools::Itertools;
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
use shell_escape::escape;
use std::ffi::{OsStr, OsString};
use std::ops::ControlFlow;
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 87117832fb9..5fd65017cfb 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -441,7 +441,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
#[allow(clippy::too_many_lines)]
fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> {
- use super::update_lints::{match_tokens, LintDeclSearchResult};
+ use super::update_lints::{LintDeclSearchResult, match_tokens};
use rustc_lexer::TokenKind;
let lint_name_upper = lint.name.to_uppercase();
diff --git a/src/tools/clippy/clippy_dev/src/serve.rs b/src/tools/clippy/clippy_dev/src/serve.rs
index 19560b31fd3..cc14cd8dae6 100644
--- a/src/tools/clippy/clippy_dev/src/serve.rs
+++ b/src/tools/clippy/clippy_dev/src/serve.rs
@@ -29,7 +29,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
}
if let Some(url) = url.take() {
thread::spawn(move || {
- Command::new(PYTHON)
+ let mut child = Command::new(PYTHON)
.arg("-m")
.arg("http.server")
.arg(port.to_string())
@@ -40,6 +40,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
thread::sleep(Duration::from_millis(500));
// Launch browser after first export.py has completed and http.server is up
let _result = opener::open(url);
+ child.wait().unwrap();
});
}
thread::sleep(Duration::from_millis(1000));
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 8dbda1c634c..d6ed36d52f4 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -1,7 +1,7 @@
use crate::clippy_project_root;
use aho_corasick::AhoCorasickBuilder;
use itertools::Itertools;
-use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
+use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape};
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::fmt::{self, Write};
@@ -1048,23 +1048,17 @@ mod tests {
Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
];
let mut expected: HashMap<String, Vec<Lint>> = HashMap::new();
- expected.insert(
- "group1".to_string(),
- vec![
- Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
- Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
- ],
- );
- expected.insert(
- "group2".to_string(),
- vec![Lint::new(
- "should_assert_eq2",
- "group2",
- "\"abc\"",
- "module_name",
- Range::default(),
- )],
- );
+ expected.insert("group1".to_string(), vec![
+ Lint::new("should_assert_eq", "group1", "\"abc\"", "module_name", Range::default()),
+ Lint::new("incorrect_match", "group1", "\"abc\"", "module_name", Range::default()),
+ ]);
+ expected.insert("group2".to_string(), vec![Lint::new(
+ "should_assert_eq2",
+ "group2",
+ "\"abc\"",
+ "module_name",
+ Range::default(),
+ )]);
assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
}
}
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index fbd4566da58..d1188940b46 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.82"
+version = "0.1.83"
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/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs
index c72b3f1318c..1af6d448a93 100644
--- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs
@@ -3,12 +3,12 @@ use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_from_proc_macro;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc_hir::{HirId, ItemKind, Node, Path};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::kw;
use rustc_span::Symbol;
+use rustc_span::symbol::kw;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
index 451bae95987..370f0c482fd 100644
--- a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
+++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{trim_span, walk_span_to_context};
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 56f5e903dc3..4f8f091a095 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -1,10 +1,10 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{impl_lint_pass, RustcVersion};
+use rustc_session::{RustcVersion, impl_lint_pass};
use rustc_span::symbol;
use std::f64::consts as f64;
diff --git a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
index 4eafa330faf..2643f850879 100644
--- a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
@@ -4,8 +4,8 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
-use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::GenericArgKind;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_session::declare_lint_pass;
use rustc_span::symbol::sym;
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index 7eaac80f969..b6684825835 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -1,7 +1,7 @@
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_inside_always_const_context;
-use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_node};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
index f1cb4a05af8..c073dee855e 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_node};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
use clippy_utils::usage::local_used_after_expr;
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index 55645d04eef..0b82c0cd04c 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -1,7 +1,7 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap};
+use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir};
use clippy_utils::sugg::Sugg;
use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
index 4ab97118df1..40959eccd3a 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -1,4 +1,4 @@
-use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON};
+use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_ast::{MetaItemKind, NestedMetaItem};
@@ -26,7 +26,7 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet
cx,
ALLOW_ATTRIBUTES_WITHOUT_REASON,
attr.span,
- format!("`{}` attribute without specifying a reason", name.as_str()),
+ format!("`{name}` attribute without specifying a reason"),
|diag| {
diag.help("try adding a reason at the end with `, reason = \"..\"`");
},
diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
index 9b08fd6d654..508963a20ea 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
@@ -1,10 +1,10 @@
-use super::utils::extract_clippy_lint;
use super::BLANKET_CLIPPY_RESTRICTION_LINTS;
+use super::utils::extract_clippy_lint;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use rustc_ast::NestedMetaItem;
use rustc_lint::{LateContext, Level, LintContext};
use rustc_span::symbol::Symbol;
-use rustc_span::{sym, DUMMY_SP};
+use rustc_span::{DUMMY_SP, sym};
pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
for lint in items {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
index e872ab6b4b5..abf924f7542 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
@@ -1,4 +1,4 @@
-use super::{unnecessary_clippy_cfg, Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR};
+use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg};
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast::AttrStyle;
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index 40a1c4e2884..55f8e1072db 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::{Attribute, MetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::collections::hash_map::Entry;
fn emit_if_duplicated(
@@ -36,7 +36,7 @@ fn check_duplicated_attr(
}
let Some(ident) = attr.ident() else { return };
let name = ident.name;
- if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented {
+ if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented || name == sym::reason {
// FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
// conditions are the same.
// `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected.
diff --git a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs
deleted file mode 100644
index 7ff644b4c44..00000000000
--- a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::{is_present_in_source, without_block_comments, SpanRangeExt};
-use rustc_ast::{AttrKind, AttrStyle};
-use rustc_lint::EarlyContext;
-use rustc_span::Span;
-
-/// Check for empty lines after outer attributes.
-///
-/// Attributes and documentation comments are both considered outer attributes
-/// by the AST. However, the average user likely considers them to be different.
-/// Checking for empty lines after each of these attributes is split into two different
-/// lints but can share the same logic.
-pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
- let mut iter = item.attrs.iter().peekable();
- while let Some(attr) = iter.next() {
- if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
- && attr.style == AttrStyle::Outer
- && is_present_in_source(cx, attr.span)
- {
- let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
- let end_of_attr_to_next_attr_or_item = Span::new(
- attr.span.hi(),
- iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()),
- item.span.ctxt(),
- item.span.parent(),
- );
-
- if let Some(snippet) = end_of_attr_to_next_attr_or_item.get_source_text(cx) {
- let lines = snippet.split('\n').collect::<Vec<_>>();
- let lines = without_block_comments(lines);
-
- if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
- let (lint_msg, lint_type) = match attr.kind {
- AttrKind::DocComment(..) => (
- "found an empty line after a doc comment. \
- Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
- EMPTY_LINE_AFTER_DOC_COMMENTS,
- ),
- AttrKind::Normal(..) => (
- "found an empty line after an outer attribute. \
- Perhaps you forgot to add a `!` to make it an inner attribute?",
- EMPTY_LINE_AFTER_OUTER_ATTR,
- ),
- };
-
- span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
- }
- }
- }
- }
-}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
index 3b5b80ffefa..d41bb580c6c 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
@@ -1,10 +1,10 @@
-use super::utils::is_word;
use super::INLINE_ALWAYS;
+use super::utils::is_word;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::Attribute;
use rustc_lint::LateContext;
use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) {
if span.from_expansion() {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index 3b14e9aee7f..888f28fa225 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -4,7 +4,6 @@ mod blanket_clippy_restriction_lints;
mod deprecated_cfg_attr;
mod deprecated_semver;
mod duplicated_attributes;
-mod empty_line_after;
mod inline_always;
mod mixed_attributes_style;
mod non_minimal_cfg;
@@ -13,8 +12,8 @@ mod unnecessary_clippy_cfg;
mod useless_attribute;
mod utils;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
@@ -128,94 +127,6 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for empty lines after outer attributes
- ///
- /// ### Why is this bad?
- /// Most likely the attribute was meant to be an inner attribute using a '!'.
- /// If it was meant to be an outer attribute, then the following item
- /// should not be separated by empty lines.
- ///
- /// ### Known problems
- /// Can cause false positives.
- ///
- /// From the clippy side it's difficult to detect empty lines between an attributes and the
- /// following item because empty lines and comments are not part of the AST. The parsing
- /// currently works for basic cases but is not perfect.
- ///
- /// ### Example
- /// ```no_run
- /// #[allow(dead_code)]
- ///
- /// fn not_quite_good_code() { }
- /// ```
- ///
- /// Use instead:
- /// ```no_run
- /// // Good (as inner attribute)
- /// #![allow(dead_code)]
- ///
- /// fn this_is_fine() { }
- ///
- /// // or
- ///
- /// // Good (as outer attribute)
- /// #[allow(dead_code)]
- /// fn this_is_fine_too() { }
- /// ```
- #[clippy::version = "pre 1.29.0"]
- pub EMPTY_LINE_AFTER_OUTER_ATTR,
- nursery,
- "empty line after outer attribute"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for empty lines after documentation comments.
- ///
- /// ### Why is this bad?
- /// The documentation comment was most likely meant to be an inner attribute or regular comment.
- /// If it was intended to be a documentation comment, then the empty line should be removed to
- /// be more idiomatic.
- ///
- /// ### Known problems
- /// Only detects empty lines immediately following the documentation. If the doc comment is followed
- /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
- /// in combination with this lint to detect both cases.
- ///
- /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
- ///
- /// ### Example
- /// ```no_run
- /// /// Some doc comment with a blank line after it.
- ///
- /// fn not_quite_good_code() { }
- /// ```
- ///
- /// Use instead:
- /// ```no_run
- /// /// Good (no blank line)
- /// fn this_is_fine() { }
- /// ```
- ///
- /// ```no_run
- /// // Good (convert to a regular comment)
- ///
- /// fn this_is_fine_too() { }
- /// ```
- ///
- /// ```no_run
- /// //! Good (convert to a comment on an inner attribute)
- ///
- /// fn this_is_fine_as_well() { }
- /// ```
- #[clippy::version = "1.70.0"]
- pub EMPTY_LINE_AFTER_DOC_COMMENTS,
- nursery,
- "empty line after documentation comments"
-}
-
-declare_clippy_lint! {
- /// ### What it does
/// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
///
/// ### Why is this bad?
@@ -601,18 +512,12 @@ impl EarlyAttributes {
impl_lint_pass!(EarlyAttributes => [
DEPRECATED_CFG_ATTR,
- EMPTY_LINE_AFTER_OUTER_ATTR,
- EMPTY_LINE_AFTER_DOC_COMMENTS,
NON_MINIMAL_CFG,
DEPRECATED_CLIPPY_CFG_ATTR,
UNNECESSARY_CLIPPY_CFG,
]);
impl EarlyLintPass for EarlyAttributes {
- fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
- empty_line_after::check(cx, item);
- }
-
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
deprecated_cfg_attr::check(cx, attr, &self.msrv);
deprecated_cfg_attr::check_clippy(cx, attr);
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index 67ba605a59f..12668c616c1 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -1,7 +1,7 @@
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
use super::{Attribute, USELESS_ATTRIBUTE};
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{first_line_of_span, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, first_line_of_span};
use rustc_ast::NestedMetaItem;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
@@ -51,6 +51,7 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute])
| "module_name_repetitions"
| "single_component_path_imports"
| "disallowed_types"
+ | "unused_trait_names"
)
}) {
return;
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index d5f017b2650..9952d0af99e 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -7,7 +7,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::CoroutineLayout;
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index e933fdf1d6e..3c2af72624f 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -4,12 +4,12 @@ use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
use rustc_lint::{LateContext, LateLintPass, Level};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index 8459f051d3d..8261c65354f 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -4,7 +4,7 @@ use clippy_utils::ty::expr_sig;
use clippy_utils::{is_default_equivalent, path_def_id};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_ty};
use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/byte_char_slices.rs b/src/tools/clippy/clippy_lints/src/byte_char_slices.rs
index a9fe190f177..dd2620b0b9d 100644
--- a/src/tools/clippy/clippy_lints/src/byte_char_slices.rs
+++ b/src/tools/clippy/clippy_lints/src/byte_char_slices.rs
@@ -22,7 +22,7 @@ declare_clippy_lint! {
/// ```ignore
/// b"Hello"
/// ```
- #[clippy::version = "1.68.0"]
+ #[clippy::version = "1.81.0"]
pub BYTE_CHAR_SLICES,
style,
"hard to read byte char slice"
diff --git a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
index e924542fea2..ffd6c520c9a 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs
@@ -2,7 +2,7 @@ use super::LINT_GROUPS_PRIORITY;
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
-use rustc_lint::{unerased_lint_store, LateContext};
+use rustc_lint::{LateContext, unerased_lint_store};
use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index 346aed7e9f1..84a44b14dde 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -10,7 +10,7 @@ use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
use rustc_span::hygiene;
-use super::{utils, CAST_LOSSLESS};
+use super::{CAST_LOSSLESS, utils};
pub(super) fn check(
cx: &LateContext<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 5708aae3f3e..40a1a9d1ce8 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::{self, FloatTy, Ty};
use rustc_span::Span;
use rustc_target::abi::IntegerType;
-use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
+use super::{CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION, utils};
fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
if let Some(Constant::Int(c)) = ConstEvalCtxt::new(cx).eval(expr) {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
index 11274383595..3cf4a43b0d4 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -3,7 +3,7 @@ use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
-use super::{utils, CAST_POSSIBLE_WRAP};
+use super::{CAST_POSSIBLE_WRAP, utils};
// this should be kept in sync with the allowed bit widths of `usize` and `isize`
const ALLOWED_POINTER_SIZES: [u64; 3] = [16, 32, 64];
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
index 035666e4d4c..1eb115ce6bd 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
@@ -4,7 +4,7 @@ use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
-use super::{utils, CAST_PRECISION_LOSS};
+use super::{CAST_PRECISION_LOSS, utils};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
if !cast_from.is_integral() || cast_to.is_integral() {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 9daf237344a..4be53ace687 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
-use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
use clippy_utils::{method_chain_args, sext};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
index dbe03e4ae80..ac1a355c8d9 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
@@ -5,7 +5,7 @@ use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty, UintTy};
-use super::{utils, FN_TO_NUMERIC_CAST};
+use super::{FN_TO_NUMERIC_CAST, utils};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
// We only want to check casts to `ty::Uint` or `ty::Int`
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
index dfbae1618ac..18e7798452e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
@@ -5,7 +5,7 @@ use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
-use super::{utils, FN_TO_NUMERIC_CAST_WITH_TRUNCATION};
+use super::{FN_TO_NUMERIC_CAST_WITH_TRUNCATION, utils};
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
// We only want to check casts to `ty::Uint` or `ty::Int`
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index c31716fbcee..3acd4eca420 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -23,8 +23,8 @@ mod unnecessary_cast;
mod utils;
mod zero_ptr;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::is_hir_ty_cfg_dependant;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -410,19 +410,27 @@ declare_clippy_lint! {
/// ### Why is this bad?
/// Though `as` casts between raw pointers are not terrible, `pointer::cast_mut` and
/// `pointer::cast_const` are safer because they cannot accidentally cast the pointer to another
- /// type.
+ /// type. Or, when null pointers are involved, `null()` and `null_mut()` can be used directly.
///
/// ### Example
/// ```no_run
/// let ptr: *const u32 = &42_u32;
/// let mut_ptr = ptr as *mut u32;
/// let ptr = mut_ptr as *const u32;
+ /// let ptr1 = std::ptr::null::<u32>() as *mut u32;
+ /// let ptr2 = std::ptr::null_mut::<u32>() as *const u32;
+ /// let ptr3 = std::ptr::null::<u32>().cast_mut();
+ /// let ptr4 = std::ptr::null_mut::<u32>().cast_const();
/// ```
/// Use instead:
/// ```no_run
/// let ptr: *const u32 = &42_u32;
/// let mut_ptr = ptr.cast_mut();
/// let ptr = mut_ptr.cast_const();
+ /// let ptr1 = std::ptr::null_mut::<u32>();
+ /// let ptr2 = std::ptr::null::<u32>();
+ /// let ptr3 = std::ptr::null_mut::<u32>();
+ /// let ptr4 = std::ptr::null::<u32>();
/// ```
#[clippy::version = "1.72.0"]
pub PTR_CAST_CONSTNESS,
@@ -809,6 +817,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
char_lit_as_u8::check(cx, expr);
ptr_as_ptr::check(cx, expr, &self.msrv);
cast_slice_different_sizes::check(cx, expr, &self.msrv);
+ ptr_cast_constness::check_null_ptr_cast_method(cx, expr);
}
extract_msrv_attr!(LateContext);
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
index 7513e18d408..7518dd2435a 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs
@@ -1,10 +1,12 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::std_or_core;
use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, Mutability};
+use rustc_hir::{Expr, ExprKind, Mutability, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use rustc_span::sym;
use super::PTR_CAST_CONSTNESS;
@@ -16,8 +18,7 @@ pub(super) fn check<'tcx>(
cast_to: Ty<'tcx>,
msrv: &Msrv,
) {
- if msrv.meets(msrvs::POINTER_CAST_CONSTNESS)
- && let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind()
+ if let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind()
&& let ty::RawPtr(to_ty, to_mutbl) = cast_to.kind()
&& matches!(
(from_mutbl, to_mutbl),
@@ -26,20 +27,74 @@ pub(super) fn check<'tcx>(
&& from_ty == to_ty
&& !from_ty.has_erased_regions()
{
- let sugg = Sugg::hir(cx, cast_expr, "_");
- let constness = match *to_mutbl {
- Mutability::Not => "const",
- Mutability::Mut => "mut",
- };
+ if let ExprKind::Call(func, []) = cast_expr.kind
+ && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
+ && let Some(defid) = path.res.opt_def_id()
+ && let Some(prefix) = std_or_core(cx)
+ && let mut app = Applicability::MachineApplicable
+ && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app))
+ && let Some((_, after_lt)) = sugg.split_once("::<")
+ && let Some((source, target, target_func)) = match cx.tcx.get_diagnostic_name(defid) {
+ Some(sym::ptr_null) => Some(("const", "mutable", "null_mut")),
+ Some(sym::ptr_null_mut) => Some(("mutable", "const", "null")),
+ _ => None,
+ }
+ {
+ span_lint_and_sugg(
+ cx,
+ PTR_CAST_CONSTNESS,
+ expr.span,
+ format!("`as` casting to make a {source} null pointer into a {target} null pointer"),
+ format!("use `{target_func}()` directly instead"),
+ format!("{prefix}::ptr::{target_func}::<{after_lt}"),
+ app,
+ );
+ return;
+ }
+ if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) {
+ let sugg = Sugg::hir(cx, cast_expr, "_");
+ let constness = match *to_mutbl {
+ Mutability::Not => "const",
+ Mutability::Mut => "mut",
+ };
+
+ span_lint_and_sugg(
+ cx,
+ PTR_CAST_CONSTNESS,
+ expr.span,
+ "`as` casting between raw pointers while changing only its constness",
+ format!("try `pointer::cast_{constness}`, a safer alternative"),
+ format!("{}.cast_{constness}()", sugg.maybe_par()),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+}
+
+pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>) {
+ if let ExprKind::MethodCall(method, cast_expr, [], _) = expr.kind
+ && let ExprKind::Call(func, []) = cast_expr.kind
+ && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind
+ && let Some(defid) = path.res.opt_def_id()
+ && let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.as_str()) {
+ (Some(sym::ptr_null), "cast_mut") => "null_mut",
+ (Some(sym::ptr_null_mut), "cast_const") => "null",
+ _ => return,
+ }
+ && let Some(prefix) = std_or_core(cx)
+ && let mut app = Applicability::MachineApplicable
+ && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app))
+ && let Some((_, after_lt)) = sugg.split_once("::<")
+ {
span_lint_and_sugg(
cx,
PTR_CAST_CONSTNESS,
expr.span,
- "`as` casting between raw pointers while changing only its constness",
- format!("try `pointer::cast_{constness}`, a safer alternative"),
- format!("{}.cast_{constness}()", sugg.maybe_par()),
- Applicability::MachineApplicable,
+ "changing constness of a null pointer",
+ format!("use `{method}()` directly instead"),
+ format!("{prefix}::ptr::{method}::<{after_lt}"),
+ app,
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs
index 5f48b8bd206..dfa240ccec6 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
-use clippy_utils::{expr_use_ctxt, is_no_std_crate, ExprUseNode};
+use clippy_utils::{ExprUseNode, expr_use_ctxt, is_no_std_crate};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability, Ty, TyKind};
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index 566adc83d69..811d33c8bde 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::numeric_literal::NumericLiteral;
-use clippy_utils::source::{snippet_opt, SpanRangeExt};
-use clippy_utils::visitors::{for_each_expr_without_closures, Visitable};
+use clippy_utils::source::{SpanRangeExt, snippet_opt};
+use clippy_utils::visitors::{Visitable, for_each_expr_without_closures};
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
use rustc_ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/casts/utils.rs b/src/tools/clippy/clippy_lints/src/casts/utils.rs
index 5a4f20f0990..5ccba92a0af 100644
--- a/src/tools/clippy/clippy_lints/src/casts/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/utils.rs
@@ -1,4 +1,4 @@
-use clippy_utils::ty::{read_explicit_enum_value, EnumValue};
+use clippy_utils::ty::{EnumValue, read_explicit_enum_value};
use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, UintTy, VariantDiscr};
/// Returns the size in bits of an integral type.
diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
index d820c1e0720..884d15cabff 100644
--- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
+++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs
@@ -22,7 +22,7 @@ declare_clippy_lint! {
/// # fn important_check() {}
/// important_check();
/// ```
- #[clippy::version = "1.73.0"]
+ #[clippy::version = "1.81.0"]
pub CFG_NOT_TEST,
restriction,
"enforce against excluding code from test builds"
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index dd7c34d1e46..d3aa2fd1ea1 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -1,8 +1,8 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_in_const_context, is_integer_literal, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 0099eefbc8d..495d8ce3fa7 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::{IntoSpan, SpanRangeExt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{get_async_fn_body, is_async_fn, LimitStack};
+use clippy_utils::{LimitStack, get_async_fn_body, is_async_fn};
use core::ops::ControlFlow;
use rustc_ast::ast::Attribute;
use rustc_hir::intravisit::FnKind;
@@ -11,7 +11,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnDecl};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
index c6847411c75..8276e53648c 100644
--- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
+++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
-use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::visitors::{Visitable, for_each_expr};
use clippy_utils::{get_enclosing_block, path_to_local_id};
use core::ops::ControlFlow;
use rustc_hir::{Body, ExprKind, HirId, LangItem, LetStmt, Node, PatKind};
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index 5d78744e9b5..b9baf9af248 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{if_sequence, is_else_clause, is_in_const_context, SpanlessEq};
+use clippy_utils::{SpanlessEq, if_sequence, is_else_clause, is_in_const_context};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 86e0368c4e4..d90a22bb62a 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -1,16 +1,17 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then};
-use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, IntoSpan, SpanRangeExt};
-use clippy_utils::ty::{needs_ordered_drop, InteriorMut};
+use clippy_utils::source::{IntoSpan, SpanRangeExt, first_line_of_span, indent_of, reindent_multiline, snippet};
+use clippy_utils::ty::{InteriorMut, needs_ordered_drop};
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{
- capture_local_usage, eq_expr_value, find_binding_init, get_enclosing_block, hash_expr, hash_stmt, if_sequence,
- is_else_clause, is_lint_allowed, path_to_local, search_same, ContainsName, HirEqInterExpr, SpanlessEq,
+ ContainsName, HirEqInterExpr, SpanlessEq, capture_local_usage, eq_expr_value, find_binding_init,
+ get_enclosing_block, hash_expr, hash_stmt, if_sequence, is_else_clause, is_lint_allowed, path_to_local,
+ search_same,
};
use core::iter;
use core::ops::ControlFlow;
use rustc_errors::Applicability;
-use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind};
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind, intravisit};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index 678bdbc0ffb..c8f81413728 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -5,8 +5,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 93c8fff05e9..a96c86f0765 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -1,7 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_test;
-use clippy_utils::macros::{macro_backtrace, MacroCall};
+use clippy_utils::macros::{MacroCall, macro_backtrace};
use clippy_utils::source::snippet_with_applicability;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
@@ -9,7 +9,7 @@ use rustc_hir::{Expr, ExprKind, Node};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext};
+use rustc_span::{Span, SyntaxContext, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 60e51713173..2b229d2fe6a 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -49,8 +49,6 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO,
crate::attrs::DEPRECATED_SEMVER_INFO,
crate::attrs::DUPLICATED_ATTRIBUTES_INFO,
- crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
- crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
crate::attrs::INLINE_ALWAYS_INFO,
crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO,
crate::attrs::NON_MINIMAL_CFG_INFO,
@@ -138,6 +136,8 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::doc::DOC_LINK_WITH_QUOTES_INFO,
crate::doc::DOC_MARKDOWN_INFO,
crate::doc::EMPTY_DOCS_INFO,
+ crate::doc::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
+ crate::doc::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
crate::doc::MISSING_ERRORS_DOC_INFO,
crate::doc::MISSING_PANICS_DOC_INFO,
crate::doc::MISSING_SAFETY_DOC_INFO,
@@ -217,6 +217,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::implicit_return::IMPLICIT_RETURN_INFO,
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO,
+ crate::implicit_saturating_sub::INVERTED_SATURATING_SUB_INFO,
crate::implied_bounds_in_impls::IMPLIED_BOUNDS_IN_IMPLS_INFO,
crate::incompatible_msrv::INCOMPATIBLE_MSRV_INFO,
crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO,
@@ -300,10 +301,12 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::manual_async_fn::MANUAL_ASYNC_FN_INFO,
crate::manual_bits::MANUAL_BITS_INFO,
crate::manual_clamp::MANUAL_CLAMP_INFO,
+ crate::manual_div_ceil::MANUAL_DIV_CEIL_INFO,
crate::manual_float_methods::MANUAL_IS_FINITE_INFO,
crate::manual_float_methods::MANUAL_IS_INFINITE_INFO,
crate::manual_hash_one::MANUAL_HASH_ONE_INFO,
crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO,
+ crate::manual_is_power_of_two::MANUAL_IS_POWER_OF_TWO_INFO,
crate::manual_let_else::MANUAL_LET_ELSE_INFO,
crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO,
crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
@@ -464,6 +467,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::methods::UNNECESSARY_FALLIBLE_CONVERSIONS_INFO,
crate::methods::UNNECESSARY_FILTER_MAP_INFO,
crate::methods::UNNECESSARY_FIND_MAP_INFO,
+ crate::methods::UNNECESSARY_FIRST_THEN_CHECK_INFO,
crate::methods::UNNECESSARY_FOLD_INFO,
crate::methods::UNNECESSARY_GET_THEN_CHECK_INFO,
crate::methods::UNNECESSARY_JOIN_INFO,
@@ -486,6 +490,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::misc::SHORT_CIRCUIT_STATEMENT_INFO,
crate::misc::TOPLEVEL_REF_ARG_INFO,
crate::misc::USED_UNDERSCORE_BINDING_INFO,
+ crate::misc::USED_UNDERSCORE_ITEMS_INFO,
crate::misc_early::BUILTIN_TYPE_SHADOW_INFO,
crate::misc_early::DOUBLE_NEG_INFO,
crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO,
@@ -553,6 +558,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::non_expressive_names::SIMILAR_NAMES_INFO,
crate::non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS_INFO,
crate::non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY_INFO,
+ crate::non_zero_suggestions::NON_ZERO_SUGGESTIONS_INFO,
crate::nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES_INFO,
crate::octal_escapes::OCTAL_ESCAPES_INFO,
crate::only_used_in_recursion::ONLY_USED_IN_RECURSION_INFO,
@@ -598,6 +604,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::pathbuf_init_then_push::PATHBUF_INIT_THEN_PUSH_INFO,
crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO,
crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO,
+ crate::pointers_in_nomem_asm_block::POINTERS_IN_NOMEM_ASM_BLOCK_INFO,
crate::precedence::PRECEDENCE_INFO,
crate::ptr::CMP_NULL_INFO,
crate::ptr::INVALID_NULL_PTR_USAGE_INFO,
@@ -741,6 +748,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::unused_result_ok::UNUSED_RESULT_OK_INFO,
crate::unused_rounding::UNUSED_ROUNDING_INFO,
crate::unused_self::UNUSED_SELF_INFO,
+ crate::unused_trait_names::UNUSED_TRAIT_NAMES_INFO,
crate::unused_unit::UNUSED_UNIT_INFO,
crate::unwrap::PANICKING_UNWRAP_INFO,
crate::unwrap::UNNECESSARY_UNWRAP_INFO,
@@ -767,4 +775,5 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO,
crate::zero_repeat_side_effects::ZERO_REPEAT_SIDE_EFFECTS_INFO,
crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO,
+ crate::zombie_processes::ZOMBIE_PROCESSES_INFO,
];
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 0b7279f2b36..dc10b64698b 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_session::impl_lint_pass;
use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index 13778175496..33a97222b8f 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_ty_alias;
-use hir::def::Res;
use hir::ExprKind;
+use hir::def::Res;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
index ac49e6f1a48..056e39c02af 100644
--- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -2,10 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::{last_path_segment, std_or_core};
use rustc_errors::Applicability;
-use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind};
+use rustc_hir::{Expr, ExprKind, GenericArg, QPath, TyKind, def};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 05c3cd3c814..a065dc2cf7e 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -3,7 +3,7 @@ use clippy_utils::numeric_literal;
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 0e55d3db469..f34f5e05606 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -3,14 +3,14 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
use clippy_utils::ty::{implements_trait, is_manually_drop};
use clippy_utils::{
- expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, peel_middle_ty_refs, DefinedTy,
- ExprUseNode,
+ DefinedTy, ExprUseNode, expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local,
+ peel_middle_ty_refs,
};
use core::mem;
use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_ty};
use rustc_hir::{
self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat,
PatKind, Path, QPath, TyKind, UnOp,
@@ -290,13 +290,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
&& let Some(ty) = use_node.defined_ty(cx)
&& TyCoercionStability::for_defined_ty(cx, ty, use_node.is_return()).is_deref_stable()
{
- self.state = Some((
- State::ExplicitDeref { mutability: None },
- StateData {
- first_expr: expr,
- adjusted_ty,
- },
- ));
+ self.state = Some((State::ExplicitDeref { mutability: None }, StateData {
+ first_expr: expr,
+ adjusted_ty,
+ }));
}
},
RefOp::Method { mutbl, is_ufcs }
@@ -458,13 +455,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
&& next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
&& iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_)))
{
- self.state = Some((
- State::Borrow { mutability },
- StateData {
- first_expr: expr,
- adjusted_ty,
- },
- ));
+ self.state = Some((State::Borrow { mutability }, StateData {
+ first_expr: expr,
+ adjusted_ty,
+ }));
}
},
_ => {},
@@ -508,13 +502,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
let stability = state.stability;
report(cx, expr, State::DerefedBorrow(state), data, typeck);
if stability.is_deref_stable() {
- self.state = Some((
- State::Borrow { mutability },
- StateData {
- first_expr: expr,
- adjusted_ty,
- },
- ));
+ self.state = Some((State::Borrow { mutability }, StateData {
+ first_expr: expr,
+ adjusted_ty,
+ }));
}
},
(Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
@@ -539,13 +530,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
} else if stability.is_deref_stable()
&& let Some(parent) = get_parent_expr(cx, expr)
{
- self.state = Some((
- State::ExplicitDeref { mutability: None },
- StateData {
- first_expr: parent,
- adjusted_ty,
- },
- ));
+ self.state = Some((State::ExplicitDeref { mutability: None }, StateData {
+ first_expr: parent,
+ adjusted_ty,
+ }));
}
},
@@ -1138,20 +1126,17 @@ impl<'tcx> Dereferencing<'tcx> {
if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
if let Some(pat) = outer_pat {
// Check for auto-deref
- if !matches!(
- cx.typeck_results().expr_adjustments(e),
- [
- Adjustment {
- kind: Adjust::Deref(_),
- ..
- },
- Adjustment {
- kind: Adjust::Deref(_),
- ..
- },
+ if !matches!(cx.typeck_results().expr_adjustments(e), [
+ Adjustment {
+ kind: Adjust::Deref(_),
+ ..
+ },
+ Adjustment {
+ kind: Adjust::Deref(_),
..
- ]
- ) {
+ },
+ ..
+ ]) {
match get_parent_expr(cx, e) {
// Field accesses are the same no matter the number of references.
Some(Expr {
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index f27f68e2cbc..2920bbb4c81 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::indent_of;
use clippy_utils::{is_default_equivalent, peel_blocks};
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 636698e96f6..61c151d4f9d 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -3,7 +3,7 @@ use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths};
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, walk_item};
use rustc_hir::{
self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, Safety, UnsafeSource,
};
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs
new file mode 100644
index 00000000000..de7a2c2433f
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/doc/empty_line_after.rs
@@ -0,0 +1,342 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::{SpanRangeExt, snippet_indent};
+use clippy_utils::tokenize_with_text;
+use itertools::Itertools;
+use rustc_ast::token::CommentKind;
+use rustc_ast::{AttrKind, AttrStyle, Attribute};
+use rustc_errors::{Applicability, Diag, SuggestionStyle};
+use rustc_hir::{ItemKind, Node};
+use rustc_lexer::TokenKind;
+use rustc_lint::LateContext;
+use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData};
+
+use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+enum StopKind {
+ Attr,
+ Doc(CommentKind),
+}
+
+impl StopKind {
+ fn is_doc(self) -> bool {
+ matches!(self, StopKind::Doc(_))
+ }
+}
+
+#[derive(Debug)]
+struct Stop {
+ span: Span,
+ kind: StopKind,
+ first: usize,
+ last: usize,
+}
+
+impl Stop {
+ fn convert_to_inner(&self) -> (Span, String) {
+ let inner = match self.kind {
+ // #|[...]
+ StopKind::Attr => InnerSpan::new(1, 1),
+ // /// or /**
+ // ^ ^
+ StopKind::Doc(_) => InnerSpan::new(2, 3),
+ };
+ (self.span.from_inner(inner), "!".into())
+ }
+
+ fn comment_out(&self, cx: &LateContext<'_>, suggestions: &mut Vec<(Span, String)>) {
+ match self.kind {
+ StopKind::Attr => {
+ if cx.tcx.sess.source_map().is_multiline(self.span) {
+ suggestions.extend([
+ (self.span.shrink_to_lo(), "/* ".into()),
+ (self.span.shrink_to_hi(), " */".into()),
+ ]);
+ } else {
+ suggestions.push((self.span.shrink_to_lo(), "// ".into()));
+ }
+ },
+ StopKind::Doc(CommentKind::Line) => suggestions.push((self.span.shrink_to_lo(), "// ".into())),
+ StopKind::Doc(CommentKind::Block) => {
+ // /** outer */ /*! inner */
+ // ^ ^
+ let asterisk = self.span.from_inner(InnerSpan::new(1, 2));
+ suggestions.push((asterisk, String::new()));
+ },
+ }
+ }
+
+ fn from_attr(cx: &LateContext<'_>, attr: &Attribute) -> Option<Self> {
+ let SpanData { lo, hi, .. } = attr.span.data();
+ let file = cx.tcx.sess.source_map().lookup_source_file(lo);
+
+ Some(Self {
+ span: attr.span,
+ kind: match attr.kind {
+ AttrKind::Normal(_) => StopKind::Attr,
+ AttrKind::DocComment(comment_kind, _) => StopKind::Doc(comment_kind),
+ },
+ first: file.lookup_line(file.relative_position(lo))?,
+ last: file.lookup_line(file.relative_position(hi))?,
+ })
+ }
+}
+
+/// Represents a set of attrs/doc comments separated by 1 or more empty lines
+///
+/// ```ignore
+/// /// chunk 1 docs
+/// // not an empty line so also part of chunk 1
+/// #[chunk_1_attrs] // <-- prev_stop
+///
+/// /* gap */
+///
+/// /// chunk 2 docs // <-- next_stop
+/// #[chunk_2_attrs]
+/// ```
+struct Gap<'a> {
+ /// The span of individual empty lines including the newline at the end of the line
+ empty_lines: Vec<Span>,
+ has_comment: bool,
+ next_stop: &'a Stop,
+ prev_stop: &'a Stop,
+ /// The chunk that includes [`prev_stop`](Self::prev_stop)
+ prev_chunk: &'a [Stop],
+}
+
+impl<'a> Gap<'a> {
+ fn new(cx: &LateContext<'_>, prev_chunk: &'a [Stop], next_chunk: &'a [Stop]) -> Option<Self> {
+ let prev_stop = prev_chunk.last()?;
+ let next_stop = next_chunk.first()?;
+ let gap_span = prev_stop.span.between(next_stop.span);
+ let gap_snippet = gap_span.get_source_text(cx)?;
+
+ let mut has_comment = false;
+ let mut empty_lines = Vec::new();
+
+ for (token, source, inner_span) in tokenize_with_text(&gap_snippet) {
+ match token {
+ TokenKind::BlockComment {
+ doc_style: None,
+ terminated: true,
+ }
+ | TokenKind::LineComment { doc_style: None } => has_comment = true,
+ TokenKind::Whitespace => {
+ let newlines = source.bytes().positions(|b| b == b'\n');
+ empty_lines.extend(
+ newlines
+ .tuple_windows()
+ .map(|(a, b)| InnerSpan::new(inner_span.start + a + 1, inner_span.start + b))
+ .map(|inner_span| gap_span.from_inner(inner_span)),
+ );
+ },
+ // Ignore cfg_attr'd out attributes as they may contain empty lines, could also be from macro
+ // shenanigans
+ _ => return None,
+ }
+ }
+
+ (!empty_lines.is_empty()).then_some(Self {
+ empty_lines,
+ has_comment,
+ next_stop,
+ prev_stop,
+ prev_chunk,
+ })
+ }
+
+ fn contiguous_empty_lines(&self) -> impl Iterator<Item = Span> + '_ {
+ self.empty_lines
+ // The `+ BytePos(1)` means "next line", because each empty line span is "N:1-N:1".
+ .chunk_by(|a, b| a.hi() + BytePos(1) == b.lo())
+ .map(|chunk| {
+ let first = chunk.first().expect("at least one empty line");
+ let last = chunk.last().expect("at least one empty line");
+ // The BytePos subtraction here is safe, as before an empty line, there must be at least one
+ // attribute/comment. The span needs to start at the end of the previous line.
+ first.with_lo(first.lo() - BytePos(1)).with_hi(last.hi())
+ })
+ }
+}
+
+/// If the node the attributes/docs apply to is the first in the module/crate suggest converting
+/// them to inner attributes/docs
+fn suggest_inner(cx: &LateContext<'_>, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_>]) {
+ let Some(owner) = cx.last_node_with_lint_attrs.as_owner() else {
+ return;
+ };
+ let parent_desc = match cx.tcx.parent_hir_node(owner.into()) {
+ Node::Item(item)
+ if let ItemKind::Mod(parent_mod) = item.kind
+ && let [first, ..] = parent_mod.item_ids
+ && first.owner_id == owner =>
+ {
+ "parent module"
+ },
+ Node::Crate(crate_mod)
+ if let Some(first) = crate_mod
+ .item_ids
+ .iter()
+ .map(|&id| cx.tcx.hir().item(id))
+ // skip prelude imports
+ .find(|item| !matches!(item.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
+ && first.owner_id == owner =>
+ {
+ "crate"
+ },
+ _ => return,
+ };
+
+ diag.multipart_suggestion_verbose(
+ match kind {
+ StopKind::Attr => format!("if the attribute should apply to the {parent_desc} use an inner attribute"),
+ StopKind::Doc(_) => format!("if the comment should document the {parent_desc} use an inner doc comment"),
+ },
+ gaps.iter()
+ .flat_map(|gap| gap.prev_chunk)
+ .map(Stop::convert_to_inner)
+ .collect(),
+ Applicability::MaybeIncorrect,
+ );
+}
+
+fn check_gaps(cx: &LateContext<'_>, gaps: &[Gap<'_>]) -> bool {
+ let Some(first_gap) = gaps.first() else {
+ return false;
+ };
+ let empty_lines = || gaps.iter().flat_map(|gap| gap.empty_lines.iter().copied());
+ let contiguous_empty_lines = || gaps.iter().flat_map(Gap::contiguous_empty_lines);
+ let mut has_comment = false;
+ let mut has_attr = false;
+ for gap in gaps {
+ has_comment |= gap.has_comment;
+ if !has_attr {
+ has_attr = gap.prev_chunk.iter().any(|stop| stop.kind == StopKind::Attr);
+ }
+ }
+ let kind = first_gap.prev_stop.kind;
+ let (lint, kind_desc) = match kind {
+ StopKind::Attr => (EMPTY_LINE_AFTER_OUTER_ATTR, "outer attribute"),
+ StopKind::Doc(_) => (EMPTY_LINE_AFTER_DOC_COMMENTS, "doc comment"),
+ };
+ let (lines, are, them) = if empty_lines().nth(1).is_some() {
+ ("lines", "are", "them")
+ } else {
+ ("line", "is", "it")
+ };
+ span_lint_and_then(
+ cx,
+ lint,
+ first_gap.prev_stop.span.to(empty_lines().last().unwrap()),
+ format!("empty {lines} after {kind_desc}"),
+ |diag| {
+ if let Some(owner) = cx.last_node_with_lint_attrs.as_owner() {
+ let def_id = owner.to_def_id();
+ let def_descr = cx.tcx.def_descr(def_id);
+ diag.span_label(cx.tcx.def_span(def_id), match kind {
+ StopKind::Attr => format!("the attribute applies to this {def_descr}"),
+ StopKind::Doc(_) => format!("the comment documents this {def_descr}"),
+ });
+ }
+
+ diag.multipart_suggestion_with_style(
+ format!("if the empty {lines} {are} unintentional remove {them}"),
+ contiguous_empty_lines()
+ .map(|empty_lines| (empty_lines, String::new()))
+ .collect(),
+ Applicability::MaybeIncorrect,
+ SuggestionStyle::HideCodeAlways,
+ );
+
+ if has_comment && kind.is_doc() {
+ // Likely doc comments that applied to some now commented out code
+ //
+ // /// Old docs for Foo
+ // // struct Foo;
+
+ let mut suggestions = Vec::new();
+ for stop in gaps.iter().flat_map(|gap| gap.prev_chunk) {
+ stop.comment_out(cx, &mut suggestions);
+ }
+ let name = match cx.tcx.hir().opt_name(cx.last_node_with_lint_attrs) {
+ Some(name) => format!("`{name}`"),
+ None => "this".into(),
+ };
+ diag.multipart_suggestion_verbose(
+ format!("if the doc comment should not document {name} comment it out"),
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ suggest_inner(cx, diag, kind, gaps);
+ }
+
+ if kind == StopKind::Doc(CommentKind::Line)
+ && gaps
+ .iter()
+ .all(|gap| !gap.has_comment && gap.next_stop.kind == StopKind::Doc(CommentKind::Line))
+ {
+ // Commentless empty gaps between line doc comments, possibly intended to be part of the markdown
+
+ let indent = snippet_indent(cx, first_gap.prev_stop.span).unwrap_or_default();
+ diag.multipart_suggestion_verbose(
+ format!("if the documentation should include the empty {lines} include {them} in the comment"),
+ empty_lines()
+ .map(|empty_line| (empty_line, format!("{indent}///")))
+ .collect(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ },
+ );
+ kind.is_doc()
+}
+
+/// Returns `true` if [`EMPTY_LINE_AFTER_DOC_COMMENTS`] triggered, used to skip other doc comment
+/// lints where they would be confusing
+///
+/// [`EMPTY_LINE_AFTER_OUTER_ATTR`] is also here to share an implementation but does not return
+/// `true` if it triggers
+pub(super) fn check(cx: &LateContext<'_>, attrs: &[Attribute]) -> bool {
+ let mut outer = attrs
+ .iter()
+ .filter(|attr| attr.style == AttrStyle::Outer && !attr.span.from_expansion())
+ .map(|attr| Stop::from_attr(cx, attr))
+ .collect::<Option<Vec<_>>>()
+ .unwrap_or_default();
+
+ if outer.is_empty() {
+ return false;
+ }
+
+ // Push a fake attribute Stop for the item itself so we check for gaps between the last outer
+ // attr/doc comment and the item they apply to
+ let span = cx.tcx.hir().span(cx.last_node_with_lint_attrs);
+ if !span.from_expansion()
+ && let Ok(line) = cx.tcx.sess.source_map().lookup_line(span.lo())
+ {
+ outer.push(Stop {
+ span,
+ kind: StopKind::Attr,
+ first: line.line,
+ // last doesn't need to be accurate here, we don't compare it with anything
+ last: line.line,
+ });
+ }
+
+ let mut gaps = Vec::new();
+ let mut last = 0;
+ for pos in outer
+ .array_windows()
+ .positions(|[a, b]| b.first.saturating_sub(a.last) > 1)
+ {
+ // we want to be after the first stop in the window
+ let pos = pos + 1;
+ if let Some(gap) = Gap::new(cx, &outer[last..pos], &outer[pos..]) {
+ last = pos;
+ gaps.push(gap);
+ }
+ }
+
+ check_gaps(cx, &gaps)
+}
diff --git a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
index 771bcac2441..f9e4a43c0e7 100644
--- a/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/lazy_continuation.rs
@@ -22,7 +22,6 @@ pub(super) fn check(
range: Range<usize>,
mut span: Span,
containers: &[super::Container],
- line_break_span: Span,
) {
if doc[range.clone()].contains('\t') {
// We don't do tab stops correctly.
@@ -52,29 +51,6 @@ pub(super) fn check(
"doc list item without indentation"
};
span_lint_and_then(cx, DOC_LAZY_CONTINUATION, span, msg, |diag| {
- let snippet = clippy_utils::source::snippet(cx, line_break_span, "");
- if snippet.chars().filter(|&c| c == '\n').count() > 1
- && let Some(doc_comment_start) = snippet.rfind('\n')
- && let doc_comment = snippet[doc_comment_start..].trim()
- && (doc_comment == "///" || doc_comment == "//!")
- {
- // suggest filling in a blank line
- diag.span_suggestion_verbose(
- line_break_span.shrink_to_lo(),
- "if this should be its own paragraph, add a blank doc comment line",
- format!("\n{doc_comment}"),
- Applicability::MaybeIncorrect,
- );
- if ccount > 0 || blockquote_level > 0 {
- diag.help("if this not intended to be a quote at all, escape it with `\\>`");
- } else {
- let indent = list_indentation - lcount;
- diag.help(format!(
- "if this is intended to be part of the list, indent {indent} spaces"
- ));
- }
- return;
- }
if ccount == 0 && blockquote_level == 0 {
// simpler suggestion style for indentation
let indent = list_indentation - lcount;
diff --git a/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs b/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs
index 01191e811b0..1d4345e4541 100644
--- a/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/link_with_quotes.rs
@@ -3,7 +3,7 @@ use std::ops::Range;
use clippy_utils::diagnostics::span_lint;
use rustc_lint::LateContext;
-use super::{Fragments, DOC_LINK_WITH_QUOTES};
+use super::{DOC_LINK_WITH_QUOTES, Fragments};
pub fn check(cx: &LateContext<'_>, trimmed_text: &str, range: Range<usize>, fragments: Fragments<'_>) {
if ((trimmed_text.starts_with('\'') && trimmed_text.ends_with('\''))
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index e3d74840726..c9173030a55 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -5,7 +5,7 @@ use clippy_utils::{is_doc_hidden, return_ty};
use rustc_hir::{BodyId, FnSig, OwnerId, Safety};
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
pub fn check(
cx: &LateContext<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 790579b21c9..0ae1fad5692 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -23,15 +23,16 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_resolve::rustdoc::{
- add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, span_of_fragments,
- DocFragment,
+ DocFragment, add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range,
+ span_of_fragments,
};
use rustc_session::impl_lint_pass;
use rustc_span::edition::Edition;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::ops::Range;
use url::Url;
+mod empty_line_after;
mod link_with_quotes;
mod markdown;
mod missing_headers;
@@ -449,13 +450,88 @@ declare_clippy_lint! {
/// /// and probably spanning a many rows.
/// struct Foo {}
/// ```
- #[clippy::version = "1.81.0"]
+ #[clippy::version = "1.82.0"]
pub TOO_LONG_FIRST_DOC_PARAGRAPH,
style,
"ensure that the first line of a documentation paragraph isn't too long"
}
-#[derive(Clone)]
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for empty lines after outer attributes
+ ///
+ /// ### Why is this bad?
+ /// The attribute may have meant to be an inner attribute (`#![attr]`). If
+ /// it was meant to be an outer attribute (`#[attr]`) then the empty line
+ /// should be removed
+ ///
+ /// ### Example
+ /// ```no_run
+ /// #[allow(dead_code)]
+ ///
+ /// fn not_quite_good_code() {}
+ /// ```
+ ///
+ /// Use instead:
+ /// ```no_run
+ /// // Good (as inner attribute)
+ /// #![allow(dead_code)]
+ ///
+ /// fn this_is_fine() {}
+ ///
+ /// // or
+ ///
+ /// // Good (as outer attribute)
+ /// #[allow(dead_code)]
+ /// fn this_is_fine_too() {}
+ /// ```
+ #[clippy::version = "pre 1.29.0"]
+ pub EMPTY_LINE_AFTER_OUTER_ATTR,
+ suspicious,
+ "empty line after outer attribute"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for empty lines after doc comments.
+ ///
+ /// ### Why is this bad?
+ /// The doc comment may have meant to be an inner doc comment, regular
+ /// comment or applied to some old code that is now commented out. If it was
+ /// intended to be a doc comment, then the empty line should be removed.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// /// Some doc comment with a blank line after it.
+ ///
+ /// fn f() {}
+ ///
+ /// /// Docs for `old_code`
+ /// // fn old_code() {}
+ ///
+ /// fn new_code() {}
+ /// ```
+ ///
+ /// Use instead:
+ /// ```no_run
+ /// //! Convert it to an inner doc comment
+ ///
+ /// // Or a regular comment
+ ///
+ /// /// Or remove the empty line
+ /// fn f() {}
+ ///
+ /// // /// Docs for `old_code`
+ /// // fn old_code() {}
+ ///
+ /// fn new_code() {}
+ /// ```
+ #[clippy::version = "1.70.0"]
+ pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+ suspicious,
+ "empty line after doc comments"
+}
+
pub struct Documentation {
valid_idents: FxHashSet<String>,
check_private_items: bool,
@@ -482,6 +558,8 @@ impl_lint_pass!(Documentation => [
SUSPICIOUS_DOC_COMMENTS,
EMPTY_DOCS,
DOC_LAZY_CONTINUATION,
+ EMPTY_LINE_AFTER_OUTER_ATTR,
+ EMPTY_LINE_AFTER_DOC_COMMENTS,
TOO_LONG_FIRST_DOC_PARAGRAPH,
]);
@@ -612,12 +690,10 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
Some(("fake".into(), "fake".into()))
}
- if is_doc_hidden(attrs) {
+ if suspicious_doc_comments::check(cx, attrs) || empty_line_after::check(cx, attrs) || is_doc_hidden(attrs) {
return None;
}
- suspicious_doc_comments::check(cx, attrs);
-
let (fragments, _) = attrs_to_doc_fragments(
attrs.iter().filter_map(|attr| {
if in_external_macro(cx.sess(), attr.span) {
@@ -816,7 +892,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
range.end..next_range.start,
Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
&containers[..],
- span,
);
}
},
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index c3e3c0431e6..9ba2723157a 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -13,7 +13,7 @@ use rustc_parse::parser::ForceCollect;
use rustc_session::parse::ParseSess;
use rustc_span::edition::Edition;
use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{sym, FileName, Pos};
+use rustc_span::{FileName, Pos, sym};
use super::Fragments;
diff --git a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
index d7ad30efec3..f6f942b10ca 100644
--- a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
@@ -7,7 +7,7 @@ use rustc_span::Span;
use super::SUSPICIOUS_DOC_COMMENTS;
-pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
+pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) -> bool {
let replacements: Vec<_> = collect_doc_replacements(attrs);
if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) {
@@ -24,6 +24,10 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
);
},
);
+
+ true
+ } else {
+ false
}
}
diff --git a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
index 7bb3bb12f2c..0165d24c7df 100644
--- a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
@@ -79,10 +79,17 @@ pub(super) fn check(
&& let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi())
&& let Some(snippet) = snippet_opt(cx, new_span)
{
+ let Some(first) = snippet_opt(cx, first_span) else {
+ return;
+ };
+ let Some(comment_form) = first.get(..3) else {
+ return;
+ };
+
diag.span_suggestion(
new_span,
"add an empty line",
- format!("{snippet}///\n"),
+ format!("{snippet}{comment_form}{snippet}"),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 9c5100a8c1a..70524e458c7 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -1,17 +1,17 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context};
use clippy_utils::{
- can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
- peel_hir_expr_while, SpanlessEq,
+ SpanlessEq, can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
+ peel_hir_expr_while,
};
use core::fmt::{self, Write};
use rustc_errors::Applicability;
use rustc_hir::hir_id::HirIdSet;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, SyntaxContext, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index 4755cefe784..e9e9d00907e 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{mir_to_const, Constant};
+use clippy_utils::consts::{Constant, mir_to_const};
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 80360697941..5588124e791 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,15 +1,15 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_hir;
-use rustc_hir::{intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
+use rustc_hir::{AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind, intravisit};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
use rustc_session::impl_lint_pass;
+use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::kw;
-use rustc_span::Span;
use rustc_target::spec::abi::Abi;
pub struct BoxedLocal {
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index 8f469efb1b5..c88fb50b5af 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -5,8 +5,8 @@ use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
use rustc_target::spec::abi::Abi;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
index 5154edd4399..ce0e0faa014 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet;
use rustc_ast::node_id::NodeSet;
-use rustc_ast::visit::{walk_block, walk_item, Visitor};
+use rustc_ast::visit::{Visitor, walk_block, walk_item};
use rustc_ast::{Block, Crate, Inline, Item, ItemKind, ModKind, NodeId};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index 3c4a043a732..5b423a96918 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{format_args_inputs_span, FormatArgsStorage};
+use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_expn_of, path_def_id};
use rustc_errors::Applicability;
@@ -7,7 +7,7 @@ use rustc_hir::def::Res;
use rustc_hir::{BindingMode, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, ExpnId};
+use rustc_span::{ExpnId, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index bfe4e253ae4..bf9388b4a70 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use clippy_utils::{is_from_proc_macro, trait_ref_of_method};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty};
use rustc_hir::{
BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
PredicateOrigin, Ty, TyKind, WherePredicate,
@@ -12,8 +12,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
+use rustc_span::def_id::{DefId, LocalDefId};
declare_clippy_lint! {
/// ### What it does
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 0446943321a..747ea9a4344 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -6,7 +6,7 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index 95b8e882da7..ba2b37fbf11 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -41,7 +41,7 @@ declare_clippy_lint! {
/// }
/// }
/// ```
- #[clippy::version = "1.78.0"]
+ #[clippy::version = "1.81.0"]
pub FIELD_SCOPED_VISIBILITY_MODIFIERS,
restriction,
"checks for usage of a scoped visibility modifier, like `pub(crate)`, on fields"
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 bf4bcabfe89..8da6623f34d 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::Constant::{Int, F32, F64};
+use clippy_utils::consts::Constant::{F32, F64, Int};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index 4dedff69b9a..5e3f6b6a137 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage};
-use clippy_utils::source::{snippet_with_context, SpanRangeExt};
+use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, root_macro_call_first_node};
+use clippy_utils::source::{SpanRangeExt, snippet_with_context};
use clippy_utils::sugg::Sugg;
use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
use rustc_errors::Applicability;
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 020c0c5440d..83ab9f6557b 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -1,11 +1,12 @@
use arrayvec::ArrayVec;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::{
- find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro,
- is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall,
+ FormatArgsStorage, FormatParamUsage, MacroCall, find_format_arg_expr, format_arg_removal_span,
+ format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call,
+ root_macro_call_first_node,
};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::{implements_trait, is_type_lang_item};
@@ -18,11 +19,11 @@ use rustc_errors::Applicability;
use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode};
use rustc_hir::{Expr, ExprKind, LangItem};
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::Ty;
+use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_session::impl_lint_pass;
use rustc_span::edition::Edition::Edition2021;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index 7cd12ac7db8..c196f404ce6 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::macros::{find_format_arg_expr, is_format_macro, root_macro_call_first_node, FormatArgsStorage};
+use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, is_format_macro, root_macro_call_first_node};
use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
use rustc_ast::{FormatArgsPiece, FormatTrait};
use rustc_errors::Applicability;
@@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::symbol::kw;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs
index c6f03c3a7cf..8b1f86cbb91 100644
--- a/src/tools/clippy/clippy_lints/src/format_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::ty::is_type_lang_item;
use clippy_utils::higher;
+use clippy_utils::ty::is_type_lang_item;
use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
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 b84bf7c821c..8832cd42dd9 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -1,11 +1,11 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local;
use clippy_utils::path_def_id;
use clippy_utils::source::SpanRangeExt;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_path};
use rustc_hir::{
FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItemKind, ImplItemRef, Item, ItemKind, PatKind, Path,
PathSegment, Ty, TyKind,
diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
index e5fa67d6964..7361546153c 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -3,7 +3,7 @@ use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::{is_in_const_context, is_integer_literal};
use rustc_errors::Applicability;
-use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
+use rustc_hir::{Expr, ExprKind, LangItem, PrimTy, QPath, TyKind, def};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 0f48941783b..ba8a459c917 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -14,8 +14,8 @@ use rustc_hir::intravisit;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{DefIdSet, LocalDefId};
use rustc_span::Span;
+use rustc_span::def_id::{DefIdSet, LocalDefId};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index 93828121047..cfd11e9339f 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use clippy_utils::attrs::is_proc_macro;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 1aeefe73cf6..c2b40ae01d4 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -1,4 +1,4 @@
-use rustc_hir::{self as hir, intravisit, HirId, HirIdSet};
+use rustc_hir::{self as hir, HirId, HirIdSet, intravisit};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::def_id::LocalDefId;
diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
index c7de0385c02..ac2e866e4ff 100644
--- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs
@@ -4,8 +4,8 @@ use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_hir::hir_id::OwnerId;
use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef};
use rustc_lint::LateContext;
-use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, kw};
use super::RENAMED_FUNCTION_PARAMS;
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index c3a0b40a677..d4eaa166320 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -3,11 +3,11 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, Ty};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use clippy_utils::trait_ref_of_method;
-use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item, AdtVariantInfo};
+use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_type_diagnostic_item};
use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
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 9488ba75686..a4dbe134f36 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::print::PrintTraitRefExt;
use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index 0bca53c1536..d63c18c0eda 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::source::snippet_with_context;
@@ -105,6 +105,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
snippet_with_context(cx, first_stmt.span.until(then_arg.span), ctxt, "..", &mut app);
let closure = if method_name == "then" { "|| " } else { "" };
format!("{closure} {{ {block_snippet}; {arg_snip} }}")
+ } else if method_name == "then" {
+ (std::borrow::Cow::Borrowed("|| ") + arg_snip).into_owned()
} else {
arg_snip.into_owned()
};
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index e56f33f8dcf..f683925145a 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -3,18 +3,18 @@ use std::collections::BTreeMap;
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_body, walk_expr, walk_inf, walk_ty};
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{Ty, TypeckResults};
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{snippet, IntoSpan, SpanRangeExt};
+use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet};
use clippy_utils::ty::is_type_diagnostic_item;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 127c73ed637..f4a64f5c20b 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,11 +1,17 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq};
+use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{
+ SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt,
+};
use rustc_ast::ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
-use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
+use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
+use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
@@ -39,7 +45,49 @@ declare_clippy_lint! {
"Perform saturating subtraction instead of implicitly checking lower bound of data type"
}
-declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB]);
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for comparisons between integers, followed by subtracting the greater value from the
+ /// lower one.
+ ///
+ /// ### Why is this bad?
+ /// This could result in an underflow and is most likely not what the user wants. If this was
+ /// intended to be a saturated subtraction, consider using the `saturating_sub` method directly.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// let a = 12u32;
+ /// let b = 13u32;
+ ///
+ /// let result = if a > b { b - a } else { 0 };
+ /// ```
+ ///
+ /// Use instead:
+ /// ```no_run
+ /// let a = 12u32;
+ /// let b = 13u32;
+ ///
+ /// let result = a.saturating_sub(b);
+ /// ```
+ #[clippy::version = "1.44.0"]
+ pub INVERTED_SATURATING_SUB,
+ correctness,
+ "Check if a variable is smaller than another one and still subtract from it even if smaller"
+}
+
+pub struct ImplicitSaturatingSub {
+ msrv: Msrv,
+}
+
+impl_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]);
+
+impl ImplicitSaturatingSub {
+ pub fn new(conf: &'static Conf) -> Self {
+ Self {
+ msrv: conf.msrv.clone(),
+ }
+ }
+}
impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -50,73 +98,260 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
// Check if the conditional expression is a binary operation
&& let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind
+ {
+ check_with_condition(cx, expr, cond_op.node, cond_left, cond_right, then);
+ } else if let Some(higher::If {
+ cond,
+ then: if_block,
+ r#else: Some(else_block),
+ }) = higher::If::hir(expr)
+ && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind
+ {
+ check_manual_check(
+ cx, expr, cond_op, cond_left, cond_right, if_block, else_block, &self.msrv,
+ );
+ }
+ }
+
+ extract_msrv_attr!(LateContext);
+}
- // Ensure that the binary operator is >, !=, or <
- && (BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node)
+#[allow(clippy::too_many_arguments)]
+fn check_manual_check<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &Expr<'tcx>,
+ condition: &BinOp,
+ left_hand: &Expr<'tcx>,
+ right_hand: &Expr<'tcx>,
+ if_block: &Expr<'tcx>,
+ else_block: &Expr<'tcx>,
+ msrv: &Msrv,
+) {
+ let ty = cx.typeck_results().expr_ty(left_hand);
+ if ty.is_numeric() && !ty.is_signed() {
+ match condition.node {
+ BinOpKind::Gt | BinOpKind::Ge => check_gt(
+ cx,
+ condition.span,
+ expr.span,
+ left_hand,
+ right_hand,
+ if_block,
+ else_block,
+ msrv,
+ ),
+ BinOpKind::Lt | BinOpKind::Le => check_gt(
+ cx,
+ condition.span,
+ expr.span,
+ right_hand,
+ left_hand,
+ if_block,
+ else_block,
+ msrv,
+ ),
+ _ => {},
+ }
+ }
+}
- // Check if assign operation is done
- && let Some(target) = subtracts_one(cx, then)
+#[allow(clippy::too_many_arguments)]
+fn check_gt(
+ cx: &LateContext<'_>,
+ condition_span: Span,
+ expr_span: Span,
+ big_var: &Expr<'_>,
+ little_var: &Expr<'_>,
+ if_block: &Expr<'_>,
+ else_block: &Expr<'_>,
+ msrv: &Msrv,
+) {
+ if let Some(big_var) = Var::new(big_var)
+ && let Some(little_var) = Var::new(little_var)
+ {
+ check_subtraction(
+ cx,
+ condition_span,
+ expr_span,
+ big_var,
+ little_var,
+ if_block,
+ else_block,
+ msrv,
+ );
+ }
+}
- // Extracting out the variable name
- && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind
+struct Var {
+ span: Span,
+ hir_id: HirId,
+}
+
+impl Var {
+ fn new(expr: &Expr<'_>) -> Option<Self> {
+ path_to_local(expr).map(|hir_id| Self {
+ span: expr.span,
+ hir_id,
+ })
+ }
+}
+
+#[allow(clippy::too_many_arguments)]
+fn check_subtraction(
+ cx: &LateContext<'_>,
+ condition_span: Span,
+ expr_span: Span,
+ big_var: Var,
+ little_var: Var,
+ if_block: &Expr<'_>,
+ else_block: &Expr<'_>,
+ msrv: &Msrv,
+) {
+ let if_block = peel_blocks(if_block);
+ let else_block = peel_blocks(else_block);
+ if is_integer_literal(if_block, 0) {
+ // We need to check this case as well to prevent infinite recursion.
+ if is_integer_literal(else_block, 0) {
+ // Well, seems weird but who knows?
+ return;
+ }
+ // If the subtraction is done in the `else` block, then we need to also revert the two
+ // variables as it means that the check was reverted too.
+ check_subtraction(
+ cx,
+ condition_span,
+ expr_span,
+ little_var,
+ big_var,
+ else_block,
+ if_block,
+ msrv,
+ );
+ return;
+ }
+ if is_integer_literal(else_block, 0)
+ && let ExprKind::Binary(op, left, right) = if_block.kind
+ && let BinOpKind::Sub = op.node
+ {
+ let local_left = path_to_local(left);
+ let local_right = path_to_local(right);
+ if Some(big_var.hir_id) == local_left && Some(little_var.hir_id) == local_right {
+ // This part of the condition is voluntarily split from the one before to ensure that
+ // if `snippet_opt` fails, it won't try the next conditions.
+ if let Some(big_var_snippet) = snippet_opt(cx, big_var.span)
+ && let Some(little_var_snippet) = snippet_opt(cx, little_var.span)
+ && (!is_in_const_context(cx) || msrv.meets(msrvs::SATURATING_SUB_CONST))
+ {
+ span_lint_and_sugg(
+ cx,
+ IMPLICIT_SATURATING_SUB,
+ expr_span,
+ "manual arithmetic check found",
+ "replace it with",
+ format!("{big_var_snippet}.saturating_sub({little_var_snippet})"),
+ Applicability::MachineApplicable,
+ );
+ }
+ } else if Some(little_var.hir_id) == local_left
+ && Some(big_var.hir_id) == local_right
+ && let Some(big_var_snippet) = snippet_opt(cx, big_var.span)
+ && let Some(little_var_snippet) = snippet_opt(cx, little_var.span)
{
- // Handle symmetric conditions in the if statement
- let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
- if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node {
- (cond_left, cond_right)
- } else {
- return;
- }
- } else if SpanlessEq::new(cx).eq_expr(cond_right, target) {
- if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node {
- (cond_right, cond_left)
- } else {
- return;
- }
+ span_lint_and_then(
+ cx,
+ INVERTED_SATURATING_SUB,
+ condition_span,
+ "inverted arithmetic check before subtraction",
+ |diag| {
+ diag.span_note(
+ if_block.span,
+ format!("this subtraction underflows when `{little_var_snippet} < {big_var_snippet}`"),
+ );
+ diag.span_suggestion(
+ if_block.span,
+ "try replacing it with",
+ format!("{big_var_snippet} - {little_var_snippet}"),
+ Applicability::MaybeIncorrect,
+ );
+ },
+ );
+ }
+ }
+}
+
+fn check_with_condition<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &Expr<'tcx>,
+ cond_op: BinOpKind,
+ cond_left: &Expr<'tcx>,
+ cond_right: &Expr<'tcx>,
+ then: &Expr<'tcx>,
+) {
+ // Ensure that the binary operator is >, !=, or <
+ if (BinOpKind::Ne == cond_op || BinOpKind::Gt == cond_op || BinOpKind::Lt == cond_op)
+
+ // Check if assign operation is done
+ && let Some(target) = subtracts_one(cx, then)
+
+ // Extracting out the variable name
+ && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind
+ {
+ // Handle symmetric conditions in the if statement
+ let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) {
+ if BinOpKind::Gt == cond_op || BinOpKind::Ne == cond_op {
+ (cond_left, cond_right)
} else {
return;
- };
-
- // Check if the variable in the condition statement is an integer
- if !cx.typeck_results().expr_ty(cond_var).is_integral() {
+ }
+ } else if SpanlessEq::new(cx).eq_expr(cond_right, target) {
+ if BinOpKind::Lt == cond_op || BinOpKind::Ne == cond_op {
+ (cond_right, cond_left)
+ } else {
return;
}
+ } else {
+ return;
+ };
- // Get the variable name
- let var_name = ares_path.segments[0].ident.name.as_str();
- match cond_num_val.kind {
- ExprKind::Lit(cond_lit) => {
- // Check if the constant is zero
- if let LitKind::Int(Pu128(0), _) = cond_lit.node {
- if cx.typeck_results().expr_ty(cond_left).is_signed() {
- } else {
- print_lint_and_sugg(cx, var_name, expr);
- };
- }
- },
- ExprKind::Path(QPath::TypeRelative(_, name)) => {
- if name.ident.as_str() == "MIN"
- && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id)
- && let Some(impl_id) = cx.tcx.impl_of_method(const_id)
- && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
- && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
- {
- print_lint_and_sugg(cx, var_name, expr);
- }
- },
- ExprKind::Call(func, []) => {
- if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind
- && name.ident.as_str() == "min_value"
- && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id)
- && let Some(impl_id) = cx.tcx.impl_of_method(func_id)
- && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
- && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
- {
+ // Check if the variable in the condition statement is an integer
+ if !cx.typeck_results().expr_ty(cond_var).is_integral() {
+ return;
+ }
+
+ // Get the variable name
+ let var_name = ares_path.segments[0].ident.name.as_str();
+ match cond_num_val.kind {
+ ExprKind::Lit(cond_lit) => {
+ // Check if the constant is zero
+ if let LitKind::Int(Pu128(0), _) = cond_lit.node {
+ if cx.typeck_results().expr_ty(cond_left).is_signed() {
+ } else {
print_lint_and_sugg(cx, var_name, expr);
- }
- },
- _ => (),
- }
+ };
+ }
+ },
+ ExprKind::Path(QPath::TypeRelative(_, name)) => {
+ if name.ident.as_str() == "MIN"
+ && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id)
+ && let Some(impl_id) = cx.tcx.impl_of_method(const_id)
+ && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
+ && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
+ {
+ print_lint_and_sugg(cx, var_name, expr);
+ }
+ },
+ ExprKind::Call(func, []) => {
+ if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind
+ && name.ident.as_str() == "min_value"
+ && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id)
+ && let Some(impl_id) = cx.tcx.impl_of_method(func_id)
+ && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl
+ && cx.tcx.type_of(impl_id).instantiate_identity().is_integral()
+ {
+ print_lint_and_sugg(cx, var_name, expr);
+ }
+ },
+ _ => (),
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index 2ad045e1268..0b3a6ee1bea 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::Msrv;
use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_in_test;
use rustc_attr::{StabilityLevel, StableSince};
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{Expr, ExprKind, HirId};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt;
-use rustc_session::{impl_lint_pass, RustcVersion};
+use rustc_session::{RustcVersion, impl_lint_pass};
use rustc_span::def_id::DefId;
use rustc_span::{ExpnKind, Span};
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 2f9661c9ea3..39afb6810b8 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
@@ -8,14 +8,14 @@ use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_errors::Applicability;
use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
+use rustc_hir::intravisit::{self, Visitor};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::Ident;
use rustc_span::Span;
+use rustc_span::symbol::Ident;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs b/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs
index af5b1f95739..3a28553b55e 100644
--- a/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/ineffective_open_options.rs
@@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 6d6820311b6..66931a7f98c 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index 74bf82f58bd..66a8a3167a4 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -8,8 +8,8 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use rustc_span::symbol::Symbol;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
index 8caa484bb99..1ac549b74ac 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs
@@ -6,7 +6,7 @@ use rustc_hir::{HirId, Item, ItemKind, Mod};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::hygiene::AstPass;
-use rustc_span::{sym, ExpnKind};
+use rustc_span::{ExpnKind, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
index ba0cd5d6eb3..b19b348c743 100644
--- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::{FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs
index f162948bb44..5131f5b7269 100644
--- a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs
@@ -55,7 +55,9 @@ impl LateLintPass<'_> for IterOverHashType {
if let Some(for_loop) = ForLoop::hir(expr)
&& !for_loop.body.span.from_expansion()
&& let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
- && hash_iter_tys.into_iter().any(|sym| is_type_diagnostic_item(cx, ty, sym))
+ && hash_iter_tys
+ .into_iter()
+ .any(|sym| is_type_diagnostic_item(cx, ty, sym))
{
span_lint(
cx,
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 2f027c11707..923089c7223 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -1,7 +1,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::ty::{approx_ty_size, is_copy, AdtVariantInfo};
+use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_copy};
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
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 15a75b06089..0f061d6de50 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -8,7 +8,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ConstKind};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
index ccab1e27d3b..e17d6213679 100644
--- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS};
use clippy_config::Conf;
+use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::{get_parent_expr, is_from_proc_macro};
use hir::def_id::DefId;
@@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
use rustc_span::symbol::kw;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 0bc7fc2dd9d..3cd5f76e6b6 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet_with_context, SpanRangeExt};
-use clippy_utils::sugg::{has_enclosing_paren, Sugg};
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
+use clippy_utils::source::{SpanRangeExt, snippet_with_context};
+use clippy_utils::sugg::{Sugg, has_enclosing_paren};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, is_trait_method, peel_ref_operators};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
@@ -185,6 +185,19 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
);
}
+ if let ExprKind::MethodCall(method, lhs_expr, [rhs_expr], _) = expr.kind
+ && is_trait_method(cx, expr, sym::PartialEq)
+ && !expr.span.from_expansion()
+ {
+ check_empty_expr(
+ cx,
+ expr.span,
+ lhs_expr,
+ peel_ref_operators(cx, rhs_expr),
+ (method.ident.name == sym::ne).then_some("!").unwrap_or_default(),
+ );
+ }
+
if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind
&& !expr.span.from_expansion()
{
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 2ac06b360be..1d41f568f37 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -203,9 +203,11 @@ mod manual_assert;
mod manual_async_fn;
mod manual_bits;
mod manual_clamp;
+mod manual_div_ceil;
mod manual_float_methods;
mod manual_hash_one;
mod manual_is_ascii_check;
+mod manual_is_power_of_two;
mod manual_let_else;
mod manual_main_separator_str;
mod manual_non_exhaustive;
@@ -271,6 +273,7 @@ mod non_copy_const;
mod non_expressive_names;
mod non_octal_unix_permissions;
mod non_send_fields_in_send_ty;
+mod non_zero_suggestions;
mod nonstandard_macro_braces;
mod octal_escapes;
mod only_used_in_recursion;
@@ -287,6 +290,7 @@ mod pass_by_ref_or_value;
mod pathbuf_init_then_push;
mod pattern_type_mismatch;
mod permissions_set_readonly_false;
+mod pointers_in_nomem_asm_block;
mod precedence;
mod ptr;
mod ptr_offset_with_cast;
@@ -372,6 +376,7 @@ mod unused_peekable;
mod unused_result_ok;
mod unused_rounding;
mod unused_self;
+mod unused_trait_names;
mod unused_unit;
mod unwrap;
mod unwrap_in_result;
@@ -386,9 +391,10 @@ mod write;
mod zero_div_zero;
mod zero_repeat_side_effects;
mod zero_sized_map_values;
+mod zombie_processes;
// end lints modules, do not remove this comment, it’s used in `update_lints`
-use clippy_config::{get_configuration_metadata, Conf};
+use clippy_config::{Conf, get_configuration_metadata};
use clippy_utils::macros::FormatArgsStorage;
use rustc_data_structures::fx::FxHashSet;
use rustc_lint::{Lint, LintId};
@@ -623,7 +629,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
store.register_late_pass(|_| Box::new(strings::StringAdd));
store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn));
- store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub));
+ store.register_late_pass(move |_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub::new(conf)));
store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback));
store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor));
store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
@@ -632,8 +638,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
let format_args = format_args_storage.clone();
store.register_late_pass(move |_| Box::new(methods::Methods::new(conf, format_args.clone())));
store.register_late_pass(move |_| Box::new(matches::Matches::new(conf)));
- store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(conf)));
- store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(conf)));
+ store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustive::new(conf)));
store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(conf)));
store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(conf)));
store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(conf)));
@@ -933,5 +938,11 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(set_contains_or_insert::SetContainsOrInsert));
store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice));
store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest));
+ store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses));
+ store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock));
+ store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf)));
+ store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo));
+ store.register_late_pass(|_| Box::new(non_zero_suggestions::NonZeroSuggestions));
+ store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf)));
// add lints here, do not remove this comment, it's used in `new_lint`
}
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index ba34af9c100..755afe959b3 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -3,25 +3,25 @@ use clippy_utils::trait_ref_of_method;
use itertools::Itertools;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
+use rustc_hir::FnRetTy::Return;
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
use rustc_hir::intravisit::{
- walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
- walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
+ Visitor, walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
+ walk_poly_trait_ref, walk_trait_ref, walk_ty,
};
-use rustc_hir::FnRetTy::Return;
use rustc_hir::{
- lang_items, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics,
- Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
- PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+ BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl,
+ ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
+ PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter as middle_nested_filter;
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
-use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
+use rustc_span::symbol::{Ident, Symbol, kw};
use std::ops::ControlFlow;
declare_clippy_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 73a23615c2d..9aa4d2f0adc 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
@@ -1,4 +1,4 @@
-use super::{make_iterator_snippet, IncrementVisitor, InitializeVisitor, EXPLICIT_COUNTER_LOOP};
+use super::{EXPLICIT_COUNTER_LOOP, IncrementVisitor, InitializeVisitor, make_iterator_snippet};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{get_enclosing_block, is_integer_const};
diff --git a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs
index 5b5bb88c179..858e3be5093 100644
--- a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{fn_def_id, is_from_proc_macro, is_lint_allowed};
-use hir::intravisit::{walk_expr, Visitor};
+use hir::intravisit::{Visitor, walk_expr};
use hir::{Expr, ExprKind, FnRetTy, FnSig, Node};
use rustc_ast::Label;
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index b27528c11d4..bfe2e68b5d1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -1,5 +1,5 @@
-use super::utils::make_iterator_snippet;
use super::MANUAL_FIND;
+use super::utils::make_iterator_snippet;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::implements_trait;
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index dbc094a6d73..366c310592f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -1,5 +1,5 @@
-use super::utils::make_iterator_snippet;
use super::MANUAL_FLATTEN;
+use super::utils::make_iterator_snippet;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
index 55d1b9ee676..7476a87267f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
@@ -1,10 +1,10 @@
+use clippy_utils::SpanlessEq;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
-use clippy_utils::SpanlessEq;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp};
use rustc_lint::LateContext;
-use rustc_span::{sym, Symbol, Span};
+use rustc_span::{Span, Symbol, sym};
use std::borrow::Cow;
use super::MANUAL_WHILE_LET_SOME;
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 92ccc0cc0a1..17215621d2a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -22,15 +22,15 @@ mod while_immutable_condition;
mod while_let_loop;
mod while_let_on_iterator;
-use clippy_config::msrvs::Msrv;
use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
use clippy_utils::higher;
use rustc_ast::Label;
use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::Span;
-use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor};
+use utils::{IncrementVisitor, InitializeVisitor, make_iterator_snippet};
declare_clippy_lint! {
/// ### What it does
@@ -188,22 +188,22 @@ declare_clippy_lint! {
/// The `while let` loop is usually shorter and more
/// readable.
///
- /// ### Known problems
- /// Sometimes the wrong binding is displayed ([#383](https://github.com/rust-lang/rust-clippy/issues/383)).
- ///
/// ### Example
/// ```rust,no_run
- /// # let y = Some(1);
+ /// let y = Some(1);
/// loop {
/// let x = match y {
/// Some(x) => x,
/// None => break,
/// };
- /// // .. do something with x
+ /// // ..
/// }
- /// // is easier written as
+ /// ```
+ /// Use instead:
+ /// ```rust,no_run
+ /// let y = Some(1);
/// while let Some(x) = y {
- /// // .. do something with x
+ /// // ..
/// };
/// ```
#[clippy::version = "pre 1.29.0"]
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 e18e4374667..20dd5a311dc 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
@@ -3,17 +3,17 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::has_iter_method;
use clippy_utils::visitors::is_local_used;
-use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
+use clippy_utils::{SpanlessEq, contains_name, higher, is_integer_const, sugg};
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
use rustc_lint::LateContext;
use rustc_middle::middle::region;
use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
use std::{iter, mem};
/// Checks for looping over a range and then indexing a sequence with it.
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 313a5bfefbc..1c55e3e22e8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -1,5 +1,5 @@
-use super::utils::make_iterator_snippet;
use super::NEVER_LOOP;
+use super::utils::make_iterator_snippet;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::ForLoop;
use clippy_utils::macros::root_macro_call_first_node;
@@ -7,7 +7,7 @@ use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::iter::once;
pub(super) fn check<'tcx>(
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 9185cf1f8b2..5662d3013e1 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
@@ -6,11 +6,11 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, Mutability, Node, Pat, PatKind, Stmt, StmtKind};
use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
use rustc_span::SyntaxContext;
+use rustc_span::symbol::sym;
/// Detects for loop pushing the same item into a Vec
pub(super) fn check<'tcx>(
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 2b41911e8ec..70f76ced09a 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
@@ -2,10 +2,10 @@ use super::SINGLE_ELEMENT_LOOP;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, snippet, snippet_with_applicability};
use clippy_utils::visitors::contains_break_or_continue;
-use rustc_ast::util::parser::PREC_PREFIX;
use rustc_ast::Mutability;
+use rustc_ast::util::parser::PREC_PREFIX;
use rustc_errors::Applicability;
-use rustc_hir::{is_range_literal, BorrowKind, Expr, ExprKind, Pat, PatKind};
+use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal};
use rustc_lint::LateContext;
use rustc_span::edition::Edition;
use rustc_span::sym;
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 7b45cc95431..9a89a41d2b3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -2,13 +2,13 @@ use clippy_utils::ty::{has_iter_method, implements_trait};
use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_local, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr, walk_local};
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, LetStmt, Mutability, PatKind};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
#[derive(Debug, PartialEq, Eq)]
enum IncrementVisitorVarState {
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 cc1bd5929d0..eab096e9a22 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
@@ -4,7 +4,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::usage::mutated_variables;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefIdMap;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Expr, ExprKind, HirIdSet, QPath};
use rustc_lint::LateContext;
use std::ops::ControlFlow;
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index c171fa1c622..7d9fbaf3cea 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -5,13 +5,13 @@ use clippy_utils::visitors::is_res_used;
use clippy_utils::{get_enclosing_loop_or_multi_call_closure, higher, is_refutable, is_res_lang_ctor, is_trait_method};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Closure, Expr, ExprKind, HirId, LangItem, LetStmt, Mutability, PatKind, UnOp};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::ty::adjustment::Adjust;
-use rustc_span::symbol::sym;
use rustc_span::Symbol;
+use rustc_span::symbol::sym;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let Some(higher::WhileLet { if_then, let_pat, let_expr, label, .. }) = higher::WhileLet::hir(expr)
diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
index e215097142b..ccc554042d6 100644
--- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs
@@ -3,13 +3,13 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::is_lint_allowed;
use itertools::Itertools;
use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext};
-use std::collections::btree_map::Entry;
+use rustc_span::{Span, SyntaxContext, sym};
use std::collections::BTreeMap;
+use std::collections::btree_map::Entry;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 067384b0901..bd6b3f1a47b 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
use rustc_span::edition::Edition;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::collections::BTreeMap;
declare_clippy_lint! {
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 61723aec590..fc3bba9e512 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{position_before_rarrow, snippet_block, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, position_before_rarrow, snippet_block};
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
@@ -9,7 +9,7 @@ use rustc_hir::{
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs
index 5cbdc7f864a..c0e87e8a1fa 100644
--- a/src/tools/clippy/clippy_lints/src/manual_bits.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_context;
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index 4123c933660..788649fd4f9 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::higher::If;
@@ -7,8 +7,8 @@ use clippy_utils::sugg::Sugg;
use clippy_utils::ty::implements_trait;
use clippy_utils::visitors::is_const_evaluatable;
use clippy_utils::{
- eq_expr_value, is_diag_trait_item, is_in_const_context, is_trait_method, path_res, path_to_local_id, peel_blocks,
- peel_blocks_with_stmt, MaybePath,
+ MaybePath, eq_expr_value, is_diag_trait_item, is_in_const_context, is_trait_method, path_res, path_to_local_id,
+ peel_blocks, peel_blocks_with_stmt,
};
use itertools::Itertools;
use rustc_errors::{Applicability, Diag};
@@ -17,8 +17,8 @@ use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, HirId, PatKind, PathSegme
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use std::cmp::Ordering;
use std::ops::Deref;
diff --git a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
new file mode 100644
index 00000000000..00e02e2a336
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs
@@ -0,0 +1,158 @@
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::SpanlessEq;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
+use rustc_ast::{BinOpKind, LitKind};
+use rustc_data_structures::packed::Pu128;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self};
+use rustc_session::impl_lint_pass;
+use rustc_span::symbol::Symbol;
+
+use clippy_config::Conf;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for an expression like `(x + (y - 1)) / y` which is a common manual reimplementation
+ /// of `x.div_ceil(y)`.
+ ///
+ /// ### Why is this bad?
+ /// It's simpler, clearer and more readable.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// let x: i32 = 7;
+ /// let y: i32 = 4;
+ /// let div = (x + (y - 1)) / y;
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// #![feature(int_roundings)]
+ /// let x: i32 = 7;
+ /// let y: i32 = 4;
+ /// let div = x.div_ceil(y);
+ /// ```
+ #[clippy::version = "1.81.0"]
+ pub MANUAL_DIV_CEIL,
+ complexity,
+ "manually reimplementing `div_ceil`"
+}
+
+pub struct ManualDivCeil {
+ msrv: Msrv,
+}
+
+impl ManualDivCeil {
+ #[must_use]
+ pub fn new(conf: &'static Conf) -> Self {
+ Self {
+ msrv: conf.msrv.clone(),
+ }
+ }
+}
+
+impl_lint_pass!(ManualDivCeil => [MANUAL_DIV_CEIL]);
+
+impl<'tcx> LateLintPass<'tcx> for ManualDivCeil {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+ if !self.msrv.meets(msrvs::MANUAL_DIV_CEIL) {
+ return;
+ }
+
+ let mut applicability = Applicability::MachineApplicable;
+
+ if let ExprKind::Binary(div_op, div_lhs, div_rhs) = expr.kind
+ && div_op.node == BinOpKind::Div
+ && check_int_ty_and_feature(cx, div_lhs)
+ && check_int_ty_and_feature(cx, div_rhs)
+ && let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = div_lhs.kind
+ {
+ // (x + (y - 1)) / y
+ if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind
+ && inner_op.node == BinOpKind::Add
+ && sub_op.node == BinOpKind::Sub
+ && check_literal(sub_rhs)
+ && check_eq_expr(cx, sub_lhs, div_rhs)
+ {
+ build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability);
+ return;
+ }
+
+ // ((y - 1) + x) / y
+ if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_lhs.kind
+ && inner_op.node == BinOpKind::Add
+ && sub_op.node == BinOpKind::Sub
+ && check_literal(sub_rhs)
+ && check_eq_expr(cx, sub_lhs, div_rhs)
+ {
+ build_suggestion(cx, expr, inner_rhs, div_rhs, &mut applicability);
+ return;
+ }
+
+ // (x + y - 1) / y
+ if let ExprKind::Binary(add_op, add_lhs, add_rhs) = inner_lhs.kind
+ && inner_op.node == BinOpKind::Sub
+ && add_op.node == BinOpKind::Add
+ && check_literal(inner_rhs)
+ && check_eq_expr(cx, add_rhs, div_rhs)
+ {
+ build_suggestion(cx, expr, add_lhs, div_rhs, &mut applicability);
+ }
+ }
+ }
+
+ extract_msrv_attr!(LateContext);
+}
+
+fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ let expr_ty = cx.typeck_results().expr_ty(expr);
+ match expr_ty.peel_refs().kind() {
+ ty::Uint(_) => true,
+ ty::Int(_) => cx
+ .tcx
+ .features()
+ .declared_features
+ .contains(&Symbol::intern("int_roundings")),
+
+ _ => false,
+ }
+}
+
+fn check_literal(expr: &Expr<'_>) -> bool {
+ if let ExprKind::Lit(lit) = expr.kind
+ && let LitKind::Int(Pu128(1), _) = lit.node
+ {
+ return true;
+ }
+ false
+}
+
+fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
+ SpanlessEq::new(cx).eq_expr(lhs, rhs)
+}
+
+fn build_suggestion(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ lhs: &Expr<'_>,
+ rhs: &Expr<'_>,
+ applicability: &mut Applicability,
+) {
+ let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_par();
+ let divisor_snippet = snippet_with_applicability(cx, rhs.span.source_callsite(), "..", applicability);
+
+ let sugg = format!("{dividend_sugg}.div_ceil({divisor_snippet})");
+
+ span_lint_and_sugg(
+ cx,
+ MANUAL_DIV_CEIL,
+ expr.span,
+ "manually reimplementing `div_ceil`",
+ "consider using `.div_ceil()`",
+ sugg,
+ *applicability,
+ );
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
index 11716a539ab..c62bd65bea6 100644
--- a/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_hash_one.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::visitors::{is_local_used, local_used_once};
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 31c37c3bc3b..24207705743 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,17 +1,17 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::sugg::Sugg;
use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators};
-use rustc_ast::ast::RangeLimits;
use rustc_ast::LitKind::{Byte, Char};
+use rustc_ast::ast::RangeLimits;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
new file mode 100644
index 00000000000..da2a982ee17
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs
@@ -0,0 +1,142 @@
+use clippy_utils::SpanlessEq;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use rustc_ast::LitKind;
+use rustc_data_structures::packed::Pu128;
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Uint;
+use rustc_session::declare_lint_pass;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, with x and unsigned integer, which are manual
+ /// reimplementations of `x.is_power_of_two()`.
+ /// ### Why is this bad?
+ /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit.
+ /// ### Example
+ /// ```no_run
+ /// let a: u32 = 4;
+ /// let result = a.count_ones() == 1;
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// let a: u32 = 4;
+ /// let result = a.is_power_of_two();
+ /// ```
+ #[clippy::version = "1.82.0"]
+ pub MANUAL_IS_POWER_OF_TWO,
+ complexity,
+ "manually reimplementing `is_power_of_two`"
+}
+
+declare_lint_pass!(ManualIsPowerOfTwo => [MANUAL_IS_POWER_OF_TWO]);
+
+impl LateLintPass<'_> for ManualIsPowerOfTwo {
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+ let mut applicability = Applicability::MachineApplicable;
+
+ if let ExprKind::Binary(bin_op, left, right) = expr.kind
+ && bin_op.node == BinOpKind::Eq
+ {
+ // a.count_ones() == 1
+ if let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind
+ && method_name.ident.as_str() == "count_ones"
+ && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
+ && check_lit(right, 1)
+ {
+ build_sugg(cx, expr, reciever, &mut applicability);
+ }
+
+ // 1 == a.count_ones()
+ if let ExprKind::MethodCall(method_name, reciever, _, _) = right.kind
+ && method_name.ident.as_str() == "count_ones"
+ && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind()
+ && check_lit(left, 1)
+ {
+ build_sugg(cx, expr, reciever, &mut applicability);
+ }
+
+ // a & (a - 1) == 0
+ if let ExprKind::Binary(op1, left1, right1) = left.kind
+ && op1.node == BinOpKind::BitAnd
+ && let ExprKind::Binary(op2, left2, right2) = right1.kind
+ && op2.node == BinOpKind::Sub
+ && check_eq_expr(cx, left1, left2)
+ && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
+ && check_lit(right2, 1)
+ && check_lit(right, 0)
+ {
+ build_sugg(cx, expr, left1, &mut applicability);
+ }
+
+ // (a - 1) & a == 0;
+ if let ExprKind::Binary(op1, left1, right1) = left.kind
+ && op1.node == BinOpKind::BitAnd
+ && let ExprKind::Binary(op2, left2, right2) = left1.kind
+ && op2.node == BinOpKind::Sub
+ && check_eq_expr(cx, right1, left2)
+ && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind()
+ && check_lit(right2, 1)
+ && check_lit(right, 0)
+ {
+ build_sugg(cx, expr, right1, &mut applicability);
+ }
+
+ // 0 == a & (a - 1);
+ if let ExprKind::Binary(op1, left1, right1) = right.kind
+ && op1.node == BinOpKind::BitAnd
+ && let ExprKind::Binary(op2, left2, right2) = right1.kind
+ && op2.node == BinOpKind::Sub
+ && check_eq_expr(cx, left1, left2)
+ && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind()
+ && check_lit(right2, 1)
+ && check_lit(left, 0)
+ {
+ build_sugg(cx, expr, left1, &mut applicability);
+ }
+
+ // 0 == (a - 1) & a
+ if let ExprKind::Binary(op1, left1, right1) = right.kind
+ && op1.node == BinOpKind::BitAnd
+ && let ExprKind::Binary(op2, left2, right2) = left1.kind
+ && op2.node == BinOpKind::Sub
+ && check_eq_expr(cx, right1, left2)
+ && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind()
+ && check_lit(right2, 1)
+ && check_lit(left, 0)
+ {
+ build_sugg(cx, expr, right1, &mut applicability);
+ }
+ }
+ }
+}
+
+fn build_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, reciever: &Expr<'_>, applicability: &mut Applicability) {
+ let snippet = snippet_with_applicability(cx, reciever.span, "..", applicability);
+
+ span_lint_and_sugg(
+ cx,
+ MANUAL_IS_POWER_OF_TWO,
+ expr.span,
+ "manually reimplementing `is_power_of_two`",
+ "consider using `.is_power_of_two()`",
+ format!("{snippet}.is_power_of_two()"),
+ *applicability,
+ );
+}
+
+fn check_lit(expr: &Expr<'_>, expected_num: u128) -> bool {
+ if let ExprKind::Lit(lit) = expr.kind
+ && let LitKind::Int(Pu128(num), _) = lit.node
+ && num == expected_num
+ {
+ return true;
+ }
+ false
+}
+
+fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool {
+ SpanlessEq::new(cx).eq_expr(lhs, rhs)
+}
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 ebebdf679a8..17185df5d76 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -1,4 +1,4 @@
-use crate::question_mark::{QuestionMark, QUESTION_MARK};
+use crate::question_mark::{QUESTION_MARK, QuestionMark};
use clippy_config::msrvs;
use clippy_config::types::MatchLintBehaviour;
use clippy_utils::diagnostics::span_lint_and_then;
@@ -12,8 +12,8 @@ use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
-use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{Symbol, sym};
use std::slice;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
index 5198d7838a2..85e99a92cf5 100644
--- a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{is_trait_method, peel_hir_expr_refs};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 6b1d90483cc..25868ccae40 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -1,18 +1,18 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::is_doc_hidden;
-use clippy_utils::source::SpanRangeExt;
-use rustc_ast::ast::{self, VisibilityKind};
+use clippy_utils::source::snippet_indent;
+use itertools::Itertools;
use rustc_ast::attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::{self as hir, Expr, ExprKind, QPath};
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData};
+use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{DefId, LocalDefId};
-use rustc_span::{sym, Span};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
@@ -62,29 +62,13 @@ declare_clippy_lint! {
"manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
}
-#[expect(clippy::module_name_repetitions)]
-pub struct ManualNonExhaustiveStruct {
+pub struct ManualNonExhaustive {
msrv: Msrv,
-}
-
-impl ManualNonExhaustiveStruct {
- pub fn new(conf: &'static Conf) -> Self {
- Self {
- msrv: conf.msrv.clone(),
- }
- }
-}
-
-impl_lint_pass!(ManualNonExhaustiveStruct => [MANUAL_NON_EXHAUSTIVE]);
-
-#[expect(clippy::module_name_repetitions)]
-pub struct ManualNonExhaustiveEnum {
- msrv: Msrv,
- constructed_enum_variants: FxHashSet<(DefId, DefId)>,
+ constructed_enum_variants: FxHashSet<LocalDefId>,
potential_enums: Vec<(LocalDefId, LocalDefId, Span, Span)>,
}
-impl ManualNonExhaustiveEnum {
+impl ManualNonExhaustive {
pub fn new(conf: &'static Conf) -> Self {
Self {
msrv: conf.msrv.clone(),
@@ -94,96 +78,78 @@ impl ManualNonExhaustiveEnum {
}
}
-impl_lint_pass!(ManualNonExhaustiveEnum => [MANUAL_NON_EXHAUSTIVE]);
-
-impl EarlyLintPass for ManualNonExhaustiveStruct {
- fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
- if let ast::ItemKind::Struct(variant_data, _) = &item.kind
- && let (fields, delimiter) = match variant_data {
- ast::VariantData::Struct { fields, .. } => (&**fields, '{'),
- ast::VariantData::Tuple(fields, _) => (&**fields, '('),
- ast::VariantData::Unit(_) => return,
- }
- && fields.len() > 1
- && self.msrv.meets(msrvs::NON_EXHAUSTIVE)
- {
- let mut iter = fields.iter().filter_map(|f| match f.vis.kind {
- VisibilityKind::Public => None,
- VisibilityKind::Inherited => Some(Ok(f)),
- VisibilityKind::Restricted { .. } => Some(Err(())),
- });
- if let Some(Ok(field)) = iter.next()
- && iter.next().is_none()
- && field.ty.kind.is_unit()
- {
- span_lint_and_then(
- cx,
- MANUAL_NON_EXHAUSTIVE,
- item.span,
- "this seems like a manual implementation of the non-exhaustive pattern",
- |diag| {
- if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive))
- && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter)
- && let Some(snippet) = header_span.get_source_text(cx)
- {
- diag.span_suggestion(
- header_span,
- "add the attribute",
- format!("#[non_exhaustive] {snippet}"),
- Applicability::Unspecified,
- );
- }
- diag.span_help(field.span, "remove this field");
- },
- );
- }
- }
- }
-
- extract_msrv_attr!(EarlyContext);
-}
+impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
-impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
- fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
- if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) {
+impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+ if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) || !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
return;
}
- if let hir::ItemKind::Enum(def, _) = &item.kind
- && def.variants.len() > 1
- {
- let mut iter = def.variants.iter().filter_map(|v| {
- (matches!(v.data, hir::VariantData::Unit(_, _))
- && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id))
- && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive))
- .then_some((v.def_id, v.span))
- });
- if let Some((id, span)) = iter.next()
- && iter.next().is_none()
- {
- self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
- }
+ match item.kind {
+ ItemKind::Enum(def, _) if def.variants.len() > 1 => {
+ let iter = def.variants.iter().filter_map(|v| {
+ (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
+ .then_some((v.def_id, v.span))
+ });
+ if let Ok((id, span)) = iter.exactly_one()
+ && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+ {
+ self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
+ }
+ },
+ ItemKind::Struct(variant_data, _) => {
+ let fields = variant_data.fields();
+ let private_fields = fields
+ .iter()
+ .filter(|field| !cx.effective_visibilities.is_exported(field.def_id));
+ if fields.len() > 1
+ && let Ok(field) = private_fields.exactly_one()
+ && let TyKind::Tup([]) = field.ty.kind
+ {
+ span_lint_and_then(
+ cx,
+ MANUAL_NON_EXHAUSTIVE,
+ item.span,
+ "this seems like a manual implementation of the non-exhaustive pattern",
+ |diag| {
+ if let Some(non_exhaustive) =
+ attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+ {
+ diag.span_note(non_exhaustive.span, "the struct is already non-exhaustive");
+ } else {
+ let indent = snippet_indent(cx, item.span).unwrap_or_default();
+ diag.span_suggestion_verbose(
+ item.span.shrink_to_lo(),
+ "use the `#[non_exhaustive]` attribute instead",
+ format!("#[non_exhaustive]\n{indent}"),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ diag.span_help(field.span, "remove this field");
+ },
+ );
+ }
+ },
+ _ => {},
}
}
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if let ExprKind::Path(QPath::Resolved(None, p)) = &e.kind
- && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res
+ && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), ctor_id) = p.res
+ && let Some(local_ctor) = ctor_id.as_local()
{
- let variant_id = cx.tcx.parent(id);
- let enum_id = cx.tcx.parent(variant_id);
-
- self.constructed_enum_variants.insert((enum_id, variant_id));
+ let variant_id = cx.tcx.local_parent(local_ctor);
+ self.constructed_enum_variants.insert(variant_id);
}
}
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
- for &(enum_id, _, enum_span, variant_span) in
- self.potential_enums.iter().filter(|&&(enum_id, variant_id, _, _)| {
- !self
- .constructed_enum_variants
- .contains(&(enum_id.to_def_id(), variant_id.to_def_id()))
- })
+ for &(enum_id, _, enum_span, variant_span) in self
+ .potential_enums
+ .iter()
+ .filter(|(_, variant_id, _, _)| !self.constructed_enum_variants.contains(variant_id))
{
let hir_id = cx.tcx.local_def_id_to_hir_id(enum_id);
span_lint_hir_and_then(
@@ -193,15 +159,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
enum_span,
"this seems like a manual implementation of the non-exhaustive pattern",
|diag| {
- let header_span = cx.sess().source_map().span_until_char(enum_span, '{');
- if let Some(snippet) = header_span.get_source_text(cx) {
- diag.span_suggestion(
- header_span,
- "add the attribute",
- format!("#[non_exhaustive] {snippet}"),
- Applicability::Unspecified,
- );
- }
+ let indent = snippet_indent(cx, enum_span).unwrap_or_default();
+ diag.span_suggestion_verbose(
+ enum_span.shrink_to_lo(),
+ "use the `#[non_exhaustive]` attribute instead",
+ format!("#[non_exhaustive]\n{indent}"),
+ Applicability::MaybeIncorrect,
+ );
diag.span_help(variant_span, "remove this variant");
},
);
diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
index 9afb2b5bc84..ffa3eacf354 100644
--- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
@@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span};
declare_clippy_lint! {
/// ### What it does
@@ -77,9 +77,10 @@ impl Num {
impl LateLintPass<'_> for ManualRangePatterns {
fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) {
// a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives
- // or at least one range
+ // or more then one range (exclude triggering on stylistic using OR with one element
+ // like described https://github.com/rust-lang/rust-clippy/issues/11825)
if let PatKind::Or(pats) = pat.kind
- && (pats.len() >= 3 || pats.iter().any(|p| matches!(p.kind, PatKind::Range(..))))
+ && (pats.len() >= 3 || (pats.len() > 1 && pats.iter().any(|p| matches!(p.kind, PatKind::Range(..)))))
&& !in_external_macro(cx.sess(), pat.span)
{
let mut min = Num::dummy(i128::MAX);
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 6cf5d272d7d..86293169ea2 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index a35b0f914e0..a60163be770 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -1,17 +1,17 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::SpanlessEq;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
-use clippy_utils::SpanlessEq;
use rustc_errors::Applicability;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
use rustc_hir::ExprKind::Assign;
+use rustc_hir::def_id::DefId;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{Symbol, sym};
const ACCEPTABLE_METHODS: [Symbol; 5] = [
sym::binaryheap_iter,
diff --git a/src/tools/clippy/clippy_lints/src/manual_string_new.rs b/src/tools/clippy/clippy_lints/src/manual_string_new.rs
index 781db4b97f0..198f7aaddc7 100644
--- a/src/tools/clippy/clippy_lints/src/manual_string_new.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_string_new.rs
@@ -5,7 +5,7 @@ use rustc_hir::{Expr, ExprKind, PathSegment, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, symbol, Span};
+use rustc_span::{Span, sym, symbol};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 02d433ecc5a..9aceca66bf7 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
@@ -8,13 +8,13 @@ use clippy_utils::{eq_expr_value, higher};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::iter;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index 2db71b1f7a3..a97dbbbc33f 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
index b666e77c09e..50e6dfc6298 100644
--- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
@@ -4,7 +4,7 @@ use clippy_utils::higher::IfLetOrMatch;
use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{
- is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq,
+ SpanlessEq, is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators,
};
use rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone;
@@ -12,7 +12,7 @@ use rustc_hir::{Arm, Expr, HirId, Pat, PatKind};
use rustc_lint::LateContext;
use rustc_span::Span;
-use super::{pat_contains_disallowed_or, COLLAPSIBLE_MATCH};
+use super::{COLLAPSIBLE_MATCH, pat_contains_disallowed_or};
pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], msrv: &Msrv) {
if let Some(els_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) {
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 619ec83127a..cfa054706d6 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
@@ -6,10 +6,10 @@ use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind};
use rustc_lint::LateContext;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
-use super::manual_utils::{check_with, SomeExpr};
use super::MANUAL_FILTER;
+use super::manual_utils::{SomeExpr, check_with};
// Function called on the <expr> of `[&+]Some((ref | ref mut) x) => <expr>`
// Need to check if it's of the form `<expr>=if <cond> {<then_expr>} else {<else_expr>}`
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_map.rs b/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
index ed3d8b09fdc..de57d1eee92 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
@@ -1,5 +1,5 @@
-use super::manual_utils::{check_with, SomeExpr};
use super::MANUAL_MAP;
+use super::manual_utils::{SomeExpr, check_with};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{is_res_lang_ctor, path_res};
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index d5d83df9347..59d37520011 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -1,12 +1,12 @@
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
use rustc_errors::Applicability;
-use rustc_hir::def::{DefKind, Res};
use rustc_hir::LangItem::{OptionNone, ResultErr};
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Arm, Expr, Pat, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
index be80aebed6d..d38560998a5 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
@@ -4,16 +4,16 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
use clippy_utils::{
- can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
- peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
+ CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res,
+ path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while,
};
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
use rustc_errors::Applicability;
-use rustc_hir::def::Res;
use rustc_hir::LangItem::{OptionNone, OptionSome};
+use rustc_hir::def::Res;
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
use rustc_lint::LateContext;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
#[expect(clippy::too_many_arguments)]
#[expect(clippy::too_many_lines)]
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 da8c918a62b..f9ffbc5dc0b 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
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash};
+use clippy_utils::{SpanlessEq, SpanlessHash, is_lint_allowed, path_to_local, search_same};
use core::cmp::Ordering;
use core::{iter, slice};
use rustc_arena::DroplessArena;
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
index 322e9c3ebe5..40518ce2ca7 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -2,12 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::is_type_lang_item;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use rustc_span::symbol::Symbol;
use super::MATCH_STR_CASE_MISMATCH;
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index cf5377e0725..686fc4a0fa0 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -24,8 +24,8 @@ mod single_match;
mod try_err;
mod wild_in_or_pats;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::source::walk_span_to_context;
use clippy_utils::{higher, is_direct_expn_of, is_in_const_context, is_span_match, span_contains_cfg};
use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind};
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 71f211be925..6a4c553cee0 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{mir_to_const, ConstEvalCtxt, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, FullInt, mir_to_const};
use clippy_utils::diagnostics::span_lint_and_note;
use core::cmp::Ordering;
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index 8222c3057f7..564c598a334 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -10,11 +10,11 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, MatchSource, Node, PatKind, UnOp};
use rustc_lint::LateContext;
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
use std::borrow::Cow;
use std::ops::ControlFlow;
-use super::{pat_contains_disallowed_or, REDUNDANT_GUARDS};
+use super::{REDUNDANT_GUARDS, pat_contains_disallowed_or};
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: &Msrv) {
for outer_arm in arms {
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index 0e4b2d9d34a..b646e87a439 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -1,18 +1,18 @@
use super::REDUNDANT_PATTERN_MATCHING;
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, walk_span_to_context};
-use clippy_utils::sugg::{make_unop, Sugg};
+use clippy_utils::sugg::{Sugg, make_unop};
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr_without_closures};
use clippy_utils::{higher, is_expn_of, is_trait_method};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
-use rustc_hir::def::{DefKind, Res};
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, GenericArgKind, Ty};
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
use std::fmt::Write;
use std::ops::ControlFlow;
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 9c2f42d2187..537f7272f7f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -8,7 +8,7 @@ use clippy_utils::{get_attr, is_lint_allowed};
use itertools::Itertools;
use rustc_ast::Mutability;
use rustc_errors::{Applicability, Diag};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Arm, Expr, ExprKind, MatchSource};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty::{GenericArgKind, Region, RegionKind, Ty, TyCtxt, TypeVisitable, TypeVisitor};
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index b6930f7b9d1..2eda238ae8c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{expr_block, snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, expr_block, snippet, snippet_block_with_context};
use clippy_utils::ty::implements_trait;
use clippy_utils::{
is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
@@ -8,11 +8,11 @@ use core::ops::ControlFlow;
use rustc_arena::DroplessArena;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_pat, Visitor};
-use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind, QPath};
+use rustc_hir::intravisit::{Visitor, walk_pat};
+use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
@@ -91,6 +91,29 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
});
+ if snippet(cx, ex.span, "..") == snippet(cx, arm.pat.span, "..") {
+ let msg = "this pattern is irrefutable, `match` is useless";
+ let (sugg, help) = if is_unit_expr(arm.body) {
+ (String::new(), "`match` expression can be removed")
+ } else {
+ let mut sugg = snippet_block_with_context(cx, arm.body.span, ctxt, "..", Some(expr.span), &mut app)
+ .0
+ .to_string();
+ if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
+ && let StmtKind::Expr(_) = stmt.kind
+ && match arm.body.kind {
+ ExprKind::Block(block, _) => block.span.from_expansion(),
+ _ => true,
+ }
+ {
+ sugg.push(';');
+ }
+ (sugg, "try")
+ };
+ span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg.to_string(), app);
+ return;
+ }
+
let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
&& let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index 72a5945ad9b..146748734cf 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
@@ -13,8 +13,8 @@ use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 2a8a5fcc3b6..91a5de16e96 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -1,4 +1,4 @@
-use super::{contains_return, BIND_INSTEAD_OF_MAP};
+use super::{BIND_INSTEAD_OF_MAP, contains_return};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::peel_blocks;
use clippy_utils::source::{snippet, snippet_with_context};
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 740cce0a6c2..76bdbe55e2f 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,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
use clippy_utils::ty::is_type_lang_item;
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;
use rustc_span::Span;
+use rustc_span::source_map::Spanned;
use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
diff --git a/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs
index 5389861245a..6e24cabca8b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs
@@ -4,8 +4,8 @@ use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, QPath};
use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use super::CLEAR_WITH_DRAIN;
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 e7a2060be04..79a473e0e6f 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
@@ -7,7 +7,7 @@ use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::{self};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
use super::CLONE_ON_COPY;
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
index e0826b53004..96e2de0dc1c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
use super::CLONE_ON_REF_PTR;
diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
index fcafa162236..fa04f74eec1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::CLONED_INSTEAD_OF_COPIED;
diff --git a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
index 1fab6c0e499..f7bf8764bde 100644
--- a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_lint::LateContext;
use std::collections::VecDeque;
-use super::{method_call, COLLAPSIBLE_STR_REPLACE};
+use super::{COLLAPSIBLE_STR_REPLACE, method_call};
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs b/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
index 56171a13452..10360b4817b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::Ty;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
/// Checks if both types match the given diagnostic item, e.g.:
///
diff --git a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
index dc978c8a584..3b1adb16b80 100644
--- a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::Ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
pub(super) fn check(
cx: &LateContext<'_>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index c9f56e1d980..2922086522c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{format_args_inputs_span, root_macro_call_first_node, FormatArgsStorage};
+use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span, root_macro_call_first_node};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use std::borrow::Cow;
use super::EXPECT_FUN_CALL;
diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
index 2ab0401947c..35008c39c08 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
@@ -3,7 +3,7 @@ use clippy_utils::get_parent_expr;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::FILETYPE_IS_FILE;
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 02a11257007..06482a743dd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::macros::{is_panic, matching_root_macro_call, root_macro_call};
use clippy_utils::source::{indent_of, reindent_multiline, snippet};
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{higher, is_trait_method, path_to_local_id, peel_blocks, SpanlessEq};
+use clippy_utils::{SpanlessEq, higher, is_trait_method, path_to_local_id, peel_blocks};
use hir::{Body, HirId, MatchSource, Pat};
use rustc_errors::Applicability;
use rustc_hir as hir;
@@ -10,8 +10,8 @@ use rustc_hir::def::Res;
use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
-use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, sym};
use std::borrow::Cow;
use super::{MANUAL_FILTER_MAP, MANUAL_FIND_MAP, OPTION_FILTER_MAP, RESULT_FILTER_MAP};
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
index 77a62fbb4fb..129e6925428 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -7,9 +7,9 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::Binder;
-use rustc_span::{sym, Span};
+use rustc_middle::ty::adjustment::Adjust;
+use rustc_span::{Span, sym};
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &Expr<'_>, call_span: Span) {
if !in_external_macro(cx.sess(), expr.span)
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
index 999df875c75..cf7f276dabb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_identity.rs
@@ -3,7 +3,7 @@ use clippy_utils::{is_expr_identity_function, is_expr_untyped_identity_function,
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::FILTER_MAP_IDENTITY;
diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
index 651ea34f9d0..0c2ecfbc8ff 100644
--- a/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_identity.rs
@@ -3,7 +3,7 @@ use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::FLAT_MAP_IDENTITY;
diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs
index 0a4a381b861..3242dcadb70 100644
--- a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs
@@ -4,7 +4,7 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::FLAT_MAP_OPTION;
use clippy_utils::ty::is_type_diagnostic_item;
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
index 62037651134..5f6fb4c821d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_integer_literal, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_integer_literal};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
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 230a8eb2ec4..4ed7de81ea3 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
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{Symbol, sym};
use super::INEFFICIENT_TO_STRING;
diff --git a/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs b/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs
index ad4b6fa130e..3706f3b670b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inspect_for_each.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_trait_method;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::INSPECT_FOR_EACH;
diff --git a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
index bbc7ce8d78a..bedeb63367d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -5,8 +5,8 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{Symbol, sym};
use super::INTO_ITER_ON_REF;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
index b93d51eac64..f6612c984a7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
@@ -10,8 +10,8 @@ use clippy_utils::{get_parent_expr, is_trait_method, peel_blocks, span_contains_
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::QPath;
-use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, sym};
use std::borrow::Cow;
///
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 33de3b87abc..390dd24b505 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
@@ -14,7 +14,6 @@ use rustc_span::sym;
/// - `hashmap.into_iter().map(|(_, v)| v)`
///
/// on `HashMaps` and `BTreeMaps` in std
-
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
map_type: &'tcx str, // iter / into_iter
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
index e31fa2f777d..82bda5d9512 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
@@ -3,8 +3,8 @@ use clippy_utils::ty::get_type_diagnostic_name;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use super::ITER_NTH;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index 7f6b666e434..9d562f5e51d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -5,9 +5,9 @@ use clippy_utils::source::snippet;
use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core};
use rustc_errors::Applicability;
+use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::def_id::DefId;
use rustc_hir::hir_id::HirId;
-use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind, Node};
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
index 1378a07cbc4..16305871337 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
@@ -3,8 +3,8 @@ use clippy_utils::is_range_full;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use super::ITER_WITH_DRAIN;
diff --git a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs
index 2dad7fcf3c1..2ad070793cb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs
@@ -6,8 +6,8 @@ use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use super::JOIN_ABSOLUTE_PATHS;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs
index cb9fb373c10..96af9db1af7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs
@@ -6,7 +6,7 @@ use rustc_ast::{LitKind, StrStyle};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Node, QPath, TyKind};
use rustc_lint::LateContext;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
use super::MANUAL_C_STR_LITERALS;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
index cac2e11f591..64c19c327b2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs
@@ -3,13 +3,13 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{IntoSpan, SpanRangeExt};
use clippy_utils::ty::get_field_by_name;
use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures};
-use clippy_utils::{expr_use_ctxt, is_diag_item_method, is_diag_trait_item, path_to_local_id, ExprUseNode};
+use clippy_utils::{ExprUseNode, expr_use_ctxt, is_diag_item_method, is_diag_trait_item, path_to_local_id};
use core::ops::ControlFlow;
use rustc_errors::Applicability;
use rustc_hir::{BindingMode, BorrowKind, ByRef, ClosureKind, Expr, ExprKind, Mutability, Node, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use super::MANUAL_INSPECT;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
index d29acd4622a..c377abd6237 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_errors::Applicability;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::MANUAL_IS_VARIANT_AND;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
index b1a8e1e5e47..4321dd6b0e0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{indent_of, reindent_multiline, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, indent_of, reindent_multiline};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
index 11fba35c16e..31449d41770 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::MANUAL_TRY_FOLD;
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 08ce7e204dd..ac378ff3702 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::Mutability;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::MAP_CLONE;
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
index 22a03825194..07a7a12b162 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
@@ -6,8 +6,8 @@ use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use super::MAP_FLATTEN;
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
index 5dd7b1b02ad..1f204de01da 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
@@ -4,7 +4,7 @@ use clippy_utils::{is_expr_untyped_identity_function, is_trait_method};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::MAP_IDENTITY;
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index f61bb3a6bf4..7696dd16b25 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -111,6 +111,7 @@ mod uninit_assumed_init;
mod unit_hash;
mod unnecessary_fallible_conversions;
mod unnecessary_filter_map;
+mod unnecessary_first_then_check;
mod unnecessary_fold;
mod unnecessary_get_then_check;
mod unnecessary_iter_cloned;
@@ -131,8 +132,8 @@ mod waker_clone_wake;
mod wrong_self_convention;
mod zst_offset;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::macros::FormatArgsStorage;
@@ -146,7 +147,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, TraitRef, Ty};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
@@ -441,6 +442,17 @@ declare_clippy_lint! {
/// }
/// }
/// ```
+ ///
+ /// Use instead:
+ /// ```no_run
+ /// # struct X;
+ /// impl X {
+ /// fn as_str(&self) -> &'static str {
+ /// // ..
+ /// # ""
+ /// }
+ /// }
+ /// ```
#[clippy::version = "pre 1.29.0"]
pub WRONG_SELF_CONVENTION,
style,
@@ -3964,7 +3976,7 @@ declare_clippy_lint! {
/// ```no_run
/// let _ = 0;
/// ```
- #[clippy::version = "1.78.0"]
+ #[clippy::version = "1.81.0"]
pub UNNECESSARY_MIN_OR_MAX,
complexity,
"using 'min()/max()' when there is no need for it"
@@ -4025,7 +4037,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.78.0"]
pub MANUAL_C_STR_LITERALS,
- pedantic,
+ complexity,
r#"creating a `CStr` through functions when `c""` literals can be used"#
}
@@ -4099,7 +4111,7 @@ declare_clippy_lint! {
/// ```no_run
/// "foo".is_ascii();
/// ```
- #[clippy::version = "1.80.0"]
+ #[clippy::version = "1.81.0"]
pub NEEDLESS_CHARACTER_ITERATION,
suspicious,
"is_ascii() called on a char iterator"
@@ -4126,6 +4138,34 @@ declare_clippy_lint! {
"use of `map` returning the original item"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks the usage of `.first().is_some()` or `.first().is_none()` to check if a slice is
+ /// empty.
+ ///
+ /// ### Why is this bad?
+ /// Using `.is_empty()` is shorter and better communicates the intention.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// let v = vec![1, 2, 3];
+ /// if v.first().is_none() {
+ /// // The vector is empty...
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// let v = vec![1, 2, 3];
+ /// if v.is_empty() {
+ /// // The vector is empty...
+ /// }
+ /// ```
+ #[clippy::version = "1.83.0"]
+ pub UNNECESSARY_FIRST_THEN_CHECK,
+ complexity,
+ "calling `.first().is_some()` or `.first().is_none()` instead of `.is_empty()`"
+}
+
pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Msrv,
@@ -4283,6 +4323,7 @@ impl_lint_pass!(Methods => [
UNNECESSARY_RESULT_MAP_OR_ELSE,
MANUAL_C_STR_LITERALS,
UNNECESSARY_GET_THEN_CHECK,
+ UNNECESSARY_FIRST_THEN_CHECK,
NEEDLESS_CHARACTER_ITERATION,
MANUAL_INSPECT,
UNNECESSARY_MIN_OR_MAX,
@@ -5055,6 +5096,9 @@ fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>,
Some(("get", f_recv, [arg], _, _)) => {
unnecessary_get_then_check::check(cx, call_span, recv, f_recv, arg, is_some);
},
+ Some(("first", f_recv, [], _, _)) => {
+ unnecessary_first_then_check::check(cx, call_span, recv, f_recv, is_some);
+ },
_ => {},
}
}
@@ -5130,12 +5174,9 @@ impl ShouldImplTraitCase {
fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
self.lint_explicit_lifetime
|| !impl_item.generics.params.iter().any(|p| {
- matches!(
- p.kind,
- hir::GenericParamKind::Lifetime {
- kind: hir::LifetimeParamKind::Explicit
- }
- )
+ matches!(p.kind, hir::GenericParamKind::Lifetime {
+ kind: hir::LifetimeParamKind::Explicit
+ })
})
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
index 1a0fce2876d..83e8370f939 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability};
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::MUT_MUTEX_LOCK;
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
index 332da722a37..348f740e7dd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs
@@ -4,8 +4,8 @@ use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::Span;
-use super::utils::get_last_chain_binding_hir_id;
use super::NEEDLESS_CHARACTER_ITERATION;
+use super::utils::get_last_chain_binding_hir_id;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::SpanRangeExt;
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks};
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 f61923e5bf5..421c7a5e070 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -4,12 +4,12 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{get_type_diagnostic_name, make_normalized_projection, make_projection};
use clippy_utils::{
- can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local, path_to_local_id,
- CaptureKind,
+ CaptureKind, can_move_expr_to_closure, fn_def_id, get_enclosing_block, higher, is_trait_method, path_to_local,
+ path_to_local_id,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
use rustc_hir::{
BindingMode, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, PatKind, Stmt, StmtKind,
};
@@ -17,7 +17,7 @@ use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs
index 9f714fdd47b..538aa9097a4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_option_as_deref.rs
@@ -4,8 +4,8 @@ use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::local_used_after_expr;
use rustc_errors::Applicability;
-use rustc_hir::def::Res;
use rustc_hir::Expr;
+use rustc_hir::def::Res;
use rustc_lint::LateContext;
use rustc_span::sym;
diff --git a/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs b/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs
index a301a5f7d65..32f32f1b216 100644
--- a/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/no_effect_replace.rs
@@ -1,6 +1,6 @@
+use clippy_utils::SpanlessEq;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::SpanlessEq;
use rustc_ast::LitKind;
use rustc_hir::{ExprKind, LangItem};
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index f1a3c81cebb..da084871402 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS};
@@ -126,17 +126,13 @@ fn get_open_options(
&& let ExprKind::Path(path) = callee.kind
&& let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id()
{
- let std_file_options = [
- sym::file_options,
- sym::open_options_new,
- ];
+ let std_file_options = [sym::file_options, sym::open_options_new];
- let tokio_file_options: &[&[&str]] = &[
- &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
- &paths::TOKIO_FILE_OPTIONS,
- ];
+ let tokio_file_options: &[&[&str]] = &[&paths::TOKIO_IO_OPEN_OPTIONS_NEW, &paths::TOKIO_FILE_OPTIONS];
- let is_std_options = std_file_options.into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, did));
+ let is_std_options = std_file_options
+ .into_iter()
+ .any(|sym| cx.tcx.is_diagnostic_item(sym, did));
is_std_options || match_any_def_paths(cx, did, tokio_file_options).is_some()
} else {
false
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs
index ba167f9d9c2..9b22494888f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs
@@ -3,9 +3,9 @@ use clippy_utils::ty::is_type_diagnostic_item;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
-use super::{method_call, OPTION_AS_REF_CLONED};
+use super::{OPTION_AS_REF_CLONED, method_call};
pub(super) fn check(cx: &LateContext<'_>, cloned_recv: &Expr<'_>, cloned_ident_span: Span) {
if let Some((method @ ("as_ref" | "as_mut"), as_ref_recv, [], as_ref_ident_span, _)) = method_call(cloned_recv)
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 9a18d8a1421..389e02056b2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
use super::OPTION_AS_REF_DEREF;
@@ -48,7 +48,9 @@ pub(super) fn check(
.map_or(false, |fun_def_id| {
cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
- || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
+ || deref_aliases
+ .iter()
+ .any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
})
},
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
@@ -69,7 +71,9 @@ pub(super) fn check(
let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
- || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
+ || deref_aliases
+ .iter()
+ .any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
} else {
false
}
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 ed3bed42eb3..b160ab6de8e 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
@@ -5,11 +5,11 @@ use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_path};
use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::ops::ControlFlow;
use super::MAP_UNWRAP_OR;
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index e4326cb958e..8a7e72b63bb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -11,8 +11,8 @@ use clippy_utils::{
use rustc_errors::Applicability;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::symbol::{self, sym, Symbol};
use rustc_span::Span;
+use rustc_span::symbol::{self, Symbol, sym};
use {rustc_ast as ast, rustc_hir as hir};
use super::{OR_FUN_CALL, UNWRAP_OR_DEFAULT};
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
index 7b0bdcf99e7..3e64e15dc86 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::OR_THEN_UNWRAP;
diff --git a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs
index 28ca76832eb..f4d206c5307 100644
--- a/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/range_zip_with_len.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet;
-use clippy_utils::{higher, is_integer_const, is_trait_method, SpanlessEq};
+use clippy_utils::{SpanlessEq, higher, is_integer_const, is_trait_method};
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::LateContext;
use rustc_span::sym;
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index 3b2dd285b8c..4ab165a5528 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -8,8 +8,8 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::PatKind;
use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use super::SEARCH_IS_SOME;
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
index 8bc535ac47a..7ef07fe899c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
@@ -6,9 +6,9 @@ use rustc_lint::LateContext;
use rustc_span::sym;
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_enum_variant_ctor;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::implements_trait;
-use clippy_utils::is_enum_variant_ctor;
use super::SEEK_FROM_CURRENT;
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 7c09cc252e1..9c966f010f1 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,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_expr_used_or_unified, is_enum_variant_ctor};
+use clippy_utils::{is_enum_variant_ctor, is_expr_used_or_unified};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::SEEK_TO_START_INSTEAD_OF_REWIND;
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 12cabd43cb1..69032776b2b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -3,7 +3,7 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_context;
use clippy_utils::usage::local_used_after_expr;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths};
use core::ops::ControlFlow;
use rustc_errors::Applicability;
@@ -12,7 +12,7 @@ use rustc_hir::{
};
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Span, Symbol, SyntaxContext};
+use rustc_span::{Span, Symbol, SyntaxContext, sym};
use super::{MANUAL_SPLIT_ONCE, NEEDLESS_SPLITN};
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
index 38f2c916912..c60a49067ec 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_errors::{Applicability, Diag};
use rustc_lint::LateContext;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use {rustc_ast as ast, rustc_hir as hir};
use super::SUSPICIOUS_COMMAND_ARG_SPACE;
diff --git a/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs b/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs
index db8cc4595d4..e67ba5c4d31 100644
--- a/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs
@@ -7,7 +7,7 @@ use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::{self, ExistentialPredicate, Ty};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
/// Checks if the given type is `dyn Any`, or a trait object that has `Any` as a supertrait.
/// Only in those cases will its vtable have a `type_id` method that returns the implementor's
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
index d46b584f8f4..ce81282ddfe 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fallible_conversions.rs
@@ -6,7 +6,7 @@ use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::print::with_forced_trimmed_paths;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::UNNECESSARY_FALLIBLE_CONVERSIONS;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index c9b9d98dbe6..ca46da81fa0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_copy;
use clippy_utils::usage::mutated_variables;
-use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
use core::ops::ControlFlow;
use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_first_then_check.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_first_then_check.rs
new file mode 100644
index 00000000000..7ae1bb54e60
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_first_then_check.rs
@@ -0,0 +1,56 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::SpanRangeExt;
+
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::UNNECESSARY_FIRST_THEN_CHECK;
+
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ call_span: Span,
+ first_call: &Expr<'_>,
+ first_caller: &Expr<'_>,
+ is_some: bool,
+) {
+ if !cx
+ .typeck_results()
+ .expr_ty_adjusted(first_caller)
+ .peel_refs()
+ .is_slice()
+ {
+ return;
+ }
+
+ let ExprKind::MethodCall(_, _, _, first_call_span) = first_call.kind else {
+ return;
+ };
+
+ let both_calls_span = first_call_span.with_hi(call_span.hi());
+ if let Some(both_calls_snippet) = both_calls_span.get_source_text(cx)
+ && let Some(first_caller_snippet) = first_caller.span.get_source_text(cx)
+ {
+ let (sugg_span, suggestion) = if is_some {
+ (
+ first_caller.span.with_hi(call_span.hi()),
+ format!("!{first_caller_snippet}.is_empty()"),
+ )
+ } else {
+ (both_calls_span, "is_empty()".to_owned())
+ };
+ span_lint_and_sugg(
+ cx,
+ UNNECESSARY_FIRST_THEN_CHECK,
+ sugg_span,
+ format!(
+ "unnecessary use of `{both_calls_snippet}` to check if slice {}",
+ if is_some { "is not empty" } else { "is empty" }
+ ),
+ "replace this with",
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index ccc8d17970e..b5d8972d7aa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_hir::PatKind;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::UNNECESSARY_FOLD;
@@ -123,58 +123,32 @@ pub(super) fn check(
if let hir::ExprKind::Lit(lit) = init.kind {
match lit.node {
ast::LitKind::Bool(false) => {
- check_fold_with_op(
- cx,
- expr,
- acc,
- fold_span,
- hir::BinOpKind::Or,
- Replacement {
- has_args: true,
- has_generic_return: false,
- method_name: "any",
- },
- );
+ check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Or, Replacement {
+ has_args: true,
+ has_generic_return: false,
+ method_name: "any",
+ });
},
ast::LitKind::Bool(true) => {
- check_fold_with_op(
- cx,
- expr,
- acc,
- fold_span,
- hir::BinOpKind::And,
- Replacement {
- has_args: true,
- has_generic_return: false,
- method_name: "all",
- },
- );
+ check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, Replacement {
+ has_args: true,
+ has_generic_return: false,
+ method_name: "all",
+ });
},
- ast::LitKind::Int(Pu128(0), _) => check_fold_with_op(
- cx,
- expr,
- acc,
- fold_span,
- hir::BinOpKind::Add,
- Replacement {
+ ast::LitKind::Int(Pu128(0), _) => {
+ check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, Replacement {
has_args: false,
has_generic_return: needs_turbofish(cx, expr),
method_name: "sum",
- },
- ),
+ });
+ },
ast::LitKind::Int(Pu128(1), _) => {
- check_fold_with_op(
- cx,
- expr,
- acc,
- fold_span,
- hir::BinOpKind::Mul,
- Replacement {
- has_args: false,
- has_generic_return: needs_turbofish(cx, expr),
- method_name: "product",
- },
- );
+ check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, Replacement {
+ has_args: false,
+ has_generic_return: needs_turbofish(cx, expr),
+ method_name: "product",
+ });
},
_ => (),
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs
index 64eb8411795..39fce2c40c9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_get_then_check.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::UNNECESSARY_GET_THEN_CHECK;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 4d18bc7ac77..029704882dd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -10,7 +10,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{BindingMode, Expr, ExprKind, Node, PatKind};
use rustc_lint::LateContext;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
use super::UNNECESSARY_TO_OWNED;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
index 494d71fc053..6dc8adb42df 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{is_res_lang_ctor, last_path_segment, path_res, MaybePath};
+use clippy_utils::{MaybePath, is_res_lang_ctor, last_path_segment, path_res};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
index 86c0a6322b6..062d1348555 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
@@ -1,16 +1,15 @@
use std::cmp::Ordering;
use super::UNNECESSARY_MIN_OR_MAX;
-use clippy_utils::diagnostics::span_lint_and_sugg;
-
use clippy_utils::consts::{ConstEvalCtxt, Constant, ConstantSource, FullInt};
+use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::Span;
+use rustc_span::{Span, sym};
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
@@ -21,26 +20,30 @@ pub(super) fn check<'tcx>(
) {
let typeck_results = cx.typeck_results();
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results);
- if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv)
- && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg)
+ if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id)
+ && (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id))
{
- let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else {
- return;
- };
+ if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv)
+ && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg)
+ {
+ let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else {
+ return;
+ };
- lint(cx, expr, name, recv.span, arg.span, ord);
- } else if let Some(extrema) = detect_extrema(cx, recv) {
- let ord = match extrema {
- Extrema::Minimum => Ordering::Less,
- Extrema::Maximum => Ordering::Greater,
- };
- lint(cx, expr, name, recv.span, arg.span, ord);
- } else if let Some(extrema) = detect_extrema(cx, arg) {
- let ord = match extrema {
- Extrema::Minimum => Ordering::Greater,
- Extrema::Maximum => Ordering::Less,
- };
- lint(cx, expr, name, recv.span, arg.span, ord);
+ lint(cx, expr, name, recv.span, arg.span, ord);
+ } else if let Some(extrema) = detect_extrema(cx, recv) {
+ let ord = match extrema {
+ Extrema::Minimum => Ordering::Less,
+ Extrema::Maximum => Ordering::Greater,
+ };
+ lint(cx, expr, name, recv.span, arg.span, ord);
+ } else if let Some(extrema) = detect_extrema(cx, arg) {
+ let ord = match extrema {
+ Extrema::Minimum => Ordering::Greater,
+ Extrema::Maximum => Ordering::Less,
+ };
+ lint(cx, expr, name, recv.span, arg.span, ord);
+ }
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
index c14a87c1534..dc50717112d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
@@ -8,8 +8,8 @@ use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
-use super::utils::get_last_chain_binding_hir_id;
use super::UNNECESSARY_RESULT_MAP_OR_ELSE;
+use super::utils::get_last_chain_binding_hir_id;
fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) {
let msg = "unused \"map closure\" when calling `Result::map_or_else` value";
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index bf7555a29e2..cfa1fdb8137 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -2,12 +2,11 @@ use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter};
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{
- fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs,
- return_ty,
+ fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs, return_ty,
};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@@ -20,7 +19,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::{
self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
};
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{Obligation, ObligationCause};
@@ -717,7 +716,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx
// check that:
// 1. This is a method with only one argument that doesn't come from a trait.
// 2. That it has `Borrow` in its generic predicates.
-// 3. `Self` is a std "map type" (ie `HashSet`, `HashMap`, BTreeSet`, `BTreeMap`).
+// 3. `Self` is a std "map type" (ie `HashSet`, `HashMap`, `BTreeSet`, `BTreeMap`).
fn check_borrow_predicate<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
if let ExprKind::MethodCall(_, caller, &[arg], _) = expr.kind
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
index ee5177d1ffa..6c2ae9cc6bf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, FnDecl, PatKind, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::AdtDef;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use crate::loops::UNUSED_ENUMERATE_INDEX;
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index ebad4ae6ee9..eafe7486bb0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -9,7 +9,7 @@ use rustc_hir::{self as hir, LangItem};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use core::ops::ControlFlow;
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index fe860e5ae26..4e33dc1df54 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -1,12 +1,12 @@
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{get_parent_expr, path_to_local_id, usage};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, QPath, Stmt, StmtKind};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty};
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
pub(super) fn derefs_to_slice<'tcx>(
cx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
index 3e271a60611..5ea4ada128a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use super::VEC_RESIZE_TO_ZERO;
diff --git a/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs b/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs
index 9b64cc7589c..b5f34a9be2e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet_with_applicability;
use clippy_utils::is_trait_method;
+use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
index c83e5198c27..a99e21d938c 100644
--- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
+++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_from_proc_macro;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_item, walk_trait_item, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_item, walk_trait_item};
use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, TraitItem, UsePath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index a9aafe7ed56..408dbef9cb1 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -2,11 +2,12 @@ use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir, span_lint_hir
use clippy_utils::source::{snippet, snippet_with_context};
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- fulfill_or_allowed, get_parent_expr, in_automatically_derived, is_lint_allowed, iter_input_pats, last_path_segment,
- SpanlessEq,
+ SpanlessEq, fulfill_or_allowed, get_parent_expr, in_automatically_derived, is_lint_allowed, iter_input_pats,
+ last_path_segment,
};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
+use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
BinOpKind, BindingMode, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind,
@@ -14,8 +15,8 @@ use rustc_hir::{
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
use crate::ref_patterns::REF_PATTERNS;
@@ -82,6 +83,45 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
+ /// Checks for the use of item with a single leading
+ /// underscore.
+ ///
+ /// ### Why is this bad?
+ /// A single leading underscore is usually used to indicate
+ /// that a item will not be used. Using such a item breaks this
+ /// expectation.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// fn _foo() {}
+ ///
+ /// struct _FooStruct {}
+ ///
+ /// fn main() {
+ /// _foo();
+ /// let _ = _FooStruct{};
+ /// }
+ /// ```
+ ///
+ /// Use instead:
+ /// ```no_run
+ /// fn foo() {}
+ ///
+ /// struct FooStruct {}
+ ///
+ /// fn main() {
+ /// foo();
+ /// let _ = FooStruct{};
+ /// }
+ /// ```
+ #[clippy::version = "pre 1.29.0"]
+ pub USED_UNDERSCORE_ITEMS,
+ pedantic,
+ "using a item which is prefixed with an underscore"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
/// Checks for the use of short circuit boolean conditions as
/// a
/// statement.
@@ -104,6 +144,7 @@ declare_clippy_lint! {
declare_lint_pass!(LintPass => [
TOPLEVEL_REF_ARG,
USED_UNDERSCORE_BINDING,
+ USED_UNDERSCORE_ITEMS,
SHORT_CIRCUIT_STATEMENT,
]);
@@ -205,51 +246,104 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
{
return;
}
- let (definition_hir_id, ident) = match expr.kind {
- ExprKind::Path(ref qpath) => {
- if let QPath::Resolved(None, path) = qpath
- && let Res::Local(id) = path.res
- && is_used(cx, expr)
- {
- (id, last_path_segment(qpath).ident)
- } else {
- return;
- }
- },
- ExprKind::Field(recv, ident) => {
- if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def()
- && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name)
- && let Some(local_did) = field.did.as_local()
- && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data()
- {
- (cx.tcx.local_def_id_to_hir_id(local_did), ident)
- } else {
- return;
- }
+
+ used_underscore_binding(cx, expr);
+ used_underscore_items(cx, expr);
+ }
+}
+
+fn used_underscore_items<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ let (def_id, ident) = match expr.kind {
+ ExprKind::Call(func, ..) => {
+ if let ExprKind::Path(QPath::Resolved(.., path)) = func.kind
+ && let Some(last_segment) = path.segments.last()
+ && let Res::Def(_, def_id) = last_segment.res
+ {
+ (def_id, last_segment.ident)
+ } else {
+ return;
+ }
+ },
+ ExprKind::MethodCall(path, ..) => {
+ if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+ (def_id, path.ident)
+ } else {
+ return;
+ }
+ },
+ ExprKind::Struct(QPath::Resolved(_, path), ..) => {
+ if let Some(last_segment) = path.segments.last()
+ && let Res::Def(_, def_id) = last_segment.res
+ {
+ (def_id, last_segment.ident)
+ } else {
+ return;
+ }
+ },
+ _ => return,
+ };
+
+ let name = ident.name.as_str();
+ let definition_span = cx.tcx.def_span(def_id);
+ if name.starts_with('_')
+ && !name.starts_with("__")
+ && !definition_span.from_expansion()
+ && def_id.krate == LOCAL_CRATE
+ {
+ span_lint_and_then(
+ cx,
+ USED_UNDERSCORE_ITEMS,
+ expr.span,
+ "used underscore-prefixed item".to_string(),
+ |diag| {
+ diag.span_note(definition_span, "item is defined here".to_string());
},
- _ => return,
- };
+ );
+ }
+}
- let name = ident.name.as_str();
- if name.starts_with('_')
- && !name.starts_with("__")
- && let definition_span = cx.tcx.hir().span(definition_hir_id)
- && !definition_span.from_expansion()
- && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id])
- {
- span_lint_and_then(
- cx,
- USED_UNDERSCORE_BINDING,
- expr.span,
- format!(
- "used binding `{name}` which is prefixed with an underscore. A leading \
- underscore signals that a binding will not be used"
- ),
- |diag| {
- diag.span_note(definition_span, format!("`{name}` is defined here"));
- },
- );
- }
+fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ let (definition_hir_id, ident) = match expr.kind {
+ ExprKind::Path(ref qpath) => {
+ if let QPath::Resolved(None, path) = qpath
+ && let Res::Local(id) = path.res
+ && is_used(cx, expr)
+ {
+ (id, last_path_segment(qpath).ident)
+ } else {
+ return;
+ }
+ },
+ ExprKind::Field(recv, ident) => {
+ if let Some(adt_def) = cx.typeck_results().expr_ty_adjusted(recv).ty_adt_def()
+ && let Some(field) = adt_def.all_fields().find(|field| field.name == ident.name)
+ && let Some(local_did) = field.did.as_local()
+ && !cx.tcx.type_of(field.did).skip_binder().is_phantom_data()
+ {
+ (cx.tcx.local_def_id_to_hir_id(local_did), ident)
+ } else {
+ return;
+ }
+ },
+ _ => return,
+ };
+
+ let name = ident.name.as_str();
+ if name.starts_with('_')
+ && !name.starts_with("__")
+ && let definition_span = cx.tcx.hir().span(definition_hir_id)
+ && !definition_span.from_expansion()
+ && !fulfill_or_allowed(cx, USED_UNDERSCORE_BINDING, [expr.hir_id, definition_hir_id])
+ {
+ span_lint_and_then(
+ cx,
+ USED_UNDERSCORE_BINDING,
+ expr.span,
+ "used underscore-prefixed binding".to_string(),
+ |diag| {
+ diag.span_note(definition_span, "binding is defined here".to_string());
+ },
+ );
}
}
diff --git a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
index a9ea11f4c2b..86348f04600 100644
--- a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_test;
-use clippy_utils::macros::{find_assert_args, find_assert_eq_args, root_macro_call_first_node, PanicExpn};
+use clippy_utils::macros::{PanicExpn, find_assert_args, find_assert_eq_args, root_macro_call_first_node};
use rustc_hir::Expr;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
index 94c91b09517..b40d7eba15e 100644
--- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
@@ -1,7 +1,7 @@
use std::mem;
use std::ops::ControlFlow;
-use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::comparisons::{Rel, normalize_comparison};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::visitors::for_each_expr_without_closures;
@@ -14,7 +14,7 @@ use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 859afe1b963..eea0459e026 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::qualify_min_const_fn::is_min_const_fn;
use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};
@@ -11,8 +11,8 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
use rustc_target::spec::abi::Abi;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
index 954216038fb..c2f524a6353 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_thread_local.rs
@@ -1,12 +1,12 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::macro_backtrace;
use clippy_utils::qualify_min_const_fn::is_min_const_fn;
use clippy_utils::source::snippet;
use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks};
use rustc_errors::Applicability;
-use rustc_hir::{intravisit, Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, intravisit};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::sym::{self, thread_local_macro};
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 2166b0fe5a0..64fc1a8a1a5 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -17,7 +17,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::Visibility;
use rustc_session::impl_lint_pass;
use rustc_span::def_id::CRATE_DEF_ID;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
index 77595b121aa..fc01b6753f1 100644
--- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_path_lang_item;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{for_each_expr, Visitable};
+use clippy_utils::visitors::{Visitable, for_each_expr};
use rustc_ast::LitKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
@@ -13,7 +13,7 @@ use rustc_hir::{
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{Ty, TypeckResults};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 33a14d8b7fe..d342be4545c 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -3,7 +3,7 @@ use rustc_ast::ast;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 0b3769ecb7c..d333b71edb1 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
@@ -1,6 +1,7 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
@@ -134,6 +135,11 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
}
fn report_diverging_sub_expr(&mut self, e: &Expr<'_>) {
+ if let Some(macro_call) = root_macro_call_first_node(self.cx, e) {
+ if self.cx.tcx.item_name(macro_call.def_id).as_str() == "todo" {
+ return;
+ }
+ }
span_lint(self.cx, DIVERGING_SUB_EXPRESSION, e.span, "sub-expression diverges");
}
}
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
index 0bde0da3cd8..12bcc608174 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::visitors::{for_each_expr, Descend, Visitable};
+use clippy_utils::visitors::{Descend, Visitable, for_each_expr};
use core::ops::ControlFlow::Continue;
use hir::def::{DefKind, Res};
use hir::{BlockCheckMode, ExprKind, QPath, Safety, UnOp};
@@ -153,19 +153,16 @@ fn collect_unsafe_exprs<'tcx>(
ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
if matches!(
lhs.kind,
- ExprKind::Path(QPath::Resolved(
- _,
- hir::Path {
- res: Res::Def(
- DefKind::Static {
- mutability: Mutability::Mut,
- ..
- },
- _
- ),
- ..
- }
- ))
+ ExprKind::Path(QPath::Resolved(_, hir::Path {
+ res: Res::Def(
+ DefKind::Static {
+ mutability: Mutability::Mut,
+ ..
+ },
+ _
+ ),
+ ..
+ }))
) {
unsafe_ops.push(("modification of a mutable static occurs here", expr.span));
collect_unsafe_exprs(cx, rhs, unsafe_ops);
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index f52b3a6a5a1..8118c14bd4a 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -6,9 +6,9 @@ use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::impl_lint_pass;
+use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::sym;
-use rustc_span::Span;
use std::iter;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index e92ba93942e..785bf70a3ec 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
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 60c44382059..3c47d0edfdc 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
@@ -3,8 +3,8 @@ use rustc_ast::ast::{BindingMode, ByRef, Lifetime, Mutability, Param, PatKind, P
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::kw;
use rustc_span::Span;
+use rustc_span::symbol::kw;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index df155a7a412..2eacd6875d6 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -2,16 +2,16 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, is_receiver_of_method_call,
- peel_blocks, peel_blocks_with_stmt, span_extract_comment, SpanlessEq,
+ SpanlessEq, get_parent_expr, higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt,
+ is_receiver_of_method_call, peel_blocks, peel_blocks_with_stmt, span_extract_comment,
};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::source_map::Spanned;
use rustc_span::Span;
+use rustc_span::source_map::Spanned;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index 32e7fde03b2..f6db12ed84e 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -1,10 +1,10 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
+use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir, expr_local, local_assignments, used_exactly_once};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode};
+use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 6390e51f916..b54eb164e81 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -1,9 +1,9 @@
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Block, BlockCheckMode, Closure, Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_trait_method;
diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs
index 62e41088f37..bb44ff37b20 100644
--- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs
@@ -26,7 +26,7 @@ declare_clippy_lint! {
///
/// // or choose alternative bounds for `T` so that it can be unsized
/// ```
- #[clippy::version = "1.79.0"]
+ #[clippy::version = "1.81.0"]
pub NEEDLESS_MAYBE_SIZED,
suspicious,
"a `?Sized` bound that is unusable due to a `Sized` requirement"
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index d543fd467ab..19cbf595908 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -17,9 +17,9 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
use rustc_session::impl_lint_pass;
+use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::kw;
-use rustc_span::Span;
use rustc_target::spec::abi::Abi;
declare_clippy_lint! {
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 addb4b1aee8..0775d7abdbb 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
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_self;
use clippy_utils::ptr::get_spans;
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
use clippy_utils::ty::{
implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
};
@@ -19,7 +19,7 @@ use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::kw;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
@@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
})
.collect::<Vec<_>>();
- // Collect moved variables and spans which will need dereferencings from the
+ // Collect moved variables and spans which will need dereferencing from the
// function body.
let MovedVariablesCtxt { moved_vars } = {
let mut ctx = MovedVariablesCtxt::default();
@@ -148,12 +148,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
return;
}
- // Ignore `self`s.
- if idx == 0 {
- if let PatKind::Binding(.., ident, _) = arg.pat.kind {
- if ident.name == kw::SelfLower {
- continue;
- }
+ // Ignore `self`s and params whose variable name starts with an underscore
+ if let PatKind::Binding(.., ident, _) = arg.pat.kind {
+ if idx == 0 && ident.name == kw::SelfLower {
+ continue;
+ }
+ if ident.name.as_str().starts_with('_') {
+ continue;
}
}
@@ -181,14 +182,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
&& !is_copy(cx, ty)
&& ty.is_sized(cx.tcx, cx.param_env)
&& !allowed_traits.iter().any(|&t| {
- implements_trait_with_env_from_iter(
- cx.tcx,
- cx.param_env,
- ty,
- t,
- None,
- [Option::<ty::GenericArg<'tcx>>::None],
- )
+ implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::<
+ ty::GenericArg<'tcx>,
+ >::None])
})
&& !implements_borrow_trait
&& !all_borrowable_trait
@@ -207,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
)
.is_ok()
{
- diag.span_help(span, "consider marking this type as `Copy`");
+ diag.span_help(span, "or consider marking this type as `Copy`");
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index b181791699a..392cfcb813e 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -7,8 +7,8 @@ use clippy_utils::{
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
- is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, LocalSource, Node, PatKind,
- Stmt, StmtKind, UnsafeSource,
+ BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, LocalSource, Node, PatKind, Stmt, StmtKind,
+ UnsafeSource, is_range_literal,
};
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_lint::{LateContext, LateLintPass, LintContext};
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 25f547f1a43..5e20b406426 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -4,7 +4,7 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_const_context;
use clippy_utils::macros::macro_backtrace;
-use clippy_utils::ty::{implements_trait, InteriorMut};
+use clippy_utils::ty::{InteriorMut, implements_trait};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{
@@ -15,7 +15,7 @@ use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, sym};
use rustc_target::abi::VariantIdx;
// FIXME: this is a correctness problem but there's no suitable
diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index 832518d2d35..d85032e9eee 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -3,12 +3,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use rustc_ast::ast::{
self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
};
-use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
+use rustc_ast::visit::{Visitor, walk_block, walk_expr, walk_pat};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::cmp::Ordering;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
index cfc15d92715..3f156aa5510 100644
--- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
new file mode 100644
index 00000000000..90a9f2e994b
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/non_zero_suggestions.rs
@@ -0,0 +1,143 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use rustc_ast::ast::BinOpKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty};
+use rustc_session::declare_lint_pass;
+use rustc_span::symbol::sym;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for conversions from `NonZero` types to regular integer types,
+ /// and suggests using `NonZero` types for the target as well.
+ ///
+ /// ### Why is this bad?
+ /// Converting from `NonZero` types to regular integer types and then back to `NonZero`
+ /// types is less efficient and loses the type-safety guarantees provided by `NonZero` types.
+ /// Using `NonZero` types consistently can lead to more optimized code and prevent
+ /// certain classes of errors related to zero values.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// use std::num::{NonZeroU32, NonZeroU64};
+ ///
+ /// fn example(x: u64, y: NonZeroU32) {
+ /// // Bad: Converting NonZeroU32 to u64 unnecessarily
+ /// let r1 = x / u64::from(y.get());
+ /// let r2 = x % u64::from(y.get());
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// use std::num::{NonZeroU32, NonZeroU64};
+ ///
+ /// fn example(x: u64, y: NonZeroU32) {
+ /// // Good: Preserving the NonZero property
+ /// let r1 = x / NonZeroU64::from(y);
+ /// let r2 = x % NonZeroU64::from(y);
+ /// }
+ /// ```
+ #[clippy::version = "1.81.0"]
+ pub NON_ZERO_SUGGESTIONS,
+ restriction,
+ "suggests using `NonZero#` from `u#` or `i#` for more efficient and type-safe conversions"
+}
+
+declare_lint_pass!(NonZeroSuggestions => [NON_ZERO_SUGGESTIONS]);
+
+impl<'tcx> LateLintPass<'tcx> for NonZeroSuggestions {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if let ExprKind::Binary(op, _, rhs) = expr.kind
+ && matches!(op.node, BinOpKind::Div | BinOpKind::Rem)
+ {
+ check_non_zero_conversion(cx, rhs, Applicability::MachineApplicable);
+ } else {
+ // Check if the parent expression is a binary operation
+ let parent_is_binary = cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, node)| {
+ matches!(node, rustc_hir::Node::Expr(parent_expr) if matches!(parent_expr.kind, ExprKind::Binary(..)))
+ });
+
+ if !parent_is_binary {
+ check_non_zero_conversion(cx, expr, Applicability::MaybeIncorrect);
+ }
+ }
+ }
+}
+
+fn check_non_zero_conversion(cx: &LateContext<'_>, expr: &Expr<'_>, applicability: Applicability) {
+ // Check if the expression is a function call with one argument
+ if let ExprKind::Call(func, [arg]) = expr.kind
+ && let ExprKind::Path(qpath) = &func.kind
+ && let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id()
+ && let ExprKind::MethodCall(rcv_path, receiver, _, _) = &arg.kind
+ && rcv_path.ident.name.as_str() == "get"
+ {
+ let fn_name = cx.tcx.item_name(def_id);
+ let target_ty = cx.typeck_results().expr_ty(expr);
+ let receiver_ty = cx.typeck_results().expr_ty(receiver);
+
+ // Check if the receiver type is a NonZero type
+ if let ty::Adt(adt_def, _) = receiver_ty.kind()
+ && adt_def.is_struct()
+ && cx.tcx.get_diagnostic_name(adt_def.did()) == Some(sym::NonZero)
+ {
+ if let Some(target_non_zero_type) = get_target_non_zero_type(target_ty) {
+ let arg_snippet = get_arg_snippet(cx, arg, rcv_path);
+ suggest_non_zero_conversion(cx, expr, fn_name, target_non_zero_type, &arg_snippet, applicability);
+ }
+ }
+ }
+}
+
+fn get_arg_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, rcv_path: &rustc_hir::PathSegment<'_>) -> String {
+ let arg_snippet = snippet(cx, arg.span, "..");
+ if let Some(index) = arg_snippet.rfind(&format!(".{}", rcv_path.ident.name)) {
+ arg_snippet[..index].trim().to_string()
+ } else {
+ arg_snippet.to_string()
+ }
+}
+
+fn suggest_non_zero_conversion(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ fn_name: rustc_span::Symbol,
+ target_non_zero_type: &str,
+ arg_snippet: &str,
+ applicability: Applicability,
+) {
+ let suggestion = format!("{target_non_zero_type}::{fn_name}({arg_snippet})");
+ span_lint_and_sugg(
+ cx,
+ NON_ZERO_SUGGESTIONS,
+ expr.span,
+ format!("consider using `{target_non_zero_type}::{fn_name}()` for more efficient and type-safe conversion"),
+ "replace with",
+ suggestion,
+ applicability,
+ );
+}
+
+fn get_target_non_zero_type(ty: Ty<'_>) -> Option<&'static str> {
+ match ty.kind() {
+ ty::Uint(uint_ty) => Some(match uint_ty {
+ ty::UintTy::U8 => "NonZeroU8",
+ ty::UintTy::U16 => "NonZeroU16",
+ ty::UintTy::U32 => "NonZeroU32",
+ ty::UintTy::U64 => "NonZeroU64",
+ ty::UintTy::U128 => "NonZeroU128",
+ ty::UintTy::Usize => "NonZeroUsize",
+ }),
+ ty::Int(int_ty) => Some(match int_ty {
+ ty::IntTy::I8 => "NonZeroI8",
+ ty::IntTy::I16 => "NonZeroI16",
+ ty::IntTy::I32 => "NonZeroI32",
+ ty::IntTy::I64 => "NonZeroI64",
+ ty::IntTy::I128 => "NonZeroI128",
+ ty::IntTy::Isize => "NonZeroIsize",
+ }),
+ _ => None,
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
index 51ba29d7389..a13391a5945 100644
--- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
@@ -1,5 +1,5 @@
-use clippy_config::types::MacroMatcher;
use clippy_config::Conf;
+use clippy_config::types::MacroMatcher;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{SourceText, SpanRangeExt};
use rustc_ast::ast;
@@ -8,8 +8,8 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::Span;
+use rustc_span::hygiene::{ExpnKind, MacroKind};
declare_clippy_lint! {
/// ### What it does
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 aadd729f32a..372128ac16f 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
@@ -9,8 +9,8 @@ use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKi
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, ConstKind, EarlyBinder, GenericArgKind, GenericArgsRef};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
+use rustc_span::symbol::{Ident, kw};
use std::iter;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index a0de5ea711c..dbc9948eeed 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -2,7 +2,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
-use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::comparisons::{Rel, normalize_comparison};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet;
diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
index c1317524396..5d94cfab3b0 100644
--- a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
@@ -7,12 +7,12 @@ use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{Ty, TypeckResults};
-use rustc_span::source_map::Spanned;
use rustc_span::Span;
+use rustc_span::source_map::Spanned;
+use clippy_utils::SpanlessEq;
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::source::snippet;
-use clippy_utils::SpanlessEq;
use super::{IMPOSSIBLE_COMPARISONS, REDUNDANT_COMPARISONS};
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
index be97ad389bf..34f7dbea84e 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
@@ -6,7 +6,8 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
-use rustc_span::{sym, source_map::Spanned};
+use rustc_span::source_map::Spanned;
+use rustc_span::sym;
use super::FLOAT_EQUALITY_WITHOUT_ABS;
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index ae02d22512e..6d9e75f51d6 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, is_res_lang_ctor,
- peel_blocks, peel_hir_expr_while, CaptureKind,
+ CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context,
+ is_res_lang_ctor, peel_blocks, peel_hir_expr_while,
};
use rustc_errors::Applicability;
-use rustc_hir::def::Res;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::def::Res;
use rustc_hir::{Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
index 381975199d2..eebc62e2a5a 100644
--- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs
@@ -1,15 +1,15 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::root_macro_call_first_node;
-use clippy_utils::return_ty;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
+use clippy_utils::{is_inside_always_const_context, return_ty};
use core::ops::ControlFlow;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
@@ -68,10 +68,12 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir
let Some(macro_call) = root_macro_call_first_node(cx, e) else {
return ControlFlow::Continue(Descend::Yes);
};
- if matches!(
- cx.tcx.item_name(macro_call.def_id).as_str(),
- "panic" | "assert" | "assert_eq" | "assert_ne"
- ) {
+ if !is_inside_always_const_context(cx.tcx, e.hir_id)
+ && matches!(
+ cx.tcx.item_name(macro_call.def_id).as_str(),
+ "panic" | "assert" | "assert_eq" | "assert_ne"
+ )
+ {
panics.push(macro_call.span);
ControlFlow::Continue(Descend::No)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
index 4eefd0065f6..fa5b02a5a41 100644
--- a/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
+++ b/src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
@@ -1,8 +1,9 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_in_test;
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
-use rustc_hir::Expr;
+use clippy_utils::{is_in_test, match_def_path, paths};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
@@ -95,10 +96,49 @@ impl_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC])
impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- let Some(macro_call) = root_macro_call_first_node(cx, expr) else {
- return;
- };
- if is_panic(cx, macro_call.def_id) {
+ if let Some(macro_call) = root_macro_call_first_node(cx, expr) {
+ if is_panic(cx, macro_call.def_id) {
+ if cx.tcx.hir().is_inside_const_context(expr.hir_id)
+ || self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id)
+ {
+ return;
+ }
+
+ span_lint(
+ cx,
+ PANIC,
+ macro_call.span,
+ "`panic` should not be present in production code",
+ );
+ return;
+ }
+ match cx.tcx.item_name(macro_call.def_id).as_str() {
+ "todo" => {
+ span_lint(
+ cx,
+ TODO,
+ macro_call.span,
+ "`todo` should not be present in production code",
+ );
+ },
+ "unimplemented" => {
+ span_lint(
+ cx,
+ UNIMPLEMENTED,
+ macro_call.span,
+ "`unimplemented` should not be present in production code",
+ );
+ },
+ "unreachable" => {
+ span_lint(cx, UNREACHABLE, macro_call.span, "usage of the `unreachable!` macro");
+ },
+ _ => {},
+ }
+ } else if let ExprKind::Call(func, [_]) = expr.kind
+ && let ExprKind::Path(QPath::Resolved(None, expr_path)) = func.kind
+ && let Res::Def(DefKind::Fn, def_id) = expr_path.res
+ && match_def_path(cx, def_id, &paths::PANIC_ANY)
+ {
if cx.tcx.hir().is_inside_const_context(expr.hir_id)
|| self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id)
{
@@ -108,32 +148,10 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
span_lint(
cx,
PANIC,
- macro_call.span,
- "`panic` should not be present in production code",
+ expr.span,
+ "`panic_any` should not be present in production code",
);
return;
}
- match cx.tcx.item_name(macro_call.def_id).as_str() {
- "todo" => {
- span_lint(
- cx,
- TODO,
- macro_call.span,
- "`todo` should not be present in production code",
- );
- },
- "unimplemented" => {
- span_lint(
- cx,
- UNIMPLEMENTED,
- macro_call.span,
- "`unimplemented` should not be present in production code",
- );
- },
- "unreachable" => {
- span_lint(cx, UNREACHABLE, macro_call.span, "usage of the `unreachable!` macro");
- },
- _ => {},
- }
}
}
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 5ca244f0141..75d8c09f2b0 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
@@ -18,7 +18,7 @@ use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, RegionKind, TyCtxt};
use rustc_session::impl_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use rustc_target::spec::abi::Abi;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
index d7fa48c1e38..1b9a5a44382 100644
--- a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::path_to_local_id;
-use clippy_utils::source::{snippet, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet};
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_ast::{LitKind, StrStyle};
use rustc_errors::Applicability;
@@ -9,7 +9,7 @@ use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, PatKind, QPa
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index c1296b04387..42fbba8ef6d 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir::{
- intravisit, Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind,
+ Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind, intravisit,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs b/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs
new file mode 100644
index 00000000000..385f634a150
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs
@@ -0,0 +1,88 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_ast::InlineAsmOptions;
+use rustc_hir::{Expr, ExprKind, InlineAsm, InlineAsmOperand};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks if any pointer is being passed to an asm! block with `nomem` option.
+ ///
+ /// ### Why is this bad?
+ /// `nomem` forbids any reads or writes to memory and passing a pointer suggests
+ /// that either of those will happen.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// fn f(p: *mut u32) {
+ /// unsafe { core::arch::asm!("mov [{p}], 42", p = in(reg) p, options(nomem, nostack)); }
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// fn f(p: *mut u32) {
+ /// unsafe { core::arch::asm!("mov [{p}], 42", p = in(reg) p, options(nostack)); }
+ /// }
+ /// ```
+ #[clippy::version = "1.81.0"]
+ pub POINTERS_IN_NOMEM_ASM_BLOCK,
+ suspicious,
+ "pointers in nomem asm block"
+}
+
+declare_lint_pass!(PointersInNomemAsmBlock => [POINTERS_IN_NOMEM_ASM_BLOCK]);
+
+impl<'tcx> LateLintPass<'tcx> for PointersInNomemAsmBlock {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+ if let ExprKind::InlineAsm(asm) = &expr.kind {
+ check_asm(cx, asm);
+ }
+ }
+}
+
+fn check_asm(cx: &LateContext<'_>, asm: &InlineAsm<'_>) {
+ if !asm.options.contains(InlineAsmOptions::NOMEM) {
+ return;
+ }
+
+ let spans = asm
+ .operands
+ .iter()
+ .filter(|(op, _span)| has_in_operand_pointer(cx, op))
+ .map(|(_op, span)| *span)
+ .collect::<Vec<Span>>();
+
+ if spans.is_empty() {
+ return;
+ }
+
+ span_lint_and_then(
+ cx,
+ POINTERS_IN_NOMEM_ASM_BLOCK,
+ spans,
+ "passing pointers to nomem asm block",
+ additional_notes,
+ );
+}
+
+fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) -> bool {
+ let asm_in_expr = match asm_op {
+ InlineAsmOperand::SymStatic { .. }
+ | InlineAsmOperand::Out { .. }
+ | InlineAsmOperand::Const { .. }
+ | InlineAsmOperand::SymFn { .. }
+ | InlineAsmOperand::Label { .. } => return false,
+ InlineAsmOperand::SplitInOut { in_expr, .. } => in_expr,
+ InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => expr,
+ };
+
+ // This checks for raw ptrs, refs and function pointers - the last one
+ // also technically counts as reading memory.
+ cx.typeck_results().expr_ty(asm_in_expr).is_any_ptr()
+}
+
+fn additional_notes(diag: &mut rustc_errors::Diag<'_, ()>) {
+ diag.note("`nomem` means that no memory write or read happens inside the asm! block");
+ diag.note("if this is intentional and no pointers are read or written to, consider allowing the lint");
+}
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 125f694996c..807636bb642 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -1,13 +1,11 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::source::SpanRangeExt;
-use clippy_utils::ty::expr_sig;
use clippy_utils::visitors::contains_unsafe_block;
use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local};
use hir::LifetimeName;
use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::def_id::DefId;
use rustc_hir::hir_id::{HirId, HirIdMap};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{
self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind,
ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, Safety, TraitFn, TraitItem, TraitItemKind, TyKind,
@@ -19,7 +17,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Binder, ClauseKind, ExistentialPredicate, List, PredicateKind, Ty};
use rustc_session::declare_lint_pass;
use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -34,7 +32,7 @@ declare_clippy_lint! {
/// with the appropriate `.to_owned()`/`to_string()` calls.
///
/// ### Why is this bad?
- /// Requiring the argument to be of the specific size
+ /// Requiring the argument to be of the specific type
/// makes the function less useful for no benefit; slices in the form of `&[T]`
/// or `&str` usually suffice and can be obtained from other types, too.
///
@@ -323,7 +321,6 @@ struct PtrArg<'tcx> {
idx: usize,
emission_id: HirId,
span: Span,
- ty_did: DefId,
ty_name: Symbol,
method_renames: &'static [(&'static str, &'static str)],
ref_prefix: RefPrefix,
@@ -411,7 +408,6 @@ impl<'tcx> DerefTy<'tcx> {
}
}
-#[expect(clippy::too_many_lines)]
fn check_fn_args<'cx, 'tcx: 'cx>(
cx: &'cx LateContext<'tcx>,
fn_sig: ty::FnSig<'tcx>,
@@ -514,7 +510,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
idx: i,
emission_id,
span: hir_ty.span,
- ty_did: adt.did(),
ty_name: name.ident.name,
method_renames,
ref_prefix: RefPrefix { lt: *lt, mutability },
@@ -610,65 +605,50 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[
set_skip_flag();
}
},
- Some((Node::Expr(e), child_id)) => match e.kind {
- ExprKind::Call(f, expr_args) => {
- let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
- if expr_sig(self.cx, f).and_then(|sig| sig.input(i)).map_or(true, |ty| {
- match *ty.skip_binder().peel_refs().kind() {
- ty::Dynamic(preds, _, _) => !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds),
- ty::Param(_) => true,
- ty::Adt(def, _) => def.did() == args.ty_did,
- _ => false,
- }
- }) {
- // Passed to a function taking the non-dereferenced type.
- set_skip_flag();
- }
- },
- ExprKind::MethodCall(name, self_arg, expr_args, _) => {
- let i = iter::once(self_arg)
- .chain(expr_args.iter())
- .position(|arg| arg.hir_id == child_id)
- .unwrap_or(0);
- if i == 0 {
- // Check if the method can be renamed.
- let name = name.ident.as_str();
- if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) {
- result.replacements.push(PtrArgReplacement {
- expr_span: e.span,
- self_span: self_arg.span,
- replacement,
- });
- return;
- }
+ Some((Node::Expr(use_expr), child_id)) => {
+ if let ExprKind::Index(e, ..) = use_expr.kind
+ && e.hir_id == child_id
+ {
+ // Indexing works with both owned and its dereferenced type
+ return;
+ }
+
+ if let ExprKind::MethodCall(name, receiver, ..) = use_expr.kind
+ && receiver.hir_id == child_id
+ {
+ let name = name.ident.as_str();
+
+ // Check if the method can be renamed.
+ if let Some((_, replacement)) = args.method_renames.iter().find(|&&(x, _)| x == name) {
+ result.replacements.push(PtrArgReplacement {
+ expr_span: use_expr.span,
+ self_span: receiver.span,
+ replacement,
+ });
+ return;
}
- let Some(id) = self.cx.typeck_results().type_dependent_def_id(e.hir_id) else {
- set_skip_flag();
+ // Some methods exist on both `[T]` and `Vec<T>`, such as `len`, where the receiver type
+ // doesn't coerce to a slice and our adjusted type check below isn't enough,
+ // but it would still be valid to call with a slice
+ if is_allowed_vec_method(self.cx, use_expr) {
return;
- };
-
- match *self.cx.tcx.fn_sig(id).instantiate_identity().skip_binder().inputs()[i]
- .peel_refs()
- .kind()
- {
- ty::Dynamic(preds, _, _) if !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds) => {
- set_skip_flag();
- },
- ty::Param(_) => {
- set_skip_flag();
- },
- // If the types match check for methods which exist on both types. e.g. `Vec::len` and
- // `slice::len`
- ty::Adt(def, _) if def.did() == args.ty_did && !is_allowed_vec_method(self.cx, e) => {
- set_skip_flag();
- },
- _ => (),
}
- },
- // Indexing is fine for currently supported types.
- ExprKind::Index(e, _, _) if e.hir_id == child_id => (),
- _ => set_skip_flag(),
+ }
+
+ let deref_ty = args.deref_ty.ty(self.cx);
+ let adjusted_ty = self.cx.typeck_results().expr_ty_adjusted(e).peel_refs();
+ if adjusted_ty == deref_ty {
+ return;
+ }
+
+ if let ty::Dynamic(preds, ..) = adjusted_ty.kind()
+ && matches_preds(self.cx, deref_ty, preds)
+ {
+ return;
+ }
+
+ set_skip_flag();
},
_ => set_skip_flag(),
}
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
index 77b707567e4..db03657c9af 100644
--- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -1,5 +1,5 @@
-use clippy_config::types::PubUnderscoreFieldsBehaviour;
use clippy_config::Conf;
+use clippy_config::types::PubUnderscoreFieldsBehaviour;
use clippy_utils::attrs::is_doc_hidden;
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::is_path_lang_item;
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index e1e3ded2c79..aa9a9001afb 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -1,8 +1,8 @@
use crate::manual_let_else::MANUAL_LET_ELSE;
use crate::question_mark_used::QUESTION_MARK_USED;
+use clippy_config::Conf;
use clippy_config::msrvs::Msrv;
use clippy_config::types::MatchLintBehaviour;
-use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
@@ -12,8 +12,8 @@ use clippy_utils::{
span_contains_comment,
};
use rustc_errors::Applicability;
-use rustc_hir::def::Res;
use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::def::Res;
use rustc_hir::{
BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt,
StmtKind,
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 81189fe517c..21cd3367262 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -1,8 +1,8 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::{get_parent_expr, higher, is_in_const_context, is_integer_const, path_to_local};
use rustc_ast::ast::RangeLimits;
@@ -11,8 +11,8 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, HirId};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
-use rustc_span::source_map::Spanned;
use rustc_span::Span;
+use rustc_span::source_map::Spanned;
use std::cmp::Ordering;
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
index d0b45b59526..e877f5d6ed4 100644
--- a/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
+++ b/src/tools/clippy/clippy_lints/src/rc_clone_in_vec_init.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{Span, Symbol, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index 7f4735c6a88..6bd68dd4109 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
use clippy_utils::get_enclosing_block;
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
use clippy_utils::source::snippet;
use hir::{Expr, ExprKind, HirId, LetStmt, PatKind, PathSegment, QPath, StmtKind};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::Res;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 4e24ddad83a..b9e0106fc86 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -1,17 +1,17 @@
use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
-use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
+use clippy_utils::fn_has_unsatisfiable_preds;
+use clippy_utils::mir::{LocalUsage, PossibleBorrowerMap, visit_local_usage};
use clippy_utils::source::SpanRangeExt;
use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
-use clippy_utils::fn_has_unsatisfiable_preds;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{def_id, Body, FnDecl, LangItem};
+use rustc_hir::{Body, FnDecl, LangItem, def_id};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
macro_rules! unwrap_or_continue {
($x:expr) => {
@@ -349,14 +349,10 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
local_use_locs: _,
local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
},
- )) = visit_local_usage(
- &[cloned, clone],
- mir,
- mir::Location {
- block: bb,
- statement_index: mir.basic_blocks[bb].statements.len(),
- },
- )
+ )) = visit_local_usage(&[cloned, clone], mir, mir::Location {
+ block: bb,
+ statement_index: mir.basic_blocks[bb].statements.len(),
+ })
.map(|mut vec| (vec.remove(0), vec.remove(0)))
{
CloneUsage {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index bad9b979203..6930a01d48b 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
use rustc_hir::{
- intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node,
+ ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node, intravisit as hir_visit,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::nested_filter;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs
index 3bdf13dbbea..6a1d40334e7 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_else.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind};
-use rustc_ast::visit::{walk_expr, Visitor};
+use rustc_ast::visit::{Visitor, walk_expr};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
index 0e637538615..d0dbff081f9 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
index d94ca5bc7ec..4f46ca3c715 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs
@@ -9,8 +9,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::UpvarCapture;
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::Ident;
use rustc_span::DesugaringKind;
+use rustc_span::symbol::Ident;
declare_clippy_lint! {
/// ### What it does
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 d6e741dd974..b27bb2e78af 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind};
diff --git a/src/tools/clippy/clippy_lints/src/reference.rs b/src/tools/clippy/clippy_lints/src/reference.rs
index 2b4ef21fc48..4bff37216ed 100644
--- a/src/tools/clippy/clippy_lints/src/reference.rs
+++ b/src/tools/clippy/clippy_lints/src/reference.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_with_applicability};
use rustc_ast::ast::{Expr, ExprKind, Mutability, UnOp};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index f6ef02b7c23..12cbdb854ef 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -3,7 +3,7 @@ use std::fmt::Display;
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::source::SpanRangeExt;
-use clippy_utils::{def_path_def_ids, path_def_id, paths};
+use clippy_utils::{def_path_res_with_base, find_crates, path_def_id, paths};
use rustc_ast::ast::{LitKind, StrStyle};
use rustc_hir::def_id::DefIdMap;
use rustc_hir::{BorrowKind, Expr, ExprKind};
@@ -75,11 +75,14 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
// We don't use `match_def_path` here because that relies on matching the exact path, which changed
// between regex 1.8 and 1.9
//
- // `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform
- // the operation once and store the results
- let mut resolve = |path, kind| {
- for id in def_path_def_ids(cx.tcx, path) {
- self.definitions.insert(id, kind);
+ // `def_path_res_with_base` will resolve through re-exports but is relatively heavy, so we only
+ // perform the operation once and store the results
+ let regex_crates = find_crates(cx.tcx, sym!(regex));
+ let mut resolve = |path: &[&str], kind: RegexKind| {
+ for res in def_path_res_with_base(cx.tcx, regex_crates.clone(), &path[1..]) {
+ if let Some(id) = res.opt_def_id() {
+ self.definitions.insert(id, kind);
+ }
}
};
diff --git a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
index 08de10f69b0..f54cafffb83 100644
--- a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -8,7 +8,7 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs b/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs
index caf3fb8707d..6157adad059 100644
--- a/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
use clippy_utils::source::snippet;
use clippy_utils::{is_from_proc_macro, path_to_local_id};
use rustc_errors::Applicability;
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
index 5962e8be959..42d9cf2c88c 100644
--- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -7,7 +7,7 @@ use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 5ce091b7a7a..3754fdddedf 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::source::{snippet_with_context, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr, for_each_unconsumed_temporary};
use clippy_utils::{
binary_expr_needs_parentheses, fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res,
path_to_local_id, span_contains_cfg, span_find_starting_semi,
@@ -9,8 +9,8 @@ use clippy_utils::{
use core::ops::ControlFlow;
use rustc_ast::NestedMetaItem;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::FnKind;
use rustc_hir::LangItem::ResultErr;
+use rustc_hir::intravisit::FnKind;
use rustc_hir::{
Block, Body, Expr, ExprKind, FnDecl, HirId, ItemKind, LangItem, MatchSource, Node, OwnerNode, PatKind, QPath, Stmt,
StmtKind,
@@ -21,7 +21,7 @@ use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, GenericArgKind, Ty};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos, Span, sym};
use std::borrow::Cow;
use std::fmt::Display;
@@ -389,10 +389,24 @@ fn check_final_expr<'tcx>(
}
};
- let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
- if borrows {
- return;
+ if let Some(inner) = inner {
+ if for_each_unconsumed_temporary(cx, inner, |temporary_ty| {
+ if temporary_ty.has_significant_drop(cx.tcx, cx.param_env)
+ && temporary_ty
+ .walk()
+ .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
+ {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
+ }
+ })
+ .is_break()
+ {
+ return;
+ }
}
+
if ret_span.from_expansion() {
return;
}
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 508f3ae6def..8d31641d483 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -5,8 +5,8 @@ use rustc_hir::{HirId, Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::AssocKind;
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use rustc_span::symbol::Symbol;
use std::collections::{BTreeMap, BTreeSet};
declare_clippy_lint! {
@@ -62,13 +62,10 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
&& let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
{
if !map.contains_key(res) {
- map.insert(
- *res,
- ExistingName {
- impl_methods: BTreeMap::new(),
- trait_methods: BTreeMap::new(),
- },
- );
+ map.insert(*res, ExistingName {
+ impl_methods: BTreeMap::new(),
+ trait_methods: BTreeMap::new(),
+ });
}
let existing_name = map.get_mut(res).unwrap();
diff --git a/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs b/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
index e6fe7649397..1185d67b125 100644
--- a/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
+++ b/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
@@ -3,12 +3,12 @@ use std::ops::ControlFlow;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::for_each_expr;
-use clippy_utils::{higher, peel_hir_expr_while, SpanlessEq};
+use clippy_utils::{SpanlessEq, higher, peel_hir_expr_while};
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
@@ -42,7 +42,7 @@ declare_clippy_lint! {
/// println!("inserted {value:?}");
/// }
/// ```
- #[clippy::version = "1.80.0"]
+ #[clippy::version = "1.81.0"]
pub SET_CONTAINS_OR_INSERT,
nursery,
"call to `<set>::contains` followed by `<set>::insert`"
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index 979d6dc77ae..d1114cb29f7 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -4,13 +4,13 @@ use clippy_utils::{expr_or_init, get_attr, path_to_local, peel_hir_expr_unary};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{self as hir, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::{GenericArgKind, Ty};
use rustc_session::impl_lint_pass;
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, sym};
use std::borrow::Cow;
use std::collections::hash_map::Entry;
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index acf44a9bb5a..c986c3e8aa6 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
use rustc_ast::node_id::{NodeId, NodeMap};
use rustc_ast::ptr::P;
-use rustc_ast::visit::{walk_expr, Visitor};
+use rustc_ast::visit::{Visitor, walk_expr};
use rustc_ast::{Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index 04c16281ec4..5129bbf2665 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -2,11 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local,
- path_to_local_id, SpanlessEq,
+ SpanlessEq, get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local, path_to_local_id,
};
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt};
use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, PatKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index 44283a49e84..8dd99858793 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::Msrv;
use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_attr::{StabilityLevel, StableSince};
@@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
use rustc_span::symbol::kw;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
index 7e211d64da1..ba2ddac2ec3 100644
--- a/src/tools/clippy/clippy_lints/src/string_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -1,13 +1,13 @@
use std::ops::ControlFlow;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::path_to_local_id;
use clippy_utils::source::{snippet, str_literal_to_char_literal};
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
use itertools::Itertools;
use rustc_ast::{BinOpKind, LitKind};
use rustc_errors::Applicability;
@@ -15,7 +15,7 @@ use rustc_hir::{Expr, ExprKind, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
@@ -33,7 +33,7 @@ declare_clippy_lint! {
/// ```no_run
/// "Hello World!".trim_end_matches(['.', ',', '!', '?']);
/// ```
- #[clippy::version = "1.80.0"]
+ #[clippy::version = "1.81.0"]
pub MANUAL_PATTERN_CHAR_COMPARISON,
style,
"manual char comparison in string patterns"
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 6ca4ca000e9..1fb82b66ab8 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
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, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls,
- peel_blocks, SpanlessEq,
+ SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item,
+ method_calls, peel_blocks,
};
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index 1c1de805db0..be32dc0aab0 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -1,4 +1,4 @@
-use clippy_utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter};
+use clippy_utils::ast_utils::{IdentIter, eq_id, is_useless_with_eq_exprs};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use core::ops::{Add, AddAssign};
@@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
+use rustc_span::Span;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
-use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index 744d6392e06..e9779d437d4 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
+use clippy_utils::{BINOP_TRAITS, OP_ASSIGN_TRAITS, binop_traits, trait_ref_of_method};
use core::ops::ControlFlow;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 197011cde3a..e05fa4095b8 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -6,7 +6,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core};
use itertools::Itertools;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use crate::FxHashSet;
use rustc_errors::Applicability;
@@ -17,7 +17,7 @@ use rustc_middle::ty;
use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, SyntaxContext};
+use rustc_span::{Span, SyntaxContext, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
index 20e9608a15d..8c5cf93ab6e 100644
--- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span, SyntaxContext};
+use rustc_span::{Span, SyntaxContext, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
index 25d0a16e2ab..3cd4fefffad 100644
--- a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
+++ b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
@@ -4,8 +4,8 @@ use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
index dafe9e38818..4f96a566b63 100644
--- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
@@ -56,11 +56,13 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
&& let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind
&& let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id)
&& let Some(to_digits_def_id) = to_digits_call_res.opt_def_id()
- && match_def_path(
- cx,
- to_digits_def_id,
- &["core", "char", "methods", "<impl char>", "to_digit"],
- )
+ && match_def_path(cx, to_digits_def_id, &[
+ "core",
+ "char",
+ "methods",
+ "<impl char>",
+ "to_digit",
+ ])
{
Some((false, char_arg, radix_arg))
} else {
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index 2e87d36df31..00277593622 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -1,8 +1,8 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
-use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
-use clippy_utils::{is_from_proc_macro, SpanlessEq, SpanlessHash};
+use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability};
+use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro};
use core::hash::{Hash, Hasher};
use itertools::Itertools;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index da7906b1183..25fec9f688c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -19,8 +19,8 @@ mod useless_transmute;
mod utils;
mod wrong_transmute;
-use clippy_config::msrvs::Msrv;
use clippy_config::Conf;
+use clippy_config::msrvs::Msrv;
use clippy_utils::is_in_const_context;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
@@ -527,24 +527,44 @@ declare_clippy_lint! {
/// Checks if transmute calls have all generics specified.
///
/// ### Why is this bad?
- /// If not set, some unexpected output type could be retrieved instead of the expected one,
- /// potentially leading to invalid code.
+ /// If not, one or more unexpected types could be used during `transmute()`, potentially leading
+ /// to Undefined Behavior or other problems.
+ ///
+ /// This is particularly dangerous in case a seemingly innocent/unrelated change causes type
+ /// inference to result in a different type. For example, if `transmute()` is the tail
+ /// expression of an `if`-branch, and the `else`-branch type changes, the compiler may silently
+ /// infer a different type to be returned by `transmute()`. That is because the compiler is
+ /// free to change the inference of a type as long as that inference is technically correct,
+ /// regardless of the programmer's unknown expectation.
///
- /// This is particularly dangerous in case a seemingly innocent/unrelated change can cause type
- /// inference to start inferring a different type. E.g. the transmute is the tail expression of
- /// an `if` branch, and a different branches type changes, causing the transmute to silently
- /// have a different type, instead of a proper error.
+ /// Both type-parameters, the input- and the output-type, to any `transmute()` should
+ /// be given explicitly: Setting the input-type explicitly avoids confusion about what the
+ /// argument's type actually is. Setting the output-type explicitly avoids type-inference
+ /// to infer a technically correct yet unexpected type.
///
/// ### Example
/// ```no_run
/// # unsafe {
+ /// // Avoid "naked" calls to `transmute()`!
/// let x: i32 = std::mem::transmute([1u16, 2u16]);
+ ///
+ /// // `first_answers` is intended to transmute a slice of bool to a slice of u8.
+ /// // But the programmer forgot to index the first element of the outer slice,
+ /// // so we are actually transmuting from "pointers to slices" instead of
+ /// // transmuting from "a slice of bool", causing a nonsensical result.
+ /// let the_answers: &[&[bool]] = &[&[true, false, true]];
+ /// let first_answers: &[u8] = std::mem::transmute(the_answers);
/// # }
/// ```
/// Use instead:
/// ```no_run
/// # unsafe {
/// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+ ///
+ /// // The explicit type parameters on `transmute()` makes the intention clear,
+ /// // and cause a type-error if the actual types don't match our expectation.
+ /// let the_answers: &[&[bool]] = &[&[true, false, true]];
+ /// let first_answers: &[u8] = std::mem::transmute::<&[bool], &[u8]>(the_answers[0]);
/// # }
/// ```
#[clippy::version = "1.79.0"]
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 ba8c7d6bfcb..fca332dba40 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
@@ -6,8 +6,8 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, Node};
use rustc_hir_typeck::cast::check_cast;
use rustc_lint::LateContext;
-use rustc_middle::ty::cast::CastKind;
use rustc_middle::ty::Ty;
+use rustc_middle::ty::cast::CastKind;
/// Checks for `transmutes_expressible_as_ptr_casts` lint.
/// Returns `true` if it's triggered, otherwise returns `false`.
diff --git a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
index 35e93830766..f46e95b0b83 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
@@ -1,5 +1,5 @@
-use super::utils::is_layout_incompatible;
use super::UNSOUND_COLLECTION_TRANSMUTE;
+use super::utils::is_layout_incompatible;
use clippy_utils::diagnostics::span_lint;
use rustc_hir::Expr;
use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
index 1d0de932754..3da8a449a7c 100644
--- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::visitors::for_each_local_use_after_expr;
use clippy_utils::{is_from_proc_macro, path_to_local};
diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
index 9ac73394548..24fe4e08a5b 100644
--- a/src/tools/clippy/clippy_lints/src/types/box_collection.rs
+++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
@@ -3,7 +3,7 @@ use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, QPath};
use rustc_lint::LateContext;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
use super::BOX_COLLECTION;
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 3a14927802b..363aea8be72 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -18,8 +18,8 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
declare_clippy_lint! {
/// ### What it does
@@ -261,8 +261,59 @@ declare_clippy_lint! {
/// ### Example
/// ```no_run
/// # use std::rc::Rc;
- /// struct Foo {
- /// inner: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
+ /// struct PointMatrixContainer {
+ /// matrix: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>>,
+ /// }
+ ///
+ /// fn main() {
+ /// let point_matrix: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![
+ /// vec![
+ /// Box::new((1, 2, 3, 4)),
+ /// Box::new((5, 6, 7, 8)),
+ /// ],
+ /// vec![
+ /// Box::new((9, 10, 11, 12)),
+ /// ],
+ /// ];
+ ///
+ /// let shared_point_matrix: Rc<Vec<Vec<Box<(u32, u32, u32, u32)>>>> = Rc::new(point_matrix);
+ ///
+ /// let container = PointMatrixContainer {
+ /// matrix: shared_point_matrix,
+ /// };
+ ///
+ /// // ...
+ /// }
+ /// ```
+ /// Use instead:
+ /// ### Example
+ /// ```no_run
+ /// # use std::rc::Rc;
+ /// type PointMatrix = Vec<Vec<Box<(u32, u32, u32, u32)>>>;
+ /// type SharedPointMatrix = Rc<PointMatrix>;
+ ///
+ /// struct PointMatrixContainer {
+ /// matrix: SharedPointMatrix,
+ /// }
+ ///
+ /// fn main() {
+ /// let point_matrix: PointMatrix = vec![
+ /// vec![
+ /// Box::new((1, 2, 3, 4)),
+ /// Box::new((5, 6, 7, 8)),
+ /// ],
+ /// vec![
+ /// Box::new((9, 10, 11, 12)),
+ /// ],
+ /// ];
+ ///
+ /// let shared_point_matrix: SharedPointMatrix = Rc::new(point_matrix);
+ ///
+ /// let container = PointMatrixContainer {
+ /// matrix: shared_point_matrix,
+ /// };
+ ///
+ /// // ...
/// }
/// ```
#[clippy::version = "pre 1.29.0"]
@@ -335,30 +386,22 @@ impl<'tcx> LateLintPass<'tcx> for Types {
let is_exported = cx.effective_visibilities.is_exported(def_id);
- self.check_fn_decl(
- cx,
- decl,
- CheckTyContext {
- is_in_trait_impl,
- is_exported,
- in_body: matches!(fn_kind, FnKind::Closure),
- ..CheckTyContext::default()
- },
- );
+ self.check_fn_decl(cx, decl, CheckTyContext {
+ is_in_trait_impl,
+ is_exported,
+ in_body: matches!(fn_kind, FnKind::Closure),
+ ..CheckTyContext::default()
+ });
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
match item.kind {
- ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(
- cx,
- ty,
- CheckTyContext {
- is_exported,
- ..CheckTyContext::default()
- },
- ),
+ ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(cx, ty, CheckTyContext {
+ is_exported,
+ ..CheckTyContext::default()
+ }),
// functions, enums, structs, impls and traits are covered
_ => (),
}
@@ -376,14 +419,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
false
};
- self.check_ty(
- cx,
- ty,
- CheckTyContext {
- is_in_trait_impl,
- ..CheckTyContext::default()
- },
- );
+ self.check_ty(cx, ty, CheckTyContext {
+ is_in_trait_impl,
+ ..CheckTyContext::default()
+ });
},
// Methods are covered by check_fn.
// Type aliases are ignored because oftentimes it's impossible to
@@ -399,14 +438,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
let is_exported = cx.effective_visibilities.is_exported(field.def_id);
- self.check_ty(
- cx,
- field.ty,
- CheckTyContext {
- is_exported,
- ..CheckTyContext::default()
- },
- );
+ self.check_ty(cx, field.ty, CheckTyContext {
+ is_exported,
+ ..CheckTyContext::default()
+ });
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) {
@@ -434,14 +469,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) {
if let Some(ty) = local.ty {
- self.check_ty(
- cx,
- ty,
- CheckTyContext {
- in_body: true,
- ..CheckTyContext::default()
- },
- );
+ self.check_ty(cx, ty, CheckTyContext {
+ in_body: true,
+ ..CheckTyContext::default()
+ });
}
}
}
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 0801eace4fc..1a656088b17 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -9,7 +9,7 @@ use rustc_lint::LateContext;
use rustc_middle::ty::TypeVisitableExt;
use rustc_span::symbol::sym;
-use super::{utils, REDUNDANT_ALLOCATION};
+use super::{REDUNDANT_ALLOCATION, utils};
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool {
let mut applicability = Applicability::MaybeIncorrect;
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 7fcfd5c8f35..0b64fddb447 100644
--- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_inf, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
use rustc_hir::{GenericParamKind, TyKind};
use rustc_lint::LateContext;
use rustc_target::spec::abi::Abi;
diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
index 29996a6f783..230239335c6 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -6,8 +6,8 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, GenericArg, LangItem, QPath, TyKind};
use rustc_hir_analysis::lower_ty;
use rustc_lint::LateContext;
-use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::layout::LayoutOf;
use rustc_span::symbol::sym;
use super::VEC_BOX;
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index 42100e1d755..3fc08e8192d 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{walk_body, walk_expr, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_body, walk_expr};
use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath, TyKind};
use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass};
@@ -13,8 +13,8 @@ use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, AssocKind, Ty, TyCtxt};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::{kw, Ident};
-use rustc_span::{sym, Span};
+use rustc_span::symbol::{Ident, kw};
+use rustc_span::{Span, sym};
use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
use std::ops::ControlFlow;
@@ -257,13 +257,10 @@ fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>,
}
if matches!(
ty.kind,
- TyKind::Path(QPath::Resolved(
- _,
- hir::Path {
- res: Res::SelfTyAlias { .. },
- ..
- },
- ))
+ TyKind::Path(QPath::Resolved(_, hir::Path {
+ res: Res::SelfTyAlias { .. },
+ ..
+ },))
) {
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index f51c5f74d99..44eb0a6c593 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -4,12 +4,12 @@ use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::source::walk_span_to_context;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, for_each_expr};
use hir::HirId;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs
index 88039372ebd..cfa565cf803 100644
--- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs
+++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs
@@ -5,8 +5,8 @@ use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
-use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
index 9ffcfcc0f50..93ed15777e0 100644
--- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty};
-use clippy_utils::{is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while};
use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
// TODO: add `ReadBuf` (RFC 2930) in "How to fix" once it is available in std
declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index a8cc2f97963..87478a120dd 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -5,7 +5,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index 80b661a757c..bf2d75ea1a9 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -4,7 +4,7 @@ use clippy_utils::visitors::{for_each_local_assignment, for_each_value_source, i
use core::ops::ControlFlow;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_body, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_body};
use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, LetStmt, MatchSource, Node, PatKind, QPath, TyKind};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::{in_external_macro, is_from_async_await};
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 978d49f09c3..41b2ca5d268 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
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
-use clippy_utils::source::{indent_of, reindent_multiline, SourceText, SpanRangeExt};
+use clippy_utils::source::{SourceText, SpanRangeExt, indent_of, reindent_multiline};
use rustc_errors::Applicability;
use rustc_hir::{Block, Expr, ExprKind, MatchSource, Node, StmtKind};
use rustc_lint::LateContext;
-use super::{utils, UNIT_ARG};
+use super::{UNIT_ARG, utils};
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if expr.span.from_expansion() {
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 080efe983c2..937e35dea96 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -4,15 +4,15 @@ use clippy_utils::source::snippet;
use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty};
use rustc_errors::Applicability;
-use rustc_hir::intravisit::FnKind;
use rustc_hir::LangItem::{OptionSome, ResultOk};
+use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, ExprKind, FnDecl, Impl, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
+use rustc_span::Span;
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::sym;
-use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 98f0be3135d..104be63bb15 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -1,14 +1,14 @@
#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::over;
+use rustc_ast::PatKind::*;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
-use rustc_ast::PatKind::*;
-use rustc_ast::{self as ast, Mutability, Pat, PatKind, DUMMY_NODE_ID};
+use rustc_ast::{self as ast, DUMMY_NODE_ID, Mutability, Pat, PatKind};
use rustc_ast_pretty::pprust;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -16,7 +16,7 @@ use rustc_session::impl_lint_pass;
use rustc_span::DUMMY_SP;
use std::cell::Cell;
use std::mem;
-use thin_vec::{thin_vec, ThinVec};
+use thin_vec::{ThinVec, thin_vec};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
index 309eaedac8d..e70d2a2dafe 100644
--- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::Ident;
use rustc_span::Span;
+use rustc_span::symbol::Ident;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index 738fba54fa8..a1f08cf6623 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::is_def_id_trait_method;
use rustc_hir::def::DefKind;
-use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
use rustc_hir::{Body, Expr, ExprKind, FnDecl, Node, YieldSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_session::impl_lint_pass;
-use rustc_span::def_id::{LocalDefId, LocalDefIdSet};
use rustc_span::Span;
+use rustc_span::def_id::{LocalDefId, LocalDefIdSet};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index af7abd009d2..d2a21b11ef4 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -5,7 +5,7 @@ use hir::{ExprKind, HirId, PatKind};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index 86a811e17ca..71aa57e0a14 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, peel_ref_operators};
use rustc_ast::Mutability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Block, Expr, ExprKind, HirId, LetStmt, Node, PatKind, PathSegment, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter::OnlyBodies;
diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
new file mode 100644
index 00000000000..9fd6ebccd02
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs
@@ -0,0 +1,94 @@
+use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_from_proc_macro;
+use clippy_utils::source::snippet_opt;
+use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{Item, ItemKind, UseKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext as _};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::Visibility;
+use rustc_session::impl_lint_pass;
+use rustc_span::symbol::kw;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for `use Trait` where the Trait is only used for its methods and not referenced by a path directly.
+ ///
+ /// ### Why is this bad?
+ /// Traits imported that aren't used directly can be imported anonymously with `use Trait as _`.
+ /// It is more explicit, avoids polluting the current scope with unused names and can be useful to show which imports are required for traits.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// use std::fmt::Write;
+ ///
+ /// fn main() {
+ /// let mut s = String::new();
+ /// let _ = write!(s, "hello, world!");
+ /// println!("{s}");
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// use std::fmt::Write as _;
+ ///
+ /// fn main() {
+ /// let mut s = String::new();
+ /// let _ = write!(s, "hello, world!");
+ /// println!("{s}");
+ /// }
+ /// ```
+ #[clippy::version = "1.83.0"]
+ pub UNUSED_TRAIT_NAMES,
+ restriction,
+ "use items that import a trait but only use it anonymously"
+}
+
+pub struct UnusedTraitNames {
+ msrv: Msrv,
+}
+
+impl UnusedTraitNames {
+ pub fn new(conf: &'static Conf) -> Self {
+ Self {
+ msrv: conf.msrv.clone(),
+ }
+ }
+}
+
+impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]);
+
+impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+ if self.msrv.meets(msrvs::UNDERSCORE_IMPORTS)
+ && !in_external_macro(cx.sess(), item.span)
+ && let ItemKind::Use(path, UseKind::Single) = item.kind
+ // Ignore imports that already use Underscore
+ && item.ident.name != kw::Underscore
+ // Only check traits
+ && let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
+ && cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id)
+ // Only check this import if it is visible to its module only (no pub, pub(crate), ...)
+ && let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id)
+ && cx.tcx.visibility(item.owner_id.def_id) == Visibility::Restricted(module.to_def_id())
+ && let Some(last_segment) = path.segments.last()
+ && let Some(snip) = snippet_opt(cx, last_segment.ident.span)
+ && !is_from_proc_macro(cx, &last_segment.ident)
+ {
+ let complete_span = last_segment.ident.span.to(item.ident.span);
+ span_lint_and_sugg(
+ cx,
+ UNUSED_TRAIT_NAMES,
+ complete_span,
+ "importing trait that is only used anonymously",
+ "use",
+ format!("{snip} as _"),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ extract_msrv_attr!(LateContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs
index 65f431d338b..d5309aade7a 100644
--- a/src/tools/clippy/clippy_lints/src/unused_unit.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{position_before_rarrow, SpanRangeExt};
+use clippy_utils::source::{SpanRangeExt, position_before_rarrow};
use rustc_ast::visit::FnKind;
-use rustc_ast::{ast, ClosureBinder};
+use rustc_ast::{ClosureBinder, ast};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 0b4ea0752b6..596f0fd9c8b 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::is_potentially_local_place;
use clippy_utils::{higher, path_to_local};
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceWithHirId};
use rustc_lint::{LateContext, LateLintPass};
@@ -13,7 +13,7 @@ use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
index f77badd97b7..9b9a2ffbbc8 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::ImplItemKind;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 5da48f4f7fb..e340b419bd0 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -1,5 +1,5 @@
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_from_proc_macro;
use clippy_utils::ty::same_type_and_consts;
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{walk_inf, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
use rustc_hir::{
self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl,
ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 2f7d54e73ed..29a7949b343 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -12,7 +12,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
declare_clippy_lint! {
@@ -217,12 +217,12 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
},
ExprKind::MethodCall(.., args, _) => {
cx.typeck_results().type_dependent_def_id(parent.hir_id).map(|did| {
- return (
+ (
did,
args,
cx.typeck_results().node_args(parent.hir_id),
MethodOrFunction::Method,
- );
+ )
})
},
_ => None,
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 0cce45290cf..31f9d84f5e4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -1,6 +1,6 @@
use clippy_utils::{get_attr, higher};
-use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::LitIntType;
+use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{
self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
index f50ce6c99de..8f314ce7a60 100644
--- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
@@ -3,10 +3,10 @@ use clippy_utils::source::SpanRangeExt;
use itertools::Itertools;
use rustc_ast::{Crate, Expr, ExprKind, FormatArgs};
use rustc_data_structures::fx::FxHashMap;
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::impl_lint_pass;
-use rustc_span::{hygiene, Span};
+use rustc_span::{Span, hygiene};
use std::iter::once;
use std::mem;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
index f7529682675..d8f101a8614 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
-use clippy_utils::{is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt, SpanlessEq};
+use clippy_utils::{SpanlessEq, is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt};
use rustc_errors::Applicability;
use rustc_hir::{Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
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 0ffcb433481..d444ad45087 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
@@ -2,11 +2,11 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::def_path_res;
use clippy_utils::diagnostics::span_lint;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
use rustc_hir::Item;
+use rustc_hir::def::DefKind;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::FloatTy;
+use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_session::declare_lint_pass;
use rustc_span::symbol::Symbol;
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 20526113d69..7c45a5b2f09 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
@@ -12,7 +12,7 @@ use rustc_middle::hir::nested_filter;
use rustc_session::impl_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use {rustc_ast as ast, rustc_hir as hir};
declare_clippy_lint! {
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 41183700f09..76b0a52621b 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
@@ -8,12 +8,12 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, LetStmt, Mutability, Node};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
use rustc_middle::mir::ConstValue;
+use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
use rustc_middle::ty::{self, Ty};
use rustc_session::impl_lint_pass;
-use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use rustc_span::symbol::Symbol;
use std::str;
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index d3e49bff422..ce4f41e854d 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -1,8 +1,8 @@
use std::collections::BTreeMap;
use std::ops::ControlFlow;
-use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
+use clippy_config::msrvs::{self, Msrv};
use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::SpanRangeExt;
@@ -15,7 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::layout::LayoutOf;
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, DesugaringKind, Span};
+use rustc_span::{DesugaringKind, Span, sym};
#[expect(clippy::module_name_repetitions)]
pub struct UselessVec {
diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
index a599415a2dd..91dff5a9523 100644
--- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
+use clippy_utils::higher::{VecInitKind, get_vec_init_kind};
use clippy_utils::source::snippet;
use clippy_utils::visitors::for_each_local_use_after_expr;
use clippy_utils::{get_parent_expr, path_to_local_id};
diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs
index 7a85196ceca..2e5fc5834e2 100644
--- a/src/tools/clippy/clippy_lints/src/visibility.rs
+++ b/src/tools/clippy/clippy_lints/src/visibility.rs
@@ -5,8 +5,8 @@ use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass;
-use rustc_span::symbol::kw;
use rustc_span::Span;
+use rustc_span::symbol::kw;
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 7d9e58ad2f8..405310512df 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
use rustc_span::symbol::kw;
-use rustc_span::{sym, BytePos};
+use rustc_span::{BytePos, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index ec5a5896fb2..1dd46ed5a89 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,8 +1,8 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::is_in_test;
-use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall};
-use clippy_utils::source::{expand_past_previous_comma, SpanRangeExt};
+use clippy_utils::macros::{FormatArgsStorage, MacroCall, format_arg_removal_span, root_macro_call_first_node};
+use clippy_utils::source::{SpanRangeExt, expand_past_previous_comma};
use rustc_ast::token::LitKind;
use rustc_ast::{
FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
@@ -12,7 +12,7 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
-use rustc_span::{sym, BytePos, Span};
+use rustc_span::{BytePos, Span, sym};
declare_clippy_lint! {
/// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/zombie_processes.rs b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
new file mode 100644
index 00000000000..ba2a80ee66b
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/zombie_processes.rs
@@ -0,0 +1,334 @@
+use ControlFlow::{Break, Continue};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{fn_def_id, get_enclosing_block, match_any_def_paths, match_def_path, path_to_local_id, paths};
+use rustc_ast::Mutability;
+use rustc_errors::Applicability;
+use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_local};
+use rustc_hir::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::sym;
+use std::ops::ControlFlow;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Looks for code that spawns a process but never calls `wait()` on the child.
+ ///
+ /// ### Why is this bad?
+ /// As explained in the [standard library documentation](https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning),
+ /// calling `wait()` is necessary on Unix platforms to properly release all OS resources associated with the process.
+ /// Not doing so will effectively leak process IDs and/or other limited global resources,
+ /// which can eventually lead to resource exhaustion, so it's recommended to call `wait()` in long-running applications.
+ /// Such processes are called "zombie processes".
+ ///
+ /// ### Example
+ /// ```rust
+ /// use std::process::Command;
+ ///
+ /// let _child = Command::new("ls").spawn().expect("failed to execute child");
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// use std::process::Command;
+ ///
+ /// let mut child = Command::new("ls").spawn().expect("failed to execute child");
+ /// child.wait().expect("failed to wait on child");
+ /// ```
+ #[clippy::version = "1.74.0"]
+ pub ZOMBIE_PROCESSES,
+ suspicious,
+ "not waiting on a spawned child process"
+}
+declare_lint_pass!(ZombieProcesses => [ZOMBIE_PROCESSES]);
+
+impl<'tcx> LateLintPass<'tcx> for ZombieProcesses {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if let ExprKind::Call(..) | ExprKind::MethodCall(..) = expr.kind
+ && let Some(child_adt) = cx.typeck_results().expr_ty(expr).ty_adt_def()
+ && match_def_path(cx, child_adt.did(), &paths::CHILD)
+ {
+ match cx.tcx.parent_hir_node(expr.hir_id) {
+ Node::LetStmt(local)
+ if let PatKind::Binding(_, local_id, ..) = local.pat.kind
+ && let Some(enclosing_block) = get_enclosing_block(cx, expr.hir_id) =>
+ {
+ let mut vis = WaitFinder::WalkUpTo(cx, local_id);
+
+ // If it does have a `wait()` call, we're done. Don't lint.
+ if let Break(BreakReason::WaitFound) = walk_block(&mut vis, enclosing_block) {
+ return;
+ }
+
+ // Don't emit a suggestion since the binding is used later
+ check(cx, expr, false);
+ },
+ Node::LetStmt(&LetStmt { pat, .. }) if let PatKind::Wild = pat.kind => {
+ // `let _ = child;`, also dropped immediately without `wait()`ing
+ check(cx, expr, true);
+ },
+ Node::Stmt(&Stmt {
+ kind: StmtKind::Semi(_),
+ ..
+ }) => {
+ // Immediately dropped. E.g. `std::process::Command::new("echo").spawn().unwrap();`
+ check(cx, expr, true);
+ },
+ _ => {},
+ }
+ }
+ }
+}
+
+enum BreakReason {
+ WaitFound,
+ EarlyReturn,
+}
+
+/// A visitor responsible for finding a `wait()` call on a local variable.
+///
+/// Conditional `wait()` calls are assumed to not call wait:
+/// ```ignore
+/// let mut c = Command::new("").spawn().unwrap();
+/// if true {
+/// c.wait();
+/// }
+/// ```
+///
+/// Note that this visitor does NOT explicitly look for `wait()` calls directly, but rather does the
+/// inverse -- checking if all uses of the local are either:
+/// - a field access (`child.{stderr,stdin,stdout}`)
+/// - calling `id` or `kill`
+/// - no use at all (e.g. `let _x = child;`)
+/// - taking a shared reference (`&`), `wait()` can't go through that
+///
+/// None of these are sufficient to prevent zombie processes.
+/// Doing it like this means more FNs, but FNs are better than FPs.
+///
+/// `return` expressions, conditional or not, short-circuit the visitor because
+/// if a `wait()` call hadn't been found at that point, it might never reach one at a later point:
+/// ```ignore
+/// let mut c = Command::new("").spawn().unwrap();
+/// if true {
+/// return; // Break(BreakReason::EarlyReturn)
+/// }
+/// c.wait(); // this might not be reachable
+/// ```
+enum WaitFinder<'a, 'tcx> {
+ WalkUpTo(&'a LateContext<'tcx>, HirId),
+ Found(&'a LateContext<'tcx>, HirId),
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for WaitFinder<'a, 'tcx> {
+ type Result = ControlFlow<BreakReason>;
+
+ fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) -> Self::Result {
+ if let Self::WalkUpTo(cx, local_id) = *self
+ && let PatKind::Binding(_, pat_id, ..) = l.pat.kind
+ && local_id == pat_id
+ {
+ *self = Self::Found(cx, local_id);
+ }
+
+ walk_local(self, l)
+ }
+
+ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result {
+ let Self::Found(cx, local_id) = *self else {
+ return walk_expr(self, ex);
+ };
+
+ if path_to_local_id(ex, local_id) {
+ match cx.tcx.parent_hir_node(ex.hir_id) {
+ Node::Stmt(Stmt {
+ kind: StmtKind::Semi(_),
+ ..
+ }) => {},
+ Node::Expr(expr) if let ExprKind::Field(..) = expr.kind => {},
+ Node::Expr(expr) if let ExprKind::AddrOf(_, Mutability::Not, _) = expr.kind => {},
+ Node::Expr(expr)
+ if let Some(fn_did) = fn_def_id(cx, expr)
+ && match_any_def_paths(cx, fn_did, &[&paths::CHILD_ID, &paths::CHILD_KILL]).is_some() => {},
+
+ // Conservatively assume that all other kinds of nodes call `.wait()` somehow.
+ _ => return Break(BreakReason::WaitFound),
+ }
+ } else {
+ match ex.kind {
+ ExprKind::Ret(..) => return Break(BreakReason::EarlyReturn),
+ ExprKind::If(cond, then, None) => {
+ walk_expr(self, cond)?;
+
+ // A `wait()` call in an if expression with no else is not enough:
+ //
+ // let c = spawn();
+ // if true {
+ // c.wait();
+ // }
+ //
+ // This might not call wait(). However, early returns are propagated,
+ // because they might lead to a later wait() not being called.
+ if let Break(BreakReason::EarlyReturn) = walk_expr(self, then) {
+ return Break(BreakReason::EarlyReturn);
+ }
+
+ return Continue(());
+ },
+
+ ExprKind::If(cond, then, Some(else_)) => {
+ walk_expr(self, cond)?;
+
+ #[expect(clippy::unnested_or_patterns)]
+ match (walk_expr(self, then), walk_expr(self, else_)) {
+ (Continue(()), Continue(()))
+
+ // `wait()` in one branch but nothing in the other does not count
+ | (Continue(()), Break(BreakReason::WaitFound))
+ | (Break(BreakReason::WaitFound), Continue(())) => {},
+
+ // `wait()` in both branches is ok
+ (Break(BreakReason::WaitFound), Break(BreakReason::WaitFound)) => {
+ return Break(BreakReason::WaitFound);
+ },
+
+ // Propagate early returns in either branch
+ (Break(BreakReason::EarlyReturn), _) | (_, Break(BreakReason::EarlyReturn)) => {
+ return Break(BreakReason::EarlyReturn);
+ },
+ }
+
+ return Continue(());
+ },
+ _ => {},
+ }
+ }
+
+ walk_expr(self, ex)
+ }
+}
+
+/// This function has shared logic between the different kinds of nodes that can trigger the lint.
+///
+/// In particular, `let <binding> = <expr that spawns child>;` requires some custom additional logic
+/// such as checking that the binding is not used in certain ways, which isn't necessary for
+/// `let _ = <expr that spawns child>;`.
+///
+/// This checks if the program doesn't unconditionally exit after the spawn expression.
+fn check<'tcx>(cx: &LateContext<'tcx>, spawn_expr: &'tcx Expr<'tcx>, emit_suggestion: bool) {
+ let Some(block) = get_enclosing_block(cx, spawn_expr.hir_id) else {
+ return;
+ };
+
+ let mut vis = ExitPointFinder {
+ cx,
+ state: ExitPointState::WalkUpTo(spawn_expr.hir_id),
+ };
+ if let Break(ExitCallFound) = vis.visit_block(block) {
+ // Visitor found an unconditional `exit()` call, so don't lint.
+ return;
+ }
+
+ span_lint_and_then(
+ cx,
+ ZOMBIE_PROCESSES,
+ spawn_expr.span,
+ "spawned process is never `wait()`ed on",
+ |diag| {
+ if emit_suggestion {
+ diag.span_suggestion(
+ spawn_expr.span.shrink_to_hi(),
+ "try",
+ ".wait()",
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ diag.note("consider calling `.wait()`");
+ }
+
+ diag.note("not doing so might leave behind zombie processes")
+ .note("see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning");
+ },
+ );
+}
+
+/// Checks if the given expression exits the process.
+fn is_exit_expression(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ fn_def_id(cx, expr).is_some_and(|fn_did| {
+ cx.tcx.is_diagnostic_item(sym::process_exit, fn_did) || match_def_path(cx, fn_did, &paths::ABORT)
+ })
+}
+
+#[derive(Debug)]
+enum ExitPointState {
+ /// Still walking up to the expression that initiated the visitor.
+ WalkUpTo(HirId),
+ /// We're inside of a control flow construct (e.g. `if`, `match`, `loop`)
+ /// Within this, we shouldn't accept any `exit()` calls in here, but we can leave all of these
+ /// constructs later and still continue looking for an `exit()` call afterwards. Example:
+ /// ```ignore
+ /// Command::new("").spawn().unwrap();
+ ///
+ /// if true { // depth=1
+ /// if true { // depth=2
+ /// match () { // depth=3
+ /// () => loop { // depth=4
+ ///
+ /// std::process::exit();
+ /// ^^^^^^^^^^^^^^^^^^^^^ conditional exit call, ignored
+ ///
+ /// } // depth=3
+ /// } // depth=2
+ /// } // depth=1
+ /// } // depth=0
+ ///
+ /// std::process::exit();
+ /// ^^^^^^^^^^^^^^^^^^^^^ this exit call is accepted because we're now unconditionally calling it
+ /// ```
+ /// We can only get into this state from `NoExit`.
+ InControlFlow { depth: u32 },
+ /// No exit call found yet, but looking for one.
+ NoExit,
+}
+
+fn expr_enters_control_flow(expr: &Expr<'_>) -> bool {
+ matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Loop(..))
+}
+
+struct ExitPointFinder<'a, 'tcx> {
+ state: ExitPointState,
+ cx: &'a LateContext<'tcx>,
+}
+
+struct ExitCallFound;
+
+impl<'a, 'tcx> Visitor<'tcx> for ExitPointFinder<'a, 'tcx> {
+ type Result = ControlFlow<ExitCallFound>;
+
+ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result {
+ match self.state {
+ ExitPointState::WalkUpTo(id) if expr.hir_id == id => {
+ self.state = ExitPointState::NoExit;
+ walk_expr(self, expr)
+ },
+ ExitPointState::NoExit if expr_enters_control_flow(expr) => {
+ self.state = ExitPointState::InControlFlow { depth: 1 };
+ walk_expr(self, expr)?;
+ if let ExitPointState::InControlFlow { .. } = self.state {
+ self.state = ExitPointState::NoExit;
+ }
+ Continue(())
+ },
+ ExitPointState::NoExit if is_exit_expression(self.cx, expr) => Break(ExitCallFound),
+ ExitPointState::InControlFlow { ref mut depth } if expr_enters_control_flow(expr) => {
+ *depth += 1;
+ walk_expr(self, expr)?;
+ match self.state {
+ ExitPointState::InControlFlow { depth: 1 } => self.state = ExitPointState::NoExit,
+ ExitPointState::InControlFlow { ref mut depth } => *depth -= 1,
+ _ => {},
+ }
+ Continue(())
+ },
+ _ => Continue(()),
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index 629ce9d04d4..fe30b10c435 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.82"
+version = "0.1.83"
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 de8bbb619f8..49323492e12 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -242,13 +242,16 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
}
fn eq_coroutine_kind(a: Option<CoroutineKind>, b: Option<CoroutineKind>) -> bool {
- match (a, b) {
+ matches!(
+ (a, b),
(Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. }))
- | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. }))
- | (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. }))
- | (None, None) => true,
- _ => false,
- }
+ | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. }))
+ | (
+ Some(CoroutineKind::AsyncGen { .. }),
+ Some(CoroutineKind::AsyncGen { .. })
+ )
+ | (None, None)
+ )
}
pub fn eq_field(l: &ExprField, r: &ExprField) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs b/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs
index eefcbabd835..032cd3ed739 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/ident_iter.rs
@@ -1,5 +1,5 @@
use core::iter::FusedIterator;
-use rustc_ast::visit::{walk_attribute, walk_expr, Visitor};
+use rustc_ast::visit::{Visitor, walk_attribute, walk_expr};
use rustc_ast::{Attribute, Expr};
use rustc_span::symbol::Ident;
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index 42c8b218d14..edc9c6ccdff 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -4,7 +4,7 @@ use rustc_lexer::TokenKind;
use rustc_lint::LateContext;
use rustc_middle::ty::{AdtDef, TyCtxt};
use rustc_session::Session;
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
use std::str::FromStr;
use crate::source::SpanRangeExt;
@@ -183,15 +183,15 @@ pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
let mut iter = tokenize_with_text(src);
// Search for the token sequence [`#`, `[`, `cfg`]
- while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
- let mut iter = iter.by_ref().skip_while(|(t, _)| {
+ while iter.any(|(t, ..)| matches!(t, TokenKind::Pound)) {
+ let mut iter = iter.by_ref().skip_while(|(t, ..)| {
matches!(
t,
TokenKind::Whitespace | TokenKind::LineComment { .. } | TokenKind::BlockComment { .. }
)
});
- if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
- && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
+ if matches!(iter.next(), Some((TokenKind::OpenBracket, ..)))
+ && matches!(iter.next(), Some((TokenKind::Ident, "cfg", _)))
{
return true;
}
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 2bd6837d973..9143d292f67 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -12,9 +12,9 @@
//! code was written, and check if the span contains that text. Note this will only work correctly
//! if the span is not from a `macro_rules` based macro.
+use rustc_ast::AttrStyle;
use rustc_ast::ast::{AttrKind, Attribute, IntTy, LitIntType, LitKind, StrStyle, TraitObjectSyntax, UintTy};
use rustc_ast::token::CommentKind;
-use rustc_ast::AttrStyle;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
@@ -24,7 +24,7 @@ use rustc_hir::{
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{Ident, kw};
use rustc_span::{Span, Symbol};
use rustc_target::spec::abi::Abi;
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 760d5bc95f7..bf47cf6d372 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -1,24 +1,24 @@
#![allow(clippy::float_cmp)]
use crate::macros::HirNode;
-use crate::source::{walk_span_to_context, SpanRangeExt};
+use crate::source::{SpanRangeExt, walk_span_to_context};
use crate::{clip, is_direct_expn_of, sext, unsext};
-use rustc_apfloat::ieee::{Half, Quad};
use rustc_apfloat::Float;
+use rustc_apfloat::ieee::{Half, Quad};
use rustc_ast::ast::{self, LitFloatType, LitKind};
use rustc_data_structures::sync::Lrc;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
use rustc_lexer::tokenize;
use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::{alloc_range, Scalar};
use rustc_middle::mir::ConstValue;
+use rustc_middle::mir::interpret::{Scalar, alloc_range};
use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::symbol::Ident;
-use rustc_span::{sym, SyntaxContext};
+use rustc_span::{SyntaxContext, sym};
use rustc_target::abi::Size;
use std::cell::Cell;
use std::cmp::Ordering;
@@ -581,7 +581,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
}
fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>> {
- use self::Constant::{Int, F32, F64};
+ use self::Constant::{F32, F64, Int};
match *o {
Int(value) => {
let ty::Int(ity) = *ty.kind() else { return None };
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index a6dd12a28c5..9420d84b959 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -14,12 +14,12 @@ use crate::ty::{all_predicates_of, is_copy};
use crate::visitors::is_const_evaluatable;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
-use rustc_span::{sym, Symbol};
+use rustc_span::{Symbol, sym};
use std::{cmp, ops};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index e09cc9edf3a..3175a9a1dd3 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -3,14 +3,14 @@
#![deny(clippy::missing_docs_in_private_items)]
use crate::consts::{ConstEvalCtxt, Constant};
-use crate::ty::is_type_diagnostic_item;
use crate::is_expn_of;
+use crate::ty::is_type_diagnostic_item;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath};
use rustc_lint::LateContext;
-use rustc_span::{sym, symbol, Span};
+use rustc_span::{Span, sym, symbol};
/// The essential nodes of a desugared for loop as well as the entire span:
/// `for pat in arg { body }` becomes `(pat, arg, body)`. Returns `(pat, arg, body, span)`.
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index f61ef9ac1b0..76900379ac7 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,20 +1,20 @@
use crate::consts::ConstEvalCtxt;
use crate::macros::macro_backtrace;
-use crate::source::{walk_span_to_context, SpanRange, SpanRangeExt};
+use crate::source::{SpanRange, SpanRangeExt, walk_span_to_context};
use crate::tokenize_with_text;
use rustc_ast::ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxHasher;
-use rustc_hir::def::Res;
use rustc_hir::MatchSource::TryDesugar;
+use rustc_hir::def::Res;
use rustc_hir::{
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::LateContext;
use rustc_middle::ty::TypeckResults;
-use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext};
+use rustc_span::{BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext, sym};
use std::hash::{Hash, Hasher};
use std::ops::Range;
@@ -1194,8 +1194,8 @@ fn eq_span_tokens(
&& let Some(rsrc) = right.get_source_range(cx)
&& let Some(rsrc) = rsrc.as_str()
{
- let pred = |t: &(_, _)| pred(t.0);
- let map = |(_, x)| x;
+ let pred = |&(token, ..): &(TokenKind, _, _)| pred(token);
+ let map = |(_, source, _)| source;
let ltok = tokenize_with_text(lsrc).filter(pred).map(map);
let rtok = tokenize_with_text(rsrc).filter(pred).map(map);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 0d0d6219c5e..2fee6473910 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -78,7 +78,7 @@ pub mod visitors;
pub use self::attrs::*;
pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match};
pub use self::hir_utils::{
- both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
+ HirEqInterExpr, SpanlessEq, SpanlessHash, both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over,
};
use core::mem;
@@ -94,20 +94,20 @@ use rustc_ast::ast::{self, LitKind, RangeLimits};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::packed::Pu128;
use rustc_data_structures::unhash::UnhashMap;
+use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalModDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::definitions::{DefPath, DefPathData};
use rustc_hir::hir_id::{HirIdMap, HirIdSet};
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
use rustc_hir::{
- self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
- ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
- ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
- Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
- TraitRef, TyKind, UnOp,
+ self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
+ Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
+ ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
+ PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
+ TyKind, UnOp, def,
};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::{LateContext, Level, Lint, LintContext};
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::Const;
@@ -120,12 +120,12 @@ use rustc_middle::ty::{
};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::symbol::{Ident, Symbol, kw};
+use rustc_span::{InnerSpan, Span, sym};
use rustc_target::abi::Integer;
use visitors::Visitable;
-use crate::consts::{mir_to_const, ConstEvalCtxt, Constant};
+use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
use crate::higher::Range;
use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
use crate::visitors::for_each_expr_without_closures;
@@ -263,9 +263,13 @@ pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) ->
}
}
-
/// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`.
-pub fn is_enum_variant_ctor(cx: &LateContext<'_>, enum_item: Symbol, variant_name: Symbol, ctor_call_id: DefId) -> bool {
+pub fn is_enum_variant_ctor(
+ cx: &LateContext<'_>,
+ enum_item: Symbol,
+ variant_name: Symbol,
+ ctor_call_id: DefId,
+) -> bool {
let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else {
return false;
};
@@ -667,6 +671,17 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
}
}
+/// Finds the crates called `name`, may be multiple due to multiple major versions.
+pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> Vec<Res> {
+ tcx.crates(())
+ .iter()
+ .copied()
+ .filter(move |&num| tcx.crate_name(num) == name)
+ .map(CrateNum::as_def_id)
+ .map(|id| Res::Def(tcx.def_kind(id), id))
+ .collect()
+}
+
/// Resolves a def path like `std::vec::Vec`.
///
/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
@@ -677,15 +692,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
///
/// This function is expensive and should be used sparingly.
pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
- fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
- tcx.crates(())
- .iter()
- .copied()
- .filter(move |&num| tcx.crate_name(num) == name)
- .map(CrateNum::as_def_id)
- }
-
- let (base, mut path) = match *path {
+ let (base, path) = match *path {
[primitive] => {
return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
},
@@ -701,18 +708,25 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
None
};
- let starts = find_primitive_impls(tcx, base)
- .chain(find_crates(tcx, base_sym))
+ let crates = find_primitive_impls(tcx, base)
.chain(local_crate)
- .map(|id| Res::Def(tcx.def_kind(id), id));
+ .map(|id| Res::Def(tcx.def_kind(id), id))
+ .chain(find_crates(tcx, base_sym))
+ .collect();
- let mut resolutions: Vec<Res> = starts.collect();
+ def_path_res_with_base(tcx, crates, path)
+}
+/// Resolves a def path like `vec::Vec` with the base `std`.
+///
+/// This is lighter than [`def_path_res`], and should be called with [`find_crates`] looking up
+/// items from the same crate repeatedly, although should still be used sparingly.
+pub fn def_path_res_with_base(tcx: TyCtxt<'_>, mut base: Vec<Res>, mut path: &[&str]) -> Vec<Res> {
while let [segment, rest @ ..] = path {
path = rest;
let segment = Symbol::intern(segment);
- resolutions = resolutions
+ base = base
.into_iter()
.filter_map(|res| res.opt_def_id())
.flat_map(|def_id| {
@@ -731,7 +745,7 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
.collect();
}
- resolutions
+ base
}
/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
@@ -2944,13 +2958,14 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU
}
/// Tokenizes the input while keeping the text associated with each token.
-pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> {
+pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, InnerSpan)> {
let mut pos = 0;
tokenize(s).map(move |t| {
let end = pos + t.len;
let range = pos as usize..end as usize;
+ let inner = InnerSpan::new(range.start, range.end);
pos = end;
- (t.kind, s.get(range).unwrap_or_default())
+ (t.kind, s.get(range).unwrap_or_default(), inner)
})
}
@@ -2974,8 +2989,8 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
let snippet = sm.span_to_snippet(span).unwrap_or_default();
let res = tokenize_with_text(&snippet)
- .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
- .map(|(_, s)| s)
+ .filter(|(t, ..)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+ .map(|(_, s, _)| s)
.join("\n");
res
}
@@ -2995,7 +3010,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
/// pat: Some(a)
/// else_body: return None
/// ```
-
+///
/// And for this example:
/// ```ignore
/// let Some(FooBar { a, b }) = ex else { return None };
@@ -3005,7 +3020,7 @@ pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
/// pat: Some(FooBar { a, b })
/// else_body: return None
/// ```
-
+///
/// We output `Some(a)` in the first instance, and `Some(FooBar { a, b })` in the second, because
/// the question mark operator is applicable here. Callers have to check whether we are in a
/// constant or not.
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 1d7479bff82..9c4d19ac1f1 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -1,6 +1,6 @@
#![allow(clippy::similar_names)] // `expr` and `expn`
-use crate::visitors::{for_each_expr_without_closures, Descend};
+use crate::visitors::{Descend, for_each_expr_without_closures};
use arrayvec::ArrayVec;
use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
@@ -10,7 +10,7 @@ use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
use rustc_lint::LateContext;
use rustc_span::def_id::DefId;
use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
-use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol};
+use rustc_span::{BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol, sym};
use std::ops::ControlFlow;
const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
index 654fb564848..59bb5e35cda 100644
--- a/src/tools/clippy/clippy_utils/src/mir/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -2,7 +2,7 @@ use rustc_hir::{Expr, HirId};
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{
- traversal, BasicBlock, Body, InlineAsmOperand, Local, Location, Place, StatementKind, TerminatorKind, START_BLOCK,
+ BasicBlock, Body, InlineAsmOperand, Local, Location, Place, START_BLOCK, StatementKind, TerminatorKind, traversal,
};
use rustc_middle::ty::TyCtxt;
@@ -112,14 +112,10 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool {
/// Convenience wrapper around `visit_local_usage`.
pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option<bool> {
- visit_local_usage(
- &[local],
- mir,
- Location {
- block: START_BLOCK,
- statement_index: 0,
- },
- )
+ visit_local_usage(&[local], mir, Location {
+ block: START_BLOCK,
+ statement_index: 0,
+ })
.map(|mut vec| {
let LocalUsage { local_use_locs, .. } = vec.remove(0);
let mut locations = local_use_locs
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index a30edc48fff..11a98b02f33 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -29,7 +29,11 @@ pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
-// ... none currently!
+pub const ABORT: [&str; 3] = ["std", "process", "abort"];
+pub const CHILD: [&str; 3] = ["std", "process", "Child"];
+pub const CHILD_ID: [&str; 4] = ["std", "process", "Child", "id"];
+pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"];
+pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"];
// Paths in clippy itself
pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs
index 991ea428dc3..273c1b0defa 100644
--- a/src/tools/clippy/clippy_utils/src/ptr.rs
+++ b/src/tools/clippy/clippy_utils/src/ptr.rs
@@ -1,5 +1,5 @@
use crate::source::snippet;
-use crate::visitors::{for_each_expr_without_closures, Descend};
+use crate::visitors::{Descend, for_each_expr_without_closures};
use crate::{path_to_local_id, strip_pat_refs};
use core::ops::ControlFlow;
use rustc_hir::{Body, BodyId, ExprKind, HirId, PatKind};
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 d9befb3c157..2ed20b7202c 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
@@ -18,8 +18,8 @@ use rustc_middle::mir::{
use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt};
-use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_span::symbol::sym;
use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext};
use std::borrow::Cow;
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 482e1e0147b..4ad7575e720 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -9,10 +9,10 @@ use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
use rustc_lint::{EarlyContext, LateContext};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
-use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::source_map::{SourceMap, original_sp};
use rustc_span::{
- hygiene, BytePos, FileNameDisplayPreference, Pos, SourceFile, SourceFileAndLine, Span, SpanData, SyntaxContext,
- DUMMY_SP,
+ BytePos, DUMMY_SP, FileNameDisplayPreference, Pos, SourceFile, SourceFileAndLine, Span, SpanData, SyntaxContext,
+ hygiene,
};
use std::borrow::Cow;
use std::fmt;
@@ -666,39 +666,6 @@ pub fn walk_span_to_context(span: Span, outer: SyntaxContext) -> Option<Span> {
(outer_span.ctxt() == outer).then_some(outer_span)
}
-/// Removes block comments from the given `Vec` of lines.
-///
-/// # Examples
-///
-/// ```rust,ignore
-/// without_block_comments(vec!["/*", "foo", "*/"]);
-/// // => vec![]
-///
-/// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
-/// // => vec!["bar"]
-/// ```
-pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
- let mut without = vec![];
-
- let mut nest_level = 0;
-
- for line in lines {
- if line.contains("/*") {
- nest_level += 1;
- continue;
- } else if line.contains("*/") {
- nest_level -= 1;
- continue;
- }
-
- if nest_level == 0 {
- without.push(line);
- }
- }
-
- without
-}
-
/// Trims the whitespace from the start and the end of the span.
pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
let data = span.data();
@@ -758,15 +725,12 @@ pub fn str_literal_to_char_literal(
&snip[1..(snip.len() - 1)]
};
- let hint = format!(
- "'{}'",
- match ch {
- "'" => "\\'",
- r"\" => "\\\\",
- "\\\"" => "\"", // no need to escape `"` in `'"'`
- _ => ch,
- }
- );
+ let hint = format!("'{}'", match ch {
+ "'" => "\\'",
+ r"\" => "\\\\",
+ "\\\"" => "\"", // no need to escape `"` in `'"'`
+ _ => ch,
+ });
Some(hint)
} else {
@@ -776,7 +740,7 @@ pub fn str_literal_to_char_literal(
#[cfg(test)]
mod test {
- use super::{reindent_multiline, without_block_comments};
+ use super::reindent_multiline;
#[test]
fn test_reindent_multiline_single_line() {
@@ -844,29 +808,4 @@ mod test {
z
}".into(), true, Some(8)));
}
-
- #[test]
- fn test_without_block_comments_lines_without_block_comments() {
- let result = without_block_comments(vec!["/*", "", "*/"]);
- println!("result: {result:?}");
- assert!(result.is_empty());
-
- let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
- assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
-
- let result = without_block_comments(vec!["/* rust", "", "*/"]);
- assert!(result.is_empty());
-
- let result = without_block_comments(vec!["/* one-line comment */"]);
- assert!(result.is_empty());
-
- let result = without_block_comments(vec!["/* nested", "/* multi-line", "comment", "*/", "test", "*/"]);
- assert!(result.is_empty());
-
- let result = without_block_comments(vec!["/* nested /* inline /* comment */ test */ */"]);
- assert!(result.is_empty());
-
- let result = without_block_comments(vec!["foo", "bar", "baz"]);
- assert_eq!(result, vec!["foo", "bar", "baz"]);
- }
}
diff --git a/src/tools/clippy/clippy_utils/src/str_utils.rs b/src/tools/clippy/clippy_utils/src/str_utils.rs
index 421b25a77fe..1588ee452da 100644
--- a/src/tools/clippy/clippy_utils/src/str_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/str_utils.rs
@@ -370,9 +370,11 @@ mod test {
assert_eq!(camel_case_split("AbcDef"), vec!["Abc", "Def"]);
assert_eq!(camel_case_split("Abc"), vec!["Abc"]);
assert_eq!(camel_case_split("abcDef"), vec!["abc", "Def"]);
- assert_eq!(
- camel_case_split("\u{f6}\u{f6}AabABcd"),
- vec!["\u{f6}\u{f6}", "Aab", "A", "Bcd"]
- );
+ assert_eq!(camel_case_split("\u{f6}\u{f6}AabABcd"), vec![
+ "\u{f6}\u{f6}",
+ "Aab",
+ "A",
+ "Bcd"
+ ]);
}
}
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 0f86d89c980..3255c51d009 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -180,8 +180,10 @@ impl<'a> Sugg<'a> {
) -> Self {
use rustc_ast::ast::RangeLimits;
+ let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
+
match expr.kind {
- _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
+ _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet(expr.span)),
ast::ExprKind::AddrOf(..)
| ast::ExprKind::Closure { .. }
| ast::ExprKind::If(..)
@@ -224,46 +226,38 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::While(..)
| ast::ExprKind::Await(..)
| ast::ExprKind::Err(_)
- | ast::ExprKind::Dummy => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
+ | ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
AssocOp::DotDot,
- lhs.as_ref().map_or("".into(), |lhs| {
- snippet_with_context(cx, lhs.span, ctxt, default, app).0
- }),
- rhs.as_ref().map_or("".into(), |rhs| {
- snippet_with_context(cx, rhs.span, ctxt, default, app).0
- }),
+ lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
+ rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
AssocOp::DotDotEq,
- lhs.as_ref().map_or("".into(), |lhs| {
- snippet_with_context(cx, lhs.span, ctxt, default, app).0
- }),
- rhs.as_ref().map_or("".into(), |rhs| {
- snippet_with_context(cx, rhs.span, ctxt, default, app).0
- }),
+ lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
+ rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
),
ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
AssocOp::Assign,
- snippet_with_context(cx, lhs.span, ctxt, default, app).0,
- snippet_with_context(cx, rhs.span, ctxt, default, app).0,
+ snippet(lhs.span),
+ snippet(rhs.span),
),
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
astbinop2assignop(op),
- snippet_with_context(cx, lhs.span, ctxt, default, app).0,
- snippet_with_context(cx, rhs.span, ctxt, default, app).0,
+ snippet(lhs.span),
+ snippet(rhs.span),
),
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
AssocOp::from_ast_binop(op.node),
- snippet_with_context(cx, lhs.span, ctxt, default, app).0,
- snippet_with_context(cx, rhs.span, ctxt, default, app).0,
+ snippet(lhs.span),
+ snippet(rhs.span),
),
ast::ExprKind::Cast(ref lhs, ref ty) |
//FIXME(chenyukang), remove this after type ascription is removed from AST
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
AssocOp::As,
- snippet_with_context(cx, lhs.span, ctxt, default, app).0,
- snippet_with_context(cx, ty.span, ctxt, default, app).0,
+ snippet(lhs.span),
+ snippet(ty.span),
),
}
}
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 585134209ca..775a98fe361 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -12,8 +12,8 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, FnDecl, LangItem, Safety, TyKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::ConstValue;
+use rustc_middle::mir::interpret::Scalar;
use rustc_middle::traits::EvaluationResult;
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{
@@ -22,7 +22,7 @@ use rustc_middle::ty::{
TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
};
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use rustc_target::abi::VariantIdx;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
@@ -606,10 +606,13 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t
ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)),
// Unions are always fine right now.
// This includes MaybeUninit, the main way people use uninitialized memory.
- // For ADTs, we could look at all fields just like for tuples, but that's potentially
- // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to
- // just use an `#[allow()]`.
- ty::Adt(adt, _) => adt.is_union(),
+ ty::Adt(adt, _) if adt.is_union() => true,
+ // Types (e.g. `UnsafeCell<MaybeUninit<T>>`) that recursively contain only types that can be uninit
+ // can themselves be uninit too.
+ // This purposefully ignores enums as they may have a discriminant that can't be uninit.
+ ty::Adt(adt, args) if adt.is_struct() => adt
+ .all_fields()
+ .all(|field| is_uninit_value_valid_for_ty(cx, field.ty(cx.tcx, args))),
// For the rest, conservatively assume that they cannot be uninit.
_ => false,
}
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index 875ddec259e..e612e9c6cb6 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -14,14 +14,14 @@
use crate::def_path_res;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{walk_qpath, walk_ty, Visitor};
+use rustc_hir::intravisit::{Visitor, walk_qpath, walk_ty};
use rustc_hir::{self as hir, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty};
use rustc_span::{Span, Symbol};
mod certainty;
-use certainty::{join, meet, Certainty, Meet};
+use certainty::{Certainty, Meet, join, meet};
pub fn expr_type_is_certain(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
expr_type_certainty(cx, expr).is_certain()
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index fbf3d95365a..1230b60c3a6 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -1,4 +1,4 @@
-use crate::visitors::{for_each_expr, for_each_expr_without_closures, Descend, Visitable};
+use crate::visitors::{Descend, Visitable, for_each_expr, for_each_expr_without_closures};
use crate::{self as utils, get_enclosing_loop_or_multi_call_closure};
use core::ops::ControlFlow;
use hir::def::Res;
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index e5b6d3965e9..6d9a85a1181 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -1,10 +1,10 @@
use crate::ty::needs_ordered_drop;
use crate::{get_enclosing_block, path_to_local_id};
use core::ops::ControlFlow;
-use rustc_ast::visit::{try_visit, VisitorResult};
+use rustc_ast::visit::{VisitorResult, try_visit};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
+use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr};
use rustc_hir::{
AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath,
Safety, Stmt, UnOp, UnsafeSource,
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 31270241b0b..67a1f7cc72c 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.82"
+version = "0.1.83"
edition = "2021"
publish = false
diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs
index 6aa24329b06..fefc1a0a6c4 100644
--- a/src/tools/clippy/declare_clippy_lint/src/lib.rs
+++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs
@@ -5,7 +5,7 @@
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse::{Parse, ParseStream};
-use syn::{parse_macro_input, Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token};
+use syn::{Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token, parse_macro_input};
fn parse_attr<const LEN: usize>(path: [&'static str; LEN], attr: &Attribute) -> Option<LitStr> {
if let Meta::NameValue(name_value) = &attr.meta {
@@ -140,15 +140,12 @@ pub fn declare_clippy_lint(input: TokenStream) -> TokenStream {
let mut category = category.to_string();
- let level = format_ident!(
- "{}",
- match category.as_str() {
- "correctness" => "Deny",
- "style" | "suspicious" | "complexity" | "perf" => "Warn",
- "pedantic" | "restriction" | "cargo" | "nursery" | "internal" => "Allow",
- _ => panic!("unknown category {category}"),
- },
- );
+ let level = format_ident!("{}", match category.as_str() {
+ "correctness" => "Deny",
+ "style" | "suspicious" | "complexity" | "perf" => "Warn",
+ "pedantic" | "restriction" | "cargo" | "nursery" | "internal" => "Allow",
+ _ => panic!("unknown category {category}"),
+ },);
let info_name = format_ident!("{name}_INFO");
diff --git a/src/tools/clippy/lintcheck/src/driver.rs b/src/tools/clippy/lintcheck/src/driver.rs
index 2fda2b00f87..87ab14ba0cf 100644
--- a/src/tools/clippy/lintcheck/src/driver.rs
+++ b/src/tools/clippy/lintcheck/src/driver.rs
@@ -1,4 +1,4 @@
-use crate::recursive::{deserialize_line, serialize_line, DriverInfo};
+use crate::recursive::{DriverInfo, deserialize_line, serialize_line};
use std::io::{self, BufReader, Write};
use std::net::TcpStream;
diff --git a/src/tools/clippy/lintcheck/src/recursive.rs b/src/tools/clippy/lintcheck/src/recursive.rs
index 6a662970ae8..57073f52364 100644
--- a/src/tools/clippy/lintcheck/src/recursive.rs
+++ b/src/tools/clippy/lintcheck/src/recursive.rs
@@ -3,8 +3,8 @@
//! [`LintcheckServer`] to ask if it should be skipped, and if not sends the stderr of running
//! clippy on the crate to the server
-use crate::input::RecursiveOptions;
use crate::ClippyWarning;
+use crate::input::RecursiveOptions;
use std::collections::HashSet;
use std::io::{BufRead, BufReader, Read, Write};
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 0be2e81810e..b431599c224 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,4 +1,4 @@
[toolchain]
-channel = "nightly-2024-08-23"
+channel = "nightly-2024-09-22"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
profile = "minimal"
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 0ac3f35b446..324f754e615 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -15,9 +15,9 @@ extern crate rustc_session;
extern crate rustc_span;
use rustc_interface::interface;
+use rustc_session::EarlyDiagCtxt;
use rustc_session::config::ErrorOutputType;
use rustc_session::parse::ParseSess;
-use rustc_session::EarlyDiagCtxt;
use rustc_span::symbol::Symbol;
use std::env;
@@ -268,8 +268,6 @@ pub fn main() {
},
_ => Some(s.to_string()),
})
- // FIXME: remove this line in 1.79 to only keep `--cfg clippy`.
- .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()])
.chain(vec!["--cfg".into(), "clippy".into()])
.collect::<Vec<String>>();
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 9754254cdd0..af2aa519257 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -2,26 +2,25 @@
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(unused_extern_crates)]
-use cargo_metadata::diagnostic::{Applicability, Diagnostic};
use cargo_metadata::Message;
+use cargo_metadata::diagnostic::{Applicability, Diagnostic};
use clippy_config::ClippyConfiguration;
+use clippy_lints::LintInfo;
use clippy_lints::declared_lints::LINTS;
use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED};
-use clippy_lints::LintInfo;
use serde::{Deserialize, Serialize};
use test_utils::IS_RUSTC_TEST_SUITE;
-use ui_test::custom_flags::rustfix::RustfixMode;
use ui_test::custom_flags::Flag;
+use ui_test::custom_flags::rustfix::RustfixMode;
use ui_test::spanned::Spanned;
-use ui_test::test_result::TestRun;
-use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling};
+use ui_test::{Args, CommandBuilder, Config, Match, OutputConflictHandling, status_emitter};
use std::collections::{BTreeMap, HashMap};
use std::env::{self, set_var, var_os};
use std::ffi::{OsStr, OsString};
use std::fmt::Write;
use std::path::{Path, PathBuf};
-use std::sync::mpsc::{channel, Sender};
+use std::sync::mpsc::{Sender, channel};
use std::{fs, iter, thread};
// Test dependencies may need an `extern crate` here to ensure that they show up
@@ -469,15 +468,14 @@ fn applicability_ord(applicability: &Applicability) -> u8 {
impl Flag for DiagnosticCollector {
fn post_test_action(
&self,
- _config: &ui_test::per_test_config::TestConfig<'_>,
- _cmd: &mut std::process::Command,
+ _config: &ui_test::per_test_config::TestConfig,
output: &std::process::Output,
- _build_manager: &ui_test::build_manager::BuildManager<'_>,
- ) -> Result<Vec<TestRun>, ui_test::Errored> {
+ _build_manager: &ui_test::build_manager::BuildManager,
+ ) -> Result<(), ui_test::Errored> {
if !output.stderr.is_empty() {
self.sender.send(output.stderr.clone()).unwrap();
}
- Ok(Vec::new())
+ Ok(())
}
fn clone_inner(&self) -> Box<dyn Flag> {
diff --git a/src/tools/clippy/tests/config-metadata.rs b/src/tools/clippy/tests/config-metadata.rs
index 3e3711873ba..628dfc8f758 100644
--- a/src/tools/clippy/tests/config-metadata.rs
+++ b/src/tools/clippy/tests/config-metadata.rs
@@ -1,6 +1,6 @@
#![feature(rustc_private)]
-use clippy_config::{get_configuration_metadata, ClippyConfiguration};
+use clippy_config::{ClippyConfiguration, get_configuration_metadata};
use itertools::Itertools;
use regex::Regex;
use std::borrow::Cow;
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 8d10d5e7161..858be389a9e 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -6,11 +6,9 @@
#![warn(rust_2018_idioms, unused_lifetimes)]
use itertools::Itertools;
-use std::fs::File;
use std::io::{self, IsTerminal};
use std::path::PathBuf;
use std::process::Command;
-use std::time::SystemTime;
use test_utils::IS_RUSTC_TEST_SUITE;
use ui_test::Args;
@@ -28,11 +26,7 @@ fn main() {
println!("dogfood: test");
}
} else if !args.skip.iter().any(|arg| arg == "dogfood") {
- if args.filters.iter().any(|arg| arg == "collect_metadata") {
- collect_metadata();
- } else {
- dogfood();
- }
+ dogfood();
}
}
@@ -61,47 +55,6 @@ fn dogfood() {
);
}
-fn collect_metadata() {
- assert!(cfg!(feature = "internal"));
-
- // Setup for validation
- let metadata_output_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/lints.json");
- let start_time = SystemTime::now();
-
- // Run collection as is
- std::env::set_var("ENABLE_METADATA_COLLECTION", "1");
- assert!(run_clippy_for_package(
- "clippy_lints",
- &["-A", "unfulfilled_lint_expectations"]
- ));
-
- // Check if cargo caching got in the way
- if let Ok(file) = File::open(metadata_output_path) {
- if let Ok(metadata) = file.metadata() {
- if let Ok(last_modification) = metadata.modified() {
- if last_modification > start_time {
- // The output file has been modified. Most likely by a hungry
- // metadata collection monster. So We'll return.
- return;
- }
- }
- }
- }
-
- // Force cargo to invalidate the caches
- filetime::set_file_mtime(
- PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"),
- filetime::FileTime::now(),
- )
- .unwrap();
-
- // Running the collection again
- assert!(run_clippy_for_package(
- "clippy_lints",
- &["-A", "unfulfilled_lint_expectations"]
- ));
-}
-
#[must_use]
fn run_clippy_for_package(project: &str, args: &[&str]) -> bool {
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
index 3908411da82..0a994842834 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -13,7 +13,7 @@ extern crate rustc_span;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
#[allow(unused)]
use clippy_utils::{
- is_expr_path_def_path, is_path_diagnostic_item, is_res_diagnostic_ctor, is_res_lang_ctor, is_trait_method,
+ is_enum_variant_ctor, is_expr_path_def_path, is_path_diagnostic_item, is_res_lang_ctor, is_trait_method,
match_def_path, match_trait_method, path_res,
};
@@ -22,8 +22,8 @@ use rustc_hir::LangItem;
#[allow(unused)]
use rustc_span::sym;
-use rustc_hir::def_id::DefId;
use rustc_hir::Expr;
+use rustc_hir::def_id::DefId;
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
index 632e26215a4..ba68de6c6d0 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
@@ -13,7 +13,7 @@ extern crate rustc_span;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
#[allow(unused)]
use clippy_utils::{
- is_expr_path_def_path, is_path_diagnostic_item, is_res_diagnostic_ctor, is_res_lang_ctor, is_trait_method,
+ is_enum_variant_ctor, is_expr_path_def_path, is_path_diagnostic_item, is_res_lang_ctor, is_trait_method,
match_def_path, match_trait_method, path_res,
};
@@ -22,8 +22,8 @@ use rustc_hir::LangItem;
#[allow(unused)]
use rustc_span::sym;
-use rustc_hir::def_id::DefId;
use rustc_hir::Expr;
+use rustc_hir::def_id::DefId;
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_names_append/disallowed_names.rs b/src/tools/clippy/tests/ui-toml/disallowed_names_append/disallowed_names.rs
index a2e2b46c426..61ae8de8e33 100644
--- a/src/tools/clippy/tests/ui-toml/disallowed_names_append/disallowed_names.rs
+++ b/src/tools/clippy/tests/ui-toml/disallowed_names_append/disallowed_names.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::disallowed_names)]
+#![warn(clippy::disallowed_names)]
fn main() {
// `foo` is part of the default configuration
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.rs b/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.rs
index a2e2b46c426..61ae8de8e33 100644
--- a/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.rs
+++ b/src/tools/clippy/tests/ui-toml/disallowed_names_replace/disallowed_names.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::disallowed_names)]
+#![warn(clippy::disallowed_names)]
fn main() {
// `foo` is part of the default configuration
diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed
index 5f4f007cf5c..a6072111dc0 100644
--- a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed
+++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.fixed
@@ -2,7 +2,7 @@
use std::alloc as colla;
use std::option::Option as Maybe;
-use std::process::{exit as goodbye, Child as Kid};
+use std::process::{Child as Kid, exit as goodbye};
use std::thread::sleep as thread_sleep;
#[rustfmt::skip]
use std::{
diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
index f60058c8628..c2b61aab5b3 100644
--- a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
+++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs
@@ -2,7 +2,7 @@
use std::alloc as colla;
use std::option::Option as Maybe;
-use std::process::{exit as wrong_exit, Child as Kid};
+use std::process::{Child as Kid, exit as wrong_exit};
use std::thread::sleep;
#[rustfmt::skip]
use std::{
diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
index f66938c83fb..d3bb07ec47f 100644
--- a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
+++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr
@@ -1,8 +1,8 @@
error: this import should be renamed
- --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:5:20
+ --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:5:34
|
-LL | use std::process::{exit as wrong_exit, Child as Kid};
- | ^^^^^^^^^^^^^^^^^^ help: try: `exit as goodbye`
+LL | use std::process::{Child as Kid, exit as wrong_exit};
+ | ^^^^^^^^^^^^^^^^^^ help: try: `exit as goodbye`
|
= note: `-D clippy::missing-enforced-import-renames` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::missing_enforced_import_renames)]`
diff --git a/src/tools/clippy/tests/ui-toml/panic/panic.rs b/src/tools/clippy/tests/ui-toml/panic/panic.rs
index 618a37ddfc5..b6264c950e4 100644
--- a/src/tools/clippy/tests/ui-toml/panic/panic.rs
+++ b/src/tools/clippy/tests/ui-toml/panic/panic.rs
@@ -1,5 +1,6 @@
//@compile-flags: --test
#![warn(clippy::panic)]
+use std::panic::panic_any;
fn main() {
enum Enam {
@@ -12,6 +13,10 @@ fn main() {
}
}
+fn issue_13292() {
+ panic_any("should lint")
+}
+
#[test]
fn lonely_test() {
enum Enam {
diff --git a/src/tools/clippy/tests/ui-toml/panic/panic.stderr b/src/tools/clippy/tests/ui-toml/panic/panic.stderr
index bf7503e086c..a034207d919 100644
--- a/src/tools/clippy/tests/ui-toml/panic/panic.stderr
+++ b/src/tools/clippy/tests/ui-toml/panic/panic.stderr
@@ -1,5 +1,5 @@
error: `panic` should not be present in production code
- --> tests/ui-toml/panic/panic.rs:11:14
+ --> tests/ui-toml/panic/panic.rs:12:14
|
LL | _ => panic!(""),
| ^^^^^^^^^^
@@ -7,5 +7,11 @@ LL | _ => panic!(""),
= note: `-D clippy::panic` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::panic)]`
-error: aborting due to 1 previous error
+error: `panic_any` should not be present in production code
+ --> tests/ui-toml/panic/panic.rs:17:5
+ |
+LL | panic_any("should lint")
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/allow_attributes.fixed b/src/tools/clippy/tests/ui/allow_attributes.fixed
index 49ee3ee17c7..058dbb77a32 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.fixed
+++ b/src/tools/clippy/tests/ui/allow_attributes.fixed
@@ -58,3 +58,10 @@ fn msrv_1_80() {
#[allow(unused)]
let x = 1;
}
+
+#[deny(clippy::allow_attributes)]
+fn deny_allow_attributes() -> Option<u8> {
+ let allow = None;
+ allow?;
+ Some(42)
+}
diff --git a/src/tools/clippy/tests/ui/allow_attributes.rs b/src/tools/clippy/tests/ui/allow_attributes.rs
index 854acf8348d..6d94ce50e4c 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes.rs
@@ -58,3 +58,10 @@ fn msrv_1_80() {
#[allow(unused)]
let x = 1;
}
+
+#[deny(clippy::allow_attributes)]
+fn deny_allow_attributes() -> Option<u8> {
+ let allow = None;
+ allow?;
+ Some(42)
+}
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
index 86f6b2c5742..334e7ddd9d2 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs
@@ -15,7 +15,6 @@ use proc_macros::{external, with_span};
#[warn(deref_nullptr)]
#[deny(deref_nullptr)]
#[forbid(deref_nullptr)]
-
fn main() {
external! {
#[allow(dead_code)]
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
index 9bc3ca0f2af..86d7845df04 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
@@ -36,7 +36,7 @@ LL | #[expect(dead_code)]
= help: try adding a reason at the end with `, reason = ".."`
error: `allow` attribute without specifying a reason
- --> tests/ui/allow_attributes_without_reason.rs:47:5
+ --> tests/ui/allow_attributes_without_reason.rs:46:5
|
LL | #[allow(unused)]
| ^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL | #[allow(unused)]
= help: try adding a reason at the end with `, reason = ".."`
error: `allow` attribute without specifying a reason
- --> tests/ui/allow_attributes_without_reason.rs:47:5
+ --> tests/ui/allow_attributes_without_reason.rs:46:5
|
LL | #[allow(unused)]
| ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index 0838d064a5f..3f204073085 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -2,7 +2,6 @@
#![feature(f128)]
#![feature(f16)]
-
#![allow(
clippy::assign_op_pattern,
clippy::erasing_op,
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 78914667bf3..78b1aca4b8a 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:167:13
+ --> tests/ui/arithmetic_side_effects.rs:166:13
|
LL | let _ = 1f16 + 1f16;
| ^^^^^^^^^^^
@@ -8,733 +8,733 @@ LL | let _ = 1f16 + 1f16;
= help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]`
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:170:13
+ --> tests/ui/arithmetic_side_effects.rs:169:13
|
LL | let _ = 1f128 + 1f128;
| ^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:308:5
+ --> tests/ui/arithmetic_side_effects.rs:307:5
|
LL | _n += 1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:309:5
+ --> tests/ui/arithmetic_side_effects.rs:308:5
|
LL | _n += &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:310:5
+ --> tests/ui/arithmetic_side_effects.rs:309:5
|
LL | _n -= 1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:311:5
+ --> tests/ui/arithmetic_side_effects.rs:310:5
|
LL | _n -= &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:312:5
+ --> tests/ui/arithmetic_side_effects.rs:311:5
|
LL | _n /= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:313:5
+ --> tests/ui/arithmetic_side_effects.rs:312:5
|
LL | _n /= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:314:5
+ --> tests/ui/arithmetic_side_effects.rs:313:5
|
LL | _n %= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:315:5
+ --> tests/ui/arithmetic_side_effects.rs:314:5
|
LL | _n %= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:316:5
+ --> tests/ui/arithmetic_side_effects.rs:315:5
|
LL | _n *= 2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:317:5
+ --> tests/ui/arithmetic_side_effects.rs:316:5
|
LL | _n *= &2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:318:5
+ --> tests/ui/arithmetic_side_effects.rs:317:5
|
LL | _n += -1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:319:5
+ --> tests/ui/arithmetic_side_effects.rs:318:5
|
LL | _n += &-1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:320:5
+ --> tests/ui/arithmetic_side_effects.rs:319:5
|
LL | _n -= -1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:321:5
+ --> tests/ui/arithmetic_side_effects.rs:320:5
|
LL | _n -= &-1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:322:5
+ --> tests/ui/arithmetic_side_effects.rs:321:5
|
LL | _n /= -0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:323:5
+ --> tests/ui/arithmetic_side_effects.rs:322:5
|
LL | _n /= &-0;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:324:5
+ --> tests/ui/arithmetic_side_effects.rs:323:5
|
LL | _n %= -0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:325:5
+ --> tests/ui/arithmetic_side_effects.rs:324:5
|
LL | _n %= &-0;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:326:5
+ --> tests/ui/arithmetic_side_effects.rs:325:5
|
LL | _n *= -2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:327:5
+ --> tests/ui/arithmetic_side_effects.rs:326:5
|
LL | _n *= &-2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:328:5
+ --> tests/ui/arithmetic_side_effects.rs:327:5
|
LL | _custom += Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:329:5
+ --> tests/ui/arithmetic_side_effects.rs:328:5
|
LL | _custom += &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:330:5
+ --> tests/ui/arithmetic_side_effects.rs:329:5
|
LL | _custom -= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:331:5
+ --> tests/ui/arithmetic_side_effects.rs:330:5
|
LL | _custom -= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:332:5
+ --> tests/ui/arithmetic_side_effects.rs:331:5
|
LL | _custom /= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:333:5
+ --> tests/ui/arithmetic_side_effects.rs:332:5
|
LL | _custom /= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:334:5
+ --> tests/ui/arithmetic_side_effects.rs:333:5
|
LL | _custom %= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:335:5
+ --> tests/ui/arithmetic_side_effects.rs:334:5
|
LL | _custom %= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:336:5
+ --> tests/ui/arithmetic_side_effects.rs:335:5
|
LL | _custom *= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:337:5
+ --> tests/ui/arithmetic_side_effects.rs:336:5
|
LL | _custom *= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:338:5
+ --> tests/ui/arithmetic_side_effects.rs:337:5
|
LL | _custom >>= Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:339:5
+ --> tests/ui/arithmetic_side_effects.rs:338:5
|
LL | _custom >>= &Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:340:5
+ --> tests/ui/arithmetic_side_effects.rs:339:5
|
LL | _custom <<= Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:341:5
+ --> tests/ui/arithmetic_side_effects.rs:340:5
|
LL | _custom <<= &Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:342:5
+ --> tests/ui/arithmetic_side_effects.rs:341:5
|
LL | _custom += -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:343:5
+ --> tests/ui/arithmetic_side_effects.rs:342:5
|
LL | _custom += &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:344:5
+ --> tests/ui/arithmetic_side_effects.rs:343:5
|
LL | _custom -= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:345:5
+ --> tests/ui/arithmetic_side_effects.rs:344:5
|
LL | _custom -= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:346:5
+ --> tests/ui/arithmetic_side_effects.rs:345:5
|
LL | _custom /= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:347:5
+ --> tests/ui/arithmetic_side_effects.rs:346:5
|
LL | _custom /= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:348:5
+ --> tests/ui/arithmetic_side_effects.rs:347:5
|
LL | _custom %= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:349:5
+ --> tests/ui/arithmetic_side_effects.rs:348:5
|
LL | _custom %= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:350:5
+ --> tests/ui/arithmetic_side_effects.rs:349:5
|
LL | _custom *= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:351:5
+ --> tests/ui/arithmetic_side_effects.rs:350:5
|
LL | _custom *= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:352:5
+ --> tests/ui/arithmetic_side_effects.rs:351:5
|
LL | _custom >>= -Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:353:5
+ --> tests/ui/arithmetic_side_effects.rs:352:5
|
LL | _custom >>= &-Custom;
| ^^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:354:5
+ --> tests/ui/arithmetic_side_effects.rs:353:5
|
LL | _custom <<= -Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:355:5
+ --> tests/ui/arithmetic_side_effects.rs:354:5
|
LL | _custom <<= &-Custom;
| ^^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:358:10
+ --> tests/ui/arithmetic_side_effects.rs:357:10
|
LL | _n = _n + 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:359:10
+ --> tests/ui/arithmetic_side_effects.rs:358:10
|
LL | _n = _n + &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:360:10
+ --> tests/ui/arithmetic_side_effects.rs:359:10
|
LL | _n = 1 + _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:361:10
+ --> tests/ui/arithmetic_side_effects.rs:360:10
|
LL | _n = &1 + _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:362:10
+ --> tests/ui/arithmetic_side_effects.rs:361:10
|
LL | _n = _n - 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:363:10
+ --> tests/ui/arithmetic_side_effects.rs:362:10
|
LL | _n = _n - &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:364:10
+ --> tests/ui/arithmetic_side_effects.rs:363:10
|
LL | _n = 1 - _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:365:10
+ --> tests/ui/arithmetic_side_effects.rs:364:10
|
LL | _n = &1 - _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:366:10
+ --> tests/ui/arithmetic_side_effects.rs:365:10
|
LL | _n = _n / 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:367:10
+ --> tests/ui/arithmetic_side_effects.rs:366:10
|
LL | _n = _n / &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:368:10
+ --> tests/ui/arithmetic_side_effects.rs:367:10
|
LL | _n = _n % 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:369:10
+ --> tests/ui/arithmetic_side_effects.rs:368:10
|
LL | _n = _n % &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:370:10
+ --> tests/ui/arithmetic_side_effects.rs:369:10
|
LL | _n = _n * 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:371:10
+ --> tests/ui/arithmetic_side_effects.rs:370:10
|
LL | _n = _n * &2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:372:10
+ --> tests/ui/arithmetic_side_effects.rs:371:10
|
LL | _n = 2 * _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:373:10
+ --> tests/ui/arithmetic_side_effects.rs:372:10
|
LL | _n = &2 * _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:374:10
+ --> tests/ui/arithmetic_side_effects.rs:373:10
|
LL | _n = 23 + &85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:375:10
+ --> tests/ui/arithmetic_side_effects.rs:374:10
|
LL | _n = &23 + 85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:376:10
+ --> tests/ui/arithmetic_side_effects.rs:375:10
|
LL | _n = &23 + &85;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:377:15
+ --> tests/ui/arithmetic_side_effects.rs:376:15
|
LL | _custom = _custom + _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:378:15
+ --> tests/ui/arithmetic_side_effects.rs:377:15
|
LL | _custom = _custom + &_custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:379:15
+ --> tests/ui/arithmetic_side_effects.rs:378:15
|
LL | _custom = Custom + _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:380:15
+ --> tests/ui/arithmetic_side_effects.rs:379:15
|
LL | _custom = &Custom + _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:381:15
+ --> tests/ui/arithmetic_side_effects.rs:380:15
|
LL | _custom = _custom - Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:382:15
+ --> tests/ui/arithmetic_side_effects.rs:381:15
|
LL | _custom = _custom - &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:383:15
+ --> tests/ui/arithmetic_side_effects.rs:382:15
|
LL | _custom = Custom - _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:384:15
+ --> tests/ui/arithmetic_side_effects.rs:383:15
|
LL | _custom = &Custom - _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:385:15
+ --> tests/ui/arithmetic_side_effects.rs:384:15
|
LL | _custom = _custom / Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:386:15
+ --> tests/ui/arithmetic_side_effects.rs:385:15
|
LL | _custom = _custom / &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:387:15
+ --> tests/ui/arithmetic_side_effects.rs:386:15
|
LL | _custom = _custom % Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:388:15
+ --> tests/ui/arithmetic_side_effects.rs:387:15
|
LL | _custom = _custom % &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:389:15
+ --> tests/ui/arithmetic_side_effects.rs:388:15
|
LL | _custom = _custom * Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:390:15
+ --> tests/ui/arithmetic_side_effects.rs:389:15
|
LL | _custom = _custom * &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:391:15
+ --> tests/ui/arithmetic_side_effects.rs:390:15
|
LL | _custom = Custom * _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:392:15
+ --> tests/ui/arithmetic_side_effects.rs:391:15
|
LL | _custom = &Custom * _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:393:15
+ --> tests/ui/arithmetic_side_effects.rs:392:15
|
LL | _custom = Custom + &Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:394:15
+ --> tests/ui/arithmetic_side_effects.rs:393:15
|
LL | _custom = &Custom + Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:395:15
+ --> tests/ui/arithmetic_side_effects.rs:394:15
|
LL | _custom = &Custom + &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:396:15
+ --> tests/ui/arithmetic_side_effects.rs:395:15
|
LL | _custom = _custom >> _custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:397:15
+ --> tests/ui/arithmetic_side_effects.rs:396:15
|
LL | _custom = _custom >> &_custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:398:15
+ --> tests/ui/arithmetic_side_effects.rs:397:15
|
LL | _custom = Custom << _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:399:15
+ --> tests/ui/arithmetic_side_effects.rs:398:15
|
LL | _custom = &Custom << _custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:402:23
+ --> tests/ui/arithmetic_side_effects.rs:401:23
|
LL | _n.saturating_div(0);
| ^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:403:21
+ --> tests/ui/arithmetic_side_effects.rs:402:21
|
LL | _n.wrapping_div(0);
| ^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:404:21
+ --> tests/ui/arithmetic_side_effects.rs:403:21
|
LL | _n.wrapping_rem(0);
| ^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:405:28
+ --> tests/ui/arithmetic_side_effects.rs:404:28
|
LL | _n.wrapping_rem_euclid(0);
| ^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:407:23
+ --> tests/ui/arithmetic_side_effects.rs:406:23
|
LL | _n.saturating_div(_n);
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:408:21
+ --> tests/ui/arithmetic_side_effects.rs:407:21
|
LL | _n.wrapping_div(_n);
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:409:21
+ --> tests/ui/arithmetic_side_effects.rs:408:21
|
LL | _n.wrapping_rem(_n);
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:410:28
+ --> tests/ui/arithmetic_side_effects.rs:409:28
|
LL | _n.wrapping_rem_euclid(_n);
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:413:10
+ --> tests/ui/arithmetic_side_effects.rs:412:10
|
LL | _n = -_n;
| ^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:414:10
+ --> tests/ui/arithmetic_side_effects.rs:413:10
|
LL | _n = -&_n;
| ^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:415:15
+ --> tests/ui/arithmetic_side_effects.rs:414:15
|
LL | _custom = -_custom;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:416:15
+ --> tests/ui/arithmetic_side_effects.rs:415:15
|
LL | _custom = -&_custom;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:425:5
+ --> tests/ui/arithmetic_side_effects.rs:424:5
|
LL | 1 + i;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:426:5
+ --> tests/ui/arithmetic_side_effects.rs:425:5
|
LL | i * 2;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:427:5
+ --> tests/ui/arithmetic_side_effects.rs:426:5
|
LL | 1 % i / 2;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:428:5
+ --> tests/ui/arithmetic_side_effects.rs:427:5
|
LL | i - 2 + 2 - i;
| ^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:429:5
+ --> tests/ui/arithmetic_side_effects.rs:428:5
|
LL | -i;
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:440:5
+ --> tests/ui/arithmetic_side_effects.rs:439:5
|
LL | i += 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:441:5
+ --> tests/ui/arithmetic_side_effects.rs:440:5
|
LL | i -= 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:442:5
+ --> tests/ui/arithmetic_side_effects.rs:441:5
|
LL | i *= 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:444:5
+ --> tests/ui/arithmetic_side_effects.rs:443:5
|
LL | i /= 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:446:5
+ --> tests/ui/arithmetic_side_effects.rs:445:5
|
LL | i /= var1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:447:5
+ --> tests/ui/arithmetic_side_effects.rs:446:5
|
LL | i /= var2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:449:5
+ --> tests/ui/arithmetic_side_effects.rs:448:5
|
LL | i %= 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:451:5
+ --> tests/ui/arithmetic_side_effects.rs:450:5
|
LL | i %= var1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:452:5
+ --> tests/ui/arithmetic_side_effects.rs:451:5
|
LL | i %= var2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:462:5
+ --> tests/ui/arithmetic_side_effects.rs:461:5
|
LL | 10 / a
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:516:9
+ --> tests/ui/arithmetic_side_effects.rs:515:9
|
LL | x / maybe_zero
| ^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:520:9
+ --> tests/ui/arithmetic_side_effects.rs:519:9
|
LL | x % maybe_zero
| ^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:531:5
+ --> tests/ui/arithmetic_side_effects.rs:530:5
|
LL | one.add_assign(1);
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> tests/ui/arithmetic_side_effects.rs:535:5
+ --> tests/ui/arithmetic_side_effects.rs:534:5
|
LL | one.sub_assign(1);
| ^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs b/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs
index 33cea480681..a7d29cc239e 100644
--- a/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs
+++ b/src/tools/clippy/tests/ui/asm_syntax_not_x86.rs
@@ -1,5 +1,4 @@
-//@ignore-target-i686
-//@ignore-target-x86
+//@ignore-target: i686 x86
//@needs-asm-support
#[warn(clippy::inline_asm_x86_intel_syntax)]
diff --git a/src/tools/clippy/tests/ui/asm_syntax_x86.rs b/src/tools/clippy/tests/ui/asm_syntax_x86.rs
index 835943b4389..5ceaceb7527 100644
--- a/src/tools/clippy/tests/ui/asm_syntax_x86.rs
+++ b/src/tools/clippy/tests/ui/asm_syntax_x86.rs
@@ -1,6 +1,4 @@
-//@revisions: i686 x86_64
-//@[i686] only-target-i686
-//@[x86_64] only-target-x86_64
+//@only-target: i686 x86_64
#[warn(clippy::inline_asm_x86_intel_syntax)]
mod warn_intel {
diff --git a/src/tools/clippy/tests/ui/asm_syntax_x86.stderr b/src/tools/clippy/tests/ui/asm_syntax_x86.stderr
new file mode 100644
index 00000000000..1911ef66e23
--- /dev/null
+++ b/src/tools/clippy/tests/ui/asm_syntax_x86.stderr
@@ -0,0 +1,70 @@
+error: Intel x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:8:9
+ |
+LL | asm!("");
+ | ^^^^^^^^
+ |
+ = help: use AT&T x86 assembly syntax
+ = note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_intel_syntax)]`
+
+error: Intel x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:10:9
+ |
+LL | asm!("", options());
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use AT&T x86 assembly syntax
+
+error: Intel x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:12:9
+ |
+LL | asm!("", options(nostack));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use AT&T x86 assembly syntax
+
+error: Intel x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:18:5
+ |
+LL | global_asm!("");
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: use AT&T x86 assembly syntax
+
+error: Intel x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:20:5
+ |
+LL | global_asm!("", options());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use AT&T x86 assembly syntax
+
+error: AT&T x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:33:9
+ |
+LL | asm!("", options(att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use Intel x86 assembly syntax
+ = note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_att_syntax)]`
+
+error: AT&T x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:35:9
+ |
+LL | asm!("", options(nostack, att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use Intel x86 assembly syntax
+
+error: AT&T x86 assembly syntax used
+ --> tests/ui/asm_syntax_x86.rs:41:5
+ |
+LL | global_asm!("", options(att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use Intel x86 assembly syntax
+
+error: aborting due to 8 previous errors
+
diff --git a/src/tools/clippy/tests/ui/auxiliary/external_item.rs b/src/tools/clippy/tests/ui/auxiliary/external_item.rs
new file mode 100644
index 00000000000..ca4bc369e44
--- /dev/null
+++ b/src/tools/clippy/tests/ui/auxiliary/external_item.rs
@@ -0,0 +1,7 @@
+pub struct _ExternalStruct {}
+
+impl _ExternalStruct {
+ pub fn _foo(self) {}
+}
+
+pub fn _exernal_foo() {}
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index f6fdebaf252..e72d6b6cead 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -11,8 +11,8 @@ use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::token::Star;
use syn::{
- parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent,
- PatType, Signature, TraitItem, Type, Visibility,
+ FnArg, ImplItem, ItemFn, ItemImpl, ItemStruct, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature, TraitItem,
+ Type, Visibility, parse_macro_input, parse_quote,
};
#[proc_macro_attribute]
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index 4c3df472269..bd90042c1da 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -5,7 +5,7 @@
extern crate proc_macro;
-use proc_macro::{quote, Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree, quote};
#[proc_macro_derive(DeriveSomething)]
pub fn derive(_: TokenStream) -> TokenStream {
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
index 79e8eff3aa1..3d6f164d358 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs
@@ -1,5 +1,5 @@
extern crate proc_macro;
-use proc_macro::{token_stream, Delimiter, Group, Ident, Span, TokenStream, TokenTree};
+use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree, token_stream};
fn read_ident(iter: &mut token_stream::IntoIter) -> Ident {
match iter.next() {
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
index ed7412f7c40..1a2a4ec2311 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
@@ -5,9 +5,9 @@
extern crate proc_macro;
use core::mem;
-use proc_macro::token_stream::IntoIter;
use proc_macro::Delimiter::{self, Brace, Parenthesis};
use proc_macro::Spacing::{self, Alone, Joint};
+use proc_macro::token_stream::IntoIter;
use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT};
use syn::spanned::Spanned;
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
index 452d1b19813..de220505c3e 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
@@ -5,8 +5,8 @@
use std::borrow::Cow;
use std::cell::{Cell, UnsafeCell};
use std::fmt::Display;
-use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Once;
+use std::sync::atomic::{AtomicUsize, Ordering};
const ATOMIC: AtomicUsize = AtomicUsize::new(5);
const CELL: Cell<usize> = Cell::new(6);
diff --git a/src/tools/clippy/tests/ui/cast_alignment.rs b/src/tools/clippy/tests/ui/cast_alignment.rs
index 98ef5e36f94..72f5d4268cc 100644
--- a/src/tools/clippy/tests/ui/cast_alignment.rs
+++ b/src/tools/clippy/tests/ui/cast_alignment.rs
@@ -2,16 +2,16 @@
#![feature(rustc_private)]
#![feature(core_intrinsics)]
-extern crate libc;
-
-#[warn(clippy::cast_ptr_alignment)]
-#[allow(
+#![warn(clippy::cast_ptr_alignment)]
+#![allow(
clippy::no_effect,
clippy::unnecessary_operation,
clippy::cast_lossless,
clippy::borrow_as_ptr
)]
+extern crate libc;
+
fn main() {
/* These should be warned against */
diff --git a/src/tools/clippy/tests/ui/cmp_owned/without_suggestion.rs b/src/tools/clippy/tests/ui/cmp_owned/without_suggestion.rs
index ec45d635c17..913aab72747 100644
--- a/src/tools/clippy/tests/ui/cmp_owned/without_suggestion.rs
+++ b/src/tools/clippy/tests/ui/cmp_owned/without_suggestion.rs
@@ -1,5 +1,5 @@
-#[allow(clippy::unnecessary_operation)]
-#[allow(clippy::implicit_clone)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::implicit_clone)]
fn main() {
let x = &Baz;
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.fixed b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
index 3b410b2f17b..c2d76146c64 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.fixed
@@ -1,9 +1,7 @@
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)]
+#![warn(clippy::collapsible_if, clippy::collapsible_else_if)]
#[rustfmt::skip]
-#[warn(clippy::collapsible_if)]
-#[warn(clippy::collapsible_else_if)]
-
fn main() {
let x = "hello";
let y = "world";
@@ -76,7 +74,6 @@ fn main() {
}
#[rustfmt::skip]
-#[allow(dead_code)]
fn issue_7318() {
if true { println!("I've been resolved!")
}else if false {}
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.rs b/src/tools/clippy/tests/ui/collapsible_else_if.rs
index 772ef6f9fc6..3579e46cd44 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.rs
@@ -1,9 +1,7 @@
#![allow(clippy::assertions_on_constants, clippy::equatable_if_let, clippy::needless_if)]
+#![warn(clippy::collapsible_if, clippy::collapsible_else_if)]
#[rustfmt::skip]
-#[warn(clippy::collapsible_if)]
-#[warn(clippy::collapsible_else_if)]
-
fn main() {
let x = "hello";
let y = "world";
@@ -90,7 +88,6 @@ fn main() {
}
#[rustfmt::skip]
-#[allow(dead_code)]
fn issue_7318() {
if true { println!("I've been resolved!")
}else{
diff --git a/src/tools/clippy/tests/ui/collapsible_else_if.stderr b/src/tools/clippy/tests/ui/collapsible_else_if.stderr
index dc19d90b4d1..395c2dcf68d 100644
--- a/src/tools/clippy/tests/ui/collapsible_else_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_else_if.stderr
@@ -1,5 +1,5 @@
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:13:12
+ --> tests/ui/collapsible_else_if.rs:11:12
|
LL | } else {
| ____________^
@@ -19,7 +19,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:21:12
+ --> tests/ui/collapsible_else_if.rs:19:12
|
LL | } else {
| ____________^
@@ -37,7 +37,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:29:12
+ --> tests/ui/collapsible_else_if.rs:27:12
|
LL | } else {
| ____________^
@@ -60,7 +60,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:40:12
+ --> tests/ui/collapsible_else_if.rs:38:12
|
LL | } else {
| ____________^
@@ -83,7 +83,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:51:12
+ --> tests/ui/collapsible_else_if.rs:49:12
|
LL | } else {
| ____________^
@@ -106,7 +106,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:62:12
+ --> tests/ui/collapsible_else_if.rs:60:12
|
LL | } else {
| ____________^
@@ -129,7 +129,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:73:12
+ --> tests/ui/collapsible_else_if.rs:71:12
|
LL | } else {
| ____________^
@@ -152,7 +152,7 @@ LL + }
|
error: this `else { if .. }` block can be collapsed
- --> tests/ui/collapsible_else_if.rs:96:10
+ --> tests/ui/collapsible_else_if.rs:93:10
|
LL | }else{
| __________^
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.fixed b/src/tools/clippy/tests/ui/comparison_to_empty.fixed
index e102b13a761..a2a3dd9086d 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.fixed
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.fixed
@@ -33,4 +33,12 @@ fn main() {
if let [0] = &*s
&& s == [0]
{}
+
+ // Also lint the `PartialEq` methods
+ let s = String::new();
+ let _ = s.is_empty();
+ let _ = !s.is_empty();
+ let v = vec![0];
+ let _ = v.is_empty();
+ let _ = !v.is_empty();
}
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.rs b/src/tools/clippy/tests/ui/comparison_to_empty.rs
index 69a6c967d38..7c5689a4bbe 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.rs
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.rs
@@ -33,4 +33,12 @@ fn main() {
if let [0] = &*s
&& s == [0]
{}
+
+ // Also lint the `PartialEq` methods
+ let s = String::new();
+ let _ = s.eq("");
+ let _ = s.ne("");
+ let v = vec![0];
+ let _ = v.eq(&[]);
+ let _ = v.ne(&[]);
}
diff --git a/src/tools/clippy/tests/ui/comparison_to_empty.stderr b/src/tools/clippy/tests/ui/comparison_to_empty.stderr
index 6b027459ed3..2ee0efc7dbb 100644
--- a/src/tools/clippy/tests/ui/comparison_to_empty.stderr
+++ b/src/tools/clippy/tests/ui/comparison_to_empty.stderr
@@ -55,5 +55,29 @@ error: comparison to empty slice
LL | && s == []
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
-error: aborting due to 9 previous errors
+error: comparison to empty slice
+ --> tests/ui/comparison_to_empty.rs:39:13
+ |
+LL | let _ = s.eq("");
+ | ^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
+
+error: comparison to empty slice
+ --> tests/ui/comparison_to_empty.rs:40:13
+ |
+LL | let _ = s.ne("");
+ | ^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`
+
+error: comparison to empty slice
+ --> tests/ui/comparison_to_empty.rs:42:13
+ |
+LL | let _ = v.eq(&[]);
+ | ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`
+
+error: comparison to empty slice
+ --> tests/ui/comparison_to_empty.rs:43:13
+ |
+LL | let _ = v.ne(&[]);
+ | ^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`
+
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/crashes/associated-constant-ice.rs b/src/tools/clippy/tests/ui/crashes/associated-constant-ice.rs
index 948deba3ea6..fec16671eeb 100644
--- a/src/tools/clippy/tests/ui/crashes/associated-constant-ice.rs
+++ b/src/tools/clippy/tests/ui/crashes/associated-constant-ice.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1698
+// Test for https://github.com/rust-lang/rust-clippy/issues/1698
pub trait Trait {
const CONSTANT: u8;
diff --git a/src/tools/clippy/tests/ui/crashes/cc_seme.rs b/src/tools/clippy/tests/ui/crashes/cc_seme.rs
index 98588be9cf8..98897d6d7aa 100644
--- a/src/tools/clippy/tests/ui/crashes/cc_seme.rs
+++ b/src/tools/clippy/tests/ui/crashes/cc_seme.rs
@@ -1,6 +1,4 @@
-#[allow(dead_code)]
-
-/// Test for https://github.com/rust-lang/rust-clippy/issues/478
+// Test for https://github.com/rust-lang/rust-clippy/issues/478
enum Baz {
One,
diff --git a/src/tools/clippy/tests/ui/crashes/ice-11230.rs b/src/tools/clippy/tests/ui/crashes/ice-11230.rs
index 5761882273e..94044e9435e 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-11230.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-11230.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/11230
+// Test for https://github.com/rust-lang/rust-clippy/issues/11230
fn main() {
const A: &[for<'a> fn(&'a ())] = &[];
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1588.rs b/src/tools/clippy/tests/ui/crashes/ice-1588.rs
index b0a3d11bce4..9ec093721c1 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1588.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1588.rs
@@ -1,6 +1,6 @@
#![allow(clippy::all)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1588
+// Test for https://github.com/rust-lang/rust-clippy/issues/1588
fn main() {
match 1 {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-1969.rs b/src/tools/clippy/tests/ui/crashes/ice-1969.rs
index 96a8fe6c24d..eb901c76729 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-1969.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-1969.rs
@@ -1,6 +1,6 @@
#![allow(clippy::all)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1969
+// Test for https://github.com/rust-lang/rust-clippy/issues/1969
fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2499.rs b/src/tools/clippy/tests/ui/crashes/ice-2499.rs
index 45b3b1869dd..732f331ad14 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2499.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-2499.rs
@@ -1,8 +1,8 @@
#![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)]
-/// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
-///
-/// Issue: https://github.com/rust-lang/rust-clippy/issues/2499
+// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
+//
+// Issue: https://github.com/rust-lang/rust-clippy/issues/2499
fn f(s: &[u8]) -> bool {
let t = s[0] as char;
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2594.rs b/src/tools/clippy/tests/ui/crashes/ice-2594.rs
index 3f3986b6fc6..dddf860bd17 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2594.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-2594.rs
@@ -3,7 +3,6 @@
/// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
///
/// Issue: https://github.com/rust-lang/rust-clippy/issues/2594
-
fn spanless_hash_ice() {
let txt = "something";
let empty_header: [u8; 1] = [1; 1];
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2727.rs b/src/tools/clippy/tests/ui/crashes/ice-2727.rs
index 56024abc8f5..59fb9b04b86 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2727.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-2727.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2727
+// Test for https://github.com/rust-lang/rust-clippy/issues/2727
pub fn f(new: fn()) {
new();
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2760.rs b/src/tools/clippy/tests/ui/crashes/ice-2760.rs
index 61ef2480498..5f7d91abf99 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2760.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-2760.rs
@@ -5,10 +5,10 @@
dead_code
)]
-/// This should not compile-fail with:
-///
-/// error[E0277]: the trait bound `T: Foo` is not satisfied
-// See rust-lang/rust-clippy#2760.
+// This should not compile-fail with:
+//
+// error[E0277]: the trait bound `T: Foo` is not satisfied
+// See https://github.com/rust-lang/rust-clippy/issues/2760
trait Foo {
type Bar;
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2862.rs b/src/tools/clippy/tests/ui/crashes/ice-2862.rs
index 8326e3663b0..2573b571f55 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2862.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-2862.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2862
+// Test for https://github.com/rust-lang/rust-clippy/issues/2862
pub trait FooMap {
fn map<B, F: Fn() -> B>(&self, f: F) -> B;
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2865.rs b/src/tools/clippy/tests/ui/crashes/ice-2865.rs
index c6298139601..28363707acc 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2865.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-2865.rs
@@ -1,6 +1,6 @@
#![allow(dead_code, clippy::extra_unused_lifetimes)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2865
+// Test for https://github.com/rust-lang/rust-clippy/issues/2865
struct Ice {
size: String,
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3151.rs b/src/tools/clippy/tests/ui/crashes/ice-3151.rs
index 268ba86fc7a..f88a26cb485 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3151.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3151.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/3151
+// Test for https://github.com/rust-lang/rust-clippy/issues/3151
#[derive(Clone)]
pub struct HashMap<V, S> {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3462.rs b/src/tools/clippy/tests/ui/crashes/ice-3462.rs
index 21cd9d337cd..ccd617e305d 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3462.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3462.rs
@@ -2,7 +2,7 @@
#![allow(clippy::disallowed_names, clippy::equatable_if_let, clippy::needless_if)]
#![allow(unused)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/3462
+// Test for https://github.com/rust-lang/rust-clippy/issues/3462
enum Foo {
Bar,
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3747.rs b/src/tools/clippy/tests/ui/crashes/ice-3747.rs
index cdf018cbc88..44b1d7ed1b2 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3747.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3747.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/3747
+// Test for https://github.com/rust-lang/rust-clippy/issues/3747
macro_rules! a {
( $pub:tt $($attr:tt)* ) => {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3969.rs b/src/tools/clippy/tests/ui/crashes/ice-3969.rs
index d5676cbd91d..ac09ce08753 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3969.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-3969.rs
@@ -1,7 +1,7 @@
// https://github.com/rust-lang/rust-clippy/issues/3969
// used to crash: error: internal compiler error:
// src/librustc_traits/normalize_erasing_regions.rs:43: could not fully normalize `<i32 as
-// std::iter::Iterator>::Item test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs
+// std::iter::Iterator>::Item` test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs
// Check that tautalogically false bounds are accepted, and are used
// in type inference.
@@ -18,7 +18,7 @@ struct Dst<X: ?Sized> {
struct TwoStrs(str, str)
where
str: Sized;
-//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetim
+//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetime
//~| NOTE: `-D trivial-bounds` implied by `-D warnings`
fn unsized_local()
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6251.rs b/src/tools/clippy/tests/ui/crashes/ice-6251.rs
index a81137a6465..73e919b6dd2 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6251.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6251.rs
@@ -1,5 +1,5 @@
// originally from glacier/fixed/77329.rs
-// assertion failed: `(left == right) ; different DefIds
+// assertion failed: `(left == right)` ; different DefIds
//@no-rustfix
fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
std::iter::empty()
diff --git a/src/tools/clippy/tests/ui/crashes/ice-700.rs b/src/tools/clippy/tests/ui/crashes/ice-700.rs
index 0cbceedbd6b..5e004b94330 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-700.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-700.rs
@@ -1,6 +1,6 @@
#![deny(clippy::all)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/700
+// Test for https://github.com/rust-lang/rust-clippy/issues/700
fn core() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7410.rs b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
index a2683b3ce34..ccf6d7ff94f 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7410.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7410.rs
@@ -1,6 +1,5 @@
//@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-target-apple
-//@ignore-target-windows
+//@ignore-target: apple windows
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs b/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
index 30e4b11ec0b..c0671eaff14 100644
--- a/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice_exact_size.rs
@@ -1,6 +1,6 @@
#![deny(clippy::all)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1336
+// Test for https://github.com/rust-lang/rust-clippy/issues/1336
#[allow(dead_code)]
struct Foo;
diff --git a/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs b/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs
index 2f913292995..a900fe5e6bc 100644
--- a/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs
+++ b/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs
@@ -1,7 +1,7 @@
#![allow(clippy::comparison_chain)]
#![deny(clippy::if_same_then_else)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2426
+// Test for https://github.com/rust-lang/rust-clippy/issues/2426
fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/inherent_impl.rs b/src/tools/clippy/tests/ui/crashes/inherent_impl.rs
index aeb27b5ba8c..800a5a383f6 100644
--- a/src/tools/clippy/tests/ui/crashes/inherent_impl.rs
+++ b/src/tools/clippy/tests/ui/crashes/inherent_impl.rs
@@ -1,6 +1,6 @@
#![deny(clippy::multiple_inherent_impl)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/4578
+// Test for https://github.com/rust-lang/rust-clippy/issues/4578
macro_rules! impl_foo {
($struct:ident) => {
diff --git a/src/tools/clippy/tests/ui/crashes/issue-825.rs b/src/tools/clippy/tests/ui/crashes/issue-825.rs
index 05696e3d7d5..e8b455a0ec6 100644
--- a/src/tools/clippy/tests/ui/crashes/issue-825.rs
+++ b/src/tools/clippy/tests/ui/crashes/issue-825.rs
@@ -1,6 +1,6 @@
#![allow(warnings)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/825
+// Test for https://github.com/rust-lang/rust-clippy/issues/825
// this should compile in a reasonable amount of time
fn rust_type_id(name: &str) {
diff --git a/src/tools/clippy/tests/ui/crashes/match_same_arms_const.rs b/src/tools/clippy/tests/ui/crashes/match_same_arms_const.rs
index 94c939665e6..626179c0015 100644
--- a/src/tools/clippy/tests/ui/crashes/match_same_arms_const.rs
+++ b/src/tools/clippy/tests/ui/crashes/match_same_arms_const.rs
@@ -1,6 +1,6 @@
#![deny(clippy::match_same_arms)]
-/// Test for https://github.com/rust-lang/rust-clippy/issues/2427
+// Test for https://github.com/rust-lang/rust-clippy/issues/2427
const PRICE_OF_SWEETS: u32 = 5;
const PRICE_OF_KINDNESS: u32 = 0;
diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
index 90076d4338a..28479570006 100644
--- a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
+++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
@@ -4,7 +4,7 @@ error: this argument is passed by value, but not consumed in the function body
LL | fn test(x: Foo<'_>) {}
| ^^^^^^^ help: consider taking a reference instead: `&Foo<'_>`
|
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
--> tests/ui/crashes/needless_pass_by_value-w-late-bound.rs:5:1
|
LL | struct Foo<'a>(&'a [(); 100]);
diff --git a/src/tools/clippy/tests/ui/crashes/returns.rs b/src/tools/clippy/tests/ui/crashes/returns.rs
index 8021ed4607d..91cdb5306c8 100644
--- a/src/tools/clippy/tests/ui/crashes/returns.rs
+++ b/src/tools/clippy/tests/ui/crashes/returns.rs
@@ -1,4 +1,4 @@
-/// Test for https://github.com/rust-lang/rust-clippy/issues/1346
+// Test for https://github.com/rust-lang/rust-clippy/issues/1346
#[deny(warnings)]
fn cfg_return() -> i32 {
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
index aa76688d801..5d853d97bc3 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
@@ -1,4 +1,4 @@
-//@ignore-target-apple
+//@ignore-target: apple
#![feature(rustc_attrs)]
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
index 32eba969592..9e5b2a48903 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs
@@ -1,5 +1,5 @@
//@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-target-apple
+//@ignore-target: apple
#![feature(lang_items, start, libc)]
#![no_std]
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
index 9dafad8b784..0dccf18c493 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/others.rs
@@ -4,8 +4,8 @@ use std::borrow::Cow;
use std::cell::Cell;
use std::fmt::Display;
use std::ptr;
-use std::sync::atomic::AtomicUsize;
use std::sync::Once;
+use std::sync::atomic::AtomicUsize;
const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR: interior mutable
const CELL: Cell<usize> = Cell::new(6); //~ ERROR: interior mutable
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index 190d636ebf3..c9650312db8 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -1,4 +1,4 @@
-//@ignore-target-apple
+//@ignore-target: apple
#![feature(no_core, lang_items, start)]
#![no_core]
diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.rs b/src/tools/clippy/tests/ui/diverging_sub_expression.rs
index e0acf050949..1abba60fd34 100644
--- a/src/tools/clippy/tests/ui/diverging_sub_expression.rs
+++ b/src/tools/clippy/tests/ui/diverging_sub_expression.rs
@@ -67,3 +67,9 @@ fn foobar() {
};
}
}
+
+#[allow(unused)]
+fn ignore_todo() {
+ let x: u32 = todo!();
+ println!("{x}");
+}
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.fixed b/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.fixed
deleted file mode 100644
index 1aaa26afe7f..00000000000
--- a/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.fixed
+++ /dev/null
@@ -1,47 +0,0 @@
-// https://github.com/rust-lang/rust-clippy/issues/12917
-#![warn(clippy::doc_lazy_continuation)]
-
-/// This is a constant.
-///
-/// The meaning of which should not be explained.
-pub const A: i32 = 42;
-
-/// This is another constant, no longer used.
-///
-/// This block of documentation has a long
-/// explanation and derivation to explain
-/// why it is what it is, and how it's used.
-///
-/// It is left here for historical reasons, and
-/// for reference.
-///
-/// Reasons it's great:
-/// - First reason
-/// - Second reason
-///
-//pub const B: i32 = 1337;
-
-/// This is yet another constant.
-///
-/// This has a similar fate as `B`.
-///
-/// Reasons it's useful:
-/// 1. First reason
-/// 2. Second reason
-///
-//pub const C: i32 = 8008;
-
-/// This is still in use.
-pub const D: i32 = 20;
-
-/// > blockquote code path
-///
-
-/// bottom text
-pub const E: i32 = 20;
-
-/// > blockquote code path
-///
-#[repr(C)]
-/// bottom text
-pub struct Foo(i32);
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.rs b/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.rs
deleted file mode 100644
index e1ab8fc8389..00000000000
--- a/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// https://github.com/rust-lang/rust-clippy/issues/12917
-#![warn(clippy::doc_lazy_continuation)]
-
-/// This is a constant.
-///
-/// The meaning of which should not be explained.
-pub const A: i32 = 42;
-
-/// This is another constant, no longer used.
-///
-/// This block of documentation has a long
-/// explanation and derivation to explain
-/// why it is what it is, and how it's used.
-///
-/// It is left here for historical reasons, and
-/// for reference.
-///
-/// Reasons it's great:
-/// - First reason
-/// - Second reason
-//pub const B: i32 = 1337;
-
-/// This is yet another constant.
-///
-/// This has a similar fate as `B`.
-///
-/// Reasons it's useful:
-/// 1. First reason
-/// 2. Second reason
-//pub const C: i32 = 8008;
-
-/// This is still in use.
-pub const D: i32 = 20;
-
-/// > blockquote code path
-
-/// bottom text
-pub const E: i32 = 20;
-
-/// > blockquote code path
-#[repr(C)]
-/// bottom text
-pub struct Foo(i32);
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.stderr b/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.stderr
deleted file mode 100644
index 854906a7474..00000000000
--- a/src/tools/clippy/tests/ui/doc/doc_lazy_blank_line.stderr
+++ /dev/null
@@ -1,56 +0,0 @@
-error: doc list item without indentation
- --> tests/ui/doc/doc_lazy_blank_line.rs:23:5
- |
-LL | /// This is yet another constant.
- | ^
- |
- = help: if this is intended to be part of the list, indent 3 spaces
- = note: `-D clippy::doc-lazy-continuation` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::doc_lazy_continuation)]`
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// - Second reason
-LL + ///
- |
-
-error: doc list item without indentation
- --> tests/ui/doc/doc_lazy_blank_line.rs:32:5
- |
-LL | /// This is still in use.
- | ^
- |
- = help: if this is intended to be part of the list, indent 4 spaces
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// 2. Second reason
-LL + ///
- |
-
-error: doc quote line without `>` marker
- --> tests/ui/doc/doc_lazy_blank_line.rs:37:5
- |
-LL | /// bottom text
- | ^
- |
- = help: if this not intended to be a quote at all, escape it with `\>`
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// > blockquote code path
-LL + ///
- |
-
-error: doc quote line without `>` marker
- --> tests/ui/doc/doc_lazy_blank_line.rs:42:5
- |
-LL | /// bottom text
- | ^
- |
- = help: if this not intended to be a quote at all, escape it with `\>`
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// > blockquote code path
-LL + ///
- |
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed b/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed
index ea59ae4c01c..da537518a2b 100644
--- a/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_list.fixed
@@ -7,9 +7,8 @@ fn one() {}
/// 1. first line
/// lazy list continuations don't make warnings with this lint
-///
//~^ ERROR: doc list item without indentation
-/// because they don't have the
+/// because they don't have the
//~^ ERROR: doc list item without indentation
fn two() {}
@@ -20,9 +19,8 @@ fn three() {}
/// - first line
/// lazy list continuations don't make warnings with this lint
-///
//~^ ERROR: doc list item without indentation
-/// because they don't have the
+/// because they don't have the
//~^ ERROR: doc list item without indentation
fn four() {}
@@ -33,9 +31,8 @@ fn five() {}
/// - - first line
/// this will warn on the lazy continuation
-///
//~^ ERROR: doc list item without indentation
-/// and so should this
+/// and so should this
//~^ ERROR: doc list item without indentation
fn six() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr b/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr
index 52aa74df894..b38f43b7555 100644
--- a/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc_lazy_list.stderr
@@ -30,12 +30,11 @@ error: doc list item without indentation
LL | /// because they don't have the
| ^
|
- = help: if this is intended to be part of the list, indent 3 spaces
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// lazy list continuations don't make warnings with this lint
-LL + ///
+ = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
|
+LL | /// because they don't have the
+ | +++
error: doc list item without indentation
--> tests/ui/doc/doc_lazy_list.rs:16:5
@@ -67,12 +66,11 @@ error: doc list item without indentation
LL | /// because they don't have the
| ^
|
- = help: if this is intended to be part of the list, indent 4 spaces
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// lazy list continuations don't make warnings with this lint
-LL + ///
+ = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
|
+LL | /// because they don't have the
+ | ++++
error: doc list item without indentation
--> tests/ui/doc/doc_lazy_list.rs:28:5
@@ -104,12 +102,11 @@ error: doc list item without indentation
LL | /// and so should this
| ^^^^
|
- = help: if this is intended to be part of the list, indent 2 spaces
-help: if this should be its own paragraph, add a blank doc comment line
- |
-LL ~ /// this will warn on the lazy continuation
-LL + ///
+ = help: if this is supposed to be its own paragraph, add a blank line
+help: indent this line
|
+LL | /// and so should this
+ | ++
error: doc list item without indentation
--> tests/ui/doc/doc_lazy_list.rs:56:5
diff --git a/src/tools/clippy/tests/ui/duplicate_underscore_argument.rs b/src/tools/clippy/tests/ui/duplicate_underscore_argument.rs
index 118f6e4a34c..a725538436c 100644
--- a/src/tools/clippy/tests/ui/duplicate_underscore_argument.rs
+++ b/src/tools/clippy/tests/ui/duplicate_underscore_argument.rs
@@ -1,5 +1,4 @@
#![warn(clippy::duplicate_underscore_argument)]
-#[allow(dead_code, unused)]
fn join_the_dark_side(darth: i32, _darth: i32) {}
//~^ ERROR: `darth` already exists, having another argument having almost the same name ma
diff --git a/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr b/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr
index 40a24b823d1..74979b15788 100644
--- a/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr
+++ b/src/tools/clippy/tests/ui/duplicate_underscore_argument.stderr
@@ -1,5 +1,5 @@
error: `darth` already exists, having another argument having almost the same name makes code comprehension and documentation more difficult
- --> tests/ui/duplicate_underscore_argument.rs:4:23
+ --> tests/ui/duplicate_underscore_argument.rs:3:23
|
LL | fn join_the_dark_side(darth: i32, _darth: i32) {}
| ^^^^^
diff --git a/src/tools/clippy/tests/ui/duplicated_attributes.rs b/src/tools/clippy/tests/ui/duplicated_attributes.rs
index 97cf4a69682..874f5d22075 100644
--- a/src/tools/clippy/tests/ui/duplicated_attributes.rs
+++ b/src/tools/clippy/tests/ui/duplicated_attributes.rs
@@ -27,4 +27,8 @@ trait Abc {}
#[proc_macro_attr::duplicated_attr()] // Should not warn!
fn babar() {}
+#[allow(missing_docs, reason = "library for internal use only")]
+#[allow(exported_private_dependencies, reason = "library for internal use only")]
+fn duplicate_reason() {}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed
new file mode 100644
index 00000000000..fd6a94b6a80
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed
@@ -0,0 +1,135 @@
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~vvv empty_line_after_doc_comments
+/// Meant to be an
+/// inner doc comment
+/// for the crate
+fn first_in_crate() {}
+
+mod m {
+ //~vvv empty_line_after_doc_comments
+ /// Meant to be an
+ /// inner doc comment
+ /// for the module
+ fn first_in_module() {}
+}
+
+mod some_mod {
+ //! This doc comment should *NOT* produce a warning
+
+ mod some_inner_mod {
+ fn some_noop() {}
+ }
+
+ //~v empty_line_after_doc_comments
+ /// # Indented
+ /// Blank line
+ fn indented() {}
+}
+
+//~v empty_line_after_doc_comments
+/// This should produce a warning
+fn with_doc_and_newline() {}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_doc_comments
+/// This doc comment should produce a warning
+/** This is also a doc comment and is part of the warning
+ */
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(dead_code)]
+fn three_attributes() {}
+
+mod misattributed {
+ //~v empty_line_after_doc_comments
+ /// docs for `old_code`
+ // fn old_code() {}
+ fn new_code() {}
+
+ //~vv empty_line_after_doc_comments
+ /// Docs
+ /// for OldA
+ // struct OldA;
+ /// Docs
+ /// for OldB
+ // struct OldB;
+ /// Docs
+ /// for Multiple
+ #[allow(dead_code)]
+ struct Multiple;
+}
+
+mod block_comments {
+ //~v empty_line_after_doc_comments
+ /**
+ * Meant to be inner doc comment
+ */
+ fn first_in_module() {}
+
+ //~v empty_line_after_doc_comments
+ /**
+ * Docs for `old_code`
+ */
+ /* fn old_code() {} */
+ /**
+ * Docs for `new_code`
+ */
+ fn new_code() {}
+
+ //~v empty_line_after_doc_comments
+ /// Docs for `old_code2`
+ /* fn old_code2() {} */
+ /// Docs for `new_code2`
+ fn new_code2() {}
+}
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4,
+}
+
+/// Should not lint
+// some line comment
+/// gaps without an empty line
+struct LineComment;
+
+/// This should *NOT* produce a warning because the empty line is inside a block comment
+/*
+
+*/
+pub struct EmptyInBlockComment;
+
+/// This should *NOT* produce a warning
+/* test */
+pub struct BlockComment;
+
+/// Ignore the empty line inside a cfg_attr'd out attribute
+#[cfg_attr(any(), multiline(
+ foo = 1
+
+ bar = 2
+))]
+fn empty_line_in_cfg_attr() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed
new file mode 100644
index 00000000000..7a57dcd9233
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed
@@ -0,0 +1,144 @@
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~vvv empty_line_after_doc_comments
+//! Meant to be an
+//! inner doc comment
+//! for the crate
+
+fn first_in_crate() {}
+
+mod m {
+ //~vvv empty_line_after_doc_comments
+ //! Meant to be an
+ //! inner doc comment
+ //! for the module
+
+ fn first_in_module() {}
+}
+
+mod some_mod {
+ //! This doc comment should *NOT* produce a warning
+
+ mod some_inner_mod {
+ fn some_noop() {}
+ }
+
+ //~v empty_line_after_doc_comments
+ /// # Indented
+ ///
+ /// Blank line
+ fn indented() {}
+}
+
+//~v empty_line_after_doc_comments
+/// This should produce a warning
+fn with_doc_and_newline() {}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_doc_comments
+/// This doc comment should produce a warning
+/** This is also a doc comment and is part of the warning
+ */
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(dead_code)]
+fn three_attributes() {}
+
+mod misattributed {
+ //~v empty_line_after_doc_comments
+ // /// docs for `old_code`
+ // fn old_code() {}
+
+ fn new_code() {}
+
+ //~vv empty_line_after_doc_comments
+ // /// Docs
+ // /// for OldA
+ // struct OldA;
+
+ // /// Docs
+ // /// for OldB
+ // struct OldB;
+
+ /// Docs
+ /// for Multiple
+ #[allow(dead_code)]
+ struct Multiple;
+}
+
+mod block_comments {
+ //~v empty_line_after_doc_comments
+ /*!
+ * Meant to be inner doc comment
+ */
+
+ fn first_in_module() {}
+
+ //~v empty_line_after_doc_comments
+ /*
+ * Docs for `old_code`
+ */
+ /* fn old_code() {} */
+
+ /**
+ * Docs for `new_code`
+ */
+ fn new_code() {}
+
+ //~v empty_line_after_doc_comments
+ // /// Docs for `old_code2`
+ /* fn old_code2() {} */
+
+ /// Docs for `new_code2`
+ fn new_code2() {}
+}
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4,
+}
+
+/// Should not lint
+// some line comment
+/// gaps without an empty line
+struct LineComment;
+
+/// This should *NOT* produce a warning because the empty line is inside a block comment
+/*
+
+*/
+pub struct EmptyInBlockComment;
+
+/// This should *NOT* produce a warning
+/* test */
+pub struct BlockComment;
+
+/// Ignore the empty line inside a cfg_attr'd out attribute
+#[cfg_attr(any(), multiline(
+ foo = 1
+
+ bar = 2
+))]
+fn empty_line_in_cfg_attr() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs
new file mode 100644
index 00000000000..1da761a5c3d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs
@@ -0,0 +1,147 @@
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~vvv empty_line_after_doc_comments
+/// Meant to be an
+/// inner doc comment
+/// for the crate
+
+fn first_in_crate() {}
+
+mod m {
+ //~vvv empty_line_after_doc_comments
+ /// Meant to be an
+ /// inner doc comment
+ /// for the module
+
+ fn first_in_module() {}
+}
+
+mod some_mod {
+ //! This doc comment should *NOT* produce a warning
+
+ mod some_inner_mod {
+ fn some_noop() {}
+ }
+
+ //~v empty_line_after_doc_comments
+ /// # Indented
+
+ /// Blank line
+ fn indented() {}
+}
+
+//~v empty_line_after_doc_comments
+/// This should produce a warning
+
+fn with_doc_and_newline() {}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_doc_comments
+/// This doc comment should produce a warning
+
+/** This is also a doc comment and is part of the warning
+ */
+
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(dead_code)]
+fn three_attributes() {}
+
+mod misattributed {
+ //~v empty_line_after_doc_comments
+ /// docs for `old_code`
+ // fn old_code() {}
+
+ fn new_code() {}
+
+ //~vv empty_line_after_doc_comments
+ /// Docs
+ /// for OldA
+ // struct OldA;
+
+ /// Docs
+ /// for OldB
+ // struct OldB;
+
+ /// Docs
+ /// for Multiple
+ #[allow(dead_code)]
+ struct Multiple;
+}
+
+mod block_comments {
+ //~v empty_line_after_doc_comments
+ /**
+ * Meant to be inner doc comment
+ */
+
+ fn first_in_module() {}
+
+ //~v empty_line_after_doc_comments
+ /**
+ * Docs for `old_code`
+ */
+ /* fn old_code() {} */
+
+ /**
+ * Docs for `new_code`
+ */
+ fn new_code() {}
+
+ //~v empty_line_after_doc_comments
+ /// Docs for `old_code2`
+ /* fn old_code2() {} */
+
+ /// Docs for `new_code2`
+ fn new_code2() {}
+}
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4,
+}
+
+/// Should not lint
+// some line comment
+/// gaps without an empty line
+struct LineComment;
+
+/// This should *NOT* produce a warning because the empty line is inside a block comment
+/*
+
+*/
+pub struct EmptyInBlockComment;
+
+/// This should *NOT* produce a warning
+/* test */
+pub struct BlockComment;
+
+/// Ignore the empty line inside a cfg_attr'd out attribute
+#[cfg_attr(any(), multiline(
+ foo = 1
+
+ bar = 2
+))]
+fn empty_line_in_cfg_attr() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
new file mode 100644
index 00000000000..c238b4c9a17
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr
@@ -0,0 +1,176 @@
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:6:1
+ |
+LL | / /// for the crate
+LL | |
+ | |_
+LL | fn first_in_crate() {}
+ | ------------------- the comment documents this function
+ |
+ = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]`
+ = help: if the empty line is unintentional remove it
+help: if the comment should document the crate use an inner doc comment
+ |
+LL ~ //! Meant to be an
+LL ~ //! inner doc comment
+LL ~ //! for the crate
+ |
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:14:5
+ |
+LL | / /// for the module
+LL | |
+ | |_
+LL | fn first_in_module() {}
+ | -------------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+help: if the comment should document the parent module use an inner doc comment
+ |
+LL ~ //! Meant to be an
+LL ~ //! inner doc comment
+LL ~ //! for the module
+ |
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:27:5
+ |
+LL | / /// # Indented
+LL | |
+ | |_
+LL | /// Blank line
+LL | fn indented() {}
+ | ------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+help: if the documentation should include the empty line include it in the comment
+ |
+LL | ///
+ |
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:34:1
+ |
+LL | / /// This should produce a warning
+LL | |
+ | |_
+LL | fn with_doc_and_newline() {}
+ | ------------------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty lines after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:44:1
+ |
+LL | / /// This doc comment should produce a warning
+LL | |
+LL | | /** This is also a doc comment and is part of the warning
+LL | | */
+LL | |
+ | |_
+...
+LL | fn three_attributes() {}
+ | --------------------- the comment documents this function
+ |
+ = help: if the empty lines are unintentional remove them
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:56:5
+ |
+LL | / /// docs for `old_code`
+LL | | // fn old_code() {}
+LL | |
+ | |_
+LL | fn new_code() {}
+ | ------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+help: if the doc comment should not document `new_code` comment it out
+ |
+LL | // /// docs for `old_code`
+ | ++
+
+error: empty lines after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:63:5
+ |
+LL | / /// for OldA
+LL | | // struct OldA;
+LL | |
+LL | | /// Docs
+LL | | /// for OldB
+LL | | // struct OldB;
+LL | |
+ | |_
+...
+LL | struct Multiple;
+ | --------------- the comment documents this struct
+ |
+ = help: if the empty lines are unintentional remove them
+help: if the doc comment should not document `Multiple` comment it out
+ |
+LL ~ // /// Docs
+LL ~ // /// for OldA
+LL | // struct OldA;
+LL |
+LL ~ // /// Docs
+LL ~ // /// for OldB
+ |
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:78:5
+ |
+LL | / /**
+LL | | * Meant to be inner doc comment
+LL | | */
+LL | |
+ | |_
+LL | fn first_in_module() {}
+ | -------------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+help: if the comment should document the parent module use an inner doc comment
+ |
+LL | /*!
+ | ~
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:85:5
+ |
+LL | / /**
+LL | | * Docs for `old_code`
+LL | | */
+LL | | /* fn old_code() {} */
+LL | |
+ | |_
+...
+LL | fn new_code() {}
+ | ------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+help: if the doc comment should not document `new_code` comment it out
+ |
+LL - /**
+LL + /*
+ |
+
+error: empty line after doc comment
+ --> tests/ui/empty_line_after/doc_comments.rs:96:5
+ |
+LL | / /// Docs for `old_code2`
+LL | | /* fn old_code2() {} */
+LL | |
+ | |_
+LL | /// Docs for `new_code2`
+LL | fn new_code2() {}
+ | -------------- the comment documents this function
+ |
+ = help: if the empty line is unintentional remove it
+help: if the doc comment should not document `new_code2` comment it out
+ |
+LL | // /// Docs for `old_code2`
+ | ++
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.1.fixed b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.1.fixed
new file mode 100644
index 00000000000..36d80a2c95b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.1.fixed
@@ -0,0 +1,108 @@
+//@aux-build:../auxiliary/proc_macro_attr.rs
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~v empty_line_after_outer_attr
+#[crate_type = "lib"]
+fn first_in_crate() {}
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+//~v empty_line_after_outer_attr
+#[inline]
+/// some comment
+fn with_one_newline_and_comment() {}
+
+#[inline]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+fn with_one_newline() {}
+
+#[rustfmt::skip]
+mod two_lines {
+ //~v empty_line_after_outer_attr
+ #[crate_type = "lib"]
+ fn with_two_newlines() {}
+}
+
+//~v empty_line_after_outer_attr
+#[doc = "doc attributes should be considered attributes"]
+enum Baz {
+ One,
+ Two,
+}
+
+//~v empty_line_after_outer_attr
+#[repr(C)]
+struct Foo {
+ one: isize,
+ two: isize,
+}
+
+//~v empty_line_after_outer_attr
+#[allow(dead_code)]
+mod foo {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+// Still lint cases where the empty line does not immediately follow the attribute
+fn comment_before_empty_line() {}
+
+//~v empty_line_after_outer_attr
+#[allow(unused)]
+// This comment is isolated
+pub fn isolated_comment() {}
+
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4,
+}
+
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct EmptyLineInBlockComment;
+
+#[crate_type = "lib"]
+/* test */
+pub struct BlockComment;
+
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[rustfmt::skip]
+#[fake_async_trait]
+pub trait Bazz {
+ fn foo() -> Vec<u8> {
+ let _i = "";
+
+
+
+ vec![]
+ }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.2.fixed b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.2.fixed
new file mode 100644
index 00000000000..0e8e4129e85
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.2.fixed
@@ -0,0 +1,111 @@
+//@aux-build:../auxiliary/proc_macro_attr.rs
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~v empty_line_after_outer_attr
+#![crate_type = "lib"]
+
+fn first_in_crate() {}
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+//~v empty_line_after_outer_attr
+#[inline]
+/// some comment
+fn with_one_newline_and_comment() {}
+
+#[inline]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+fn with_one_newline() {}
+
+#[rustfmt::skip]
+mod two_lines {
+ //~v empty_line_after_outer_attr
+ #![crate_type = "lib"]
+
+
+ fn with_two_newlines() {}
+}
+
+//~v empty_line_after_outer_attr
+#[doc = "doc attributes should be considered attributes"]
+enum Baz {
+ One,
+ Two,
+}
+
+//~v empty_line_after_outer_attr
+#[repr(C)]
+struct Foo {
+ one: isize,
+ two: isize,
+}
+
+//~v empty_line_after_outer_attr
+#[allow(dead_code)]
+mod foo {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+// Still lint cases where the empty line does not immediately follow the attribute
+fn comment_before_empty_line() {}
+
+//~v empty_line_after_outer_attr
+#[allow(unused)]
+// This comment is isolated
+pub fn isolated_comment() {}
+
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4,
+}
+
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct EmptyLineInBlockComment;
+
+#[crate_type = "lib"]
+/* test */
+pub struct BlockComment;
+
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[rustfmt::skip]
+#[fake_async_trait]
+pub trait Bazz {
+ fn foo() -> Vec<u8> {
+ let _i = "";
+
+
+
+ vec![]
+ }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.rs
new file mode 100644
index 00000000000..1295088ac00
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.rs
@@ -0,0 +1,119 @@
+//@aux-build:../auxiliary/proc_macro_attr.rs
+#![warn(clippy::empty_line_after_outer_attr, clippy::empty_line_after_doc_comments)]
+
+//~v empty_line_after_outer_attr
+#[crate_type = "lib"]
+
+fn first_in_crate() {}
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+//~v empty_line_after_outer_attr
+#[inline]
+
+/// some comment
+fn with_one_newline_and_comment() {}
+
+#[inline]
+/// some comment
+fn with_no_newline_and_comment() {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+
+fn with_one_newline() {}
+
+#[rustfmt::skip]
+mod two_lines {
+ //~v empty_line_after_outer_attr
+ #[crate_type = "lib"]
+
+
+ fn with_two_newlines() {}
+}
+
+//~v empty_line_after_outer_attr
+#[doc = "doc attributes should be considered attributes"]
+
+enum Baz {
+ One,
+ Two,
+}
+
+//~v empty_line_after_outer_attr
+#[repr(C)]
+
+struct Foo {
+ one: isize,
+ two: isize,
+}
+
+//~v empty_line_after_outer_attr
+#[allow(dead_code)]
+
+mod foo {}
+
+//~v empty_line_after_outer_attr
+#[inline]
+// Still lint cases where the empty line does not immediately follow the attribute
+
+fn comment_before_empty_line() {}
+
+//~v empty_line_after_outer_attr
+#[allow(unused)]
+
+// This comment is isolated
+
+pub fn isolated_comment() {}
+
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+ true
+}
+
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+ Bar1,
+
+ Bar2,
+
+ Bar3,
+
+ Bar4,
+}
+
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct EmptyLineInBlockComment;
+
+#[crate_type = "lib"]
+/* test */
+pub struct BlockComment;
+
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[rustfmt::skip]
+#[fake_async_trait]
+pub trait Bazz {
+ fn foo() -> Vec<u8> {
+ let _i = "";
+
+
+
+ vec![]
+ }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
new file mode 100644
index 00000000000..958b40424a9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after/outer_attribute.stderr
@@ -0,0 +1,116 @@
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:5:1
+ |
+LL | / #[crate_type = "lib"]
+LL | |
+ | |_
+LL | fn first_in_crate() {}
+ | ------------------- the attribute applies to this function
+ |
+ = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_outer_attr)]`
+ = help: if the empty line is unintentional remove it
+help: if the attribute should apply to the crate use an inner attribute
+ |
+LL | #![crate_type = "lib"]
+ | +
+
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:13:1
+ |
+LL | / #[inline]
+LL | |
+ | |_
+LL | /// some comment
+LL | fn with_one_newline_and_comment() {}
+ | --------------------------------- the attribute applies to this function
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:23:1
+ |
+LL | / #[inline]
+LL | |
+ | |_
+LL | fn with_one_newline() {}
+ | --------------------- the attribute applies to this function
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty lines after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:30:5
+ |
+LL | / #[crate_type = "lib"]
+LL | |
+LL | |
+ | |_
+LL | fn with_two_newlines() {}
+ | ---------------------- the attribute applies to this function
+ |
+ = help: if the empty lines are unintentional remove them
+help: if the attribute should apply to the parent module use an inner attribute
+ |
+LL | #![crate_type = "lib"]
+ | +
+
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:37:1
+ |
+LL | / #[doc = "doc attributes should be considered attributes"]
+LL | |
+ | |_
+LL | enum Baz {
+ | -------- the attribute applies to this enum
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:45:1
+ |
+LL | / #[repr(C)]
+LL | |
+ | |_
+LL | struct Foo {
+ | ---------- the attribute applies to this struct
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:53:1
+ |
+LL | / #[allow(dead_code)]
+LL | |
+ | |_
+LL | mod foo {}
+ | ------- the attribute applies to this module
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty line after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:58:1
+ |
+LL | / #[inline]
+LL | | // Still lint cases where the empty line does not immediately follow the attribute
+LL | |
+ | |_
+LL | fn comment_before_empty_line() {}
+ | ------------------------------ the attribute applies to this function
+ |
+ = help: if the empty line is unintentional remove it
+
+error: empty lines after outer attribute
+ --> tests/ui/empty_line_after/outer_attribute.rs:64:1
+ |
+LL | / #[allow(unused)]
+LL | |
+LL | | // This comment is isolated
+LL | |
+ | |_
+LL | pub fn isolated_comment() {}
+ | ------------------------- the attribute applies to this function
+ |
+ = help: if the empty lines are unintentional remove them
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
deleted file mode 100644
index dd78491749c..00000000000
--- a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-//@aux-build:proc_macro_attr.rs
-#![warn(clippy::empty_line_after_doc_comments)]
-#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)]
-#![feature(custom_inner_attributes)]
-#![rustfmt::skip]
-
-#[macro_use]
-extern crate proc_macro_attr;
-
-mod some_mod {
- //! This doc comment should *NOT* produce a warning
-
- mod some_inner_mod {
- fn some_noop() {}
- }
-}
-
-/// This should produce a warning
-
-fn with_doc_and_newline() { assert!(true)}
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-/// some comment
-fn with_one_newline_and_comment() { assert!(true) }
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-/// some comment
-fn with_no_newline_and_comment() { assert!(true) }
-
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-fn with_one_newline() { assert!(true) }
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-
-fn with_two_newlines() { assert!(true) }
-
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-enum Baz {
- One,
- Two
-}
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-struct Foo {
- one: isize,
- two: isize
-}
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-
-mod foo {
-}
-
-/// This doc comment should produce a warning
-
-/** This is also a doc comment and should produce a warning
- */
-
-// This should *NOT* produce a warning
-#[allow(non_camel_case_types)]
-#[allow(missing_docs)]
-#[allow(missing_docs)]
-fn three_attributes() { assert!(true) }
-
-// This should *NOT* produce a warning
-#[doc = "
-Returns the escaped value of the textual representation of
-
-"]
-pub fn function() -> bool {
- true
-}
-
-// This should *NOT* produce a warning
-#[derive(Clone, Copy)]
-pub enum FooFighter {
- Bar1,
-
- Bar2,
-
- Bar3,
-
- Bar4
-}
-
-// This should *NOT* produce a warning because the empty line is inside a block comment
-#[crate_type = "lib"]
-/*
-
-*/
-pub struct S;
-
-// This should *NOT* produce a warning
-#[crate_type = "lib"]
-/* test */
-pub struct T;
-
-// This should *NOT* produce a warning
-// See https://github.com/rust-lang/rust-clippy/issues/5567
-#[fake_async_trait]
-pub trait Bazz {
- fn foo() -> Vec<u8> {
- let _i = "";
-
-
-
- vec![]
- }
-}
-
-#[derive(Clone, Copy)]
-#[dummy(string = "first line
-
-second line
-")]
-pub struct Args;
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
deleted file mode 100644
index 889ccf6ba19..00000000000
--- a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
+++ /dev/null
@@ -1,37 +0,0 @@
-error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
- --> tests/ui/empty_line_after_doc_comments.rs:18:1
- |
-LL | / /// This should produce a warning
-LL | |
-LL | | fn with_doc_and_newline() { assert!(true)}
- | |_
- |
- = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_doc_comments)]`
-
-error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
- --> tests/ui/empty_line_after_doc_comments.rs:68:1
- |
-LL | / /// This doc comment should produce a warning
-LL | |
-LL | | /** This is also a doc comment and should produce a warning
-LL | | */
-... |
-LL | | #[allow(missing_docs)]
-LL | | fn three_attributes() { assert!(true) }
- | |_
-
-error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
- --> tests/ui/empty_line_after_doc_comments.rs:70:1
- |
-LL | / /** This is also a doc comment and should produce a warning
-LL | | */
-LL | |
-LL | | // This should *NOT* produce a warning
-... |
-LL | | #[allow(missing_docs)]
-LL | | fn three_attributes() { assert!(true) }
- | |_
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
deleted file mode 100644
index f147cf2cd5d..00000000000
--- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-//@aux-build:proc_macro_attr.rs
-#![warn(clippy::empty_line_after_outer_attr)]
-#![allow(clippy::assertions_on_constants, clippy::duplicated_attributes)]
-#![feature(custom_inner_attributes)]
-#![rustfmt::skip]
-
-#[macro_use]
-extern crate proc_macro_attr;
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-/// some comment
-fn with_one_newline_and_comment() { assert!(true) }
-
-// This should not produce a warning
-#[crate_type = "lib"]
-/// some comment
-fn with_no_newline_and_comment() { assert!(true) }
-
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-fn with_one_newline() { assert!(true) }
-
-// This should produce a warning, too
-#[crate_type = "lib"]
-
-
-fn with_two_newlines() { assert!(true) }
-
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-enum Baz {
- One,
- Two
-}
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-struct Foo {
- one: isize,
- two: isize
-}
-
-// This should produce a warning
-#[crate_type = "lib"]
-
-mod foo {
-}
-
-/// This doc comment should not produce a warning
-
-/** This is also a doc comment and should not produce a warning
- */
-
-// This should not produce a warning
-#[allow(non_camel_case_types)]
-#[allow(missing_docs)]
-#[allow(missing_docs)]
-fn three_attributes() { assert!(true) }
-
-// This should not produce a warning
-#[doc = "
-Returns the escaped value of the textual representation of
-
-"]
-pub fn function() -> bool {
- true
-}
-
-// This should not produce a warning
-#[derive(Clone, Copy)]
-pub enum FooFighter {
- Bar1,
-
- Bar2,
-
- Bar3,
-
- Bar4
-}
-
-// This should not produce a warning because the empty line is inside a block comment
-#[crate_type = "lib"]
-/*
-
-*/
-pub struct S;
-
-// This should not produce a warning
-#[crate_type = "lib"]
-/* test */
-pub struct T;
-
-// This should not produce a warning
-// See https://github.com/rust-lang/rust-clippy/issues/5567
-#[fake_async_trait]
-pub trait Bazz {
- fn foo() -> Vec<u8> {
- let _i = "";
-
-
-
- vec![]
- }
-}
-
-#[derive(Clone, Copy)]
-#[dummy(string = "first line
-
-second line
-")]
-pub struct Args;
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr
deleted file mode 100644
index b43e6e30da2..00000000000
--- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr
+++ /dev/null
@@ -1,54 +0,0 @@
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
- --> tests/ui/empty_line_after_outer_attribute.rs:11:1
- |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | /// some comment
-LL | | fn with_one_newline_and_comment() { assert!(true) }
- | |_
- |
- = note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::empty_line_after_outer_attr)]`
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
- --> tests/ui/empty_line_after_outer_attribute.rs:23:1
- |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | fn with_one_newline() { assert!(true) }
- | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
- --> tests/ui/empty_line_after_outer_attribute.rs:28:1
- |
-LL | / #[crate_type = "lib"]
-... |
-LL | | fn with_two_newlines() { assert!(true) }
- | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
- --> tests/ui/empty_line_after_outer_attribute.rs:35:1
- |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | enum Baz {
- | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
- --> tests/ui/empty_line_after_outer_attribute.rs:43:1
- |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | struct Foo {
- | |_
-
-error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
- --> tests/ui/empty_line_after_outer_attribute.rs:51:1
- |
-LL | / #[crate_type = "lib"]
-LL | |
-LL | | mod foo {
- | |_
-
-error: aborting due to 6 previous errors
-
diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.rs b/src/tools/clippy/tests/ui/empty_loop_no_std.rs
index 5fe32351ed4..1bb895bda75 100644
--- a/src/tools/clippy/tests/ui/empty_loop_no_std.rs
+++ b/src/tools/clippy/tests/ui/empty_loop_no_std.rs
@@ -1,5 +1,5 @@
//@compile-flags: -Clink-arg=-nostartfiles
-//@ignore-target-apple
+//@ignore-target: apple
#![warn(clippy::empty_loop)]
#![feature(lang_items, start, libc)]
diff --git a/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs b/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
index c50404c5047..37849179d6a 100644
--- a/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
+++ b/src/tools/clippy/tests/ui/enum_clike_unportable_variant.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
#![warn(clippy::enum_clike_unportable_variant)]
#![allow(unused, non_upper_case_globals)]
diff --git a/src/tools/clippy/tests/ui/exit1.rs b/src/tools/clippy/tests/ui/exit1.rs
index a89f6dd4ca0..36b3c42fd99 100644
--- a/src/tools/clippy/tests/ui/exit1.rs
+++ b/src/tools/clippy/tests/ui/exit1.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::exit)]
+#![warn(clippy::exit)]
fn not_main() {
if true {
diff --git a/src/tools/clippy/tests/ui/exit2.rs b/src/tools/clippy/tests/ui/exit2.rs
index d5ff93fb9cc..9bbb7b073a4 100644
--- a/src/tools/clippy/tests/ui/exit2.rs
+++ b/src/tools/clippy/tests/ui/exit2.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::exit)]
+#![warn(clippy::exit)]
fn also_not_main() {
std::process::exit(3);
diff --git a/src/tools/clippy/tests/ui/exit3.rs b/src/tools/clippy/tests/ui/exit3.rs
index 9dc0e1015a4..cab908aafd3 100644
--- a/src/tools/clippy/tests/ui/exit3.rs
+++ b/src/tools/clippy/tests/ui/exit3.rs
@@ -1,4 +1,4 @@
-#[warn(clippy::exit)]
+#![warn(clippy::exit)]
fn main() {
if true {
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.fixed b/src/tools/clippy/tests/ui/expect_fun_call.fixed
index 6ac3c43ad29..8f800c71941 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/expect_fun_call.fixed
@@ -5,8 +5,6 @@
clippy::unnecessary_literal_unwrap
)]
-/// Checks implementation of the `EXPECT_FUN_CALL` lint
-
macro_rules! one {
() => {
1
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.rs b/src/tools/clippy/tests/ui/expect_fun_call.rs
index 22ea2db504f..b5cfafb2993 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.rs
+++ b/src/tools/clippy/tests/ui/expect_fun_call.rs
@@ -5,8 +5,6 @@
clippy::unnecessary_literal_unwrap
)]
-/// Checks implementation of the `EXPECT_FUN_CALL` lint
-
macro_rules! one {
() => {
1
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.stderr b/src/tools/clippy/tests/ui/expect_fun_call.stderr
index b41904d04fa..bae853ac5c1 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/expect_fun_call.stderr
@@ -1,5 +1,5 @@
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:37:26
+ --> tests/ui/expect_fun_call.rs:35:26
|
LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
@@ -8,85 +8,85 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code
= help: to override `-D warnings` add `#[allow(clippy::expect_fun_call)]`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:40:26
+ --> tests/ui/expect_fun_call.rs:38:26
|
LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:43:37
+ --> tests/ui/expect_fun_call.rs:41:37
|
LL | with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:53:25
+ --> tests/ui/expect_fun_call.rs:51:25
|
LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:56:25
+ --> tests/ui/expect_fun_call.rs:54:25
|
LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:68:17
+ --> tests/ui/expect_fun_call.rs:66:17
|
LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{} {}", 1, 2))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:89:21
+ --> tests/ui/expect_fun_call.rs:87:21
|
LL | Some("foo").expect(&get_string());
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:90:21
+ --> tests/ui/expect_fun_call.rs:88:21
|
LL | Some("foo").expect(get_string().as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:91:21
+ --> tests/ui/expect_fun_call.rs:89:21
|
LL | Some("foo").expect(get_string().as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:93:21
+ --> tests/ui/expect_fun_call.rs:91:21
|
LL | Some("foo").expect(get_static_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_static_str()) })`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:94:21
+ --> tests/ui/expect_fun_call.rs:92:21
|
LL | Some("foo").expect(get_non_static_str(&0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:98:16
+ --> tests/ui/expect_fun_call.rs:96:16
|
LL | Some(true).expect(&format!("key {}, {}", 1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:104:17
+ --> tests/ui/expect_fun_call.rs:102:17
|
LL | opt_ref.expect(&format!("{:?}", opt_ref));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{:?}", opt_ref))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:108:20
+ --> tests/ui/expect_fun_call.rs:106:20
|
LL | format_capture.expect(&format!("{error_code}"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}"))`
error: use of `expect` followed by a function call
- --> tests/ui/expect_fun_call.rs:111:30
+ --> tests/ui/expect_fun_call.rs:109:30
|
LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}, {}", 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 620cffb4f04..2a432751952 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -192,8 +192,8 @@ struct WrapperMulti<T, U> {
}
mod issue6312 {
- use std::sync::atomic::AtomicBool;
use std::sync::Arc;
+ use std::sync::atomic::AtomicBool;
// do not lint: type implements `Drop` but not all fields are `Copy`
#[derive(Clone, Default)]
diff --git a/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs b/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs
index 47c113d61c0..8ea75fae89b 100644
--- a/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs
+++ b/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs
@@ -4,7 +4,7 @@
#![no_std]
// The following should not lint, as the suggested methods `{f16,f32,f64,f128}.mul_add()`
-// and ``{f16,f32,f64,f128}::abs()` are not available in no_std
+// and `{f16,f32,f64,f128}::abs()` are not available in no_std
pub fn mul_add() {
let a: f64 = 1234.567;
diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed
index 4d812f6bf1d..20d1e3d9050 100644
--- a/src/tools/clippy/tests/ui/format_args.fixed
+++ b/src/tools/clippy/tests/ui/format_args.fixed
@@ -8,7 +8,7 @@
clippy::uninlined_format_args
)]
-use std::io::{stdout, Write};
+use std::io::{Write, stdout};
use std::ops::Deref;
use std::panic::Location;
diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs
index d242623feb6..18ab223db78 100644
--- a/src/tools/clippy/tests/ui/format_args.rs
+++ b/src/tools/clippy/tests/ui/format_args.rs
@@ -8,7 +8,7 @@
clippy::uninlined_format_args
)]
-use std::io::{stdout, Write};
+use std::io::{Write, stdout};
use std::ops::Deref;
use std::panic::Location;
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs
index b7492e38b25..f04715f4f01 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.rs
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs
@@ -2,7 +2,7 @@
#![allow(unused)]
#![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)]
-use std::io::{stdout, Error, ErrorKind, Write};
+use std::io::{Error, ErrorKind, Write, stdout};
use std::ops::Deref;
use std::panic::Location;
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.fixed b/src/tools/clippy/tests/ui/if_then_some_else_none.fixed
index ad13372a68b..1f47dddcbc4 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.fixed
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.fixed
@@ -113,6 +113,10 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
Ok(())
}
+fn issue13407(s: &str) -> Option<bool> {
+ (s == "1").then(|| true)
+}
+
const fn issue12103(x: u32) -> Option<u32> {
// Should not issue an error in `const` context
if x > 42 { Some(150) } else { None }
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.rs b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
index 73edbb7da2a..499f008fb87 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.rs
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
@@ -131,6 +131,10 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
Ok(())
}
+fn issue13407(s: &str) -> Option<bool> {
+ if s == "1" { Some(true) } else { None }
+}
+
const fn issue12103(x: u32) -> Option<u32> {
// Should not issue an error in `const` context
if x > 42 { Some(150) } else { None }
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
index aed01e026cb..e7bc66b3ee8 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
@@ -52,5 +52,11 @@ LL | | None
LL | | };
| |_____^ help: try: `foo().then(|| { println!("true!"); 150 })`
-error: aborting due to 5 previous errors
+error: this could be simplified with `bool::then`
+ --> tests/ui/if_then_some_else_none.rs:135:5
+ |
+LL | if s == "1" { Some(true) } else { None }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(s == "1").then(|| true)`
+
+error: aborting due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
index 118f0b48895..fde40437309 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed
@@ -21,15 +21,12 @@ fn main() {
let _ = foo().map_err(|()| todo!());
//~^ ERROR: matching over `()` is more explicit
- println!(
- "{:?}",
- match foo() {
- Ok(()) => {},
- //~^ ERROR: matching over `()` is more explicit
- Err(()) => {},
- //~^ ERROR: matching over `()` is more explicit
- }
- );
+ println!("{:?}", match foo() {
+ Ok(()) => {},
+ //~^ ERROR: matching over `()` is more explicit
+ Err(()) => {},
+ //~^ ERROR: matching over `()` is more explicit
+ });
}
// ignored_unit_patterns in derive macro should be ok
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
index 92feb9e6c28..528844d76e0 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs
@@ -21,15 +21,12 @@ fn main() {
let _ = foo().map_err(|_| todo!());
//~^ ERROR: matching over `()` is more explicit
- println!(
- "{:?}",
- match foo() {
- Ok(_) => {},
- //~^ ERROR: matching over `()` is more explicit
- Err(_) => {},
- //~^ ERROR: matching over `()` is more explicit
- }
- );
+ println!("{:?}", match foo() {
+ Ok(_) => {},
+ //~^ ERROR: matching over `()` is more explicit
+ Err(_) => {},
+ //~^ ERROR: matching over `()` is more explicit
+ });
}
// ignored_unit_patterns in derive macro should be ok
diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
index 00a254e3919..54ff4454d6b 100644
--- a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
+++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr
@@ -26,31 +26,31 @@ LL | let _ = foo().map_err(|_| todo!());
| ^ help: use `()` instead of `_`: `()`
error: matching over `()` is more explicit
- --> tests/ui/ignored_unit_patterns.rs:27:16
+ --> tests/ui/ignored_unit_patterns.rs:25:12
|
-LL | Ok(_) => {},
- | ^ help: use `()` instead of `_`: `()`
+LL | Ok(_) => {},
+ | ^ help: use `()` instead of `_`: `()`
error: matching over `()` is more explicit
- --> tests/ui/ignored_unit_patterns.rs:29:17
+ --> tests/ui/ignored_unit_patterns.rs:27:13
|
-LL | Err(_) => {},
- | ^ help: use `()` instead of `_`: `()`
+LL | Err(_) => {},
+ | ^ help: use `()` instead of `_`: `()`
error: matching over `()` is more explicit
- --> tests/ui/ignored_unit_patterns.rs:41:9
+ --> tests/ui/ignored_unit_patterns.rs:38:9
|
LL | let _ = foo().unwrap();
| ^ help: use `()` instead of `_`: `()`
error: matching over `()` is more explicit
- --> tests/ui/ignored_unit_patterns.rs:50:13
+ --> tests/ui/ignored_unit_patterns.rs:47:13
|
LL | (1, _) => unimplemented!(),
| ^ help: use `()` instead of `_`: `()`
error: matching over `()` is more explicit
- --> tests/ui/ignored_unit_patterns.rs:57:13
+ --> tests/ui/ignored_unit_patterns.rs:54:13
|
LL | for (x, _) in v {
| ^ help: use `()` instead of `_`: `()`
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
index 27f679797dd..81cc1494914 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
@@ -184,18 +184,18 @@ fn main() {
let mut m = Mock;
let mut u_32 = 3000;
let a = 200;
- let mut _b = 8;
+ let mut b = 8;
if m != 0 {
m -= 1;
}
if a > 0 {
- _b -= 1;
+ b -= 1;
}
if 0 > a {
- _b -= 1;
+ b -= 1;
}
if u_32 > 0 {
@@ -214,4 +214,11 @@ fn main() {
} else if u_32 > 0 {
u_32 -= 1;
}
+
+ let result = if a < b {
+ println!("we shouldn't remove this");
+ 0
+ } else {
+ a - b
+ };
}
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
index 5d7b95d2c65..f73396ebd27 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
@@ -230,18 +230,18 @@ fn main() {
let mut m = Mock;
let mut u_32 = 3000;
let a = 200;
- let mut _b = 8;
+ let mut b = 8;
if m != 0 {
m -= 1;
}
if a > 0 {
- _b -= 1;
+ b -= 1;
}
if 0 > a {
- _b -= 1;
+ b -= 1;
}
if u_32 > 0 {
@@ -260,4 +260,11 @@ fn main() {
} else if u_32 > 0 {
u_32 -= 1;
}
+
+ let result = if a < b {
+ println!("we shouldn't remove this");
+ 0
+ } else {
+ a - b
+ };
}
diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.rs b/src/tools/clippy/tests/ui/incompatible_msrv.rs
index 8ef1f554bc3..c23df223d50 100644
--- a/src/tools/clippy/tests/ui/incompatible_msrv.rs
+++ b/src/tools/clippy/tests/ui/incompatible_msrv.rs
@@ -2,8 +2,8 @@
#![feature(custom_inner_attributes)]
#![clippy::msrv = "1.3.0"]
-use std::collections::hash_map::Entry;
use std::collections::HashMap;
+use std::collections::hash_map::Entry;
use std::future::Future;
use std::thread::sleep;
use std::time::Duration;
diff --git a/src/tools/clippy/tests/ui/legacy_numeric_constants.fixed b/src/tools/clippy/tests/ui/legacy_numeric_constants.fixed
index a6ef8f8c119..3a2294ef4c5 100644
--- a/src/tools/clippy/tests/ui/legacy_numeric_constants.fixed
+++ b/src/tools/clippy/tests/ui/legacy_numeric_constants.fixed
@@ -22,8 +22,8 @@ macro_rules! b {
};
}
-use std::u32::MAX;
use std::u8::MIN;
+use std::u32::MAX;
use std::{f64, u32};
#[warn(clippy::legacy_numeric_constants)]
@@ -99,8 +99,8 @@ fn allow() {
::std::primitive::u8::MIN;
::std::u8::MIN;
::std::primitive::u8::min_value();
- use std::u64;
use std::u8::MIN;
+ use std::u64;
}
#[warn(clippy::legacy_numeric_constants)]
diff --git a/src/tools/clippy/tests/ui/legacy_numeric_constants.rs b/src/tools/clippy/tests/ui/legacy_numeric_constants.rs
index cd633545372..6cb3e694ea1 100644
--- a/src/tools/clippy/tests/ui/legacy_numeric_constants.rs
+++ b/src/tools/clippy/tests/ui/legacy_numeric_constants.rs
@@ -22,8 +22,8 @@ macro_rules! b {
};
}
-use std::u32::MAX;
use std::u8::MIN;
+use std::u32::MAX;
use std::{f64, u32};
#[warn(clippy::legacy_numeric_constants)]
@@ -99,8 +99,8 @@ fn allow() {
::std::primitive::u8::MIN;
::std::u8::MIN;
::std::primitive::u8::min_value();
- use std::u64;
use std::u8::MIN;
+ use std::u64;
}
#[warn(clippy::legacy_numeric_constants)]
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed
index 38ed5a957e7..28844fab747 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.fixed
+++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed
@@ -2,7 +2,7 @@
//@aux-build:macro_use_helper.rs
//@aux-build:proc_macro_derive.rs
-//@ignore-32bit
+//@ignore-bitwidth: 32
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
#![allow(clippy::single_component_path_imports)]
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs
index ae6cc16ed27..5381f295989 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports.rs
@@ -2,7 +2,7 @@
//@aux-build:macro_use_helper.rs
//@aux-build:proc_macro_derive.rs
-//@ignore-32bit
+//@ignore-bitwidth: 32
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
#![allow(clippy::single_component_path_imports)]
diff --git a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
index df6d5b9fbab..60cce1d24a2 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs
@@ -1,7 +1,7 @@
//@aux-build:macro_rules.rs
//@aux-build:macro_use_helper.rs
//@aux-build:proc_macro_derive.rs
-//@ignore-32bit
+//@ignore-bitwidth: 32
#![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)]
#![allow(clippy::single_component_path_imports)]
diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs
new file mode 100644
index 00000000000..e97e3bdfef7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs
@@ -0,0 +1,35 @@
+//@no-rustfix
+#![warn(clippy::implicit_saturating_sub)]
+#![allow(arithmetic_overflow)]
+
+fn main() {
+ let a = 12u32;
+ let b = 13u32;
+
+ let result = if a > b { b - a } else { 0 };
+ //~^ ERROR: inverted arithmetic check before subtraction
+ let result = if b < a { b - a } else { 0 };
+ //~^ ERROR: inverted arithmetic check before subtraction
+
+ let result = if a > b { 0 } else { a - b };
+ //~^ ERROR: inverted arithmetic check before subtraction
+ let result = if a >= b { 0 } else { a - b };
+ //~^ ERROR: inverted arithmetic check before subtraction
+ let result = if b < a { 0 } else { a - b };
+ //~^ ERROR: inverted arithmetic check before subtraction
+ let result = if b <= a { 0 } else { a - b };
+ //~^ ERROR: inverted arithmetic check before subtraction
+
+ let af = 12f32;
+ let bf = 13f32;
+ // Should not lint!
+ let result = if bf < af { 0. } else { af - bf };
+
+ // Should not lint!
+ let result = if a < b {
+ println!("we shouldn't remove this");
+ 0
+ } else {
+ a - b
+ };
+}
diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr
new file mode 100644
index 00000000000..4121aa7464f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr
@@ -0,0 +1,75 @@
+error: inverted arithmetic check before subtraction
+ --> tests/ui/manual_arithmetic_check-2.rs:9:23
+ |
+LL | let result = if a > b { b - a } else { 0 };
+ | ^ ----- help: try replacing it with: `a - b`
+ |
+note: this subtraction underflows when `b < a`
+ --> tests/ui/manual_arithmetic_check-2.rs:9:29
+ |
+LL | let result = if a > b { b - a } else { 0 };
+ | ^^^^^
+ = note: `#[deny(clippy::inverted_saturating_sub)]` on by default
+
+error: inverted arithmetic check before subtraction
+ --> tests/ui/manual_arithmetic_check-2.rs:11:23
+ |
+LL | let result = if b < a { b - a } else { 0 };
+ | ^ ----- help: try replacing it with: `a - b`
+ |
+note: this subtraction underflows when `b < a`
+ --> tests/ui/manual_arithmetic_check-2.rs:11:29
+ |
+LL | let result = if b < a { b - a } else { 0 };
+ | ^^^^^
+
+error: inverted arithmetic check before subtraction
+ --> tests/ui/manual_arithmetic_check-2.rs:14:23
+ |
+LL | let result = if a > b { 0 } else { a - b };
+ | ^ ----- help: try replacing it with: `b - a`
+ |
+note: this subtraction underflows when `a < b`
+ --> tests/ui/manual_arithmetic_check-2.rs:14:40
+ |
+LL | let result = if a > b { 0 } else { a - b };
+ | ^^^^^
+
+error: inverted arithmetic check before subtraction
+ --> tests/ui/manual_arithmetic_check-2.rs:16:23
+ |
+LL | let result = if a >= b { 0 } else { a - b };
+ | ^^ ----- help: try replacing it with: `b - a`
+ |
+note: this subtraction underflows when `a < b`
+ --> tests/ui/manual_arithmetic_check-2.rs:16:41
+ |
+LL | let result = if a >= b { 0 } else { a - b };
+ | ^^^^^
+
+error: inverted arithmetic check before subtraction
+ --> tests/ui/manual_arithmetic_check-2.rs:18:23
+ |
+LL | let result = if b < a { 0 } else { a - b };
+ | ^ ----- help: try replacing it with: `b - a`
+ |
+note: this subtraction underflows when `a < b`
+ --> tests/ui/manual_arithmetic_check-2.rs:18:40
+ |
+LL | let result = if b < a { 0 } else { a - b };
+ | ^^^^^
+
+error: inverted arithmetic check before subtraction
+ --> tests/ui/manual_arithmetic_check-2.rs:20:23
+ |
+LL | let result = if b <= a { 0 } else { a - b };
+ | ^^ ----- help: try replacing it with: `b - a`
+ |
+note: this subtraction underflows when `a < b`
+ --> tests/ui/manual_arithmetic_check-2.rs:20:41
+ |
+LL | let result = if b <= a { 0 } else { a - b };
+ | ^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check.fixed b/src/tools/clippy/tests/ui/manual_arithmetic_check.fixed
new file mode 100644
index 00000000000..29ecbb9ad2a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_arithmetic_check.fixed
@@ -0,0 +1,24 @@
+#![warn(clippy::implicit_saturating_sub, clippy::inverted_saturating_sub)]
+#![allow(clippy::if_same_then_else)]
+
+fn main() {
+ let a = 12u32;
+ let b = 13u32;
+ let c = 8u32;
+
+ let result = a.saturating_sub(b);
+ //~^ ERROR: manual arithmetic check found
+ let result = a.saturating_sub(b);
+ //~^ ERROR: manual arithmetic check found
+
+ let result = a.saturating_sub(b);
+ //~^ ERROR: manual arithmetic check found
+ let result = a.saturating_sub(b);
+ //~^ ERROR: manual arithmetic check found
+
+ // Should not warn!
+ let result = if a > b { a - b } else { a - c };
+
+ // Just to check it won't break clippy.
+ let result = if b > a { 0 } else { 0 };
+}
diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check.rs b/src/tools/clippy/tests/ui/manual_arithmetic_check.rs
new file mode 100644
index 00000000000..69554c6b61c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_arithmetic_check.rs
@@ -0,0 +1,24 @@
+#![warn(clippy::implicit_saturating_sub, clippy::inverted_saturating_sub)]
+#![allow(clippy::if_same_then_else)]
+
+fn main() {
+ let a = 12u32;
+ let b = 13u32;
+ let c = 8u32;
+
+ let result = if a > b { a - b } else { 0 };
+ //~^ ERROR: manual arithmetic check found
+ let result = if b < a { a - b } else { 0 };
+ //~^ ERROR: manual arithmetic check found
+
+ let result = if a < b { 0 } else { a - b };
+ //~^ ERROR: manual arithmetic check found
+ let result = if b > a { 0 } else { a - b };
+ //~^ ERROR: manual arithmetic check found
+
+ // Should not warn!
+ let result = if a > b { a - b } else { a - c };
+
+ // Just to check it won't break clippy.
+ let result = if b > a { 0 } else { 0 };
+}
diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check.stderr b/src/tools/clippy/tests/ui/manual_arithmetic_check.stderr
new file mode 100644
index 00000000000..b0cf73cd915
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_arithmetic_check.stderr
@@ -0,0 +1,29 @@
+error: manual arithmetic check found
+ --> tests/ui/manual_arithmetic_check.rs:9:18
+ |
+LL | let result = if a > b { a - b } else { 0 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+ |
+ = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]`
+
+error: manual arithmetic check found
+ --> tests/ui/manual_arithmetic_check.rs:11:18
+ |
+LL | let result = if b < a { a - b } else { 0 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+
+error: manual arithmetic check found
+ --> tests/ui/manual_arithmetic_check.rs:14:18
+ |
+LL | let result = if a < b { 0 } else { a - b };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+
+error: manual arithmetic check found
+ --> tests/ui/manual_arithmetic_check.rs:16:18
+ |
+LL | let result = if b > a { 0 } else { a - b };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.fixed b/src/tools/clippy/tests/ui/manual_div_ceil.fixed
new file mode 100644
index 00000000000..e7801f7376a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_div_ceil.fixed
@@ -0,0 +1,30 @@
+#![warn(clippy::manual_div_ceil)]
+
+fn main() {
+ let x = 7_u32;
+ let y = 4_u32;
+ let z = 11_u32;
+
+ // Lint
+ let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil`
+ let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil`
+ let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil`
+
+ let _ = 7_u32.div_ceil(4); //~ ERROR: manually reimplementing `div_ceil`
+ let _ = (7_i32 as u32).div_ceil(4); //~ ERROR: manually reimplementing `div_ceil`
+
+ // No lint
+ let _ = (x + (y - 2)) / y;
+ let _ = (x + (y + 1)) / y;
+
+ let _ = (x + (y - 1)) / z;
+
+ let x_i = 7_i32;
+ let y_i = 4_i32;
+ let z_i = 11_i32;
+
+ // No lint because `int_roundings` feature is not enabled.
+ let _ = (z as i32 + (y_i - 1)) / y_i;
+ let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
+ let _ = (7_u32 as i32 + (4 - 1)) / 4;
+}
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.rs b/src/tools/clippy/tests/ui/manual_div_ceil.rs
new file mode 100644
index 00000000000..2de74c7eaa8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_div_ceil.rs
@@ -0,0 +1,30 @@
+#![warn(clippy::manual_div_ceil)]
+
+fn main() {
+ let x = 7_u32;
+ let y = 4_u32;
+ let z = 11_u32;
+
+ // Lint
+ let _ = (x + (y - 1)) / y; //~ ERROR: manually reimplementing `div_ceil`
+ let _ = ((y - 1) + x) / y; //~ ERROR: manually reimplementing `div_ceil`
+ let _ = (x + y - 1) / y; //~ ERROR: manually reimplementing `div_ceil`
+
+ let _ = (7_u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil`
+ let _ = (7_i32 as u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil`
+
+ // No lint
+ let _ = (x + (y - 2)) / y;
+ let _ = (x + (y + 1)) / y;
+
+ let _ = (x + (y - 1)) / z;
+
+ let x_i = 7_i32;
+ let y_i = 4_i32;
+ let z_i = 11_i32;
+
+ // No lint because `int_roundings` feature is not enabled.
+ let _ = (z as i32 + (y_i - 1)) / y_i;
+ let _ = (7_u32 as i32 + (y_i - 1)) / y_i;
+ let _ = (7_u32 as i32 + (4 - 1)) / 4;
+}
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.stderr b/src/tools/clippy/tests/ui/manual_div_ceil.stderr
new file mode 100644
index 00000000000..dc652dff405
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_div_ceil.stderr
@@ -0,0 +1,35 @@
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil.rs:9:13
+ |
+LL | let _ = (x + (y - 1)) / y;
+ | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+ |
+ = note: `-D clippy::manual-div-ceil` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil.rs:10:13
+ |
+LL | let _ = ((y - 1) + x) / y;
+ | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil.rs:11:13
+ |
+LL | let _ = (x + y - 1) / y;
+ | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil.rs:13:13
+ |
+LL | let _ = (7_u32 + (4 - 1)) / 4;
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_u32.div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil.rs:14:13
+ |
+LL | let _ = (7_i32 as u32 + (4 - 1)) / 4;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.fixed b/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.fixed
new file mode 100644
index 00000000000..a1d678c6689
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.fixed
@@ -0,0 +1,25 @@
+#![warn(clippy::manual_div_ceil)]
+#![feature(int_roundings)]
+
+fn main() {
+ let x = 7_i32;
+ let y = 4_i32;
+ let z = 3_i32;
+ let z_u: u32 = 11;
+
+ // Lint.
+ let _ = x.div_ceil(y);
+ let _ = x.div_ceil(y);
+ let _ = x.div_ceil(y);
+
+ let _ = 7_i32.div_ceil(4);
+ let _ = (7_i32 as u32).div_ceil(4);
+ let _ = (7_u32 as i32).div_ceil(4);
+ let _ = z_u.div_ceil(4);
+
+ // No lint.
+ let _ = (x + (y - 2)) / y;
+ let _ = (x + (y + 1)) / y;
+
+ let _ = (x + (y - 1)) / z;
+}
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.rs b/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.rs
new file mode 100644
index 00000000000..58cb1dbe34d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.rs
@@ -0,0 +1,25 @@
+#![warn(clippy::manual_div_ceil)]
+#![feature(int_roundings)]
+
+fn main() {
+ let x = 7_i32;
+ let y = 4_i32;
+ let z = 3_i32;
+ let z_u: u32 = 11;
+
+ // Lint.
+ let _ = (x + (y - 1)) / y;
+ let _ = ((y - 1) + x) / y;
+ let _ = (x + y - 1) / y;
+
+ let _ = (7_i32 + (4 - 1)) / 4;
+ let _ = (7_i32 as u32 + (4 - 1)) / 4;
+ let _ = (7_u32 as i32 + (4 - 1)) / 4;
+ let _ = (z_u + (4 - 1)) / 4;
+
+ // No lint.
+ let _ = (x + (y - 2)) / y;
+ let _ = (x + (y + 1)) / y;
+
+ let _ = (x + (y - 1)) / z;
+}
diff --git a/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.stderr b/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.stderr
new file mode 100644
index 00000000000..361ef9bd9f4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_div_ceil_with_feature.stderr
@@ -0,0 +1,47 @@
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:11:13
+ |
+LL | let _ = (x + (y - 1)) / y;
+ | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+ |
+ = note: `-D clippy::manual-div-ceil` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:12:13
+ |
+LL | let _ = ((y - 1) + x) / y;
+ | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:13:13
+ |
+LL | let _ = (x + y - 1) / y;
+ | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:15:13
+ |
+LL | let _ = (7_i32 + (4 - 1)) / 4;
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_i32.div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:16:13
+ |
+LL | let _ = (7_i32 as u32 + (4 - 1)) / 4;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:17:13
+ |
+LL | let _ = (7_u32 as i32 + (4 - 1)) / 4;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_u32 as i32).div_ceil(4)`
+
+error: manually reimplementing `div_ceil`
+ --> tests/ui/manual_div_ceil_with_feature.rs:18:13
+ |
+LL | let _ = (z_u + (4 - 1)) / 4;
+ | ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `z_u.div_ceil(4)`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed b/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed
new file mode 100644
index 00000000000..dda5fe0ec3e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_power_of_two.fixed
@@ -0,0 +1,20 @@
+#![warn(clippy::manual_is_power_of_two)]
+
+fn main() {
+ let a = 16_u64;
+
+ let _ = a.is_power_of_two();
+ let _ = a.is_power_of_two();
+
+ // Test different orders of expression
+ let _ = a.is_power_of_two();
+ let _ = a.is_power_of_two();
+ let _ = a.is_power_of_two();
+ let _ = a.is_power_of_two();
+
+ let b = 4_i64;
+
+ // is_power_of_two only works for unsigned integers
+ let _ = b.count_ones() == 1;
+ let _ = b & (b - 1) == 0;
+}
diff --git a/src/tools/clippy/tests/ui/manual_is_power_of_two.rs b/src/tools/clippy/tests/ui/manual_is_power_of_two.rs
new file mode 100644
index 00000000000..a1d3a95c410
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_power_of_two.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::manual_is_power_of_two)]
+
+fn main() {
+ let a = 16_u64;
+
+ let _ = a.count_ones() == 1;
+ let _ = a & (a - 1) == 0;
+
+ // Test different orders of expression
+ let _ = 1 == a.count_ones();
+ let _ = (a - 1) & a == 0;
+ let _ = 0 == a & (a - 1);
+ let _ = 0 == (a - 1) & a;
+
+ let b = 4_i64;
+
+ // is_power_of_two only works for unsigned integers
+ let _ = b.count_ones() == 1;
+ let _ = b & (b - 1) == 0;
+}
diff --git a/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr b/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr
new file mode 100644
index 00000000000..3cfc6297abf
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_power_of_two.stderr
@@ -0,0 +1,41 @@
+error: manually reimplementing `is_power_of_two`
+ --> tests/ui/manual_is_power_of_two.rs:6:13
+ |
+LL | let _ = a.count_ones() == 1;
+ | ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+ |
+ = note: `-D clippy::manual-is-power-of-two` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::manual_is_power_of_two)]`
+
+error: manually reimplementing `is_power_of_two`
+ --> tests/ui/manual_is_power_of_two.rs:7:13
+ |
+LL | let _ = a & (a - 1) == 0;
+ | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+ --> tests/ui/manual_is_power_of_two.rs:10:13
+ |
+LL | let _ = 1 == a.count_ones();
+ | ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+ --> tests/ui/manual_is_power_of_two.rs:11:13
+ |
+LL | let _ = (a - 1) & a == 0;
+ | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+ --> tests/ui/manual_is_power_of_two.rs:12:13
+ |
+LL | let _ = 0 == a & (a - 1);
+ | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: manually reimplementing `is_power_of_two`
+ --> tests/ui/manual_is_power_of_two.rs:13:13
+ |
+LL | let _ = 0 == (a - 1) & a;
+ | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs
index 31c3cc80137..ffe2bb92467 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs
@@ -1,8 +1,8 @@
#![warn(clippy::manual_non_exhaustive)]
#![allow(unused)]
//@no-rustfix
-enum E {
- //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+pub enum E {
+ //~^ manual_non_exhaustive
A,
B,
#[doc(hidden)]
@@ -11,7 +11,7 @@ enum E {
// if the user explicitly marks as nonexhaustive we shouldn't warn them
#[non_exhaustive]
-enum Ep {
+pub enum Ep {
A,
B,
#[doc(hidden)]
@@ -19,14 +19,14 @@ enum Ep {
}
// marker variant does not have doc hidden attribute, should be ignored
-enum NoDocHidden {
+pub enum NoDocHidden {
A,
B,
_C,
}
// name of variant with doc hidden does not start with underscore
-enum NoUnderscore {
+pub enum NoUnderscore {
A,
B,
#[doc(hidden)]
@@ -34,7 +34,7 @@ enum NoUnderscore {
}
// variant with doc hidden is not unit, should be ignored
-enum NotUnit {
+pub enum NotUnit {
A,
B,
#[doc(hidden)]
@@ -42,13 +42,13 @@ enum NotUnit {
}
// variant with doc hidden is the only one, should be ignored
-enum OnlyMarker {
+pub enum OnlyMarker {
#[doc(hidden)]
_A,
}
// variant with multiple markers, should be ignored
-enum MultipleMarkers {
+pub enum MultipleMarkers {
A,
#[doc(hidden)]
_B,
@@ -58,13 +58,13 @@ enum MultipleMarkers {
// already non_exhaustive and no markers, should be ignored
#[non_exhaustive]
-enum NonExhaustive {
+pub enum NonExhaustive {
A,
B,
}
// marked is used, don't lint
-enum UsedHidden {
+pub enum UsedHidden {
#[doc(hidden)]
_A,
B,
@@ -77,11 +77,9 @@ fn foo(x: &mut UsedHidden) {
}
#[expect(clippy::manual_non_exhaustive)]
-enum ExpectLint {
+pub enum ExpectLint {
A,
B,
#[doc(hidden)]
_C,
}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
index dc669568dd2..0a9ac157f85 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
@@ -1,11 +1,7 @@
error: this seems like a manual implementation of the non-exhaustive pattern
--> tests/ui/manual_non_exhaustive_enum.rs:4:1
|
-LL | enum E {
- | ^-----
- | |
- | _help: add the attribute: `#[non_exhaustive] enum E`
- | |
+LL | / pub enum E {
LL | |
LL | | A,
LL | | B,
@@ -21,15 +17,16 @@ LL | _C,
| ^^
= note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]`
+help: use the `#[non_exhaustive]` attribute instead
+ |
+LL + #[non_exhaustive]
+LL | pub enum E {
+ |
error: this seems like a manual implementation of the non-exhaustive pattern
--> tests/ui/manual_non_exhaustive_enum.rs:29:1
|
-LL | enum NoUnderscore {
- | ^----------------
- | |
- | _help: add the attribute: `#[non_exhaustive] enum NoUnderscore`
- | |
+LL | / pub enum NoUnderscore {
LL | | A,
LL | | B,
LL | | #[doc(hidden)]
@@ -42,6 +39,11 @@ help: remove this variant
|
LL | C,
| ^
+help: use the `#[non_exhaustive]` attribute instead
+ |
+LL + #[non_exhaustive]
+LL | pub enum NoUnderscore {
+ |
error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.rs
index 4b2803ccc4a..31dd50281fa 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.rs
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.rs
@@ -1,9 +1,9 @@
#![warn(clippy::manual_non_exhaustive)]
#![allow(unused)]
//@no-rustfix
-mod structs {
- struct S {
- //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+pub mod structs {
+ pub struct S {
+ //~^ manual_non_exhaustive
pub a: i32,
pub b: i32,
_c: (),
@@ -11,68 +11,76 @@ mod structs {
// user forgot to remove the private field
#[non_exhaustive]
- struct Sp {
- //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+ pub struct Sp {
+ //~^ manual_non_exhaustive
pub a: i32,
pub b: i32,
_c: (),
}
// some other fields are private, should be ignored
- struct PrivateFields {
+ pub struct PrivateFields {
a: i32,
pub b: i32,
_c: (),
}
- // private field name does not start with underscore, should be ignored
- struct NoUnderscore {
+ pub struct NoUnderscore {
+ //~^ manual_non_exhaustive
pub a: i32,
pub b: i32,
c: (),
}
// private field is not unit type, should be ignored
- struct NotUnit {
+ pub struct NotUnit {
pub a: i32,
pub b: i32,
_c: i32,
}
// private field is the only field, should be ignored
- struct OnlyMarker {
+ pub struct OnlyMarker {
_a: (),
}
// already non exhaustive and no private fields, should be ignored
#[non_exhaustive]
- struct NonExhaustive {
+ pub struct NonExhaustive {
pub a: i32,
pub b: i32,
}
}
-mod tuple_structs {
- struct T(pub i32, pub i32, ());
- //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+pub mod tuple_structs {
+ pub struct T(pub i32, pub i32, ());
+ //~^ manual_non_exhaustive
// user forgot to remove the private field
#[non_exhaustive]
- struct Tp(pub i32, pub i32, ());
- //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern
+ pub struct Tp(pub i32, pub i32, ());
+ //~^ manual_non_exhaustive
// some other fields are private, should be ignored
- struct PrivateFields(pub i32, i32, ());
+ pub struct PrivateFields(pub i32, i32, ());
// private field is not unit type, should be ignored
- struct NotUnit(pub i32, pub i32, i32);
+ pub struct NotUnit(pub i32, pub i32, i32);
// private field is the only field, should be ignored
- struct OnlyMarker(());
+ pub struct OnlyMarker(());
// already non exhaustive and no private fields, should be ignored
#[non_exhaustive]
- struct NonExhaustive(pub i32, pub i32);
+ pub struct NonExhaustive(pub i32, pub i32);
}
-fn main() {}
+mod private {
+ // Don't lint structs that are not actually public as `#[non_exhaustive]` only applies to
+ // external crates. The manual pattern can still be used to get module local non exhaustiveness
+ pub struct NotPublic {
+ pub a: i32,
+ pub b: i32,
+ _c: (),
+ }
+}
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr
index 1cab812988a..81de1e4f271 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr
@@ -1,11 +1,7 @@
error: this seems like a manual implementation of the non-exhaustive pattern
--> tests/ui/manual_non_exhaustive_struct.rs:5:5
|
-LL | struct S {
- | ^-------
- | |
- | _____help: add the attribute: `#[non_exhaustive] struct S`
- | |
+LL | / pub struct S {
LL | |
LL | | pub a: i32,
LL | | pub b: i32,
@@ -20,11 +16,16 @@ LL | _c: (),
| ^^^^^^
= note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]`
+help: use the `#[non_exhaustive]` attribute instead
+ |
+LL ~ #[non_exhaustive]
+LL ~ pub struct S {
+ |
error: this seems like a manual implementation of the non-exhaustive pattern
--> tests/ui/manual_non_exhaustive_struct.rs:14:5
|
-LL | / struct Sp {
+LL | / pub struct Sp {
LL | |
LL | | pub a: i32,
LL | | pub b: i32,
@@ -32,6 +33,11 @@ LL | | _c: (),
LL | | }
| |_____^
|
+note: the struct is already non-exhaustive
+ --> tests/ui/manual_non_exhaustive_struct.rs:13:5
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
help: remove this field
--> tests/ui/manual_non_exhaustive_struct.rs:18:9
|
@@ -39,13 +45,10 @@ LL | _c: (),
| ^^^^^^
error: this seems like a manual implementation of the non-exhaustive pattern
- --> tests/ui/manual_non_exhaustive_struct.rs:29:5
+ --> tests/ui/manual_non_exhaustive_struct.rs:28:5
|
-LL | struct NoUnderscore {
- | ^------------------
- | |
- | _____help: add the attribute: `#[non_exhaustive] struct NoUnderscore`
- | |
+LL | / pub struct NoUnderscore {
+LL | |
LL | | pub a: i32,
LL | | pub b: i32,
LL | | c: (),
@@ -57,32 +60,45 @@ help: remove this field
|
LL | c: (),
| ^^^^^
+help: use the `#[non_exhaustive]` attribute instead
+ |
+LL ~ #[non_exhaustive]
+LL ~ pub struct NoUnderscore {
+ |
error: this seems like a manual implementation of the non-exhaustive pattern
--> tests/ui/manual_non_exhaustive_struct.rs:56:5
|
-LL | struct T(pub i32, pub i32, ());
- | --------^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | help: add the attribute: `#[non_exhaustive] struct T`
+LL | pub struct T(pub i32, pub i32, ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove this field
- --> tests/ui/manual_non_exhaustive_struct.rs:56:32
+ --> tests/ui/manual_non_exhaustive_struct.rs:56:36
+ |
+LL | pub struct T(pub i32, pub i32, ());
+ | ^^
+help: use the `#[non_exhaustive]` attribute instead
+ |
+LL ~ #[non_exhaustive]
+LL ~ pub struct T(pub i32, pub i32, ());
|
-LL | struct T(pub i32, pub i32, ());
- | ^^
error: this seems like a manual implementation of the non-exhaustive pattern
--> tests/ui/manual_non_exhaustive_struct.rs:61:5
|
-LL | struct Tp(pub i32, pub i32, ());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub struct Tp(pub i32, pub i32, ());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the struct is already non-exhaustive
+ --> tests/ui/manual_non_exhaustive_struct.rs:60:5
|
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
help: remove this field
- --> tests/ui/manual_non_exhaustive_struct.rs:61:33
+ --> tests/ui/manual_non_exhaustive_struct.rs:61:37
|
-LL | struct Tp(pub i32, pub i32, ());
- | ^^
+LL | pub struct Tp(pub i32, pub i32, ());
+ | ^^
error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.fixed b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
index f1b99637afd..60467bf9e88 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.fixed
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
@@ -45,4 +45,12 @@ fn main() {
};
}
mac!(f);
+
+ #[rustfmt::skip]
+ let _ = match f {
+ | 2..=15 => 4,
+ | 241..=254 => 5,
+ | 255 => 6,
+ | _ => 7,
+ };
}
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.rs b/src/tools/clippy/tests/ui/manual_range_patterns.rs
index 869ffbe80b9..9cd80333449 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.rs
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.rs
@@ -45,4 +45,12 @@ fn main() {
};
}
mac!(f);
+
+ #[rustfmt::skip]
+ let _ = match f {
+ | 2..=15 => 4,
+ | 241..=254 => 5,
+ | 255 => 6,
+ | _ => 7,
+ };
}
diff --git a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed
index 41a32df32ee..528a65790c4 100644
--- a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed
+++ b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.fixed
@@ -1,6 +1,6 @@
#![allow(clippy::legacy_numeric_constants, unused_imports)]
-use std::{i128, i32, u128, u32};
+use std::{i32, i128, u32, u128};
fn main() {
let _ = 1u32.saturating_add(1);
diff --git a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs
index 3a6b32d8069..55f3720dfcc 100644
--- a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.rs
@@ -1,6 +1,6 @@
#![allow(clippy::legacy_numeric_constants, unused_imports)]
-use std::{i128, i32, u128, u32};
+use std::{i32, i128, u32, u128};
fn main() {
let _ = 1u32.checked_add(1).unwrap_or(u32::max_value());
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.rs b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
index 4457ae73da2..a056fdeaa5d 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.rs
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
@@ -2,8 +2,6 @@
#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::if_same_then_else, clippy::equatable_if_let, clippy::needless_if)]
-/// Tests for match_overlapping_arm
-
fn overlapping() {
const FOO: u64 = 2;
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
index 65092ffbb55..a60a09a0799 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
@@ -1,11 +1,11 @@
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:11:9
+ --> tests/ui/match_overlapping_arm.rs:9:9
|
LL | 0..=10 => println!("0..=10"),
| ^^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:13:9
+ --> tests/ui/match_overlapping_arm.rs:11:9
|
LL | 0..=11 => println!("0..=11"),
| ^^^^^^
@@ -13,85 +13,85 @@ LL | 0..=11 => println!("0..=11"),
= help: to override `-D warnings` add `#[allow(clippy::match_overlapping_arm)]`
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:18:9
+ --> tests/ui/match_overlapping_arm.rs:16:9
|
LL | 0..=5 => println!("0..=5"),
| ^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:21:9
+ --> tests/ui/match_overlapping_arm.rs:19:9
|
LL | FOO..=11 => println!("FOO..=11"),
| ^^^^^^^^
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:56:9
+ --> tests/ui/match_overlapping_arm.rs:54:9
|
LL | 0..11 => println!("0..11"),
| ^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:58:9
+ --> tests/ui/match_overlapping_arm.rs:56:9
|
LL | 0..=11 => println!("0..=11"),
| ^^^^^^
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:82:9
+ --> tests/ui/match_overlapping_arm.rs:80:9
|
LL | 0..=10 => println!("0..=10"),
| ^^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:81:9
+ --> tests/ui/match_overlapping_arm.rs:79:9
|
LL | 5..14 => println!("5..14"),
| ^^^^^
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:88:9
+ --> tests/ui/match_overlapping_arm.rs:86:9
|
LL | 0..7 => println!("0..7"),
| ^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:90:9
+ --> tests/ui/match_overlapping_arm.rs:88:9
|
LL | 0..=10 => println!("0..=10"),
| ^^^^^^
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:101:9
+ --> tests/ui/match_overlapping_arm.rs:99:9
|
LL | ..=23 => println!("..=23"),
| ^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:103:9
+ --> tests/ui/match_overlapping_arm.rs:101:9
|
LL | ..26 => println!("..26"),
| ^^^^
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:111:9
+ --> tests/ui/match_overlapping_arm.rs:109:9
|
LL | 21..=30 => (),
| ^^^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:113:9
+ --> tests/ui/match_overlapping_arm.rs:111:9
|
LL | 21..=40 => (),
| ^^^^^^^
error: some ranges overlap
- --> tests/ui/match_overlapping_arm.rs:126:9
+ --> tests/ui/match_overlapping_arm.rs:124:9
|
LL | 0..=0x0000_0000_0000_00ff => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: overlaps with this
- --> tests/ui/match_overlapping_arm.rs:128:9
+ --> tests/ui/match_overlapping_arm.rs:126:9
|
LL | 0..=0x0000_0000_0000_ffff => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.rs b/src/tools/clippy/tests/ui/mixed_attributes_style.rs
index 1a646c26522..93ab9392cf8 100644
--- a/src/tools/clippy/tests/ui/mixed_attributes_style.rs
+++ b/src/tools/clippy/tests/ui/mixed_attributes_style.rs
@@ -82,7 +82,8 @@ mod issue_12530 {
#![allow(dead_code)]
}
}
- /// Nested mod //~ ERROR: item has both inner and outer attributes
+ /// Nested mod
+ //~^ ERROR: item has both inner and outer attributes
#[allow(unused)]
mod nest_mod_2 {
#![allow(unused)]
diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.stderr b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
index a1d3fc430f6..abdc2df23cf 100644
--- a/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
+++ b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
@@ -46,13 +46,14 @@ error: item has both inner and outer attributes
--> tests/ui/mixed_attributes_style.rs:85:5
|
LL | / /// Nested mod
+LL | |
LL | | #[allow(unused)]
LL | | mod nest_mod_2 {
LL | | #![allow(unused)]
| |_________________________^
error: item has both inner and outer attributes
- --> tests/ui/mixed_attributes_style.rs:90:9
+ --> tests/ui/mixed_attributes_style.rs:91:9
|
LL | / #[allow(dead_code)]
LL | | mod inner_mod {
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index adb266ffbc8..2459af60688 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -7,8 +7,8 @@
)]
#![warn(clippy::must_use_candidate)]
use std::rc::Rc;
-use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
pub struct MyAtomic(AtomicBool);
pub struct MyPure;
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index 49bb16af788..5f9b2449552 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -7,8 +7,8 @@
)]
#![warn(clippy::must_use_candidate)]
use std::rc::Rc;
-use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
pub struct MyAtomic(AtomicBool);
pub struct MyPure;
diff --git a/src/tools/clippy/tests/ui/mut_key.rs b/src/tools/clippy/tests/ui/mut_key.rs
index 81d8732b3b2..43ff705c477 100644
--- a/src/tools/clippy/tests/ui/mut_key.rs
+++ b/src/tools/clippy/tests/ui/mut_key.rs
@@ -2,9 +2,9 @@ use std::cell::Cell;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
+use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::Relaxed;
-use std::sync::Arc;
struct Key(AtomicUsize);
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.rs b/src/tools/clippy/tests/ui/needless_pass_by_value.rs
index 14cba5a7eb5..9408b8c948f 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_value.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_value.rs
@@ -84,7 +84,7 @@ trait Serialize {}
impl<'a, T> Serialize for &'a T where T: Serialize {}
impl Serialize for i32 {}
-fn test_blanket_ref<T: Foo, S: Serialize>(_foo: T, _serializable: S) {}
+fn test_blanket_ref<T: Foo, S: Serialize>(vals: T, serializable: S) {}
//~^ ERROR: this argument is passed by value, but not consumed in the function body
fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
@@ -116,7 +116,7 @@ impl<T: Serialize, U> S<T, U> {
) {
}
- fn baz(&self, _u: U, _s: Self) {}
+ fn baz(&self, uu: U, ss: Self) {}
//~^ ERROR: this argument is passed by value, but not consumed in the function body
//~| ERROR: this argument is passed by value, but not consumed in the function body
}
@@ -162,13 +162,13 @@ fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
// The following 3 lines should not cause an ICE. See #2831
trait Bar<'a, A> {}
impl<'b, T> Bar<'b, T> for T {}
-fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {}
+fn some_fun<'b, S: Bar<'b, ()>>(items: S) {}
//~^ ERROR: this argument is passed by value, but not consumed in the function body
// Also this should not cause an ICE. See #2831
trait Club<'a, A> {}
impl<T> Club<'static, T> for T {}
-fn more_fun(_item: impl Club<'static, i32>) {}
+fn more_fun(items: impl Club<'static, i32>) {}
//~^ ERROR: this argument is passed by value, but not consumed in the function body
fn is_sync<T>(_: T)
@@ -177,6 +177,10 @@ where
{
}
+struct Obj(String);
+
+fn prefix_test(_unused_with_prefix: Obj) {}
+
fn main() {
// This should not cause an ICE either
// https://github.com/rust-lang/rust-clippy/issues/3144
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr
index 827a200ba68..46ef8f3e8da 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr
+++ b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr
@@ -46,7 +46,7 @@ LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:87:49
|
-LL | fn test_blanket_ref<T: Foo, S: Serialize>(_foo: T, _serializable: S) {}
+LL | fn test_blanket_ref<T: Foo, S: Serialize>(vals: T, serializable: S) {}
| ^ help: consider taking a reference instead: `&T`
error: this argument is passed by value, but not consumed in the function body
@@ -106,13 +106,13 @@ LL | t: String,
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:119:23
|
-LL | fn baz(&self, _u: U, _s: Self) {}
+LL | fn baz(&self, uu: U, ss: Self) {}
| ^ help: consider taking a reference instead: `&U`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:119:30
|
-LL | fn baz(&self, _u: U, _s: Self) {}
+LL | fn baz(&self, uu: U, ss: Self) {}
| ^^^^ help: consider taking a reference instead: `&Self`
error: this argument is passed by value, but not consumed in the function body
@@ -121,7 +121,7 @@ error: this argument is passed by value, but not consumed in the function body
LL | fn bar_copy(x: u32, y: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
|
LL | struct CopyWrapper(u32);
@@ -133,7 +133,7 @@ error: this argument is passed by value, but not consumed in the function body
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
|
LL | struct CopyWrapper(u32);
@@ -145,7 +145,7 @@ error: this argument is passed by value, but not consumed in the function body
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
|
LL | struct CopyWrapper(u32);
@@ -157,7 +157,7 @@ error: this argument is passed by value, but not consumed in the function body
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
-help: consider marking this type as `Copy`
+help: or consider marking this type as `Copy`
--> tests/ui/needless_pass_by_value.rs:141:1
|
LL | struct CopyWrapper(u32);
@@ -166,13 +166,13 @@ LL | struct CopyWrapper(u32);
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:165:40
|
-LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {}
+LL | fn some_fun<'b, S: Bar<'b, ()>>(items: S) {}
| ^ help: consider taking a reference instead: `&S`
error: this argument is passed by value, but not consumed in the function body
--> tests/ui/needless_pass_by_value.rs:171:20
|
-LL | fn more_fun(_item: impl Club<'static, i32>) {}
+LL | fn more_fun(items: impl Club<'static, i32>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>`
error: aborting due to 22 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index fc4129e1db8..c5c570690b4 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -355,4 +355,8 @@ fn conjunctive_blocks() -> String {
({ "a".to_string() } + "b" + { "c" })
}
+fn issue12907() -> String {
+ "".split("").next().unwrap().to_string()
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 61c7a02008f..738611391df 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -365,4 +365,8 @@ fn conjunctive_blocks() -> String {
return { "a".to_string() } + "b" + { "c" };
}
+fn issue12907() -> String {
+ return "".split("").next().unwrap().to_string();
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index ea9c230eafd..da0fa220d8c 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -665,5 +665,17 @@ LL - return { "a".to_string() } + "b" + { "c" };
LL + ({ "a".to_string() } + "b" + { "c" })
|
-error: aborting due to 53 previous errors
+error: unneeded `return` statement
+ --> tests/ui/needless_return.rs:369:5
+ |
+LL | return "".split("").next().unwrap().to_string();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: remove `return`
+ |
+LL - return "".split("").next().unwrap().to_string();
+LL + "".split("").next().unwrap().to_string()
+ |
+
+error: aborting due to 54 previous errors
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
index 237f5f5b97a..f68d5e30d27 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
@@ -1,4 +1,4 @@
-//@ignore-target-windows
+//@ignore-target: windows
#![warn(clippy::non_octal_unix_permissions)]
use std::fs::{DirBuilder, File, OpenOptions, Permissions};
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
index c8da5dbcec2..647c3769d2c 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
@@ -1,4 +1,4 @@
-//@ignore-target-windows
+//@ignore-target: windows
#![warn(clippy::non_octal_unix_permissions)]
use std::fs::{DirBuilder, File, OpenOptions, Permissions};
diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions.fixed b/src/tools/clippy/tests/ui/non_zero_suggestions.fixed
new file mode 100644
index 00000000000..e67c992fdde
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_zero_suggestions.fixed
@@ -0,0 +1,65 @@
+#![warn(clippy::non_zero_suggestions)]
+use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
+
+fn main() {
+ /// Positive test cases (lint should trigger)
+ // U32 -> U64
+ let x: u64 = 100;
+ let y = NonZeroU32::new(10).unwrap();
+ let r1 = x / NonZeroU64::from(y);
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ let r2 = x % NonZeroU64::from(y);
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ // U16 -> U32
+ let a: u32 = 50;
+ let b = NonZeroU16::new(5).unwrap();
+ let r3 = a / NonZeroU32::from(b);
+ //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
+
+ let x = NonZeroU64::from(NonZeroU32::new(5).unwrap());
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ /// Negative test cases (lint should not trigger)
+ // Left hand side expressions should not be triggered
+ let c: u32 = 50;
+ let d = NonZeroU16::new(5).unwrap();
+ let r4 = u32::from(b.get()) / a;
+
+ // Should not trigger for any other operand other than `/` and `%`
+ let r5 = a + u32::from(b.get());
+ let r6 = a - u32::from(b.get());
+
+ // Same size types
+ let e: u32 = 200;
+ let f = NonZeroU32::new(20).unwrap();
+ let r7 = e / f.get();
+
+ // Smaller to larger, but not NonZero
+ let g: u64 = 1000;
+ let h: u32 = 50;
+ let r8 = g / u64::from(h);
+
+ // Using From correctly
+ let k: u64 = 300;
+ let l = NonZeroU32::new(15).unwrap();
+ let r9 = k / NonZeroU64::from(l);
+}
+
+// Additional function to test the lint in a different context
+fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
+ x / NonZeroU64::from(y)
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+}
+
+struct Calculator {
+ value: u64,
+}
+
+impl Calculator {
+ fn divide(&self, divisor: NonZeroU32) -> u64 {
+ self.value / NonZeroU64::from(divisor)
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ }
+}
diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions.rs b/src/tools/clippy/tests/ui/non_zero_suggestions.rs
new file mode 100644
index 00000000000..de82371a8f2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_zero_suggestions.rs
@@ -0,0 +1,65 @@
+#![warn(clippy::non_zero_suggestions)]
+use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
+
+fn main() {
+ /// Positive test cases (lint should trigger)
+ // U32 -> U64
+ let x: u64 = 100;
+ let y = NonZeroU32::new(10).unwrap();
+ let r1 = x / u64::from(y.get());
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ let r2 = x % u64::from(y.get());
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ // U16 -> U32
+ let a: u32 = 50;
+ let b = NonZeroU16::new(5).unwrap();
+ let r3 = a / u32::from(b.get());
+ //~^ ERROR: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
+
+ let x = u64::from(NonZeroU32::new(5).unwrap().get());
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ /// Negative test cases (lint should not trigger)
+ // Left hand side expressions should not be triggered
+ let c: u32 = 50;
+ let d = NonZeroU16::new(5).unwrap();
+ let r4 = u32::from(b.get()) / a;
+
+ // Should not trigger for any other operand other than `/` and `%`
+ let r5 = a + u32::from(b.get());
+ let r6 = a - u32::from(b.get());
+
+ // Same size types
+ let e: u32 = 200;
+ let f = NonZeroU32::new(20).unwrap();
+ let r7 = e / f.get();
+
+ // Smaller to larger, but not NonZero
+ let g: u64 = 1000;
+ let h: u32 = 50;
+ let r8 = g / u64::from(h);
+
+ // Using From correctly
+ let k: u64 = 300;
+ let l = NonZeroU32::new(15).unwrap();
+ let r9 = k / NonZeroU64::from(l);
+}
+
+// Additional function to test the lint in a different context
+fn divide_numbers(x: u64, y: NonZeroU32) -> u64 {
+ x / u64::from(y.get())
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+}
+
+struct Calculator {
+ value: u64,
+}
+
+impl Calculator {
+ fn divide(&self, divisor: NonZeroU32) -> u64 {
+ self.value / u64::from(divisor.get())
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ }
+}
diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions.stderr b/src/tools/clippy/tests/ui/non_zero_suggestions.stderr
new file mode 100644
index 00000000000..7a57f7983be
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_zero_suggestions.stderr
@@ -0,0 +1,41 @@
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions.rs:9:18
+ |
+LL | let r1 = x / u64::from(y.get());
+ | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
+ |
+ = note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions.rs:12:18
+ |
+LL | let r2 = x % u64::from(y.get());
+ | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
+
+error: consider using `NonZeroU32::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions.rs:18:18
+ |
+LL | let r3 = a / u32::from(b.get());
+ | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU32::from(b)`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions.rs:21:13
+ |
+LL | let x = u64::from(NonZeroU32::new(5).unwrap().get());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(5).unwrap())`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions.rs:52:9
+ |
+LL | x / u64::from(y.get())
+ | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions.rs:62:22
+ |
+LL | self.value / u64::from(divisor.get())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(divisor)`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.rs b/src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.rs
new file mode 100644
index 00000000000..193c710e589
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.rs
@@ -0,0 +1,23 @@
+#![warn(clippy::non_zero_suggestions)]
+//@no-rustfix
+use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
+
+fn main() {
+ let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get());
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+
+ let n = NonZeroU32::new(20).unwrap();
+ let y = u64::from(n.get());
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ some_fn_that_only_takes_u64(y);
+
+ let m = NonZeroU32::try_from(1).unwrap();
+ let _z: NonZeroU64 = m.into();
+}
+
+fn return_non_zero(x: u64, y: NonZeroU32) -> u64 {
+ u64::from(y.get())
+ //~^ ERROR: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+}
+
+fn some_fn_that_only_takes_u64(_: u64) {}
diff --git a/src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.stderr b/src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.stderr
new file mode 100644
index 00000000000..787179f2a2d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_zero_suggestions_unfixable.stderr
@@ -0,0 +1,23 @@
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions_unfixable.rs:6:18
+ |
+LL | let x: u64 = u64::from(NonZeroU32::new(5).unwrap().get());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(5).unwrap())`
+ |
+ = note: `-D clippy::non-zero-suggestions` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::non_zero_suggestions)]`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions_unfixable.rs:10:13
+ |
+LL | let y = u64::from(n.get());
+ | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(n)`
+
+error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion
+ --> tests/ui/non_zero_suggestions_unfixable.rs:19:5
+ |
+LL | u64::from(y.get())
+ | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.rs b/src/tools/clippy/tests/ui/panic_in_result_fn.rs
index aaaf9a109ac..e2375aa996f 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn.rs
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn.rs
@@ -71,6 +71,15 @@ fn function_result_with_custom_todo() -> Result<bool, String> // should not emit
Ok(true)
}
+fn issue_13381<const N: usize>() -> Result<(), String> {
+ const {
+ if N == 0 {
+ panic!();
+ }
+ }
+ Ok(())
+}
+
fn main() -> Result<(), String> {
todo!("finish main method");
Ok(())
diff --git a/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs
new file mode 100644
index 00000000000..b5abcbb3474
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.rs
@@ -0,0 +1,33 @@
+//@ needs-asm-support
+#![warn(clippy::pointers_in_nomem_asm_block)]
+#![crate_type = "lib"]
+#![no_std]
+
+use core::arch::asm;
+
+unsafe fn nomem_bad(p: &i32) {
+ asm!(
+ "asdf {p1}, {p2}, {p3}",
+ p1 = in(reg) p,
+ //~^ ERROR: passing pointers to nomem asm block
+ p2 = in(reg) p as *const _ as usize,
+ p3 = in(reg) p,
+ options(nomem, nostack, preserves_flags)
+ );
+}
+
+unsafe fn nomem_good(p: &i32) {
+ asm!("asdf {p}", p = in(reg) p, options(readonly, nostack, preserves_flags));
+ let p = p as *const i32 as usize;
+ asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+}
+
+unsafe fn nomem_bad2(p: &mut i32) {
+ asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+ //~^ ERROR: passing pointers to nomem asm block
+}
+
+unsafe fn nomem_fn(p: extern "C" fn()) {
+ asm!("call {p}", p = in(reg) p, options(nomem));
+ //~^ ERROR: passing pointers to nomem asm block
+}
diff --git a/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr
new file mode 100644
index 00000000000..cabeb37344f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/pointers_in_nomem_asm_block.stderr
@@ -0,0 +1,34 @@
+error: passing pointers to nomem asm block
+ --> tests/ui/pointers_in_nomem_asm_block.rs:11:9
+ |
+LL | p1 = in(reg) p,
+ | ^^^^^^^^^^^^^^
+...
+LL | p3 = in(reg) p,
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `nomem` means that no memory write or read happens inside the asm! block
+ = note: if this is intentional and no pointers are read or written to, consider allowing the lint
+ = note: `-D clippy::pointers-in-nomem-asm-block` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::pointers_in_nomem_asm_block)]`
+
+error: passing pointers to nomem asm block
+ --> tests/ui/pointers_in_nomem_asm_block.rs:26:22
+ |
+LL | asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags));
+ | ^^^^^^^^^^^^^
+ |
+ = note: `nomem` means that no memory write or read happens inside the asm! block
+ = note: if this is intentional and no pointers are read or written to, consider allowing the lint
+
+error: passing pointers to nomem asm block
+ --> tests/ui/pointers_in_nomem_asm_block.rs:31:22
+ |
+LL | asm!("call {p}", p = in(reg) p, options(nomem));
+ | ^^^^^^^^^^^^^
+ |
+ = note: `nomem` means that no memory write or read happens inside the asm! block
+ = note: if this is intentional and no pointers are read or written to, consider allowing the lint
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs
index e6ef6268121..e8b42d3b913 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.rs
+++ b/src/tools/clippy/tests/ui/ptr_arg.rs
@@ -309,3 +309,25 @@ mod issue_11181 {
extern "C" fn allowed(_v: &Vec<u32>) {}
}
}
+
+mod issue_13308 {
+ use std::ops::Deref;
+
+ fn repro(source: &str, destination: &mut String) {
+ source.clone_into(destination);
+ }
+ fn repro2(source: &str, destination: &mut String) {
+ ToOwned::clone_into(source, destination);
+ }
+
+ fn h1(_: &<String as Deref>::Target) {}
+ fn h2<T: Deref>(_: T, _: &T::Target) {}
+
+ // Other cases that are still ok to lint and ideally shouldn't regress
+ fn good(v1: &String, v2: &String) {
+ //~^ ERROR: writing `&String` instead of `&str`
+ //~^^ ERROR: writing `&String` instead of `&str`
+ h1(v1);
+ h2(String::new(), v2);
+ }
+}
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 4246453e64c..1a6b3aa1f8d 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -221,5 +221,17 @@ error: using a reference to `Cow` is not recommended
LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
| ^^^^^^^^^^^^^^^^ help: change this to: `&str`
-error: aborting due to 25 previous errors
+error: writing `&String` instead of `&str` involves a new object where a slice will do
+ --> tests/ui/ptr_arg.rs:327:17
+ |
+LL | fn good(v1: &String, v2: &String) {
+ | ^^^^^^^ help: change this to: `&str`
+
+error: writing `&String` instead of `&str` involves a new object where a slice will do
+ --> tests/ui/ptr_arg.rs:327:30
+ |
+LL | fn good(v1: &String, v2: &String) {
+ | ^^^^^^^ help: change this to: `&str`
+
+error: aborting due to 27 previous errors
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
index 21ac42196e1..9a5272c7adc 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.fixed
@@ -68,3 +68,20 @@ fn _msrv_1_65() {
let _ = ptr.cast_mut();
let _ = mut_ptr.cast_const();
}
+
+#[inline_macros]
+fn null_pointers() {
+ use std::ptr;
+ let _ = std::ptr::null_mut::<String>();
+ let _ = std::ptr::null::<u32>();
+ let _ = std::ptr::null_mut::<u32>();
+ let _ = std::ptr::null::<u32>();
+
+ // Make sure the lint is triggered inside a macro
+ let _ = inline!(std::ptr::null_mut::<u32>());
+ let _ = inline!(std::ptr::null_mut::<u32>());
+
+ // Do not lint inside macros from external crates
+ let _ = external!(ptr::null::<u32>() as *mut u32);
+ let _ = external!(ptr::null::<u32>().cast_mut());
+}
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.rs b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
index 5ce590b2b7e..43ab5f5ba7c 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.rs
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.rs
@@ -68,3 +68,20 @@ fn _msrv_1_65() {
let _ = ptr as *mut u32;
let _ = mut_ptr as *const u32;
}
+
+#[inline_macros]
+fn null_pointers() {
+ use std::ptr;
+ let _ = ptr::null::<String>() as *mut String;
+ let _ = ptr::null_mut::<u32>() as *const u32;
+ let _ = ptr::null::<u32>().cast_mut();
+ let _ = ptr::null_mut::<u32>().cast_const();
+
+ // Make sure the lint is triggered inside a macro
+ let _ = inline!(ptr::null::<u32>() as *mut u32);
+ let _ = inline!(ptr::null::<u32>().cast_mut());
+
+ // Do not lint inside macros from external crates
+ let _ = external!(ptr::null::<u32>() as *mut u32);
+ let _ = external!(ptr::null::<u32>().cast_mut());
+}
diff --git a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
index 2c52ebd3464..a693793a4ae 100644
--- a/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
+++ b/src/tools/clippy/tests/ui/ptr_cast_constness.stderr
@@ -43,5 +43,45 @@ error: `as` casting between raw pointers while changing only its constness
LL | let _ = mut_ptr as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()`
-error: aborting due to 7 previous errors
+error: `as` casting to make a const null pointer into a mutable null pointer
+ --> tests/ui/ptr_cast_constness.rs:75:13
+ |
+LL | let _ = ptr::null::<String>() as *mut String;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<String>()`
+
+error: `as` casting to make a mutable null pointer into a const null pointer
+ --> tests/ui/ptr_cast_constness.rs:76:13
+ |
+LL | let _ = ptr::null_mut::<u32>() as *const u32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
+
+error: changing constness of a null pointer
+ --> tests/ui/ptr_cast_constness.rs:77:13
+ |
+LL | let _ = ptr::null::<u32>().cast_mut();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+
+error: changing constness of a null pointer
+ --> tests/ui/ptr_cast_constness.rs:78:13
+ |
+LL | let _ = ptr::null_mut::<u32>().cast_const();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::<u32>()`
+
+error: `as` casting to make a const null pointer into a mutable null pointer
+ --> tests/ui/ptr_cast_constness.rs:81:21
+ |
+LL | let _ = inline!(ptr::null::<u32>() as *mut u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+ |
+ = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: changing constness of a null pointer
+ --> tests/ui/ptr_cast_constness.rs:82:21
+ |
+LL | let _ = inline!(ptr::null::<u32>().cast_mut());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::<u32>()`
+ |
+ = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/result_large_err.rs b/src/tools/clippy/tests/ui/result_large_err.rs
index b25348bf996..9c39f023da2 100644
--- a/src/tools/clippy/tests/ui/result_large_err.rs
+++ b/src/tools/clippy/tests/ui/result_large_err.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
#![warn(clippy::result_large_err)]
#![allow(clippy::large_enum_variant)]
diff --git a/src/tools/clippy/tests/ui/single_call_fn.rs b/src/tools/clippy/tests/ui/single_call_fn.rs
index 55e7508a957..a0597664da5 100644
--- a/src/tools/clippy/tests/ui/single_call_fn.rs
+++ b/src/tools/clippy/tests/ui/single_call_fn.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
//@aux-build:proc_macros.rs
#![allow(clippy::redundant_closure_call, unused)]
#![warn(clippy::single_call_fn)]
diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed
index 5249c440889..4016b2699d6 100644
--- a/src/tools/clippy/tests/ui/single_match.fixed
+++ b/src/tools/clippy/tests/ui/single_match.fixed
@@ -39,8 +39,8 @@ enum Foo {
Bar,
Baz(u8),
}
-use std::borrow::Cow;
use Foo::*;
+use std::borrow::Cow;
fn single_match_know_enum() {
let x = Some(1u8);
@@ -296,3 +296,27 @@ fn issue11365() {
if let Some(A | B) = &Some(A) { println!() }
}
+
+#[derive(Eq, PartialEq)]
+pub struct Data([u8; 4]);
+
+const DATA: Data = Data([1, 2, 3, 4]);
+const CONST_I32: i32 = 1;
+
+fn irrefutable_match() {
+ println!();
+
+ println!();
+
+ let i = 0;
+ {
+ let a = 1;
+ let b = 2;
+ }
+
+
+
+
+
+ println!()
+}
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index 882098a56e7..75edaa60605 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -51,8 +51,8 @@ enum Foo {
Bar,
Baz(u8),
}
-use std::borrow::Cow;
use Foo::*;
+use std::borrow::Cow;
fn single_match_know_enum() {
let x = Some(1u8);
@@ -360,3 +360,45 @@ fn issue11365() {
None | Some(_) => {},
}
}
+
+#[derive(Eq, PartialEq)]
+pub struct Data([u8; 4]);
+
+const DATA: Data = Data([1, 2, 3, 4]);
+const CONST_I32: i32 = 1;
+
+fn irrefutable_match() {
+ match DATA {
+ DATA => println!(),
+ _ => {},
+ }
+
+ match CONST_I32 {
+ CONST_I32 => println!(),
+ _ => {},
+ }
+
+ let i = 0;
+ match i {
+ i => {
+ let a = 1;
+ let b = 2;
+ },
+ _ => {},
+ }
+
+ match i {
+ i => {},
+ _ => {},
+ }
+
+ match i {
+ i => (),
+ _ => (),
+ }
+
+ match CONST_I32 {
+ CONST_I32 => println!(),
+ _ => {},
+ }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index ceb2a193bf7..9240b09c50a 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -216,5 +216,70 @@ LL | | None | Some(_) => {},
LL | | }
| |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }`
-error: aborting due to 20 previous errors
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match.rs:371:5
+ |
+LL | / match DATA {
+LL | | DATA => println!(),
+LL | | _ => {},
+LL | | }
+ | |_____^ help: try: `println!();`
+
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match.rs:376:5
+ |
+LL | / match CONST_I32 {
+LL | | CONST_I32 => println!(),
+LL | | _ => {},
+LL | | }
+ | |_____^ help: try: `println!();`
+
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match.rs:382:5
+ |
+LL | / match i {
+LL | | i => {
+LL | | let a = 1;
+LL | | let b = 2;
+LL | | },
+LL | | _ => {},
+LL | | }
+ | |_____^
+ |
+help: try
+ |
+LL ~ {
+LL + let a = 1;
+LL + let b = 2;
+LL + }
+ |
+
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match.rs:390:5
+ |
+LL | / match i {
+LL | | i => {},
+LL | | _ => {},
+LL | | }
+ | |_____^ help: `match` expression can be removed
+
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match.rs:395:5
+ |
+LL | / match i {
+LL | | i => (),
+LL | | _ => (),
+LL | | }
+ | |_____^ help: `match` expression can be removed
+
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match.rs:400:5
+ |
+LL | / match CONST_I32 {
+LL | | CONST_I32 => println!(),
+LL | | _ => {},
+LL | | }
+ | |_____^ help: try: `println!()`
+
+error: aborting due to 26 previous errors
diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed
index 163be16ad8b..c2ca746976b 100644
--- a/src/tools/clippy/tests/ui/single_match_else.fixed
+++ b/src/tools/clippy/tests/ui/single_match_else.fixed
@@ -171,3 +171,7 @@ fn issue_10808(bar: Option<i32>) {
},
}
}
+
+fn irrefutable_match() -> Option<&'static ExprNode> {
+ Some(&NODE)
+}
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index 3f1fd2b3183..2d9e877ee0f 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -199,3 +199,13 @@ fn issue_10808(bar: Option<i32>) {
},
}
}
+
+fn irrefutable_match() -> Option<&'static ExprNode> {
+ match ExprNode::Butterflies {
+ ExprNode::Butterflies => Some(&NODE),
+ _ => {
+ let x = 5;
+ None
+ },
+ }
+}
diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr
index 61c348260d0..a2801751a43 100644
--- a/src/tools/clippy/tests/ui/single_match_else.stderr
+++ b/src/tools/clippy/tests/ui/single_match_else.stderr
@@ -197,5 +197,17 @@ LL + println!("None");
LL + }
|
-error: aborting due to 9 previous errors
+error: this pattern is irrefutable, `match` is useless
+ --> tests/ui/single_match_else.rs:204:5
+ |
+LL | / match ExprNode::Butterflies {
+LL | | ExprNode::Butterflies => Some(&NODE),
+LL | | _ => {
+LL | | let x = 5;
+LL | | None
+LL | | },
+LL | | }
+ | |_____^ help: try: `Some(&NODE)`
+
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/string_slice.rs b/src/tools/clippy/tests/ui/string_slice.rs
index 1d1911aaa1d..dc519493a4d 100644
--- a/src/tools/clippy/tests/ui/string_slice.rs
+++ b/src/tools/clippy/tests/ui/string_slice.rs
@@ -1,7 +1,7 @@
-use std::borrow::Cow;
+#![warn(clippy::string_slice)]
+#![allow(clippy::no_effect)]
-#[warn(clippy::string_slice)]
-#[allow(clippy::no_effect)]
+use std::borrow::Cow;
fn main() {
&"Ölkanne"[1..];
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.fixed b/src/tools/clippy/tests/ui/suspicious_command_arg_space.fixed
index 5d7b1e0c17f..704d6ea1bb8 100644
--- a/src/tools/clippy/tests/ui/suspicious_command_arg_space.fixed
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.fixed
@@ -1,3 +1,4 @@
+#![allow(clippy::zombie_processes)]
fn main() {
// Things it should warn about:
std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs b/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
index 8abd9803a0c..2a2a7557381 100644
--- a/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::zombie_processes)]
fn main() {
// Things it should warn about:
std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr b/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
index d2517b66b56..6fd07d07d7b 100644
--- a/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
@@ -1,5 +1,5 @@
error: single argument that looks like it should be multiple arguments
- --> tests/ui/suspicious_command_arg_space.rs:3:44
+ --> tests/ui/suspicious_command_arg_space.rs:4:44
|
LL | std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
| ^^^^^^^^^^
@@ -12,7 +12,7 @@ LL | std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap
| ~~~~ ~~~~~~~~~~~~~~~
error: single argument that looks like it should be multiple arguments
- --> tests/ui/suspicious_command_arg_space.rs:6:43
+ --> tests/ui/suspicious_command_arg_space.rs:7:43
|
LL | std::process::Command::new("cat").arg("--number file").spawn().unwrap();
| ^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.rs b/src/tools/clippy/tests/ui/suspicious_to_owned.rs
index f32b07d45f6..794c2e7174a 100644
--- a/src/tools/clippy/tests/ui/suspicious_to_owned.rs
+++ b/src/tools/clippy/tests/ui/suspicious_to_owned.rs
@@ -3,7 +3,7 @@
#![warn(clippy::implicit_clone)]
#![allow(clippy::redundant_clone)]
use std::borrow::Cow;
-use std::ffi::{c_char, CStr};
+use std::ffi::{CStr, c_char};
fn main() {
let moo = "Moooo";
diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed b/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed
index 26cc5c27e88..3536c1746df 100644
--- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed
+++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.fixed
@@ -1,5 +1,4 @@
#![warn(clippy::tabs_in_doc_comments)]
-#[allow(dead_code)]
///
/// Struct to hold two strings:
diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs b/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs
index 14b06966ecc..033a685066e 100644
--- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.rs
@@ -1,5 +1,4 @@
#![warn(clippy::tabs_in_doc_comments)]
-#[allow(dead_code)]
///
/// Struct to hold two strings:
diff --git a/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr b/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr
index aef6c391452..f8d30b728e5 100644
--- a/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr
+++ b/src/tools/clippy/tests/ui/tabs_in_doc_comments.stderr
@@ -1,5 +1,5 @@
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:6:5
+ --> tests/ui/tabs_in_doc_comments.rs:5:5
|
LL | /// - first one
| ^^^^ help: consider using four spaces per tab
@@ -8,43 +8,43 @@ LL | /// - first one
= help: to override `-D warnings` add `#[allow(clippy::tabs_in_doc_comments)]`
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:6:13
+ --> tests/ui/tabs_in_doc_comments.rs:5:13
|
LL | /// - first one
| ^^^^^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:7:5
+ --> tests/ui/tabs_in_doc_comments.rs:6:5
|
LL | /// - second one
| ^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:7:14
+ --> tests/ui/tabs_in_doc_comments.rs:6:14
|
LL | /// - second one
| ^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:10:9
+ --> tests/ui/tabs_in_doc_comments.rs:9:9
|
LL | /// - First String:
| ^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:11:9
+ --> tests/ui/tabs_in_doc_comments.rs:10:9
|
LL | /// - needs to be inside here
| ^^^^^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:14:9
+ --> tests/ui/tabs_in_doc_comments.rs:13:9
|
LL | /// - Second String:
| ^^^^ help: consider using four spaces per tab
error: using tabs in doc comments is not recommended
- --> tests/ui/tabs_in_doc_comments.rs:15:9
+ --> tests/ui/tabs_in_doc_comments.rs:14:9
|
LL | /// - needs to be inside here
| ^^^^^^^^ help: consider using four spaces per tab
diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs
index 1042249c5b7..7d0a37cde46 100644
--- a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs
+++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.rs
@@ -2,6 +2,16 @@
#![warn(clippy::too_long_first_doc_paragraph)]
+pub mod foo {
+
+ // in foo.rs
+ //! A very short summary.
+ //! A much longer explanation that goes into a lot more detail about
+ //! how the thing works, possibly with doclinks and so one,
+ //! and probably spanning a many rows. Blablabla, it needs to be over
+ //! 200 characters so I needed to write something longeeeeeeer.
+}
+
/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
/// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
/// gravida non lacinia at, rhoncus eu lacus.
diff --git a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr
index 7f48e5cf884..39926647f54 100644
--- a/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr
+++ b/src/tools/clippy/tests/ui/too_long_first_doc_paragraph.stderr
@@ -1,16 +1,32 @@
error: first doc comment paragraph is too long
- --> tests/ui/too_long_first_doc_paragraph.rs:5:1
+ --> tests/ui/too_long_first_doc_paragraph.rs:8:5
+ |
+LL | / //! A very short summary.
+LL | | //! A much longer explanation that goes into a lot more detail about
+LL | | //! how the thing works, possibly with doclinks and so one,
+LL | | //! and probably spanning a many rows. Blablabla, it needs to be over
+LL | | //! 200 characters so I needed to write something longeeeeeeer.
+ | |____^
+ |
+ = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
+help: add an empty line
+ |
+LL ~ //! A very short summary.
+LL + //!
+LL ~ //! A much longer explanation that goes into a lot more detail about
+ |
+
+error: first doc comment paragraph is too long
+ --> tests/ui/too_long_first_doc_paragraph.rs:15:1
|
LL | / /// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris arcu libero,
LL | | /// gravida non lacinia at, rhoncus eu lacus.
| |_
- |
- = note: `-D clippy::too-long-first-doc-paragraph` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::too_long_first_doc_paragraph)]`
error: first doc comment paragraph is too long
- --> tests/ui/too_long_first_doc_paragraph.rs:26:1
+ --> tests/ui/too_long_first_doc_paragraph.rs:36:1
|
LL | / /// Lorem
LL | | /// ipsum dolor sit amet, consectetur adipiscing elit. Nunc turpis nunc, lacinia
@@ -18,5 +34,5 @@ LL | | /// a dolor in, pellentesque aliquet enim. Cras nec maximus sem. Mauris a
LL | | /// gravida non lacinia at, rhoncus eu lacus.
| |_
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/transmute_32bit.rs b/src/tools/clippy/tests/ui/transmute_32bit.rs
index 8e1316ca39d..e162bbb2d92 100644
--- a/src/tools/clippy/tests/ui/transmute_32bit.rs
+++ b/src/tools/clippy/tests/ui/transmute_32bit.rs
@@ -1,4 +1,4 @@
-//@ignore-64bit
+//@ignore-bitwidth: 64
#[warn(clippy::wrong_transmute)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/transmute_64bit.rs b/src/tools/clippy/tests/ui/transmute_64bit.rs
index 767cc503a39..fd0ad74bcfa 100644
--- a/src/tools/clippy/tests/ui/transmute_64bit.rs
+++ b/src/tools/clippy/tests/ui/transmute_64bit.rs
@@ -1,4 +1,4 @@
-//@ignore-32bit
+//@ignore-bitwidth: 32
#[warn(clippy::wrong_transmute)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/transmute_collection.rs b/src/tools/clippy/tests/ui/transmute_collection.rs
index e30b34a5d7d..6748b66e0eb 100644
--- a/src/tools/clippy/tests/ui/transmute_collection.rs
+++ b/src/tools/clippy/tests/ui/transmute_collection.rs
@@ -2,7 +2,7 @@
#![allow(clippy::missing_transmute_annotations)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
-use std::mem::{transmute, MaybeUninit};
+use std::mem::{MaybeUninit, transmute};
fn main() {
unsafe {
diff --git a/src/tools/clippy/tests/ui/transmute_undefined_repr.rs b/src/tools/clippy/tests/ui/transmute_undefined_repr.rs
index dd4bac7f1ed..5b16d71f114 100644
--- a/src/tools/clippy/tests/ui/transmute_undefined_repr.rs
+++ b/src/tools/clippy/tests/ui/transmute_undefined_repr.rs
@@ -8,7 +8,7 @@
use core::any::TypeId;
use core::ffi::c_void;
-use core::mem::{size_of, transmute, MaybeUninit};
+use core::mem::{MaybeUninit, size_of, transmute};
use core::ptr::NonNull;
fn value<T>() -> T {
diff --git a/src/tools/clippy/tests/ui/uninit_vec.rs b/src/tools/clippy/tests/ui/uninit_vec.rs
index 0cc77a8775d..464f88140bd 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.rs
+++ b/src/tools/clippy/tests/ui/uninit_vec.rs
@@ -150,4 +150,36 @@ fn main() {
vec.set_len(10);
}
}
+
+ fn nested_union<T>() {
+ let mut vec: Vec<UnsafeCell<MaybeUninit<T>>> = Vec::with_capacity(1);
+ unsafe {
+ vec.set_len(1);
+ }
+ }
+
+ struct Recursive<T>(*const Recursive<T>, MaybeUninit<T>);
+ fn recursive_union<T>() {
+ // Make sure we don't stack overflow on recursive types.
+ // The pointer acts as the base case because it can't be uninit regardless of its pointee.
+
+ let mut vec: Vec<Recursive<T>> = Vec::with_capacity(1);
+ //~^ uninit_vec
+ unsafe {
+ vec.set_len(1);
+ }
+ }
+
+ #[repr(u8)]
+ enum Enum<T> {
+ Variant(T),
+ }
+ fn union_in_enum<T>() {
+ // Enums can have a discriminant that can't be uninit, so this should still warn
+ let mut vec: Vec<Enum<T>> = Vec::with_capacity(1);
+ //~^ uninit_vec
+ unsafe {
+ vec.set_len(1);
+ }
+ }
}
diff --git a/src/tools/clippy/tests/ui/uninit_vec.stderr b/src/tools/clippy/tests/ui/uninit_vec.stderr
index e8b77d653f0..e7c81cf792f 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.stderr
+++ b/src/tools/clippy/tests/ui/uninit_vec.stderr
@@ -125,5 +125,27 @@ LL | vec.set_len(10);
|
= help: initialize the buffer or wrap the content in `MaybeUninit`
-error: aborting due to 12 previous errors
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+ --> tests/ui/uninit_vec.rs:166:9
+ |
+LL | let mut vec: Vec<Recursive<T>> = Vec::with_capacity(1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | vec.set_len(1);
+ | ^^^^^^^^^^^^^^
+ |
+ = help: initialize the buffer or wrap the content in `MaybeUninit`
+
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+ --> tests/ui/uninit_vec.rs:179:9
+ |
+LL | let mut vec: Vec<Enum<T>> = Vec::with_capacity(1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | vec.set_len(1);
+ | ^^^^^^^^^^^^^^
+ |
+ = help: initialize the buffer or wrap the content in `MaybeUninit`
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/unnecessary_first_then_check.fixed b/src/tools/clippy/tests/ui/unnecessary_first_then_check.fixed
new file mode 100644
index 00000000000..7202e1bbd17
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_first_then_check.fixed
@@ -0,0 +1,22 @@
+#![warn(clippy::unnecessary_first_then_check)]
+#![allow(clippy::useless_vec, clippy::const_is_empty)]
+
+fn main() {
+ let s = [1, 2, 3];
+ let _: bool = !s.is_empty();
+ let _: bool = s.is_empty();
+
+ let v = vec![1, 2, 3];
+ let _: bool = !v.is_empty();
+
+ let n = [[1, 2, 3], [4, 5, 6]];
+ let _: bool = !n[0].is_empty();
+ let _: bool = n[0].is_empty();
+
+ struct Foo {
+ bar: &'static [i32],
+ }
+ let f = [Foo { bar: &[] }];
+ let _: bool = !f[0].bar.is_empty();
+ let _: bool = f[0].bar.is_empty();
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_first_then_check.rs b/src/tools/clippy/tests/ui/unnecessary_first_then_check.rs
new file mode 100644
index 00000000000..762b9599928
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_first_then_check.rs
@@ -0,0 +1,22 @@
+#![warn(clippy::unnecessary_first_then_check)]
+#![allow(clippy::useless_vec, clippy::const_is_empty)]
+
+fn main() {
+ let s = [1, 2, 3];
+ let _: bool = s.first().is_some();
+ let _: bool = s.first().is_none();
+
+ let v = vec![1, 2, 3];
+ let _: bool = v.first().is_some();
+
+ let n = [[1, 2, 3], [4, 5, 6]];
+ let _: bool = n[0].first().is_some();
+ let _: bool = n[0].first().is_none();
+
+ struct Foo {
+ bar: &'static [i32],
+ }
+ let f = [Foo { bar: &[] }];
+ let _: bool = f[0].bar.first().is_some();
+ let _: bool = f[0].bar.first().is_none();
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_first_then_check.stderr b/src/tools/clippy/tests/ui/unnecessary_first_then_check.stderr
new file mode 100644
index 00000000000..bbaf7e68eda
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_first_then_check.stderr
@@ -0,0 +1,47 @@
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+ --> tests/ui/unnecessary_first_then_check.rs:6:19
+ |
+LL | let _: bool = s.first().is_some();
+ | ^^^^^^^^^^^^^^^^^^^ help: replace this with: `!s.is_empty()`
+ |
+ = note: `-D clippy::unnecessary-first-then-check` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::unnecessary_first_then_check)]`
+
+error: unnecessary use of `first().is_none()` to check if slice is empty
+ --> tests/ui/unnecessary_first_then_check.rs:7:21
+ |
+LL | let _: bool = s.first().is_none();
+ | ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()`
+
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+ --> tests/ui/unnecessary_first_then_check.rs:10:19
+ |
+LL | let _: bool = v.first().is_some();
+ | ^^^^^^^^^^^^^^^^^^^ help: replace this with: `!v.is_empty()`
+
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+ --> tests/ui/unnecessary_first_then_check.rs:13:19
+ |
+LL | let _: bool = n[0].first().is_some();
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `!n[0].is_empty()`
+
+error: unnecessary use of `first().is_none()` to check if slice is empty
+ --> tests/ui/unnecessary_first_then_check.rs:14:24
+ |
+LL | let _: bool = n[0].first().is_none();
+ | ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()`
+
+error: unnecessary use of `first().is_some()` to check if slice is not empty
+ --> tests/ui/unnecessary_first_then_check.rs:20:19
+ |
+LL | let _: bool = f[0].bar.first().is_some();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `!f[0].bar.is_empty()`
+
+error: unnecessary use of `first().is_none()` to check if slice is empty
+ --> tests/ui/unnecessary_first_then_check.rs:21:28
+ |
+LL | let _: bool = f[0].bar.first().is_none();
+ | ^^^^^^^^^^^^^^^^^ help: replace this with: `is_empty()`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unnecessary_min_or_max.fixed b/src/tools/clippy/tests/ui/unnecessary_min_or_max.fixed
index 392f6dd1fee..1f3e131516c 100644
--- a/src/tools/clippy/tests/ui/unnecessary_min_or_max.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_min_or_max.fixed
@@ -65,3 +65,32 @@ fn random_u32() -> u32 {
// random number generator
0
}
+
+struct Issue13191 {
+ min: u16,
+ max: u16,
+}
+
+impl Issue13191 {
+ fn new() -> Self {
+ Self { min: 0, max: 0 }
+ }
+
+ fn min(mut self, value: u16) -> Self {
+ self.min = value;
+ self
+ }
+
+ fn max(mut self, value: u16) -> Self {
+ self.max = value;
+ self
+ }
+}
+
+fn issue_13191() {
+ // should not fixed
+ Issue13191::new().min(0);
+
+ // should not fixed
+ Issue13191::new().max(0);
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_min_or_max.rs b/src/tools/clippy/tests/ui/unnecessary_min_or_max.rs
index b03755e6d23..58356b9d49e 100644
--- a/src/tools/clippy/tests/ui/unnecessary_min_or_max.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_min_or_max.rs
@@ -65,3 +65,32 @@ fn random_u32() -> u32 {
// random number generator
0
}
+
+struct Issue13191 {
+ min: u16,
+ max: u16,
+}
+
+impl Issue13191 {
+ fn new() -> Self {
+ Self { min: 0, max: 0 }
+ }
+
+ fn min(mut self, value: u16) -> Self {
+ self.min = value;
+ self
+ }
+
+ fn max(mut self, value: u16) -> Self {
+ self.max = value;
+ self
+ }
+}
+
+fn issue_13191() {
+ // should not fixed
+ Issue13191::new().min(0);
+
+ // should not fixed
+ Issue13191::new().max(0);
+}
diff --git a/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs b/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs
index e0e0ded140f..e9e6c8312f5 100644
--- a/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs
@@ -7,7 +7,7 @@ use std::cell::UnsafeCell as TotallySafeCell;
//~| NOTE: `-D clippy::unsafe-removed-from-name` implied by `-D warnings`
use std::cell::UnsafeCell as TotallySafeCellAgain;
-//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain
+//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain`
// Shouldn't error
use std::cell::RefCell as ProbablyNotUnsafe;
diff --git a/src/tools/clippy/tests/ui/unused_trait_names.fixed b/src/tools/clippy/tests/ui/unused_trait_names.fixed
new file mode 100644
index 00000000000..7dfd0db65aa
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_trait_names.fixed
@@ -0,0 +1,286 @@
+//@aux-build:proc_macros.rs
+
+#![allow(unused)]
+#![warn(clippy::unused_trait_names)]
+#![feature(decl_macro)]
+
+extern crate proc_macros;
+
+fn main() {}
+
+fn bad() {
+ use std::any::Any as _;
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn good() {
+ use std::any::Any as _;
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn used_good() {
+ use std::any::Any;
+
+ println!("{:?}", Any::type_id("foo"));
+ println!("{:?}", "foo".type_id());
+}
+
+fn multi_bad() {
+ use std::any::{self, Any as _, TypeId};
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn multi_good() {
+ use std::any::{self, Any as _, TypeId};
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn renamed_bad() {
+ use std::any::Any as _;
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn multi_renamed_bad() {
+ use std::any::{Any as _, TypeId as MyTypeId};
+
+ println!("{:?}", "foo".type_id());
+}
+
+mod pub_good {
+ pub use std::any::Any;
+
+ fn foo() {
+ println!("{:?}", "foo".type_id());
+ }
+}
+
+mod used_mod_good {
+ use std::any::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+}
+
+mod mod_import_bad {
+ fn mod_import_bad() {
+ use std::any::Any as _;
+
+ println!("{:?}", "foo".type_id());
+ }
+}
+
+mod nested_mod_used_good1 {
+ use std::any::Any;
+
+ mod foo {
+ fn foo() {
+ super::Any::type_id("foo");
+ }
+ }
+}
+
+mod nested_mod_used_good2 {
+ use std::any::Any;
+
+ mod foo {
+ use super::Any;
+
+ fn foo() {
+ Any::type_id("foo");
+ }
+ }
+}
+
+mod nested_mod_used_good3 {
+ use std::any::Any;
+
+ mod foo {
+ use crate::nested_mod_used_good3::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+ }
+}
+
+mod nested_mod_used_bad {
+ use std::any::Any as _;
+
+ fn bar() {
+ println!("{:?}", "foo".type_id());
+ }
+
+ mod foo {
+ use std::any::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+ }
+}
+
+// More complex example where `use std::any::Any;` should be anonymised but `use std::any::Any as
+// MyAny;` should not as it is used by a sub module. Even though if you removed `use std::any::Any;`
+// the code would still compile.
+mod nested_mod_used_bad1 {
+ use std::any::Any as _;
+
+ use std::any::Any as MyAny;
+
+ fn baz() {
+ println!("{:?}", "baz".type_id());
+ }
+
+ mod foo {
+ use crate::nested_mod_used_bad1::MyAny;
+
+ fn foo() {
+ println!("{:?}", MyAny::type_id("foo"));
+ }
+ }
+}
+
+// Example of nested import with an unused import to try and trick it
+mod nested_mod_used_good5 {
+ use std::any::Any;
+
+ mod foo {
+ use std::any::Any;
+
+ fn baz() {
+ println!("{:?}", "baz".type_id());
+ }
+
+ mod bar {
+ use crate::nested_mod_used_good5::foo::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+ }
+ }
+}
+
+mod simple_trait {
+ pub trait MyTrait {
+ fn do_things(&self);
+ }
+
+ pub struct MyStruct;
+
+ impl MyTrait for MyStruct {
+ fn do_things(&self) {}
+ }
+}
+
+// Underscore imports were stabilized in 1.33
+#[clippy::msrv = "1.32"]
+fn msrv_1_32() {
+ use simple_trait::{MyStruct, MyTrait};
+ MyStruct.do_things();
+}
+
+#[clippy::msrv = "1.33"]
+fn msrv_1_33() {
+ use simple_trait::{MyStruct, MyTrait as _};
+ MyStruct.do_things();
+}
+
+mod lint_inside_macro_expansion_bad {
+ macro_rules! foo {
+ () => {
+ use std::any::Any as _;
+ fn bar() {
+ "bar".type_id();
+ }
+ };
+ }
+
+ foo!();
+}
+
+mod macro_and_trait_same_name {
+ pub macro Foo() {}
+ pub trait Foo {
+ fn bar(&self);
+ }
+ impl Foo for () {
+ fn bar(&self) {}
+ }
+}
+
+fn call_macro_and_trait_good() {
+ // importing trait and macro but only using macro by path won't allow us to change this to
+ // `use macro_and_trait_same_name::Foo as _;`
+ use macro_and_trait_same_name::Foo;
+ Foo!();
+ ().bar();
+}
+
+proc_macros::external!(
+ fn ignore_inside_external_proc_macro() {
+ use std::any::Any;
+ "foo".type_id();
+ }
+);
+
+proc_macros::with_span!(
+ span
+
+ fn ignore_inside_with_span_proc_macro() {
+ use std::any::Any;
+ "foo".type_id();
+ }
+);
+
+// This should warn the import is unused but should not trigger unused_trait_names
+#[warn(unused)]
+mod unused_import {
+
+}
+
+#[allow(clippy::unused_trait_names)]
+fn allow_lint_fn() {
+ use std::any::Any;
+
+ "foo".type_id();
+}
+
+#[allow(clippy::unused_trait_names)]
+mod allow_lint_mod {
+ use std::any::Any;
+
+ fn foo() {
+ "foo".type_id();
+ }
+}
+
+mod allow_lint_import {
+ #[allow(clippy::unused_trait_names)]
+ use std::any::Any;
+
+ fn foo() {
+ "foo".type_id();
+ }
+}
+
+// Limitation: Suggests `use std::any::Any as _::{self};` which looks weird
+// fn use_trait_self_good() {
+// use std::any::Any::{self};
+// "foo".type_id();
+// }
+
+// Limitation: Suggests `use std::any::{Any as _, Any as _};`
+// mod repeated_renamed {
+// use std::any::{Any, Any as MyAny};
+
+// fn foo() {
+// "foo".type_id();
+// }
+// }
diff --git a/src/tools/clippy/tests/ui/unused_trait_names.rs b/src/tools/clippy/tests/ui/unused_trait_names.rs
new file mode 100644
index 00000000000..ce44eedbc79
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_trait_names.rs
@@ -0,0 +1,286 @@
+//@aux-build:proc_macros.rs
+
+#![allow(unused)]
+#![warn(clippy::unused_trait_names)]
+#![feature(decl_macro)]
+
+extern crate proc_macros;
+
+fn main() {}
+
+fn bad() {
+ use std::any::Any;
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn good() {
+ use std::any::Any as _;
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn used_good() {
+ use std::any::Any;
+
+ println!("{:?}", Any::type_id("foo"));
+ println!("{:?}", "foo".type_id());
+}
+
+fn multi_bad() {
+ use std::any::{self, Any, TypeId};
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn multi_good() {
+ use std::any::{self, Any as _, TypeId};
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn renamed_bad() {
+ use std::any::Any as MyAny;
+
+ println!("{:?}", "foo".type_id());
+}
+
+fn multi_renamed_bad() {
+ use std::any::{Any as MyAny, TypeId as MyTypeId};
+
+ println!("{:?}", "foo".type_id());
+}
+
+mod pub_good {
+ pub use std::any::Any;
+
+ fn foo() {
+ println!("{:?}", "foo".type_id());
+ }
+}
+
+mod used_mod_good {
+ use std::any::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+}
+
+mod mod_import_bad {
+ fn mod_import_bad() {
+ use std::any::Any;
+
+ println!("{:?}", "foo".type_id());
+ }
+}
+
+mod nested_mod_used_good1 {
+ use std::any::Any;
+
+ mod foo {
+ fn foo() {
+ super::Any::type_id("foo");
+ }
+ }
+}
+
+mod nested_mod_used_good2 {
+ use std::any::Any;
+
+ mod foo {
+ use super::Any;
+
+ fn foo() {
+ Any::type_id("foo");
+ }
+ }
+}
+
+mod nested_mod_used_good3 {
+ use std::any::Any;
+
+ mod foo {
+ use crate::nested_mod_used_good3::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+ }
+}
+
+mod nested_mod_used_bad {
+ use std::any::Any;
+
+ fn bar() {
+ println!("{:?}", "foo".type_id());
+ }
+
+ mod foo {
+ use std::any::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+ }
+}
+
+// More complex example where `use std::any::Any;` should be anonymised but `use std::any::Any as
+// MyAny;` should not as it is used by a sub module. Even though if you removed `use std::any::Any;`
+// the code would still compile.
+mod nested_mod_used_bad1 {
+ use std::any::Any;
+
+ use std::any::Any as MyAny;
+
+ fn baz() {
+ println!("{:?}", "baz".type_id());
+ }
+
+ mod foo {
+ use crate::nested_mod_used_bad1::MyAny;
+
+ fn foo() {
+ println!("{:?}", MyAny::type_id("foo"));
+ }
+ }
+}
+
+// Example of nested import with an unused import to try and trick it
+mod nested_mod_used_good5 {
+ use std::any::Any;
+
+ mod foo {
+ use std::any::Any;
+
+ fn baz() {
+ println!("{:?}", "baz".type_id());
+ }
+
+ mod bar {
+ use crate::nested_mod_used_good5::foo::Any;
+
+ fn foo() {
+ println!("{:?}", Any::type_id("foo"));
+ }
+ }
+ }
+}
+
+mod simple_trait {
+ pub trait MyTrait {
+ fn do_things(&self);
+ }
+
+ pub struct MyStruct;
+
+ impl MyTrait for MyStruct {
+ fn do_things(&self) {}
+ }
+}
+
+// Underscore imports were stabilized in 1.33
+#[clippy::msrv = "1.32"]
+fn msrv_1_32() {
+ use simple_trait::{MyStruct, MyTrait};
+ MyStruct.do_things();
+}
+
+#[clippy::msrv = "1.33"]
+fn msrv_1_33() {
+ use simple_trait::{MyStruct, MyTrait};
+ MyStruct.do_things();
+}
+
+mod lint_inside_macro_expansion_bad {
+ macro_rules! foo {
+ () => {
+ use std::any::Any;
+ fn bar() {
+ "bar".type_id();
+ }
+ };
+ }
+
+ foo!();
+}
+
+mod macro_and_trait_same_name {
+ pub macro Foo() {}
+ pub trait Foo {
+ fn bar(&self);
+ }
+ impl Foo for () {
+ fn bar(&self) {}
+ }
+}
+
+fn call_macro_and_trait_good() {
+ // importing trait and macro but only using macro by path won't allow us to change this to
+ // `use macro_and_trait_same_name::Foo as _;`
+ use macro_and_trait_same_name::Foo;
+ Foo!();
+ ().bar();
+}
+
+proc_macros::external!(
+ fn ignore_inside_external_proc_macro() {
+ use std::any::Any;
+ "foo".type_id();
+ }
+);
+
+proc_macros::with_span!(
+ span
+
+ fn ignore_inside_with_span_proc_macro() {
+ use std::any::Any;
+ "foo".type_id();
+ }
+);
+
+// This should warn the import is unused but should not trigger unused_trait_names
+#[warn(unused)]
+mod unused_import {
+ use std::any::Any;
+}
+
+#[allow(clippy::unused_trait_names)]
+fn allow_lint_fn() {
+ use std::any::Any;
+
+ "foo".type_id();
+}
+
+#[allow(clippy::unused_trait_names)]
+mod allow_lint_mod {
+ use std::any::Any;
+
+ fn foo() {
+ "foo".type_id();
+ }
+}
+
+mod allow_lint_import {
+ #[allow(clippy::unused_trait_names)]
+ use std::any::Any;
+
+ fn foo() {
+ "foo".type_id();
+ }
+}
+
+// Limitation: Suggests `use std::any::Any as _::{self};` which looks weird
+// fn use_trait_self_good() {
+// use std::any::Any::{self};
+// "foo".type_id();
+// }
+
+// Limitation: Suggests `use std::any::{Any as _, Any as _};`
+// mod repeated_renamed {
+// use std::any::{Any, Any as MyAny};
+
+// fn foo() {
+// "foo".type_id();
+// }
+// }
diff --git a/src/tools/clippy/tests/ui/unused_trait_names.stderr b/src/tools/clippy/tests/ui/unused_trait_names.stderr
new file mode 100644
index 00000000000..f59d8f58a17
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_trait_names.stderr
@@ -0,0 +1,73 @@
+error: unused import: `std::any::Any`
+ --> tests/ui/unused_trait_names.rs:245:9
+ |
+LL | use std::any::Any;
+ | ^^^^^^^^^^^^^
+ |
+ = note: `-D unused-imports` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(unused_imports)]`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:12:19
+ |
+LL | use std::any::Any;
+ | ^^^ help: use: `Any as _`
+ |
+ = note: `-D clippy::unused-trait-names` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::unused_trait_names)]`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:31:26
+ |
+LL | use std::any::{self, Any, TypeId};
+ | ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:43:19
+ |
+LL | use std::any::Any as MyAny;
+ | ^^^^^^^^^^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:49:20
+ |
+LL | use std::any::{Any as MyAny, TypeId as MyTypeId};
+ | ^^^^^^^^^^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:72:23
+ |
+LL | use std::any::Any;
+ | ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:113:19
+ |
+LL | use std::any::Any;
+ | ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:132:19
+ |
+LL | use std::any::Any;
+ | ^^^ help: use: `Any as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:191:34
+ |
+LL | use simple_trait::{MyStruct, MyTrait};
+ | ^^^^^^^ help: use: `MyTrait as _`
+
+error: importing trait that is only used anonymously
+ --> tests/ui/unused_trait_names.rs:198:27
+ |
+LL | use std::any::Any;
+ | ^^^ help: use: `Any as _`
+...
+LL | foo!();
+ | ------ in this macro invocation
+ |
+ = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr
index 556e1792b3e..f9e8013d3ad 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr
@@ -1,10 +1,10 @@
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
--> tests/ui/used_underscore_binding.rs:23:5
|
LL | _foo + 1
| ^^^^
|
-note: `_foo` is defined here
+note: binding is defined here
--> tests/ui/used_underscore_binding.rs:22:22
|
LL | fn prefix_underscore(_foo: u32) -> u32 {
@@ -12,61 +12,61 @@ LL | fn prefix_underscore(_foo: u32) -> u32 {
= note: `-D clippy::used-underscore-binding` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::used_underscore_binding)]`
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
--> tests/ui/used_underscore_binding.rs:28:20
|
LL | println!("{}", _foo);
| ^^^^
|
-note: `_foo` is defined here
+note: binding is defined here
--> tests/ui/used_underscore_binding.rs:27:24
|
LL | fn in_macro_or_desugar(_foo: u32) {
| ^^^^
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
--> tests/ui/used_underscore_binding.rs:29:16
|
LL | assert_eq!(_foo, _foo);
| ^^^^
|
-note: `_foo` is defined here
+note: binding is defined here
--> tests/ui/used_underscore_binding.rs:27:24
|
LL | fn in_macro_or_desugar(_foo: u32) {
| ^^^^
-error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
--> tests/ui/used_underscore_binding.rs:29:22
|
LL | assert_eq!(_foo, _foo);
| ^^^^
|
-note: `_foo` is defined here
+note: binding is defined here
--> tests/ui/used_underscore_binding.rs:27:24
|
LL | fn in_macro_or_desugar(_foo: u32) {
| ^^^^
-error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
--> tests/ui/used_underscore_binding.rs:42:5
|
LL | s._underscore_field += 1;
| ^^^^^^^^^^^^^^^^^^^
|
-note: `_underscore_field` is defined here
+note: binding is defined here
--> tests/ui/used_underscore_binding.rs:36:5
|
LL | _underscore_field: u32,
| ^^^^^^^^^^^^^^^^^^^^^^
-error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
+error: used underscore-prefixed binding
--> tests/ui/used_underscore_binding.rs:103:16
|
LL | uses_i(_i);
| ^^
|
-note: `_i` is defined here
+note: binding is defined here
--> tests/ui/used_underscore_binding.rs:102:13
|
LL | let _i = 5;
diff --git a/src/tools/clippy/tests/ui/used_underscore_items.rs b/src/tools/clippy/tests/ui/used_underscore_items.rs
new file mode 100644
index 00000000000..223016a5c96
--- /dev/null
+++ b/src/tools/clippy/tests/ui/used_underscore_items.rs
@@ -0,0 +1,63 @@
+//@aux-build:external_item.rs
+#![allow(unused)]
+#![warn(clippy::used_underscore_items)]
+
+extern crate external_item;
+
+// should not lint macro
+macro_rules! macro_wrap_func {
+ () => {
+ fn _marco_foo() {}
+ };
+}
+
+macro_wrap_func!();
+
+struct _FooStruct {}
+
+impl _FooStruct {
+ fn _method_call(self) {}
+}
+
+fn _foo1() {}
+
+fn _foo2() -> i32 {
+ 0
+}
+
+mod a {
+ pub mod b {
+ pub mod c {
+ pub fn _foo3() {}
+
+ pub struct _FooStruct2 {}
+
+ impl _FooStruct2 {
+ pub fn _method_call(self) {}
+ }
+ }
+ }
+}
+
+fn main() {
+ _foo1();
+ let _ = _foo2();
+ a::b::c::_foo3();
+ let _ = &_FooStruct {};
+ let _ = _FooStruct {};
+
+ let foo_struct = _FooStruct {};
+ foo_struct._method_call();
+
+ let foo_struct2 = a::b::c::_FooStruct2 {};
+ foo_struct2._method_call();
+}
+
+// should not lint exteranl crate.
+// user cannot control how others name their items
+fn external_item_call() {
+ let foo_struct3 = external_item::_ExternalStruct {};
+ foo_struct3._foo();
+
+ external_item::_exernal_foo();
+}
diff --git a/src/tools/clippy/tests/ui/used_underscore_items.stderr b/src/tools/clippy/tests/ui/used_underscore_items.stderr
new file mode 100644
index 00000000000..93ac3a6fec6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/used_underscore_items.stderr
@@ -0,0 +1,112 @@
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:43:5
+ |
+LL | _foo1();
+ | ^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:22:1
+ |
+LL | fn _foo1() {}
+ | ^^^^^^^^^^
+ = note: `-D clippy::used-underscore-items` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::used_underscore_items)]`
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:44:13
+ |
+LL | let _ = _foo2();
+ | ^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:24:1
+ |
+LL | fn _foo2() -> i32 {
+ | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:45:5
+ |
+LL | a::b::c::_foo3();
+ | ^^^^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:31:13
+ |
+LL | pub fn _foo3() {}
+ | ^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:46:14
+ |
+LL | let _ = &_FooStruct {};
+ | ^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:16:1
+ |
+LL | struct _FooStruct {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:47:13
+ |
+LL | let _ = _FooStruct {};
+ | ^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:16:1
+ |
+LL | struct _FooStruct {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:49:22
+ |
+LL | let foo_struct = _FooStruct {};
+ | ^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:16:1
+ |
+LL | struct _FooStruct {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:50:5
+ |
+LL | foo_struct._method_call();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:19:5
+ |
+LL | fn _method_call(self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:52:23
+ |
+LL | let foo_struct2 = a::b::c::_FooStruct2 {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:33:13
+ |
+LL | pub struct _FooStruct2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: used underscore-prefixed item
+ --> tests/ui/used_underscore_items.rs:53:5
+ |
+LL | foo_struct2._method_call();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: item is defined here
+ --> tests/ui/used_underscore_items.rs:36:17
+ |
+LL | pub fn _method_call(self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/zombie_processes.rs b/src/tools/clippy/tests/ui/zombie_processes.rs
new file mode 100644
index 00000000000..a2abc7fc3a1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zombie_processes.rs
@@ -0,0 +1,138 @@
+#![warn(clippy::zombie_processes)]
+#![allow(clippy::if_same_then_else, clippy::ifs_same_cond)]
+
+use std::process::{Child, Command};
+
+fn main() {
+ {
+ // Check that #[expect] works
+ #[expect(clippy::zombie_processes)]
+ let mut x = Command::new("").spawn().unwrap();
+ }
+
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ x.kill();
+ x.id();
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ x.wait().unwrap(); // OK
+ }
+ {
+ let x = Command::new("").spawn().unwrap();
+ x.wait_with_output().unwrap(); // OK
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ x.try_wait().unwrap(); // OK
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ let mut r = &mut x;
+ r.wait().unwrap(); // OK, not calling `.wait()` directly on `x` but through `r` -> `x`
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ process_child(x); // OK, other function might call `.wait()` so assume it does
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ let v = &x;
+ // (allow shared refs is fine because one cannot call `.wait()` through that)
+ }
+
+ // https://github.com/rust-lang/rust-clippy/pull/11476#issuecomment-1718456033
+ // Unconditionally exiting the process in various ways (should not lint)
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ std::process::exit(0);
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ std::process::abort(); // same as above, but abort instead of exit
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ if true { /* nothing */ }
+ std::process::abort(); // still unconditionally exits
+ }
+
+ // Conditionally exiting
+ // It should assume that it might not exit and still lint
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ if true {
+ std::process::exit(0);
+ }
+ }
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ if true {
+ while false {}
+ // Calling `exit()` after leaving a while loop should still be linted.
+ std::process::exit(0);
+ }
+ }
+
+ {
+ let mut x = { Command::new("").spawn().unwrap() };
+ x.wait().unwrap();
+ }
+
+ {
+ struct S {
+ c: Child,
+ }
+
+ let mut s = S {
+ c: Command::new("").spawn().unwrap(),
+ };
+ s.c.wait().unwrap();
+ }
+
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ if true {
+ return;
+ }
+ x.wait().unwrap();
+ }
+
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ if true {
+ x.wait().unwrap();
+ }
+ }
+
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ if true {
+ x.wait().unwrap();
+ } else if true {
+ x.wait().unwrap();
+ } else {
+ x.wait().unwrap();
+ }
+ }
+
+ {
+ let mut x = Command::new("").spawn().unwrap();
+ if true {
+ x.wait().unwrap();
+ return;
+ }
+ x.wait().unwrap();
+ }
+}
+
+fn process_child(c: Child) {
+ todo!()
+}
diff --git a/src/tools/clippy/tests/ui/zombie_processes.stderr b/src/tools/clippy/tests/ui/zombie_processes.stderr
new file mode 100644
index 00000000000..eec821a4c8f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zombie_processes.stderr
@@ -0,0 +1,64 @@
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes.rs:14:21
+ |
+LL | let mut x = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: consider calling `.wait()`
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+ = note: `-D clippy::zombie-processes` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]`
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes.rs:41:21
+ |
+LL | let mut x = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: consider calling `.wait()`
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes.rs:66:21
+ |
+LL | let mut x = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: consider calling `.wait()`
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes.rs:73:21
+ |
+LL | let mut x = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: consider calling `.wait()`
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes.rs:99:21
+ |
+LL | let mut x = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: consider calling `.wait()`
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes.rs:108:21
+ |
+LL | let mut x = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: consider calling `.wait()`
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/zombie_processes_fixable.fixed b/src/tools/clippy/tests/ui/zombie_processes_fixable.fixed
new file mode 100644
index 00000000000..6045262f519
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zombie_processes_fixable.fixed
@@ -0,0 +1,26 @@
+#![warn(clippy::zombie_processes)]
+#![allow(clippy::needless_return)]
+
+use std::process::{Child, Command};
+
+fn main() {
+ let _ = Command::new("").spawn().unwrap().wait();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ Command::new("").spawn().unwrap().wait();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ spawn_proc().wait();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ spawn_proc().wait().unwrap(); // OK
+}
+
+fn not_main() {
+ Command::new("").spawn().unwrap().wait();
+}
+
+fn spawn_proc() -> Child {
+ Command::new("").spawn().unwrap()
+}
+
+fn spawn_proc_2() -> Child {
+ return Command::new("").spawn().unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/zombie_processes_fixable.rs b/src/tools/clippy/tests/ui/zombie_processes_fixable.rs
new file mode 100644
index 00000000000..e1ecb771641
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zombie_processes_fixable.rs
@@ -0,0 +1,26 @@
+#![warn(clippy::zombie_processes)]
+#![allow(clippy::needless_return)]
+
+use std::process::{Child, Command};
+
+fn main() {
+ let _ = Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ Command::new("").spawn().unwrap();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ spawn_proc();
+ //~^ ERROR: spawned process is never `wait()`ed on
+ spawn_proc().wait().unwrap(); // OK
+}
+
+fn not_main() {
+ Command::new("").spawn().unwrap();
+}
+
+fn spawn_proc() -> Child {
+ Command::new("").spawn().unwrap()
+}
+
+fn spawn_proc_2() -> Child {
+ return Command::new("").spawn().unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/zombie_processes_fixable.stderr b/src/tools/clippy/tests/ui/zombie_processes_fixable.stderr
new file mode 100644
index 00000000000..e1c40472c32
--- /dev/null
+++ b/src/tools/clippy/tests/ui/zombie_processes_fixable.stderr
@@ -0,0 +1,40 @@
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes_fixable.rs:7:13
+ |
+LL | let _ = Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()`
+ |
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+ = note: `-D clippy::zombie-processes` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]`
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes_fixable.rs:9:5
+ |
+LL | Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()`
+ |
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes_fixable.rs:11:5
+ |
+LL | spawn_proc();
+ | ^^^^^^^^^^^^- help: try: `.wait()`
+ |
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: spawned process is never `wait()`ed on
+ --> tests/ui/zombie_processes_fixable.rs:17:5
+ |
+LL | Command::new("").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()`
+ |
+ = note: not doing so might leave behind zombie processes
+ = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 99b3560a064..dcf00e4e384 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -20,7 +20,6 @@ new_pr = true
[assign]
contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
users_on_vacation = [
- "flip1995",
"matthiaskrgr",
"giraffate",
]
diff --git a/src/tools/clippy/util/gh-pages/versions.html b/src/tools/clippy/util/gh-pages/versions.html
index 31ce8819329..d38fe39a464 100644
--- a/src/tools/clippy/util/gh-pages/versions.html
+++ b/src/tools/clippy/util/gh-pages/versions.html
@@ -1,4 +1,5 @@
<!DOCTYPE html>
+<!-- Expanded by util/versions.py into the HTML file seen at https://rust-lang.github.io/rust-clippy/ -->
<html lang="en">
<head>
<meta charset="UTF-8"/>
@@ -7,26 +8,15 @@
<title>Clippy lints documentation</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css"/>
- <style>
- [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; }
- </style>
</head>
<body>
- <div class="container" ng-app="clippy" ng-controller="docVersions">
+ <div class="container">
<div class="page-header">
<h1>Clippy lints documentation</h1>
</div>
- <div ng-cloak>
- <div class="alert alert-info" role="alert" ng-if="loading">
- Loading&#x2026;
- </div>
- <div class="alert alert-danger" role="alert" ng-if="error">
- Error loading versions!<br/>
- You can always try to get <a href="master/index.html">the master branch docs</a>.
- </div>
-
- <article class="panel panel-default" ng-show="data">
+ <div>
+ <article class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
Available versions
@@ -34,55 +24,70 @@
</div>
<ul class="list-group">
- <a class="list-group-item" ng-repeat="version in data | orderBy:versionOrder:true"
- href="./{{version}}/index.html">
- {{version}}
- </a>
+ $list
</ul>
</article>
</div>
</div>
- <a href="https://github.com/rust-lang/rust-clippy">
- <img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"/>
- </a>
-
-
- <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script>
- <script>
- angular.module('clippy', [])
- .controller('docVersions', function ($scope, $http) {
- $scope.loading = true;
-
- $scope.normalizeVersion = function(v) {
- return v.replace(/^rust-/, '');
- };
-
- $scope.versionOrder = function(v) {
- if (v === 'master') { return Infinity; }
- if (v === 'stable') { return Number.MAX_VALUE; }
- if (v === 'beta') { return Number.MAX_VALUE - 1; }
- if (v === 'pre-1.29.0') { return Number.MIN_VALUE; }
-
- return $scope.normalizeVersion(v)
- .split('.')
- .reverse()
- .reduce(function(acc, val, index) {
- return acc + (val * Math.pow(100, index));
- }, 0);
+ <a
+ aria-label="View source on GitHub"
+ class="github-corner"
+ href="https://github.com/rust-lang/rust-clippy"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ <svg
+ width="80"
+ height="80"
+ viewBox="0 0 250 250"
+ style="position: absolute; top: 0; border: 0; right: 0"
+ aria-hidden="true"
+ >
+ <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" fill="var(--theme-color)"></path>
+ <path
+ d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
+ fill="currentColor"
+ style="transform-origin: 130px 106px"
+ class="octo-arm"
+ ></path>
+ <path
+ d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
+ fill="currentColor"
+ class="octo-body"
+ ></path>
+ </svg>
+ <style>
+ .github-corner svg {
+ fill: black;
+ color: white;
}
-
- $http.get('./versions.json')
- .success(function (data) {
- $scope.data = data;
- $scope.loading = false;
- })
- .error(function (data) {
- $scope.error = data;
- $scope.loading = false;
- });
- })
- ;
- </script>
+ .github-corner:hover .octo-arm {
+ animation: octocat-wave 560ms ease-in-out;
+ }
+ @keyframes octocat-wave {
+ 0%,
+ 100% {
+ transform: rotate(0);
+ }
+ 20%,
+ 60% {
+ transform: rotate(-25deg);
+ }
+ 40%,
+ 80% {
+ transform: rotate(10deg);
+ }
+ }
+ @media (max-width: 500px) {
+ .github-corner:hover .octo-arm {
+ animation: none;
+ }
+ .github-corner .octo-arm {
+ animation: octocat-wave 560ms ease-in-out;
+ }
+ }
+ </style>
+ </a>
</body>
</html>
diff --git a/src/tools/clippy/util/versions.py b/src/tools/clippy/util/versions.py
index c041fc606a8..7a21a840a6d 100755
--- a/src/tools/clippy/util/versions.py
+++ b/src/tools/clippy/util/versions.py
@@ -1,22 +1,22 @@
#!/usr/bin/env python
+from string import Template
+import argparse
import json
-import logging as log
import os
import sys
-log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")
-
-
def key(v):
if v == "master":
- return float("inf")
- if v == "stable":
return sys.maxsize
- if v == "beta":
+ if v == "stable":
return sys.maxsize - 1
+ if v == "beta":
+ return sys.maxsize - 2
if v == "pre-1.29.0":
return -1
+ if not v.startswith("rust-"):
+ return None
v = v.replace("rust-", "")
@@ -26,26 +26,27 @@ def key(v):
return s
-
def main():
- if len(sys.argv) < 2:
- log.error("specify output directory")
- return
+ parser = argparse.ArgumentParser()
+ parser.add_argument("input", help="path to the versions.html template", type=argparse.FileType("r"))
+ parser.add_argument("outdir", help="path to write the output HTML")
+ args = parser.parse_args()
- outdir = sys.argv[1]
versions = [
dir
- for dir in os.listdir(outdir)
- if not dir.startswith(".")
- and not dir.startswith("v")
- and os.path.isdir(os.path.join(outdir, dir))
+ for dir in os.listdir(args.outdir)
+ if key(dir) is not None
]
- versions.sort(key=key)
+ versions.sort(key=key, reverse=True)
+ links = [f'<a class="list-group-item" href="./{version}/index.html">{version}</a>' for version in versions]
- with open(os.path.join(outdir, "versions.json"), "w") as fp:
- json.dump(versions, fp, indent=2)
- log.info("wrote JSON for great justice")
+ template = Template(args.input.read())
+ html = template.substitute(list="\n".join(links))
+ path = os.path.join(args.outdir, "index.html")
+ with open(path, "w") as out:
+ out.write(html)
+ print(f"wrote HTML to {path}")
if __name__ == "__main__":
main()