From f5ac844296335590c30caeef9fddb1af0692ab76 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 8 Oct 2022 23:47:59 +0100 Subject: Refactor unwind from Option to a new enum --- clippy_utils/src/qualify_min_const_fn.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index d66640ba0b7..ff195cd7288 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -318,7 +318,7 @@ fn check_terminator<'tcx>( from_hir_call: _, destination: _, target: _, - cleanup: _, + unwind: _, fn_span: _, } => { let fn_ty = func.ty(body, tcx); @@ -361,7 +361,7 @@ fn check_terminator<'tcx>( expected: _, msg: _, target: _, - cleanup: _, + unwind: _, } => check_operand(tcx, cond, span, body), TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), -- cgit 1.4.1-3-g733a5 From 293c1a1a6a8ee0b56e1086a5d66e0bacb75a76df Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 10 Oct 2022 23:17:07 +0100 Subject: Fix tools --- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index ff195cd7288..354b6d71aa4 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -301,13 +301,13 @@ fn check_terminator<'tcx>( | TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::Resume + | TerminatorKind::Terminate | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), - TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn generators are unstable".into())) }, -- cgit 1.4.1-3-g733a5 From 0963a66ab3f6413a47c7c08524c3e86b02feebaf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Apr 2023 23:11:19 +0000 Subject: Make elaborator generic --- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_utils/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 327e090d38b..0bb1775aae9 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -122,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { let sized_trait = need!(cx.tcx.lang_items().sized_trait()); - let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter()) + let preds = traits::elaborate(cx.tcx, cx.param_env.caller_bounds().iter()) .filter(|p| !p.is_global()) .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 619aa9f4bf6..9051cf51658 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2104,7 +2104,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); traits::impossible_predicates( cx.tcx, - traits::elaborate_predicates(cx.tcx, predicates) + traits::elaborate(cx.tcx, predicates) .collect::>(), ) } -- cgit 1.4.1-3-g733a5 From 6b95029f176e5cdaa88de8ca7f5f59fd15a6d850 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 11 Apr 2023 15:31:08 +0200 Subject: Merge commit '83e42a2337dadac915c956d125f1d69132f36425' into clippyup --- .cargo/config.toml | 3 + .editorconfig | 1 + .github/workflows/clippy_bors.yml | 2 + .github/workflows/remark.yml | 2 +- CHANGELOG.md | 7 + README.md | 6 +- book/src/README.md | 2 +- book/src/SUMMARY.md | 1 + book/src/configuration.md | 29 +- book/src/development/README.md | 2 +- book/src/development/adding_lints.md | 32 +- book/src/development/basics.md | 6 +- book/src/development/common_tools_writing_lints.md | 14 +- book/src/development/infrastructure/book.md | 4 +- .../development/infrastructure/changelog_update.md | 2 +- book/src/development/infrastructure/release.md | 2 +- book/src/development/infrastructure/sync.md | 13 +- book/src/development/proposals/README.md | 2 +- book/src/development/proposals/roadmap-2021.md | 6 +- .../development/proposals/syntax-tree-patterns.md | 28 +- book/src/development/type_checking.md | 144 ++++ book/src/installation.md | 4 +- book/src/lint_configuration.md | 18 +- book/src/lints.md | 10 +- book/src/usage.md | 4 +- clippy_dev/src/lib.rs | 1 + clippy_dev/src/new_lint.rs | 8 +- clippy_dev/src/update_lints.rs | 14 +- clippy_lints/Cargo.toml | 1 + clippy_lints/src/booleans.rs | 39 +- clippy_lints/src/casts/cast_possible_truncation.rs | 42 +- clippy_lints/src/collection_is_never_read.rs | 39 +- clippy_lints/src/declared_lints.rs | 7 + clippy_lints/src/disallowed_script_idents.rs | 2 +- clippy_lints/src/explicit_write.rs | 29 +- clippy_lints/src/extra_unused_type_parameters.rs | 177 +++-- clippy_lints/src/format.rs | 91 ++- clippy_lints/src/format_args.rs | 224 +++--- clippy_lints/src/format_impl.rs | 60 +- clippy_lints/src/functions/must_use.rs | 18 +- clippy_lints/src/items_after_statements.rs | 31 +- clippy_lints/src/large_futures.rs | 87 +++ clippy_lints/src/lib.rs | 36 +- clippy_lints/src/lines_filter_map_ok.rs | 100 +++ clippy_lints/src/manual_slice_size_calculation.rs | 93 +++ clippy_lints/src/mem_replace.rs | 71 +- clippy_lints/src/methods/clear_with_drain.rs | 53 ++ clippy_lints/src/methods/expect_fun_call.rs | 27 +- clippy_lints/src/methods/iter_with_drain.rs | 24 +- clippy_lints/src/methods/mod.rs | 40 +- clippy_lints/src/missing_const_for_fn.rs | 1 + .../src/operators/arithmetic_side_effects.rs | 12 +- clippy_lints/src/redundant_async_block.rs | 145 ++-- clippy_lints/src/redundant_static_lifetimes.rs | 4 +- clippy_lints/src/returns.rs | 32 +- clippy_lints/src/single_component_path_imports.rs | 59 +- clippy_lints/src/suspicious_doc_comments.rs | 94 +++ clippy_lints/src/tests_outside_test_module.rs | 71 ++ .../transmutes_expressible_as_ptr_casts.rs | 11 +- clippy_lints/src/unnecessary_box_returns.rs | 120 ++++ .../src/unnecessary_struct_initialization.rs | 8 +- clippy_lints/src/use_self.rs | 4 +- clippy_lints/src/utils/conf.rs | 36 +- clippy_lints/src/utils/format_args_collector.rs | 79 +- clippy_lints/src/write.rs | 14 +- clippy_utils/src/ast_utils.rs | 39 +- clippy_utils/src/lib.rs | 72 +- clippy_utils/src/macros.rs | 800 ++------------------- clippy_utils/src/paths.rs | 2 + clippy_utils/src/ty.rs | 22 +- etc/relicense/RELICENSE_DOCUMENTATION.md | 4 +- lintcheck/README.md | 2 +- rust-toolchain | 2 +- src/driver.rs | 2 +- .../multiple_config_files/warn/src/main.stderr | 6 +- .../uninlined_format_args.stderr | 22 +- .../extra_unused_type_parameters/clippy.toml | 1 + .../extra_unused_type_parameters.rs | 9 + tests/ui-toml/large_futures/clippy.toml | 1 + tests/ui-toml/large_futures/large_futures.rs | 27 + tests/ui-toml/large_futures/large_futures.stderr | 10 + .../toml_unknown_key/conf_unknown_key.stderr | 1 + tests/ui/arithmetic_side_effects.rs | 4 + tests/ui/arithmetic_side_effects.stderr | 14 +- tests/ui/auxiliary/proc_macros.rs | 2 +- tests/ui/cast.rs | 6 + tests/ui/cast.stderr | 112 +-- tests/ui/clear_with_drain.fixed | 358 +++++++++ tests/ui/clear_with_drain.rs | 358 +++++++++ tests/ui/clear_with_drain.stderr | 130 ++++ tests/ui/collection_is_never_read.rs | 31 +- tests/ui/collection_is_never_read.stderr | 34 +- tests/ui/double_must_use.rs | 11 + tests/ui/double_must_use.stderr | 10 +- tests/ui/extra_unused_type_parameters.fixed | 105 +++ tests/ui/extra_unused_type_parameters.rs | 11 +- tests/ui/extra_unused_type_parameters.stderr | 79 +- tests/ui/extra_unused_type_parameters_unfixable.rs | 24 + .../extra_unused_type_parameters_unfixable.stderr | 27 + tests/ui/format_args_unfixable.rs | 44 ++ tests/ui/format_args_unfixable.stderr | 36 +- tests/ui/item_after_statement.rs | 53 -- tests/ui/item_after_statement.stderr | 33 - tests/ui/items_after_statement.rs | 70 ++ tests/ui/items_after_statement.stderr | 33 + tests/ui/large_futures.rs | 61 ++ tests/ui/large_futures.stderr | 82 +++ tests/ui/lines_filter_map_ok.fixed | 29 + tests/ui/lines_filter_map_ok.rs | 29 + tests/ui/lines_filter_map_ok.stderr | 51 ++ tests/ui/manual_slice_size_calculation.rs | 36 + tests/ui/manual_slice_size_calculation.stderr | 51 ++ tests/ui/mem_replace.fixed | 34 + tests/ui/mem_replace.rs | 34 + tests/ui/mem_replace.stderr | 26 +- tests/ui/needless_return.fixed | 9 + tests/ui/needless_return.rs | 9 + tests/ui/nonminimal_bool.rs | 18 + tests/ui/print_literal.rs | 4 + tests/ui/redundant_async_block.fixed | 148 +++- tests/ui/redundant_async_block.rs | 148 +++- tests/ui/redundant_async_block.stderr | 46 +- tests/ui/single_component_path_imports.fixed | 6 + tests/ui/single_component_path_imports.rs | 6 + tests/ui/single_component_path_imports.stderr | 4 +- tests/ui/suspicious_doc_comments.fixed | 81 +++ tests/ui/suspicious_doc_comments.rs | 81 +++ tests/ui/suspicious_doc_comments.stderr | 114 +++ tests/ui/suspicious_doc_comments_unfixable.rs | 16 + tests/ui/suspicious_doc_comments_unfixable.stderr | 37 + tests/ui/tests_outside_test_module.rs | 18 + tests/ui/tests_outside_test_module.stderr | 11 + tests/ui/transmutes_expressible_as_ptr_casts.fixed | 8 +- tests/ui/transmutes_expressible_as_ptr_casts.rs | 8 +- .../ui/transmutes_expressible_as_ptr_casts.stderr | 8 +- tests/ui/uninit.rs | 18 +- tests/ui/uninit.stderr | 10 +- tests/ui/uninit_vec.rs | 8 + tests/ui/uninlined_format_args.fixed | 88 ++- tests/ui/uninlined_format_args.rs | 86 ++- tests/ui/uninlined_format_args.stderr | 14 +- tests/ui/unnecessary_box_returns.rs | 60 ++ tests/ui/unnecessary_box_returns.stderr | 35 + tests/ui/unused_format_specs.fixed | 18 - tests/ui/unused_format_specs.rs | 18 - tests/ui/unused_format_specs.stderr | 54 -- tests/ui/unused_format_specs_unfixable.stderr | 12 +- 147 files changed, 4811 insertions(+), 1778 deletions(-) create mode 100644 book/src/development/type_checking.md create mode 100644 clippy_lints/src/large_futures.rs create mode 100644 clippy_lints/src/lines_filter_map_ok.rs create mode 100644 clippy_lints/src/manual_slice_size_calculation.rs create mode 100644 clippy_lints/src/methods/clear_with_drain.rs create mode 100644 clippy_lints/src/suspicious_doc_comments.rs create mode 100644 clippy_lints/src/tests_outside_test_module.rs create mode 100644 clippy_lints/src/unnecessary_box_returns.rs create mode 100644 tests/ui-toml/extra_unused_type_parameters/clippy.toml create mode 100644 tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs create mode 100644 tests/ui-toml/large_futures/clippy.toml create mode 100644 tests/ui-toml/large_futures/large_futures.rs create mode 100644 tests/ui-toml/large_futures/large_futures.stderr create mode 100644 tests/ui/clear_with_drain.fixed create mode 100644 tests/ui/clear_with_drain.rs create mode 100644 tests/ui/clear_with_drain.stderr create mode 100644 tests/ui/extra_unused_type_parameters.fixed create mode 100644 tests/ui/extra_unused_type_parameters_unfixable.rs create mode 100644 tests/ui/extra_unused_type_parameters_unfixable.stderr delete mode 100644 tests/ui/item_after_statement.rs delete mode 100644 tests/ui/item_after_statement.stderr create mode 100644 tests/ui/items_after_statement.rs create mode 100644 tests/ui/items_after_statement.stderr create mode 100644 tests/ui/large_futures.rs create mode 100644 tests/ui/large_futures.stderr create mode 100644 tests/ui/lines_filter_map_ok.fixed create mode 100644 tests/ui/lines_filter_map_ok.rs create mode 100644 tests/ui/lines_filter_map_ok.stderr create mode 100644 tests/ui/manual_slice_size_calculation.rs create mode 100644 tests/ui/manual_slice_size_calculation.stderr create mode 100644 tests/ui/suspicious_doc_comments.fixed create mode 100644 tests/ui/suspicious_doc_comments.rs create mode 100644 tests/ui/suspicious_doc_comments.stderr create mode 100644 tests/ui/suspicious_doc_comments_unfixable.rs create mode 100644 tests/ui/suspicious_doc_comments_unfixable.stderr create mode 100644 tests/ui/tests_outside_test_module.rs create mode 100644 tests/ui/tests_outside_test_module.stderr create mode 100644 tests/ui/unnecessary_box_returns.rs create mode 100644 tests/ui/unnecessary_box_returns.stderr delete mode 100644 tests/ui/unused_format_specs.fixed delete mode 100644 tests/ui/unused_format_specs.rs delete mode 100644 tests/ui/unused_format_specs.stderr diff --git a/.cargo/config.toml b/.cargo/config.toml index f3dd9275a42..4d80d3ce63d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -11,3 +11,6 @@ target-dir = "target" [unstable] binary-dep-depinfo = true + +[profile.dev] +split-debuginfo = "unpacked" diff --git a/.editorconfig b/.editorconfig index ec6e107d547..bc7642bf8c7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,7 @@ trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 4 +max_line_length = 120 [*.md] # double whitespace at end of line diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 24e677ce8e1..93198aabdb5 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -180,6 +180,8 @@ jobs: # Run - name: Build Integration Test + env: + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: off run: cargo test --test integration --features integration --no-run # Upload diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 81ef072bbb0..116058b7c75 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -29,7 +29,7 @@ jobs: - name: Install mdbook run: | mkdir mdbook - curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.18/mdbook-v0.4.18-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook + curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.28/mdbook-v0.4.28-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook echo `pwd`/mdbook >> $GITHUB_PATH # Run diff --git a/CHANGELOG.md b/CHANGELOG.md index 1323f973ccf..559b560dde4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4441,6 +4441,7 @@ Released 2018-09-13 [`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp [`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp [`checked_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions +[`clear_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#clear_with_drain [`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref [`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy [`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_ref_ptr @@ -4632,6 +4633,7 @@ Released 2018-09-13 [`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays [`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_digit_groups [`large_enum_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant +[`large_futures`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_futures [`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays [`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value @@ -4645,6 +4647,7 @@ Released 2018-09-13 [`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_untyped [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value [`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore +[`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal @@ -4671,6 +4674,7 @@ Released 2018-09-13 [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid [`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic +[`manual_slice_size_calculation`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_size_calculation [`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once [`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new @@ -4921,6 +4925,7 @@ Released 2018-09-13 [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl [`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting [`suspicious_command_arg_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_command_arg_space +[`suspicious_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_doc_comments [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl @@ -4933,6 +4938,7 @@ Released 2018-09-13 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr +[`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some [`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args @@ -4974,6 +4980,7 @@ Released 2018-09-13 [`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints +[`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast [`unnecessary_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 diff --git a/README.md b/README.md index b69ed8900a4..85798e0e80c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Lints are divided into categories, each with a default [lint level](https://doc. You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. | Category | Description | Default level | -| --------------------- | ----------------------------------------------------------------------------------- | ------------- | +|-----------------------|-------------------------------------------------------------------------------------|---------------| | `clippy::all` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** | | `clippy::correctness` | code that is outright wrong or useless | **deny** | | `clippy::suspicious` | code that is most likely wrong or useless | **warn** | @@ -130,7 +130,7 @@ for example. You can add Clippy to Travis CI in the same way you use it locally: -```yml +```yaml language: rust rust: - stable @@ -253,7 +253,7 @@ rust-version = "1.30" The MSRV can also be specified as an attribute, like below. -```rust +```rust,ignore #![feature(custom_inner_attributes)] #![clippy::msrv = "1.30.0"] diff --git a/book/src/README.md b/book/src/README.md index df4a1f2702e..3b627096268 100644 --- a/book/src/README.md +++ b/book/src/README.md @@ -14,7 +14,7 @@ much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. | Category | Description | Default level | -| --------------------- | ----------------------------------------------------------------------------------- | ------------- | +|-----------------------|-------------------------------------------------------------------------------------|---------------| | `clippy::all` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** | | `clippy::correctness` | code that is outright wrong or useless | **deny** | | `clippy::suspicious` | code that is most likely wrong or useless | **warn** | diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 0649f7a631d..cbd73376dfa 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -13,6 +13,7 @@ - [Development](development/README.md) - [Basics](development/basics.md) - [Adding Lints](development/adding_lints.md) + - [Type Checking](development/type_checking.md) - [Common Tools](development/common_tools_writing_lints.md) - [Infrastructure](development/infrastructure/README.md) - [Syncing changes between Clippy and rust-lang/rust](development/infrastructure/sync.md) diff --git a/book/src/configuration.md b/book/src/configuration.md index 87f4a697af9..1304f6a8c2f 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -3,7 +3,7 @@ > **Note:** The configuration file is unstable and may be deprecated in the future. Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a -basic `variable = value` mapping eg. +basic `variable = value` mapping e.g. ```toml avoid-breaking-exported-api = false @@ -60,7 +60,7 @@ And to warn on `lint_name`, run cargo clippy -- -W clippy::lint_name ``` -This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: +This also works with lint groups. For example, you can run Clippy with warnings for all lints enabled: ```terminal cargo clippy -- -W clippy::pedantic @@ -84,7 +84,7 @@ msrv = "1.30.0" The MSRV can also be specified as an attribute, like below. -```rust +```rust,ignore #![feature(custom_inner_attributes)] #![clippy::msrv = "1.30.0"] @@ -96,7 +96,28 @@ fn main() { You can also omit the patch version when specifying the MSRV, so `msrv = 1.30` is equivalent to `msrv = 1.30.0`. -Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly. +Note: `custom_inner_attributes` is an unstable feature, so it has to be enabled explicitly. Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv) + +### Disabling evaluation of certain code + +> **Note:** This should only be used in cases where other solutions, like `#[allow(clippy::all)]`, are not sufficient. + +Very rarely, you may wish to prevent Clippy from evaluating certain sections of code entirely. You can do this with +[conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html) by checking that the +`cargo-clippy` feature is not set. You may need to provide a stub so that the code compiles: + +```rust +#[cfg(not(feature = "cargo-clippy"))] +include!(concat!(env!("OUT_DIR"), "/my_big_function-generated.rs")); + +#[cfg(feature = "cargo-clippy")] +fn my_big_function(_input: &str) -> Option { + None +} +``` + +This feature is not actually part of your crate, so specifying `--all-features` to other tools, e.g. `cargo test +--all-features`, will not disable it. diff --git a/book/src/development/README.md b/book/src/development/README.md index 5cf7201cffa..616e6d182b7 100644 --- a/book/src/development/README.md +++ b/book/src/development/README.md @@ -5,7 +5,7 @@ making Clippy better by contributing to it. In that case, welcome to the project! > _Note:_ If you're just interested in using Clippy, there's nothing to see from -> this point onward and you should return to one of the earlier chapters. +> this point onward, and you should return to one of the earlier chapters. ## Getting started diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index f57dc627dce..9dacaaaae5c 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -18,6 +18,7 @@ because that's clearly a non-descriptive name. - [Cargo lints](#cargo-lints) - [Rustfix tests](#rustfix-tests) - [Testing manually](#testing-manually) + - [Running directly](#running-directly) - [Lint declaration](#lint-declaration) - [Lint registration](#lint-registration) - [Lint passes](#lint-passes) @@ -186,6 +187,15 @@ cargo dev lint input.rs from the working copy root. With tests in place, let's have a look at implementing our lint now. +## Running directly + +While it's easier to just use `cargo dev lint`, it might be desirable to get +`target/release/cargo-clippy` and `target/release/clippy-driver` to work as well in some cases. +By default, they don't work because clippy dynamically links rustc. To help them find rustc, +add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches) +to your library search path. +On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path. + ## Lint declaration Let's start by opening the new file created in the `clippy_lints` crate at @@ -265,7 +275,7 @@ When declaring a new lint by hand and `cargo dev update_lints` is used, the lint pass may have to be registered manually in the `register_plugins` function in `clippy_lints/src/lib.rs`: -```rust +```rust,ignore store.register_early_pass(|| Box::new(foo_functions::FooFunctions)); ``` @@ -291,7 +301,7 @@ either [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass]. In short, the `LateLintPass` has access to type information while the `EarlyLintPass` doesn't. If you don't need access to type information, use the -`EarlyLintPass`. The `EarlyLintPass` is also faster. However linting speed +`EarlyLintPass`. The `EarlyLintPass` is also faster. However, linting speed hasn't really been a concern with Clippy so far. Since we don't need type information for checking the function name, we used @@ -308,7 +318,7 @@ implementation of the lint logic. Let's start by implementing the `EarlyLintPass` for our `FooFunctions`: -```rust +```rust,ignore impl EarlyLintPass for FooFunctions { fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { // TODO: Emit lint here @@ -327,10 +337,10 @@ variety of lint emission functions. They can all be found in [`clippy_utils/src/diagnostics.rs`][diagnostics]. `span_lint_and_help` seems most appropriate in this case. It allows us to -provide an extra help message and we can't really suggest a better name +provide an extra help message, and we can't really suggest a better name automatically. This is how it looks: -```rust +```rust,ignore impl EarlyLintPass for FooFunctions { fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { span_lint_and_help( @@ -469,7 +479,7 @@ the value from `clippy.toml`. This can be accounted for using the `extract_msrv_attr!(LintContext)` macro and passing `LateContext`/`EarlyContext`. -```rust +```rust,ignore impl<'tcx> LateLintPass<'tcx> for ManualStrip { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { ... @@ -483,7 +493,7 @@ the lint's test file, `tests/ui/manual_strip.rs` in this example. It should have a case for the version below the MSRV and one with the same contents but for the MSRV version itself. -```rust +```rust,ignore ... #[clippy::msrv = "1.44"] @@ -514,7 +524,7 @@ define_Conf! { If you have trouble implementing your lint, there is also the internal `author` lint to generate Clippy code that detects the offending pattern. It does not -work for all of the Rust syntax, but can give a good starting point. +work for all the Rust syntax, but can give a good starting point. The quickest way to use it, is the [Rust playground: play.rust-lang.org][author_example]. Put the code you want to lint into the @@ -607,7 +617,7 @@ output in the `stdout` part. ## PR Checklist -Before submitting your PR make sure you followed all of the basic requirements: +Before submitting your PR make sure you followed all the basic requirements: @@ -627,7 +637,7 @@ for some users. Adding a configuration is done in the following steps: 1. Adding a new configuration entry to [`clippy_lints::utils::conf`] like this: - ```rust + ```rust,ignore /// Lint: LINT_NAME. /// /// @@ -680,7 +690,7 @@ for some users. Adding a configuration is done in the following steps: configuration value is now cloned or copied into a local value that is then passed to the impl struct like this: - ```rust + ```rust,ignore // Default generated registration: store.register_*_pass(|| box module::StructName); diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 6fb53236e6f..7615dc12f9e 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -4,8 +4,8 @@ This document explains the basics for hacking on Clippy. Besides others, this includes how to build and test Clippy. For a more in depth description on the codebase take a look at [Adding Lints] or [Common Tools]. -[Adding Lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md -[Common Tools]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/common_tools_writing_lints.md +[Adding Lints]: adding_lints.md +[Common Tools]: common_tools_writing_lints.md - [Basics for hacking on Clippy](#basics-for-hacking-on-clippy) - [Get the Code](#get-the-code) @@ -125,7 +125,7 @@ We follow a rustc no merge-commit policy. See ## Common Abbreviations | Abbreviation | Meaning | -| ------------ | -------------------------------------- | +|--------------|----------------------------------------| | UB | Undefined Behavior | | FP | False Positive | | FN | False Negative | diff --git a/book/src/development/common_tools_writing_lints.md b/book/src/development/common_tools_writing_lints.md index f5aa06e4bf6..09171d86a20 100644 --- a/book/src/development/common_tools_writing_lints.md +++ b/book/src/development/common_tools_writing_lints.md @@ -3,7 +3,7 @@ You may need following tooltips to catch up with common operations. - [Common tools for writing lints](#common-tools-for-writing-lints) - - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression) + - [Retrieving the type of expression](#retrieving-the-type-of-expression) - [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method) - [Checking for a specific type](#checking-for-a-specific-type) - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait) @@ -16,7 +16,7 @@ Useful Rustc dev guide links: - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) -## Retrieving the type of an expression +## Retrieving the type of expression Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions: @@ -45,7 +45,7 @@ impl LateLintPass<'_> for MyStructLint { } ``` -Similarly in [`TypeckResults`][TypeckResults] methods, you have the +Similarly, in [`TypeckResults`][TypeckResults] methods, you have the [`pat_ty()`][pat_ty] method to retrieve a type from a pattern. Two noticeable items here: @@ -192,7 +192,7 @@ functions to deal with macros: - `span.from_expansion()`: detects if a span is from macro expansion or desugaring. Checking this is a common first step in a lint. - ```rust + ```rust,ignore if expr.span.from_expansion() { // just forget it return; @@ -203,11 +203,11 @@ functions to deal with macros: if so, which macro call expanded it. It is sometimes useful to check if the context of two spans are equal. - ```rust + ```rust,ignore // expands to `1 + 0`, but don't lint 1 + mac!() ``` - ```rust + ```rust,ignore if left.span.ctxt() != right.span.ctxt() { // the coder most likely cannot modify this expression return; @@ -246,7 +246,7 @@ functions to deal with macros: `macro_rules!` with `a == $b`, `$b` is expanded to some expression with a different context from `a`. - ```rust + ```rust,ignore macro_rules! m { ($a:expr, $b:expr) => { if $a.is_some() { diff --git a/book/src/development/infrastructure/book.md b/book/src/development/infrastructure/book.md index dbd624ecd73..de5de4bebaa 100644 --- a/book/src/development/infrastructure/book.md +++ b/book/src/development/infrastructure/book.md @@ -13,7 +13,7 @@ guide to Clippy that you're reading right now. The Clippy book is formatted with While not strictly necessary since the book source is simply Markdown text files, having mdBook locally will allow you to build, test and serve the book locally to view changes before you commit them to the repository. You likely -already have `cargo` installed, so the easiest option is to simply: +already have `cargo` installed, so the easiest option is to: ```shell cargo install mdbook @@ -26,7 +26,7 @@ instructions for other options. The book's [src](https://github.com/rust-lang/rust-clippy/tree/master/book/src) -directory contains all of the markdown files used to generate the book. If you +directory contains all the markdown files used to generate the book. If you want to see your changes in real time, you can use the mdBook `serve` command to run a web server locally that will automatically update changes as they are made. From the top level of your `rust-clippy` directory: diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index d1ac7237b5e..df9b1bbe18f 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -101,7 +101,7 @@ Look for the [`beta-accepted`] label and make sure to also include the PRs with that label in the changelog. If you can, remove the `beta-accepted` labels **after** the changelog PR was merged. -> _Note:_ Some of those PRs might even got backported to the previous `beta`. +> _Note:_ Some of those PRs might even get backported to the previous `beta`. > Those have to be included in the changelog of the _previous_ release. ### 4. Update `clippy::version` attributes diff --git a/book/src/development/infrastructure/release.md b/book/src/development/infrastructure/release.md index 0572281803e..98fabf8e89a 100644 --- a/book/src/development/infrastructure/release.md +++ b/book/src/development/infrastructure/release.md @@ -44,7 +44,7 @@ $ git push origin backport_remerge # This can be pushed to your fork ``` After this, open a PR to the master branch. In this PR, the commit hash of the -`HEAD` of the `beta` branch must exists. In addition to that, no files should be +`HEAD` of the `beta` branch must exist. In addition to that, no files should be changed by this PR. ## Update the `beta` branch diff --git a/book/src/development/infrastructure/sync.md b/book/src/development/infrastructure/sync.md index 02cfc11b55a..e1fe92f9525 100644 --- a/book/src/development/infrastructure/sync.md +++ b/book/src/development/infrastructure/sync.md @@ -19,8 +19,7 @@ to beta. For reference, the first sync following this cadence was performed the 2020-08-27. This process is described in detail in the following sections. For general -information about `subtree`s in the Rust repository see [Rust's -`CONTRIBUTING.md`][subtree]. +information about `subtree`s in the Rust repository see [the rustc-dev-guide][subtree]. ## Patching git-subtree to work with big repos @@ -47,7 +46,7 @@ sudo chown --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subt > _Note:_ If you are a Debian user, `dash` is the shell used by default for > scripts instead of `sh`. This shell has a hardcoded recursion limit set to -> 1000. In order to make this process work, you need to force the script to run +> 1,000. In order to make this process work, you need to force the script to run > `bash` instead. You can do this by editing the first line of the `git-subtree` > script and changing `sh` to `bash`. @@ -71,10 +70,10 @@ $ git remote add clippy-local /path/to/rust-clippy ## Performing the sync from [`rust-lang/rust`] to Clippy -Here is a TL;DR version of the sync process (all of the following commands have +Here is a TL;DR version of the sync process (all the following commands have to be run inside the `rust` directory): -1. Clone the [`rust-lang/rust`] repository or make sure it is up to date. +1. Clone the [`rust-lang/rust`] repository or make sure it is up-to-date. 2. Checkout the commit from the latest available nightly. You can get it using `rustup check`. 3. Sync the changes to the rust-copy of Clippy to your Clippy fork: @@ -107,7 +106,7 @@ to be run inside the `rust` directory): ## Performing the sync from Clippy to [`rust-lang/rust`] -All of the following commands have to be run inside the `rust` directory. +All the following commands have to be run inside the `rust` directory. 1. Make sure you have checked out the latest `master` of `rust-lang/rust`. 2. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy: @@ -118,5 +117,5 @@ All of the following commands have to be run inside the `rust` directory. 3. Open a PR to [`rust-lang/rust`] [gitgitgadget-pr]: https://github.com/gitgitgadget/git/pull/493 -[subtree]: https://rustc-dev-guide.rust-lang.org/contributing.html#external-dependencies-subtree +[subtree]: https://rustc-dev-guide.rust-lang.org/external-repos.html#external-dependencies-subtree [`rust-lang/rust`]: https://github.com/rust-lang/rust diff --git a/book/src/development/proposals/README.md b/book/src/development/proposals/README.md index 78fe34ebf8f..059c22ce1ce 100644 --- a/book/src/development/proposals/README.md +++ b/book/src/development/proposals/README.md @@ -6,6 +6,6 @@ or around Clippy in the long run. Besides adding more and more lints and improve the lints that Clippy already has, Clippy is also interested in making the experience of its users, developers and maintainers better over time. Projects that address bigger picture things -like this usually take more time and it is useful to have a proposal for those +like this usually take more time, and it is useful to have a proposal for those first. This is the place where such proposals are collected, so that we can refer to them when working on them. diff --git a/book/src/development/proposals/roadmap-2021.md b/book/src/development/proposals/roadmap-2021.md index fe8b080f56f..4406616bbb6 100644 --- a/book/src/development/proposals/roadmap-2021.md +++ b/book/src/development/proposals/roadmap-2021.md @@ -52,8 +52,8 @@ In the following, plans to improve the usability are covered. #### No Output After `cargo check` -Currently when `cargo clippy` is run after `cargo check`, it does not produce -any output. This is especially problematic since `rust-analyzer` is on the rise +Currently, when `cargo clippy` is run after `cargo check`, it does not produce +any output. This is especially problematic since `rust-analyzer` is on the rise, and it uses `cargo check` for checking code. A fix is already implemented, but it still has to be pushed over the finish line. This also includes the stabilization of the `cargo clippy --fix` command or the support of multi-span @@ -221,7 +221,7 @@ regarding the user facing issues. Rust's roadmap process was established by [RFC 1728] in 2016. Since then every year a roadmap was published, that defined the bigger plans for the coming -years. This years roadmap can be found [here][Rust Roadmap 2021]. +years. This year roadmap can be found [here][Rust Roadmap 2021]. [RFC 1728]: https://rust-lang.github.io/rfcs/1728-north-star.html diff --git a/book/src/development/proposals/syntax-tree-patterns.md b/book/src/development/proposals/syntax-tree-patterns.md index ea4978011b1..36d722609f4 100644 --- a/book/src/development/proposals/syntax-tree-patterns.md +++ b/book/src/development/proposals/syntax-tree-patterns.md @@ -16,7 +16,7 @@ lints. For non-trivial lints, it often requires nested pattern matching of AST / HIR nodes. For example, testing that an expression is a boolean literal requires the following checks: -```rust +```rust,ignore if let ast::ExprKind::Lit(lit) = &expr.node { if let ast::LitKind::Bool(_) = &lit.node { ... @@ -28,7 +28,7 @@ Writing this kind of matching code quickly becomes a complex task and the resulting code is often hard to comprehend. The code below shows a simplified version of the pattern matching required by the `collapsible_if` lint: -```rust +```rust,ignore // simplified version of the collapsible_if lint if let ast::ExprKind::If(check, then, None) = &expr.node { if then.stmts.len() == 1 { @@ -111,7 +111,7 @@ expressions that are boolean literals with value `false`. The pattern can then be used to implement lints in the following way: -```rust +```rust,ignore ... impl EarlyLintPass for MyAwesomeLint { @@ -346,7 +346,7 @@ pattern!{ one could get references to the nodes that matched the subpatterns in the following way: -```rust +```rust,ignore ... fn check_expr(expr: &syntax::ast::Expr) { if let Some(result) = my_pattern(expr) { @@ -372,7 +372,7 @@ matches arrays that consist of any number of literal expressions. Because those expressions are named `foo`, the result struct contains a `foo` attribute which is a vector of expressions: -```rust +```rust,ignore ... if let Some(result) = my_pattern_seq(expr) { result.foo // type: Vec<&syntax::ast::Expr> @@ -394,7 +394,7 @@ In the pattern above, the `bar` name is only defined if the pattern matches a boolean literal. If it matches an integer literal, the name isn't set. To account for this, the result struct's `bar` attribute is an option type: -```rust +```rust,ignore ... if let Some(result) = my_pattern_alt(expr) { result.bar // type: Option<&bool> @@ -404,7 +404,7 @@ if let Some(result) = my_pattern_alt(expr) { It's also possible to use a name in multiple alternation branches if they have compatible types: -```rust +```rust,ignore pattern!{ // matches if expression is a boolean or integer literal my_pattern_mult: Expr = @@ -519,7 +519,7 @@ The `Alt`, `Seq` and `Opt` structs look like these: > Note: The current implementation can be found > [here](https://github.com/fkohlgrueber/pattern-matching/blob/dfb3bc9fbab69cec7c91e72564a63ebaa2ede638/pattern-match/src/matchers.rs#L35-L60). -```rust +```rust,ignore pub enum Alt { Any, Elmt(Box), @@ -580,7 +580,7 @@ implementations is the `IsMatch` trait. It defines how to match *PatternTree* nodes against specific syntax tree nodes. A simplified implementation of the `IsMatch` trait is shown below: -```rust +```rust,ignore pub trait IsMatch { fn is_match(&self, other: &'o O) -> bool; } @@ -619,7 +619,7 @@ approach (matching against the coarse pattern first and checking for additional properties later) might be slower than the current practice of checking for structure and additional properties in one pass. For example, the following lint -```rust +```rust,ignore pattern!{ pat_if_without_else: Expr = If( @@ -644,7 +644,7 @@ first matches against the pattern and then checks that the `then` block doesn't start with a comment. Using clippy's current approach, it's possible to check for these conditions earlier: -```rust +```rust,ignore fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { if_chain! { if let ast::ExprKind::If(ref check, ref then, None) = expr.node; @@ -708,7 +708,7 @@ is similar to actual Rust syntax (probably like the `quote!` macro). For example, a pattern that matches `if` expressions that have `false` in their condition could look like this: -```rust +```rust,ignore if false { #[*] } @@ -742,7 +742,7 @@ affects the structure of the resulting AST. `1 + 0 + 0` is parsed as `(1 + 0) + Another example of a problem would be named submatches. Take a look at this pattern: -```rust +```rust,ignore fn test() { 1 #foo } @@ -862,7 +862,7 @@ op b` and recommends changing it to `a op= b` requires that both occurrences of `a` are the same. Using `=#...` as syntax for backreferences, the lint could be implemented like this: -```rust +```rust,ignore pattern!{ assign_op_pattern: Expr = Assign(_#target, Binary(_, =#target, _) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md new file mode 100644 index 00000000000..5ce434b99a1 --- /dev/null +++ b/book/src/development/type_checking.md @@ -0,0 +1,144 @@ +# Type Checking + +When we work on a new lint or improve an existing lint, we might want +to retrieve the type `Ty` of an expression `Expr` for a variety of +reasons. This can be achieved by utilizing the [`LateContext`][LateContext] +that is available for [`LateLintPass`][LateLintPass]. + +## `LateContext` and `TypeckResults` + +The lint context [`LateContext`][LateContext] and [`TypeckResults`][TypeckResults] +(returned by `LateContext::typeck_results`) are the two most useful data structures +in `LateLintPass`. They allow us to jump to type definitions and other compilation +stages such as HIR. + +> Note: `LateContext.typeck_results`'s return value is [`TypeckResults`][TypeckResults] +> and is created in the type checking step, it includes useful information such as types of +> expressions, ways to resolve methods and so on. + +`TypeckResults` contains useful methods such as [`expr_ty`][expr_ty], +which gives us access to the underlying structure [`Ty`][Ty] of a given expression. + +```rust +pub fn expr_ty(&self, expr: &Expr<'_>) -> Ty<'tcx> +``` + +As a side note, besides `expr_ty`, [`TypeckResults`][TypeckResults] contains a +[`pat_ty()`][pat_ty] method that is useful for retrieving a type from a pattern. + +## `Ty` + +`Ty` struct contains the type information of an expression. +Let's take a look at `rustc_middle`'s [`Ty`][Ty] struct to examine this struct: + +```rust +pub struct Ty<'tcx>(Interned<'tcx, WithStableHash>>); +``` + +At a first glance, this struct looks quite esoteric. But at a closer look, +we will see that this struct contains many useful methods for type checking. + +For instance, [`is_char`][is_char] checks if the given `Ty` struct corresponds +to the primitive character type. + +### `is_*` Usage + +In some scenarios, all we need to do is check if the `Ty` of an expression +is a specific type, such as `char` type, so we could write the following: + +```rust +impl LateLintPass<'_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + // Get type of `expr` + let ty = cx.typeck_results().expr_ty(expr); + + // Check if the `Ty` of this expression is of character type + if ty.is_char() { + println!("Our expression is a char!"); + } + } +} +``` + +Furthermore, if we examine the [source code][is_char_source] for `is_char`, +we find something very interesting: + +```rust +#[inline] +pub fn is_char(self) -> bool { + matches!(self.kind(), Char) +} +``` + +Indeed, we just discovered `Ty`'s [`kind` method][kind], which provides us +with [`TyKind`][TyKind] of a `Ty`. + +## `TyKind` + +`TyKind` defines the kinds of types in Rust's type system. +Peeking into [`TyKind` documentation][TyKind], we will see that it is an +enum of 27 variants, including items such as `Bool`, `Int`, `Ref`, etc. + +### `kind` Usage + +The `TyKind` of `Ty` can be returned by calling [`Ty.kind` method][kind]. +We often use this method to perform pattern matching in Clippy. + +For instance, if we want to check for a `struct`, we could examine if the +`ty.kind` corresponds to an [`Adt`][Adt] (algebraic data type) and if its +[`AdtDef`][AdtDef] is a struct: + +```rust +impl LateLintPass<'_> for MyStructLint { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + // Get type of `expr` + let ty = cx.typeck_results().expr_ty(expr); + // Match its kind to enter the type + match ty.kind { + ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"), + _ => () + } + } +} +``` + +## `hir::Ty` and `ty::Ty` + +We've been talking about [`ty::Ty`][middle_ty] this whole time without addressing [`hir::Ty`][hir_ty], but the latter +is also important to understand. + +`hir::Ty` would represent *what* an user wrote, while `ty::Ty` would understand the meaning of it (because it has more +information). + +**Example: `fn foo(x: u32) -> u32 { x }`** + +Here the HIR sees the types without "thinking" about them, it knows that the function takes an `u32` and returns +an `u32`. But at the `ty::Ty` level the compiler understands that they're the same type, in-depth lifetimes, etc... + +you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function to convert from a `hir::Ty` to a `ty::Ty` + +## Useful Links + +Below are some useful links to further explore the concepts covered +in this chapter: + +- [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation) +- [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html) +- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) +- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) + +[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt +[AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html +[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty +[is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char +[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834 +[kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind +[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html +[LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html +[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty +[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html +[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html +[TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html +[middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html +[hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html +[hir_ty_to_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir_analysis/fn.hir_ty_to_ty.html diff --git a/book/src/installation.md b/book/src/installation.md index cce888b17d4..d54fff9deba 100644 --- a/book/src/installation.md +++ b/book/src/installation.md @@ -17,8 +17,8 @@ $ rustup component add clippy [--toolchain=] ## From Source -Take a look at the [Basics] chapter in the Clippy developer guide to find step -by step instructions on how to build and install Clippy from source. +Take a look at the [Basics] chapter in the Clippy developer guide to find step-by-step +instructions on how to build and install Clippy from source. [Basics]: development/basics.md#install-from-source [Usage]: usage.md diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 9ed6627b741..78e1a55cff3 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -54,6 +54,7 @@ Please use that command to update the file and do not edit it by hand. | [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` | | [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` | | [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` | +| [future-size-threshold](#future-size-threshold) | `16384` | ### arithmetic-side-effects-allowed Suppress checking of the passed type names in all types of operations. @@ -130,6 +131,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat * [option_option](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) * [linkedlist](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) * [rc_mutex](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) +* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) ### msrv @@ -193,7 +195,7 @@ The maximum cognitive complexity a function can have ### disallowed-names The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value `".."` can be used as part of the list to indicate, that the configured values should be appended to the -default configuration of Clippy. By default any configuration will replace the default value. +default configuration of Clippy. By default, any configuration will replace the default value. **Default Value:** `["foo", "baz", "quux"]` (`Vec`) @@ -203,7 +205,7 @@ default configuration of Clippy. By default any configuration will replace the d ### doc-valid-idents The list of words this lint should not consider as identifiers needing ticks. The value `".."` can be used as part of the list to indicate, that the configured values should be appended to the -default configuration of Clippy. By default any configuraction will replace the default value. For example: +default configuration of Clippy. By default, any configuration will replace the default value. For example: * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. @@ -413,7 +415,7 @@ For internal testing only, ignores the current `publish` settings in the Cargo m Enforce the named macros always use the braces specified. A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro -is could be used with a full path two `MacroMatcher`s have to be added one with the full path +could be used with a full path two `MacroMatcher`s have to be added one with the full path `crate_name::macro_name` and one with just the macro name. **Default Value:** `[]` (`Vec`) @@ -447,7 +449,7 @@ Whether to apply the raw pointer heuristic to determine if a type is `Send`. ### max-suggested-slice-pattern-length When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in -the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed. +the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. **Default Value:** `3` (`u64`) @@ -551,4 +553,12 @@ crate. For example, `pub(crate)` items. * [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) +### future-size-threshold +The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint + +**Default Value:** `16384` (`u64`) + +* [large_futures](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) + + diff --git a/book/src/lints.md b/book/src/lints.md index 35e30960b56..442dc63914e 100644 --- a/book/src/lints.md +++ b/book/src/lints.md @@ -17,7 +17,7 @@ The different lint groups were defined in the [Clippy 1.0 RFC]. The `clippy::correctness` group is the only lint group in Clippy which lints are deny-by-default and abort the compilation when triggered. This is for good reason: If you see a `correctness` lint, it means that your code is outright -wrong or useless and you should try to fix it. +wrong or useless, and you should try to fix it. Lints in this category are carefully picked and should be free of false positives. So just `#[allow]`ing those lints is not recommended. @@ -41,7 +41,7 @@ simplify your code. It mostly focuses on code that can be written in a shorter and more readable way, while preserving the semantics. If you should see a complexity lint, it usually means that you can remove or -replace some code and it is recommended to do so. However, if you need the more +replace some code, and it is recommended to do so. However, if you need the more complex code for some expressiveness reason, it is recommended to allow complexity lints on a case-by-case basis. @@ -50,9 +50,9 @@ complexity lints on a case-by-case basis. The `clippy::perf` group gives you suggestions on how you can increase the performance of your code. Those lints are mostly about code that the compiler can't trivially optimize, but has to be written in a slightly different way to -make the optimizer's job easier. +make the optimizer job easier. -Perf lints are usually easy to apply and it is recommended to do so. +Perf lints are usually easy to apply, and it is recommended to do so. ## Style @@ -91,7 +91,7 @@ and your use case. Lints from this group will restrict you in some way. If you enable a restriction lint for your crate it is recommended to also fix code that this lint triggers -on. However, those lints are really strict by design and you might want to +on. However, those lints are really strict by design, and you might want to `#[allow]` them in some special cases, with a comment justifying that. ## Cargo diff --git a/book/src/usage.md b/book/src/usage.md index 61a90445d75..32084a9199b 100644 --- a/book/src/usage.md +++ b/book/src/usage.md @@ -19,7 +19,7 @@ cargo clippy ### Lint configuration The above command will run the default set of lints, which are included in the -lint group `clippy::all`. You might want to use even more lints or you might not +lint group `clippy::all`. You might want to use even more lints, or you may not agree with every Clippy lint, and for that there are ways to configure lint levels. @@ -98,7 +98,7 @@ other of Clippy's lint groups. You can configure lint levels in source code the same way you can configure `rustc` lints: -```rust +```rust,ignore #![allow(clippy::style)] #[warn(clippy::double_neg)] diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 8871873c661..3a8b070d735 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(lazy_cell)] #![feature(let_chains)] #![feature(rustc_private)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 420214d9256..13a27703427 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -369,9 +369,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R }} todo!(); }} - "#, - context_import = context_import, - name_upper = name_upper, + "# ); } else { let _: fmt::Result = writedoc!( @@ -385,9 +383,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R pub(super) fn check(cx: &{context_import}) {{ todo!(); }} - "#, - context_import = context_import, - name_upper = name_upper, + "# ); } diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 779e4d0e1e3..95222a9acdf 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -537,17 +537,13 @@ fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> { /// Nothing. This lint has been deprecated. /// /// ### Deprecation reason - /// {} - #[clippy::version = \"{}\"] - pub {}, - \"{}\" + /// {deprecation_reason} + #[clippy::version = \"{version}\"] + pub {name}, + \"{reason}\" }} - ", - deprecation_reason, - version, - name, - reason, + " ) } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 0b3846c1316..18e8bf77225 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -9,6 +9,7 @@ keywords = ["clippy", "lint", "plugin"] edition = "2021" [dependencies] +arrayvec = { version = "0.7", default-features = false } cargo_metadata = "0.15.3" clippy_utils = { path = "../clippy_utils" } declare_clippy_lint = { path = "../declare_clippy_lint" } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 29fde9336c0..455f0df7cd0 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -7,7 +7,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, Level}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Span; @@ -430,23 +430,25 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } } let nonminimal_bool_lint = |suggestions: Vec<_>| { - span_lint_hir_and_then( - self.cx, - NONMINIMAL_BOOL, - e.hir_id, - e.span, - "this boolean expression can be simplified", - |diag| { - diag.span_suggestions( - e.span, - "try", - suggestions.into_iter(), - // nonminimal_bool can produce minimal but - // not human readable expressions (#3141) - Applicability::Unspecified, - ); - }, - ); + if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).0 != Level::Allow { + span_lint_hir_and_then( + self.cx, + NONMINIMAL_BOOL, + e.hir_id, + e.span, + "this boolean expression can be simplified", + |diag| { + diag.span_suggestions( + e.span, + "try", + suggestions.into_iter(), + // nonminimal_bool can produce minimal but + // not human readable expressions (#3141) + Applicability::Unspecified, + ); + }, + ); + } }; if improvements.is_empty() { let mut visitor = NotSimplificationVisitor { cx: self.cx }; @@ -498,6 +500,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> { if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind && !inner.span.from_expansion() && let Some(suggestion) = simplify_not(self.cx, inner) + && self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow { span_lint_and_sugg( self.cx, diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 823970e35ab..95c2ecbf791 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -2,8 +2,9 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::expr_or_init; use clippy_utils::source::snippet; +use clippy_utils::sugg::Sugg; use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize}; -use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_errors::{Applicability, Diagnostic, SuggestionStyle}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -163,19 +164,34 @@ pub(super) fn check( _ => return, }; - let name_of_cast_from = snippet(cx, cast_expr.span, ".."); - let cast_to_snip = snippet(cx, cast_to_span, ".."); - let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})"); - span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| { diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ..."); - diag.span_suggestion_with_style( - expr.span, - "... or use `try_from` and handle the error accordingly", - suggestion, - Applicability::Unspecified, - // always show the suggestion in a separate line - SuggestionStyle::ShowAlways, - ); + if !cast_from.is_floating_point() { + offer_suggestion(cx, expr, cast_expr, cast_to_span, diag); + } }); } + +fn offer_suggestion( + cx: &LateContext<'_>, + expr: &Expr<'_>, + cast_expr: &Expr<'_>, + cast_to_span: Span, + diag: &mut Diagnostic, +) { + let cast_to_snip = snippet(cx, cast_to_span, ".."); + let suggestion = if cast_to_snip == "_" { + format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_par()) + } else { + format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, "..")) + }; + + diag.span_suggestion_with_style( + expr.span, + "... or use `try_from` and handle the error accordingly", + suggestion, + Applicability::Unspecified, + // always show the suggestion in a separate line + SuggestionStyle::ShowAlways, + ); +} diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index 10f2bef268a..5e2eb5789f6 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::for_each_expr_with_closures; use clippy_utils::{get_enclosing_block, get_parent_node, path_to_local_id}; use core::ops::ControlFlow; -use rustc_hir::{Block, ExprKind, HirId, Local, Node, PatKind}; +use rustc_hir::{Block, ExprKind, HirId, LangItem, Local, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; @@ -44,7 +44,8 @@ declare_clippy_lint! { } declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]); -static COLLECTIONS: [Symbol; 10] = [ +// Add `String` here when it is added to diagnostic items +static COLLECTIONS: [Symbol; 9] = [ sym::BTreeMap, sym::BTreeSet, sym::BinaryHeap, @@ -52,7 +53,6 @@ static COLLECTIONS: [Symbol; 10] = [ sym::HashSet, sym::LinkedList, sym::Option, - sym::String, sym::Vec, sym::VecDeque, ]; @@ -60,8 +60,7 @@ static COLLECTIONS: [Symbol; 10] = [ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) { // Look for local variables whose type is a container. Search surrounding bock for read access. - let ty = cx.typeck_results().pat_ty(local.pat); - if COLLECTIONS.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym)) + if match_acceptable_type(cx, local, &COLLECTIONS) && let PatKind::Binding(_, local_id, _, _) = local.pat.kind && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id) && has_no_read_access(cx, local_id, enclosing_block) @@ -71,6 +70,13 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { } } +fn match_acceptable_type(cx: &LateContext<'_>, local: &Local<'_>, collections: &[rustc_span::Symbol]) -> bool { + let ty = cx.typeck_results().pat_ty(local.pat); + collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym)) + // String type is a lang item but not a diagnostic item for now so we need a separate check + || is_type_lang_item(cx, ty, LangItem::String) +} + fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Block<'tcx>) -> bool { let mut has_access = false; let mut has_read_access = false; @@ -95,9 +101,9 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc return ControlFlow::Continue(()); } - // Method call on `id` in a statement ignores any return value, so it's not a read access: + // Look for method call with receiver `id`. It might be a non-read access: // - // id.foo(...); // Not reading `id`. + // id.foo(args) // // Only assuming this for "official" methods defined on the type. For methods defined in extension // traits (identified as local, based on the orphan rule), pessimistically assume that they might @@ -105,11 +111,24 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id) && let ExprKind::MethodCall(_, receiver, _, _) = parent.kind && path_to_local_id(receiver, id) - && let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id) && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id) && !method_def_id.is_local() { - return ControlFlow::Continue(()); + // The method call is a statement, so the return value is not used. That's not a read access: + // + // id.foo(args); + if let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id) { + return ControlFlow::Continue(()); + } + + // The method call is not a statement, so its return value is used somehow but its type is the + // unit type, so this is not a real read access. Examples: + // + // let y = x.clear(); + // println!("{:?}", x.clear()); + if cx.typeck_results().expr_ty(parent).is_unit() { + return ControlFlow::Continue(()); + } } // Any other access to `id` is a read access. Stop searching. diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 8ca91301472..f24dab62780 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -218,6 +218,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO, crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO, crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO, + crate::large_futures::LARGE_FUTURES_INFO, crate::large_include_file::LARGE_INCLUDE_FILE_INFO, crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO, crate::len_zero::COMPARISON_TO_EMPTY_INFO, @@ -231,6 +232,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::let_with_type_underscore::LET_WITH_TYPE_UNDERSCORE_INFO, crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO, crate::lifetimes::NEEDLESS_LIFETIMES_INFO, + crate::lines_filter_map_ok::LINES_FILTER_MAP_OK_INFO, crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO, crate::literal_representation::INCONSISTENT_DIGIT_GROUPING_INFO, crate::literal_representation::LARGE_DIGIT_GROUPS_INFO, @@ -267,6 +269,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO, crate::manual_retain::MANUAL_RETAIN_INFO, + crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, crate::manual_string_new::MANUAL_STRING_NEW_INFO, crate::manual_strip::MANUAL_STRIP_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, @@ -307,6 +310,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS_INFO, crate::methods::CHARS_LAST_CMP_INFO, crate::methods::CHARS_NEXT_CMP_INFO, + crate::methods::CLEAR_WITH_DRAIN_INFO, crate::methods::CLONED_INSTEAD_OF_COPIED_INFO, crate::methods::CLONE_DOUBLE_REF_INFO, crate::methods::CLONE_ON_COPY_INFO, @@ -565,6 +569,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::strings::STR_TO_STRING_INFO, crate::strings::TRIM_SPLIT_WHITESPACE_INFO, crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO, + crate::suspicious_doc_comments::SUSPICIOUS_DOC_COMMENTS_INFO, crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO, crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO, crate::suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL_INFO, @@ -574,6 +579,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::swap_ptr_to_ref::SWAP_PTR_TO_REF_INFO, crate::tabs_in_doc_comments::TABS_IN_DOC_COMMENTS_INFO, crate::temporary_assignment::TEMPORARY_ASSIGNMENT_INFO, + crate::tests_outside_test_module::TESTS_OUTSIDE_TEST_MODULE_INFO, crate::to_digit_is_some::TO_DIGIT_IS_SOME_INFO, crate::trailing_empty_array::TRAILING_EMPTY_ARRAY_INFO, crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO, @@ -616,6 +622,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::unit_types::UNIT_CMP_INFO, crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO, crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO, + crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO, crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO, crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO, crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO, diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs index 084190f0013..c9fad98e437 100644 --- a/clippy_lints/src/disallowed_script_idents.rs +++ b/clippy_lints/src/disallowed_script_idents.rs @@ -32,7 +32,7 @@ declare_clippy_lint! { /// ### Example /// ```rust /// // Assuming that `clippy.toml` contains the following line: - /// // allowed-locales = ["Latin", "Cyrillic"] + /// // allowed-scripts = ["Latin", "Cyrillic"] /// let counter = 10; // OK, latin is allowed. /// let счётчик = 10; // OK, cyrillic is allowed. /// let zähler = 10; // OK, it's still latin. diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index c0ea6f338a2..315df6c714f 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::FormatArgsExpn; +use clippy_utils::macros::{find_format_args, format_args_inputs_span}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_expn_of, match_function_call, paths}; use if_chain::if_chain; @@ -8,7 +8,7 @@ use rustc_hir::def::Res; use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::sym; +use rustc_span::{sym, ExpnId}; declare_clippy_lint! { /// ### What it does @@ -43,23 +43,22 @@ declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]); impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - // match call to unwrap - if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind; - if unwrap_fun.ident.name == sym::unwrap; + // match call to unwrap + if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind + && unwrap_fun.ident.name == sym::unwrap // match call to write_fmt - if let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind); - if write_fun.ident.name == sym!(write_fmt); + && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind) + && write_fun.ident.name == sym!(write_fmt) // match calls to std::io::stdout() / std::io::stderr () - if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() { + && let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() { Some("stdout") } else if match_function_call(cx, write_recv, &paths::STDERR).is_some() { Some("stderr") } else { None - }; - if let Some(format_args) = FormatArgsExpn::parse(cx, write_arg); - then { + } + { + find_format_args(cx, write_arg, ExpnId::root(), |format_args| { let calling_macro = // ordering is important here, since `writeln!` uses `write!` internally if is_expn_of(write_call.span, "writeln").is_some() { @@ -92,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { let mut applicability = Applicability::MachineApplicable; let inputs_snippet = snippet_with_applicability( cx, - format_args.inputs_span(), + format_args_inputs_span(format_args), "..", &mut applicability, ); @@ -104,8 +103,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { "try this", format!("{prefix}{sugg_mac}!({inputs_snippet})"), applicability, - ) - } + ); + }); } } } diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index 20565e1d232..eeb4de8b58f 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -1,10 +1,10 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::trait_ref_of_method; -use rustc_data_structures::fx::FxHashMap; -use rustc_errors::MultiSpan; +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::{ - BodyId, ExprKind, GenericBound, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, + BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, PredicateOrigin, Ty, TyKind, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -53,13 +53,19 @@ impl ExtraUnusedTypeParameters { } } - /// Don't lint external macros or functions with empty bodies. Also, don't lint public items if - /// the `avoid_breaking_exported_api` config option is set. - fn check_false_positive(&self, cx: &LateContext<'_>, span: Span, def_id: LocalDefId, body_id: BodyId) -> bool { + /// Don't lint external macros or functions with empty bodies. Also, don't lint exported items + /// if the `avoid_breaking_exported_api` config option is set. + fn is_empty_exported_or_macro( + &self, + cx: &LateContext<'_>, + span: Span, + def_id: LocalDefId, + body_id: BodyId, + ) -> bool { let body = cx.tcx.hir().body(body_id).value; let fn_empty = matches!(&body.kind, ExprKind::Block(blk, None) if blk.stmts.is_empty() && blk.expr.is_none()); let is_exported = cx.effective_visibilities.is_exported(def_id); - in_external_macro(cx.sess(), span) || (self.avoid_breaking_exported_api && is_exported) || fn_empty + in_external_macro(cx.sess(), span) || fn_empty || (is_exported && self.avoid_breaking_exported_api) } } @@ -69,85 +75,129 @@ impl_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]); /// trait bounds those parameters have. struct TypeWalker<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, - /// Collection of all the function's type parameters. + /// Collection of the function's type parameters. Once the function has been walked, this will + /// contain only unused type parameters. ty_params: FxHashMap, - /// Collection of any (inline) trait bounds corresponding to each type parameter. - bounds: FxHashMap, + /// Collection of any inline trait bounds corresponding to each type parameter. + inline_bounds: FxHashMap, + /// Collection of any type parameters with trait bounds that appear in a where clause. + where_bounds: FxHashSet, /// The entire `Generics` object of the function, useful for querying purposes. generics: &'tcx Generics<'tcx>, - /// The value of this will remain `true` if *every* parameter: - /// 1. Is a type parameter, and - /// 2. Goes unused in the function. - /// Otherwise, if any type parameters end up being used, or if any lifetime or const-generic - /// parameters are present, this will be set to `false`. - all_params_unused: bool, } impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> { fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'tcx>) -> Self { - let mut all_params_unused = true; let ty_params = generics .params .iter() - .filter_map(|param| { - if let GenericParamKind::Type { synthetic, .. } = param.kind { - (!synthetic).then_some((param.def_id.into(), param.span)) - } else { - if !param.is_elided_lifetime() { - all_params_unused = false; - } - None - } + .filter_map(|param| match param.kind { + GenericParamKind::Type { synthetic, .. } if !synthetic => Some((param.def_id.into(), param.span)), + _ => None, }) .collect(); Self { cx, ty_params, - bounds: FxHashMap::default(), + inline_bounds: FxHashMap::default(), + where_bounds: FxHashSet::default(), generics, - all_params_unused, } } - fn mark_param_used(&mut self, def_id: DefId) { - if self.ty_params.remove(&def_id).is_some() { - self.all_params_unused = false; - } + fn get_bound_span(&self, param: &'tcx GenericParam<'tcx>) -> Span { + self.inline_bounds + .get(¶m.def_id.to_def_id()) + .map_or(param.span, |bound_span| param.span.with_hi(bound_span.hi())) + } + + fn emit_help(&self, spans: Vec, msg: &str, help: &'static str) { + span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, None, help); + } + + fn emit_sugg(&self, spans: Vec, msg: &str, help: &'static str) { + let suggestions: Vec<(Span, String)> = spans.iter().copied().zip(std::iter::repeat(String::new())).collect(); + span_lint_and_then(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, |diag| { + diag.multipart_suggestion(help, suggestions, Applicability::MachineApplicable); + }); } fn emit_lint(&self) { - let (msg, help) = match self.ty_params.len() { + let explicit_params = self + .generics + .params + .iter() + .filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait()) + .collect::>(); + + let extra_params = explicit_params + .iter() + .enumerate() + .filter(|(_, param)| self.ty_params.contains_key(¶m.def_id.to_def_id())) + .collect::>(); + + let (msg, help) = match extra_params.len() { 0 => return, 1 => ( - "type parameter goes unused in function definition", + format!( + "type parameter `{}` goes unused in function definition", + extra_params[0].1.name.ident() + ), "consider removing the parameter", ), _ => ( - "type parameters go unused in function definition", + format!( + "type parameters go unused in function definition: {}", + extra_params + .iter() + .map(|(_, param)| param.name.ident().to_string()) + .collect::>() + .join(", ") + ), "consider removing the parameters", ), }; - let source_map = self.cx.sess().source_map(); - let span = if self.all_params_unused { - self.generics.span.into() // Remove the entire list of generics + // If any parameters are bounded in where clauses, don't try to form a suggestion. + // Otherwise, the leftover where bound would produce code that wouldn't compile. + if extra_params + .iter() + .any(|(_, param)| self.where_bounds.contains(¶m.def_id.to_def_id())) + { + let spans = extra_params + .iter() + .map(|(_, param)| self.get_bound_span(param)) + .collect::>(); + self.emit_help(spans, &msg, help); } else { - MultiSpan::from_spans( - self.ty_params + let spans = if explicit_params.len() == extra_params.len() { + vec![self.generics.span] // Remove the entire list of generics + } else { + let mut end: Option = None; + extra_params .iter() - .map(|(def_id, &span)| { - // Extend the span past any trait bounds, and include the comma at the end. - let span_to_extend = self.bounds.get(def_id).copied().map_or(span, Span::shrink_to_hi); - let comma_range = source_map.span_extend_to_next_char(span_to_extend, '>', false); - let comma_span = source_map.span_through_char(comma_range, ','); - span.with_hi(comma_span.hi()) + .rev() + .map(|(idx, param)| { + if let Some(next) = explicit_params.get(idx + 1) && end != Some(next.def_id) { + // Extend the current span forward, up until the next param in the list. + param.span.until(next.span) + } else { + // Extend the current span back to include the comma following the previous + // param. If the span of the next param in the list has already been + // extended, we continue the chain. This is why we're iterating in reverse. + end = Some(param.def_id); + + // idx will never be 0, else we'd be removing the entire list of generics + let prev = explicit_params[idx - 1]; + let prev_span = self.get_bound_span(prev); + self.get_bound_span(param).with_lo(prev_span.hi()) + } }) - .collect(), - ) + .collect() + }; + self.emit_sugg(spans, &msg, help); }; - - span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, span, msg, None, help); } } @@ -162,7 +212,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> { fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) { if let Some((def_id, _)) = t.peel_refs().as_generic_param() { - self.mark_param_used(def_id); + self.ty_params.remove(&def_id); } else if let TyKind::OpaqueDef(id, _, _) = t.kind { // Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls // `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're @@ -176,9 +226,18 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> { fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) { if let WherePredicate::BoundPredicate(predicate) = predicate { - // Collect spans for any bounds on type parameters. We only keep bounds that appear in - // the list of generics (not in a where-clause). + // Collect spans for any bounds on type parameters. if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param() { + match predicate.origin { + PredicateOrigin::GenericParam => { + self.inline_bounds.insert(def_id, predicate.span); + }, + PredicateOrigin::WhereClause => { + self.where_bounds.insert(def_id); + }, + PredicateOrigin::ImplTrait => (), + } + // If the bound contains non-public traits, err on the safe side and don't lint the // corresponding parameter. if !predicate @@ -187,12 +246,10 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> { .filter_map(bound_to_trait_def_id) .all(|id| self.cx.effective_visibilities.is_exported(id)) { - self.mark_param_used(def_id); - } else if let PredicateOrigin::GenericParam = predicate.origin { - self.bounds.insert(def_id, predicate.span); + self.ty_params.remove(&def_id); } } - // Only walk the right-hand side of where-bounds + // Only walk the right-hand side of where bounds for bound in predicate.bounds { walk_param_bound(self, bound); } @@ -207,7 +264,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> { impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if let ItemKind::Fn(_, generics, body_id) = item.kind - && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id) + && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id) { let mut walker = TypeWalker::new(cx, generics); walk_item(&mut walker, item); @@ -219,7 +276,7 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters { // Only lint on inherent methods, not trait methods. if let ImplItemKind::Fn(.., body_id) = item.kind && trait_ref_of_method(cx, item.owner_id.def_id).is_none() - && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id) + && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id) { let mut walker = TypeWalker::new(cx, item.generics); walk_impl_item(&mut walker, item); diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 8040938c626..d34d6e9279e 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,14 +1,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn}; -use clippy_utils::source::snippet_with_context; +use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node}; +use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::Sugg; -use if_chain::if_chain; +use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::symbol::kw; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -44,55 +43,53 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]); impl<'tcx> LateLintPass<'tcx> for UselessFormat { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let (format_args, call_site) = if_chain! { - if let Some(macro_call) = root_macro_call_first_node(cx, expr); - if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id); - if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn); - then { - (format_args, macro_call.span) - } else { - return - } - }; + let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return }; + if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) { + return; + } + + find_format_args(cx, expr, macro_call.expn, |format_args| { + let mut applicability = Applicability::MachineApplicable; + let call_site = macro_call.span; - let mut applicability = Applicability::MachineApplicable; - if format_args.args.is_empty() { - match *format_args.format_string.parts { - [] => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability), - [_] => { + match (format_args.arguments.all_args(), &format_args.template[..]) { + ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability), + ([], [_]) => { // Simulate macro expansion, converting {{ and }} to { and }. - let s_expand = format_args.format_string.snippet.replace("{{", "{").replace("}}", "}"); + let Some(snippet) = snippet_opt(cx, format_args.span) else { return }; + let s_expand = snippet.replace("{{", "{").replace("}}", "}"); let sugg = format!("{s_expand}.to_string()"); span_useless_format(cx, call_site, sugg, applicability); }, - [..] => {}, - } - } else if let [arg] = &*format_args.args { - let value = arg.param.value; - if_chain! { - if format_args.format_string.parts == [kw::Empty]; - if arg.format.is_default(); - if match cx.typeck_results().expr_ty(value).peel_refs().kind() { - ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(), - ty::Str => true, - _ => false, - }; - then { - let is_new_string = match value.kind { - ExprKind::Binary(..) => true, - ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string, - _ => false, - }; - let sugg = if is_new_string { - snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned() - } else { - let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "", &mut applicability); - format!("{}.to_string()", sugg.maybe_par()) - }; - span_useless_format(cx, call_site, sugg, applicability); - } + ([arg], [piece]) => { + if let Ok(value) = find_format_arg_expr(expr, arg) + && let FormatArgsPiece::Placeholder(placeholder) = piece + && placeholder.format_trait == FormatTrait::Display + && placeholder.format_options == FormatOptions::default() + && match cx.typeck_results().expr_ty(value).peel_refs().kind() { + ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(), + ty::Str => true, + _ => false, + } + { + let is_new_string = match value.kind { + ExprKind::Binary(..) => true, + ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string, + _ => false, + }; + let sugg = if is_new_string { + snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned() + } else { + let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "", &mut applicability); + format!("{}.to_string()", sugg.maybe_par()) + }; + span_useless_format(cx, call_site, sugg, applicability); + + } + }, + _ => {}, } - }; + }); } } diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index c511d85e9cf..08e45ed7d0e 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -1,27 +1,31 @@ +use arrayvec::ArrayVec; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_diag_trait_item; -use clippy_utils::macros::FormatParamKind::{Implicit, Named, NamedInline, Numbered, Starred}; use clippy_utils::macros::{ - is_assert_macro, is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, - FormatParamUsage, + find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, + is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage, }; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use if_chain::if_chain; use itertools::Itertools; +use rustc_ast::{ + FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, + FormatPlaceholder, FormatTrait, +}; use rustc_errors::{ Applicability, SuggestionStyle::{CompletelyHidden, ShowCode}, }; -use rustc_hir::{Expr, ExprKind, HirId, LangItem, QPath}; +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_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::DefId; use rustc_span::edition::Edition::Edition2021; -use rustc_span::{sym, ExpnData, ExpnKind, Span, Symbol}; +use rustc_span::{sym, Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -184,72 +188,79 @@ impl FormatArgs { impl<'tcx> LateLintPass<'tcx> for FormatArgs { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if let Some(format_args) = FormatArgsExpn::parse(cx, expr) - && let expr_expn_data = expr.span.ctxt().outer_expn_data() - && let outermost_expn_data = outermost_expn_data(expr_expn_data) - && let Some(macro_def_id) = outermost_expn_data.macro_def_id - && is_format_macro(cx, macro_def_id) - && let ExpnKind::Macro(_, name) = outermost_expn_data.kind - { - for arg in &format_args.args { - check_unused_format_specifier(cx, arg); - if !arg.format.is_default() { - continue; - } - if is_aliased(&format_args, arg.param.value.hir_id) { - continue; + let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return }; + if !is_format_macro(cx, macro_call.def_id) { + return; + } + let name = cx.tcx.item_name(macro_call.def_id); + + find_format_args(cx, expr, macro_call.expn, |format_args| { + for piece in &format_args.template { + if let FormatArgsPiece::Placeholder(placeholder) = piece + && let Ok(index) = placeholder.argument.index + && let Some(arg) = format_args.arguments.all_args().get(index) + { + let arg_expr = find_format_arg_expr(expr, arg); + + check_unused_format_specifier(cx, placeholder, arg_expr); + + if placeholder.format_trait != FormatTrait::Display + || placeholder.format_options != FormatOptions::default() + || is_aliased(format_args, index) + { + continue; + } + + if let Ok(arg_hir_expr) = arg_expr { + check_format_in_format_args(cx, macro_call.span, name, arg_hir_expr); + check_to_string_in_format_args(cx, name, arg_hir_expr); + } } - check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value); - check_to_string_in_format_args(cx, name, arg.param.value); } + if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) { - check_uninlined_args(cx, &format_args, outermost_expn_data.call_site, macro_def_id, self.ignore_mixed); + check_uninlined_args(cx, format_args, macro_call.span, macro_call.def_id, self.ignore_mixed); } - } + }); } extract_msrv_attr!(LateContext); } -fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) { - let param_ty = cx.typeck_results().expr_ty(arg.param.value).peel_refs(); +fn check_unused_format_specifier( + cx: &LateContext<'_>, + placeholder: &FormatPlaceholder, + arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>, +) { + let ty_or_ast_expr = arg_expr.map(|expr| cx.typeck_results().expr_ty(expr).peel_refs()); - if let Count::Implied(Some(mut span)) = arg.format.precision - && !span.is_empty() - { - span_lint_and_then( - cx, - UNUSED_FORMAT_SPECS, - span, - "empty precision specifier has no effect", - |diag| { - if param_ty.is_floating_point() { - diag.note("a precision specifier is not required to format floats"); - } + let is_format_args = match ty_or_ast_expr { + Ok(ty) => is_type_lang_item(cx, ty, LangItem::FormatArguments), + Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)), + }; - if arg.format.is_default() { - // If there's no other specifiers remove the `:` too - span = arg.format_span(); - } + let options = &placeholder.format_options; - diag.span_suggestion_verbose(span, "remove the `.`", "", Applicability::MachineApplicable); - }, - ); - } + let arg_span = match arg_expr { + Ok(expr) => expr.span, + Err(expr) => expr.span, + }; - if is_type_lang_item(cx, param_ty, LangItem::FormatArguments) && !arg.format.is_default_for_trait() { + if let Some(placeholder_span) = placeholder.span + && is_format_args + && *options != FormatOptions::default() + { span_lint_and_then( cx, UNUSED_FORMAT_SPECS, - arg.span, + placeholder_span, "format specifiers have no effect on `format_args!()`", |diag| { - let mut suggest_format = |spec, span| { + let mut suggest_format = |spec| { let message = format!("for the {spec} to apply consider using `format!()`"); - if let Some(mac_call) = root_macro_call(arg.param.value.span) + if let Some(mac_call) = root_macro_call(arg_span) && cx.tcx.is_diagnostic_item(sym::format_args_macro, mac_call.def_id) - && arg.span.eq_ctxt(mac_call.span) { diag.span_suggestion( cx.sess().source_map().span_until_char(mac_call.span, '!'), @@ -257,25 +268,27 @@ fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) { "format", Applicability::MaybeIncorrect, ); - } else if let Some(span) = span { - diag.span_help(span, message); + } else { + diag.help(message); } }; - if !arg.format.width.is_implied() { - suggest_format("width", arg.format.width.span()); + if options.width.is_some() { + suggest_format("width"); } - if !arg.format.precision.is_implied() { - suggest_format("precision", arg.format.precision.span()); + if options.precision.is_some() { + suggest_format("precision"); } - diag.span_suggestion_verbose( - arg.format_span(), - "if the current behavior is intentional, remove the format specifiers", - "", - Applicability::MaybeIncorrect, - ); + if let Some(format_span) = format_placeholder_format_span(placeholder) { + diag.span_suggestion_verbose( + format_span, + "if the current behavior is intentional, remove the format specifiers", + "", + Applicability::MaybeIncorrect, + ); + } }, ); } @@ -283,12 +296,12 @@ fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) { fn check_uninlined_args( cx: &LateContext<'_>, - args: &FormatArgsExpn<'_>, + args: &rustc_ast::FormatArgs, call_site: Span, def_id: DefId, ignore_mixed: bool, ) { - if args.format_string.span.from_expansion() { + if args.span.from_expansion() { return; } if call_site.edition() < Edition2021 && (is_panic(cx, def_id) || is_assert_macro(cx, def_id)) { @@ -303,7 +316,13 @@ fn check_uninlined_args( // we cannot remove any other arguments in the format string, // because the index numbers might be wrong after inlining. // Example of an un-inlinable format: print!("{}{1}", foo, 2) - if !args.params().all(|p| check_one_arg(args, &p, &mut fixes, ignore_mixed)) || fixes.is_empty() { + for (pos, usage) in format_arg_positions(args) { + if !check_one_arg(args, pos, usage, &mut fixes, ignore_mixed) { + return; + } + } + + if fixes.is_empty() { return; } @@ -332,47 +351,40 @@ fn check_uninlined_args( } fn check_one_arg( - args: &FormatArgsExpn<'_>, - param: &FormatParam<'_>, + args: &rustc_ast::FormatArgs, + pos: &FormatArgPosition, + usage: FormatParamUsage, fixes: &mut Vec<(Span, String)>, ignore_mixed: bool, ) -> bool { - if matches!(param.kind, Implicit | Starred | Named(_) | Numbered) - && let ExprKind::Path(QPath::Resolved(None, path)) = param.value.kind - && let [segment] = path.segments + let index = pos.index.unwrap(); + let arg = &args.arguments.all_args()[index]; + + if !matches!(arg.kind, FormatArgumentKind::Captured(_)) + && let rustc_ast::ExprKind::Path(None, path) = &arg.expr.kind + && let [segment] = path.segments.as_slice() && segment.args.is_none() - && let Some(arg_span) = args.value_with_prev_comma_span(param.value.hir_id) + && let Some(arg_span) = format_arg_removal_span(args, index) + && let Some(pos_span) = pos.span { - let replacement = match param.usage { + let replacement = match usage { FormatParamUsage::Argument => segment.ident.name.to_string(), FormatParamUsage::Width => format!("{}$", segment.ident.name), FormatParamUsage::Precision => format!(".{}$", segment.ident.name), }; - fixes.push((param.span, replacement)); + fixes.push((pos_span, replacement)); fixes.push((arg_span, String::new())); true // successful inlining, continue checking } else { // Do not continue inlining (return false) in case // * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)` // * if allow_mixed_uninlined_format_args is false and this arg hasn't been inlined already - param.kind != Numbered && (!ignore_mixed || matches!(param.kind, NamedInline(_))) - } -} - -fn outermost_expn_data(expn_data: ExpnData) -> ExpnData { - if expn_data.call_site.from_expansion() { - outermost_expn_data(expn_data.call_site.ctxt().outer_expn_data()) - } else { - expn_data + pos.kind != FormatArgPositionKind::Number + && (!ignore_mixed || matches!(arg.kind, FormatArgumentKind::Captured(_))) } } -fn check_format_in_format_args( - cx: &LateContext<'_>, - call_site: Span, - name: Symbol, - arg: &Expr<'_>, -) { +fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symbol, arg: &Expr<'_>) { let expn_data = arg.span.ctxt().outer_expn_data(); if expn_data.call_site.from_expansion() { return; @@ -443,9 +455,33 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex } } -/// Returns true if `hir_id` is referred to by multiple format params -fn is_aliased(args: &FormatArgsExpn<'_>, hir_id: HirId) -> bool { - args.params().filter(|param| param.value.hir_id == hir_id).at_most_one().is_err() +fn format_arg_positions( + format_args: &rustc_ast::FormatArgs, +) -> impl Iterator { + format_args.template.iter().flat_map(|piece| match piece { + FormatArgsPiece::Placeholder(placeholder) => { + let mut positions = ArrayVec::<_, 3>::new(); + + positions.push((&placeholder.argument, FormatParamUsage::Argument)); + if let Some(FormatCount::Argument(position)) = &placeholder.format_options.width { + positions.push((position, FormatParamUsage::Width)); + } + if let Some(FormatCount::Argument(position)) = &placeholder.format_options.precision { + positions.push((position, FormatParamUsage::Precision)); + } + + positions + }, + FormatArgsPiece::Literal(_) => ArrayVec::new(), + }) +} + +/// Returns true if the format argument at `index` is referred to by multiple format params +fn is_aliased(format_args: &rustc_ast::FormatArgs, index: usize) -> bool { + format_arg_positions(format_args) + .filter(|(position, _)| position.index == Ok(index)) + .at_most_one() + .is_err() } fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>) @@ -455,7 +491,11 @@ where let mut n_total = 0; let mut n_needed = 0; loop { - if let Some(Adjustment { kind: Adjust::Deref(overloaded_deref), target }) = iter.next() { + if let Some(Adjustment { + kind: Adjust::Deref(overloaded_deref), + target, + }) = iter.next() + { n_total += 1; if overloaded_deref.is_some() { n_needed = n_total; diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index ed1342a5465..e3ddbfb5981 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -1,11 +1,13 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::macros::{is_format_macro, root_macro_call_first_node, FormatArg, FormatArgsExpn}; +use clippy_utils::macros::{find_format_arg_expr, find_format_args, 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 if_chain::if_chain; +use rustc_ast::{FormatArgsPiece, FormatTrait}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Span; use rustc_span::{sym, symbol::kw, Symbol}; declare_clippy_lint! { @@ -89,7 +91,7 @@ declare_clippy_lint! { } #[derive(Clone, Copy)] -struct FormatTrait { +struct FormatTraitNames { /// e.g. `sym::Display` name: Symbol, /// `f` in `fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {}` @@ -99,7 +101,7 @@ struct FormatTrait { #[derive(Default)] pub struct FormatImpl { // Whether we are inside Display or Debug trait impl - None for neither - format_trait_impl: Option, + format_trait_impl: Option, } impl FormatImpl { @@ -161,43 +163,57 @@ fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) { } } -fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTrait) { +fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTraitNames) { // Check each arg in format calls - do we ever use Display on self (directly or via deref)? - if_chain! { - if let Some(outer_macro) = root_macro_call_first_node(cx, expr); - if let macro_def_id = outer_macro.def_id; - if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, outer_macro.expn); - if is_format_macro(cx, macro_def_id); - then { - for arg in format_args.args { - if arg.format.r#trait != impl_trait.name { - continue; + if let Some(outer_macro) = root_macro_call_first_node(cx, expr) + && let macro_def_id = outer_macro.def_id + && is_format_macro(cx, macro_def_id) + { + find_format_args(cx, expr, outer_macro.expn, |format_args| { + for piece in &format_args.template { + if let FormatArgsPiece::Placeholder(placeholder) = piece + && let trait_name = match placeholder.format_trait { + FormatTrait::Display => sym::Display, + FormatTrait::Debug => sym::Debug, + FormatTrait::LowerExp => sym!(LowerExp), + FormatTrait::UpperExp => sym!(UpperExp), + FormatTrait::Octal => sym!(Octal), + FormatTrait::Pointer => sym::Pointer, + FormatTrait::Binary => sym!(Binary), + FormatTrait::LowerHex => sym!(LowerHex), + FormatTrait::UpperHex => sym!(UpperHex), + } + && trait_name == impl_trait.name + && let Ok(index) = placeholder.argument.index + && let Some(arg) = format_args.arguments.all_args().get(index) + && let Ok(arg_expr) = find_format_arg_expr(expr, arg) + { + check_format_arg_self(cx, expr.span, arg_expr, impl_trait); } - check_format_arg_self(cx, expr, &arg, impl_trait); } - } + }); } } -fn check_format_arg_self(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &FormatArg<'_>, impl_trait: FormatTrait) { +fn check_format_arg_self(cx: &LateContext<'_>, span: Span, arg: &Expr<'_>, impl_trait: FormatTraitNames) { // Handle multiple dereferencing of references e.g. &&self // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl) // Since the argument to fmt is itself a reference: &self - let reference = peel_ref_operators(cx, arg.param.value); + let reference = peel_ref_operators(cx, arg); let map = cx.tcx.hir(); // Is the reference self? if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) { - let FormatTrait { name, .. } = impl_trait; + let FormatTraitNames { name, .. } = impl_trait; span_lint( cx, RECURSIVE_FORMAT_IMPL, - expr.span, + span, &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"), ); } } -fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTrait) { +fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTraitNames) { if_chain! { if let Some(macro_call) = root_macro_call_first_node(cx, expr); if let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id); @@ -227,7 +243,7 @@ fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: } } -fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option { +fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option { if_chain! { if impl_item.ident.name == sym::fmt; if let ImplItemKind::Fn(_, body_id) = impl_item.kind; @@ -241,7 +257,7 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio .and_then(|param| param.pat.simple_ident()) .map(|ident| ident.name); - Some(FormatTrait { + Some(FormatTraitNames { name, formatter_name, }) diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 1e9e826631c..d0ad2628264 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -1,7 +1,9 @@ +use hir::FnSig; use rustc_ast::ast::Attribute; use rustc_errors::Applicability; use rustc_hir::def_id::DefIdSet; use rustc_hir::{self as hir, def::Res, QPath}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; use rustc_middle::{ lint::in_external_macro, @@ -27,7 +29,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some(attr) = attr { - check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr); + check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig); } else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) { check_must_use_candidate( cx, @@ -49,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); if let Some(attr) = attr { - check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr); + check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig); } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none() { check_must_use_candidate( cx, @@ -72,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.owner_id, sym::must_use); if let Some(attr) = attr { - check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr); + check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig); } else if let hir::TraitFn::Provided(eid) = *eid { let body = cx.tcx.hir().body(eid); if attr.is_none() && is_public && !is_proc_macro(attrs) { @@ -97,6 +99,7 @@ fn check_needless_must_use( item_span: Span, fn_header_span: Span, attr: &Attribute, + sig: &FnSig<'_>, ) { if in_external_macro(cx.sess(), item_span) { return; @@ -112,6 +115,15 @@ fn check_needless_must_use( }, ); } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) { + // Ignore async functions unless Future::Output type is a must_use type + if sig.header.is_async() { + let infcx = cx.tcx.infer_ctxt().build(); + if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id)) + && !is_must_use_ty(cx, future_ty) { + return; + } + } + span_lint_and_help( cx, DOUBLE_MUST_USE, diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 46d439b4497..a7ec57e2850 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -1,8 +1,8 @@ //! lint when items are used after statements -use clippy_utils::diagnostics::span_lint; -use rustc_ast::ast::{Block, ItemKind, StmtKind}; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use clippy_utils::diagnostics::span_lint_hir; +use rustc_hir::{Block, ItemKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -52,33 +52,34 @@ declare_clippy_lint! { declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]); -impl EarlyLintPass for ItemsAfterStatements { - fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) { - if in_external_macro(cx.sess(), item.span) { +impl LateLintPass<'_> for ItemsAfterStatements { + fn check_block(&mut self, cx: &LateContext<'_>, block: &Block<'_>) { + if in_external_macro(cx.sess(), block.span) { return; } - // skip initial items and trailing semicolons - let stmts = item + // skip initial items + let stmts = block .stmts .iter() - .map(|stmt| &stmt.kind) - .skip_while(|s| matches!(**s, StmtKind::Item(..) | StmtKind::Empty)); + .skip_while(|stmt| matches!(stmt.kind, StmtKind::Item(..))); // lint on all further items for stmt in stmts { - if let StmtKind::Item(ref it) = *stmt { - if in_external_macro(cx.sess(), it.span) { + if let StmtKind::Item(item_id) = stmt.kind { + let item = cx.tcx.hir().item(item_id); + if in_external_macro(cx.sess(), item.span) || !item.span.eq_ctxt(block.span) { return; } - if let ItemKind::MacroDef(..) = it.kind { + if let ItemKind::Macro(..) = item.kind { // do not lint `macro_rules`, but continue processing further statements continue; } - span_lint( + span_lint_hir( cx, ITEMS_AFTER_STATEMENTS, - it.span, + item.hir_id(), + item.span, "adding items after statements is confusing, since items exist from the \ start of the scope", ); diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs new file mode 100644 index 00000000000..1b054481371 --- /dev/null +++ b/clippy_lints/src/large_futures.rs @@ -0,0 +1,87 @@ +use clippy_utils::source::snippet; +use clippy_utils::{diagnostics::span_lint_and_sugg, ty::implements_trait}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_target::abi::Size; + +declare_clippy_lint! { + /// ### What it does + /// It checks for the size of a `Future` created by `async fn` or `async {}`. + /// + /// ### Why is this bad? + /// Due to the current [unideal implemention](https://github.com/rust-lang/rust/issues/69826) of `Generator`, + /// large size of a `Future` may cause stack overflows. + /// + /// ### Example + /// ```rust + /// async fn wait(f: impl std::future::Future) {} + /// + /// async fn big_fut(arg: [u8; 1024]) {} + /// + /// pub async fn test() { + /// let fut = big_fut([0u8; 1024]); + /// wait(fut).await; + /// } + /// ``` + /// + /// `Box::pin` the big future instead. + /// + /// ```rust + /// async fn wait(f: impl std::future::Future) {} + /// + /// async fn big_fut(arg: [u8; 1024]) {} + /// + /// pub async fn test() { + /// let fut = Box::pin(big_fut([0u8; 1024])); + /// wait(fut).await; + /// } + /// ``` + #[clippy::version = "1.68.0"] + pub LARGE_FUTURES, + pedantic, + "large future may lead to unexpected stack overflows" +} + +#[derive(Copy, Clone)] +pub struct LargeFuture { + future_size_threshold: u64, +} + +impl LargeFuture { + pub fn new(future_size_threshold: u64) -> Self { + Self { future_size_threshold } + } +} + +impl_lint_pass!(LargeFuture => [LARGE_FUTURES]); + +impl<'tcx> LateLintPass<'tcx> for LargeFuture { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if matches!(expr.span.ctxt().outer_expn_data().kind, rustc_span::ExpnKind::Macro(..)) { + return; + } + if let ExprKind::Match(expr, _, MatchSource::AwaitDesugar) = expr.kind { + if let ExprKind::Call(func, [expr, ..]) = expr.kind + && let ExprKind::Path(QPath::LangItem(LangItem::IntoFutureIntoFuture, ..)) = func.kind + && let ty = cx.typeck_results().expr_ty(expr) + && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() + && implements_trait(cx, ty, future_trait_def_id, &[]) + && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + && let size = layout.layout.size() + && size >= Size::from_bytes(self.future_size_threshold) + { + span_lint_and_sugg( + cx, + LARGE_FUTURES, + expr.span, + &format!("large future with a size of {} bytes", size.bytes()), + "consider `Box::pin` on it", + format!("Box::pin({})", snippet(cx, expr.span, "..")), + Applicability::Unspecified, + ); + } + } + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3da7f95c1b9..b0ec14855e7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,7 +1,6 @@ #![feature(array_windows)] #![feature(binary_heap_into_iter_sorted)] #![feature(box_patterns)] -#![feature(drain_filter)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] @@ -162,6 +161,7 @@ mod items_after_statements; mod iter_not_returning_iterator; mod large_const_arrays; mod large_enum_variant; +mod large_futures; mod large_include_file; mod large_stack_arrays; mod len_zero; @@ -169,6 +169,7 @@ mod let_if_seq; mod let_underscore; mod let_with_type_underscore; mod lifetimes; +mod lines_filter_map_ok; mod literal_representation; mod loops; mod macro_use; @@ -183,6 +184,7 @@ mod manual_main_separator_str; mod manual_non_exhaustive; mod manual_rem_euclid; mod manual_retain; +mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; mod map_unit_fn; @@ -281,6 +283,7 @@ mod slow_vector_initialization; mod std_instead_of_core; mod strings; mod strlen_on_c_strings; +mod suspicious_doc_comments; mod suspicious_operation_groupings; mod suspicious_trait_impl; mod suspicious_xor_used_as_pow; @@ -288,6 +291,7 @@ mod swap; mod swap_ptr_to_ref; mod tabs_in_doc_comments; mod temporary_assignment; +mod tests_outside_test_module; mod to_digit_is_some; mod trailing_empty_array; mod trait_bounds; @@ -299,6 +303,7 @@ mod uninit_vec; mod unit_return_expecting_ord; mod unit_types; mod unnamed_address; +mod unnecessary_box_returns; mod unnecessary_owned_empty_strings; mod unnecessary_self_imports; mod unnecessary_struct_initialization; @@ -344,13 +349,17 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se } #[doc(hidden)] -pub fn read_conf(sess: &Session, path: &io::Result>) -> Conf { +pub fn read_conf(sess: &Session, path: &io::Result<(Option, Vec)>) -> Conf { + if let Ok((_, warnings)) = path { + for warning in warnings { + sess.warn(warning); + } + } let file_name = match path { - Ok(Some(path)) => path, - Ok(None) => return Conf::default(), + Ok((Some(path), _)) => path, + Ok((None, _)) => return Conf::default(), Err(error) => { - sess.struct_err(format!("error finding Clippy's configuration file: {error}")) - .emit(); + sess.err(format!("error finding Clippy's configuration file: {error}")); return Conf::default(); }, }; @@ -746,7 +755,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| Box::new(unused_unit::UnusedUnit)); store.register_late_pass(|_| Box::new(returns::Return)); store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf)); - store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements)); + store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements)); store.register_early_pass(|| Box::new(precedence::Precedence)); store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals)); store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue)); @@ -808,6 +817,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv()))); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); + let future_size_threshold = conf.future_size_threshold; + store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(future_size_threshold))); store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex)); store.register_late_pass(|_| Box::new(if_not_else::IfNotElse)); store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality)); @@ -934,11 +945,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi)); store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead)); store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage)); - store.register_early_pass(|| Box::new(redundant_async_block::RedundantAsyncBlock)); + store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock)); store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped)); store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute)); store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv()))); store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct)); + store.register_late_pass(move |_| { + Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new( + avoid_breaking_exported_api, + )) + }); + store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk)); + store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule)); + store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); + store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs new file mode 100644 index 00000000000..b0f9276475d --- /dev/null +++ b/clippy_lints/src/lines_filter_map_ok.rs @@ -0,0 +1,100 @@ +use clippy_utils::{ + diagnostics::span_lint_and_then, is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths, + ty::match_type, +}; +use rustc_errors::Applicability; +use rustc_hir::{Body, Closure, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Detect uses of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` + /// when `lines` has type `std::io::Lines`. + /// + /// ### Why is this bad? + /// `Lines` instances might produce a never-ending stream of `Err`, in which case + /// `filter_map(Result::ok)` will enter an infinite loop while waiting for an + /// `Ok` variant. Calling `next()` once is sufficient to enter the infinite loop, + /// even in the absence of explicit loops in the user code. + /// + /// This situation can arise when working with user-provided paths. On some platforms, + /// `std::fs::File::open(path)` might return `Ok(fs)` even when `path` is a directory, + /// but any later attempt to read from `fs` will return an error. + /// + /// ### Known problems + /// This lint suggests replacing `filter_map()` or `flat_map()` applied to a `Lines` + /// instance in all cases. There two cases where the suggestion might not be + /// appropriate or necessary: + /// + /// - If the `Lines` instance can never produce any error, or if an error is produced + /// only once just before terminating the iterator, using `map_while()` is not + /// necessary but will not do any harm. + /// - If the `Lines` instance can produce intermittent errors then recover and produce + /// successful results, using `map_while()` would stop at the first error. + /// + /// ### Example + /// ```rust + /// # use std::{fs::File, io::{self, BufRead, BufReader}}; + /// # let _ = || -> io::Result<()> { + /// let mut lines = BufReader::new(File::open("some-path")?).lines().filter_map(Result::ok); + /// // If "some-path" points to a directory, the next statement never terminates: + /// let first_line: Option = lines.next(); + /// # Ok(()) }; + /// ``` + /// Use instead: + /// ```rust + /// # use std::{fs::File, io::{self, BufRead, BufReader}}; + /// # let _ = || -> io::Result<()> { + /// let mut lines = BufReader::new(File::open("some-path")?).lines().map_while(Result::ok); + /// let first_line: Option = lines.next(); + /// # Ok(()) }; + /// ``` + #[clippy::version = "1.70.0"] + pub LINES_FILTER_MAP_OK, + suspicious, + "filtering `std::io::Lines` with `filter_map()` or `flat_map()` might cause an infinite loop" +} +declare_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]); + +impl LateLintPass<'_> for LinesFilterMapOk { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind && + is_trait_method(cx, expr, sym::Iterator) && + (fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") && + match_type(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), &paths::STD_IO_LINES) + { + let lint = match &fm_arg.kind { + // Detect `Result::ok` + ExprKind::Path(qpath) => + cx.qpath_res(qpath, fm_arg.hir_id).opt_def_id().map(|did| + match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)).unwrap_or_default(), + // Detect `|x| x.ok()` + ExprKind::Closure(Closure { body, .. }) => + if let Body { params: [param], value, .. } = cx.tcx.hir().body(*body) && + let ExprKind::MethodCall(method, receiver, [], _) = value.kind && + path_to_local_id(receiver, param.pat.hir_id) && + let Some(method_did) = cx.typeck_results().type_dependent_def_id(value.hir_id) + { + is_diag_item_method(cx, method_did, sym::Result) && method.ident.as_str() == "ok" + } else { + false + } + _ => false, + }; + if lint { + span_lint_and_then(cx, + LINES_FILTER_MAP_OK, + fm_span, + &format!("`{}()` will run forever if the iterator repeatedly produces an `Err`", fm_method.ident), + |diag| { + diag.span_note( + fm_receiver.span, + "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error"); + diag.span_suggestion(fm_span, "replace with", "map_while(Result::ok)", Applicability::MaybeIncorrect); + }); + } + } + } +} diff --git a/clippy_lints/src/manual_slice_size_calculation.rs b/clippy_lints/src/manual_slice_size_calculation.rs new file mode 100644 index 00000000000..92ee79453a3 --- /dev/null +++ b/clippy_lints/src/manual_slice_size_calculation.rs @@ -0,0 +1,93 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{expr_or_init, in_constant}; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::sym; + +declare_clippy_lint! { + /// ### What it does + /// When `a` is `&[T]`, detect `a.len() * size_of::()` and suggest `size_of_val(a)` + /// instead. + /// + /// ### Why is this better? + /// * Shorter to write + /// * Removes the need for the human and the compiler to worry about overflow in the + /// multiplication + /// * Potentially faster at runtime as rust emits special no-wrapping flags when it + /// calculates the byte length + /// * Less turbofishing + /// + /// ### Example + /// ```rust + /// # let data : &[i32] = &[1, 2, 3]; + /// let newlen = data.len() * std::mem::size_of::(); + /// ``` + /// Use instead: + /// ```rust + /// # let data : &[i32] = &[1, 2, 3]; + /// let newlen = std::mem::size_of_val(data); + /// ``` + #[clippy::version = "1.70.0"] + pub MANUAL_SLICE_SIZE_CALCULATION, + complexity, + "manual slice size calculation" +} +declare_lint_pass!(ManualSliceSizeCalculation => [MANUAL_SLICE_SIZE_CALCULATION]); + +impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + // Does not apply inside const because size_of_value is not cost in stable. + if !in_constant(cx, expr.hir_id) + && let ExprKind::Binary(ref op, left, right) = expr.kind + && BinOpKind::Mul == op.node + && let Some(_receiver) = simplify(cx, left, right) + { + span_lint_and_help( + cx, + MANUAL_SLICE_SIZE_CALCULATION, + expr.span, + "manual slice size calculation", + None, + "consider using std::mem::size_of_value instead"); + } + } +} + +fn simplify<'tcx>( + cx: &LateContext<'tcx>, + expr1: &'tcx Expr<'tcx>, + expr2: &'tcx Expr<'tcx>, +) -> Option<&'tcx Expr<'tcx>> { + let expr1 = expr_or_init(cx, expr1); + let expr2 = expr_or_init(cx, expr2); + + simplify_half(cx, expr1, expr2).or_else(|| simplify_half(cx, expr2, expr1)) +} + +fn simplify_half<'tcx>( + cx: &LateContext<'tcx>, + expr1: &'tcx Expr<'tcx>, + expr2: &'tcx Expr<'tcx>, +) -> Option<&'tcx Expr<'tcx>> { + if + // expr1 is `[T1].len()`? + let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind + && method_path.ident.name == sym::len + && let receiver_ty = cx.typeck_results().expr_ty(receiver) + && let ty::Slice(ty1) = receiver_ty.peel_refs().kind() + // expr2 is `size_of::()`? + && let ExprKind::Call(func, _) = expr2.kind + && let ExprKind::Path(ref func_qpath) = func.kind + && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id) + && let Some(ty2) = cx.typeck_results().node_substs(func.hir_id).types().next() + // T1 == T2? + && *ty1 == ty2 + { + Some(receiver) + } else { + None + } +} diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 35024ec1224..8a921d4af16 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,12 +1,13 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; -use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res}; +use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath}; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -101,40 +102,26 @@ declare_clippy_lint! { impl_lint_pass!(MemReplace => [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]); -fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { - // Check that second argument is `Option::None` - if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { - // Since this is a late pass (already type-checked), - // and we already know that the second argument is an - // `Option`, we do not need to check the first - // argument's type. All that's left is to get - // replacee's path. - let replaced_path = match dest.kind { - ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => { - if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind { - replaced_path - } else { - return; - } - }, - ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path, - _ => return, - }; - - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - MEM_REPLACE_OPTION_WITH_NONE, - expr_span, - "replacing an `Option` with `None`", - "consider `Option::take()` instead", - format!( - "{}.take()", - snippet_with_applicability(cx, replaced_path.span, "", &mut applicability) - ), - applicability, - ); - } +fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_span: Span) { + // Since this is a late pass (already type-checked), + // and we already know that the second argument is an + // `Option`, we do not need to check the first + // argument's type. All that's left is to get + // the replacee's expr after peeling off the `&mut` + let sugg_expr = peel_ref_operators(cx, dest); + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + MEM_REPLACE_OPTION_WITH_NONE, + expr_span, + "replacing an `Option` with `None`", + "consider `Option::take()` instead", + format!( + "{}.take()", + Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_par() + ), + applicability, + ); } fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { @@ -200,10 +187,6 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< if is_non_aggregate_primitive_type(expr_type) { return; } - // disable lint for Option since it is covered in another lint - if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { - return; - } if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) { span_lint_and_then( cx, @@ -246,11 +229,13 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace { if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if cx.tcx.is_diagnostic_item(sym::mem_replace, def_id); then { - check_replace_option_with_none(cx, src, dest, expr.span); - check_replace_with_uninit(cx, src, dest, expr.span); - if self.msrv.meets(msrvs::MEM_TAKE) { + // Check that second argument is `Option::None` + if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) { + check_replace_option_with_none(cx, dest, expr.span); + } else if self.msrv.meets(msrvs::MEM_TAKE) { check_replace_with_default(cx, src, dest, expr.span); } + check_replace_with_uninit(cx, src, dest, expr.span); } } } diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs new file mode 100644 index 00000000000..67ad58d5a8c --- /dev/null +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -0,0 +1,53 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_range_full; +use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::{Expr, ExprKind, LangItem, QPath}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; +use rustc_span::Span; + +use super::CLEAR_WITH_DRAIN; + +// Add `String` here when it is added to diagnostic items +const ACCEPTABLE_TYPES_WITH_ARG: [rustc_span::Symbol; 2] = [sym::Vec, sym::VecDeque]; + +const ACCEPTABLE_TYPES_WITHOUT_ARG: [rustc_span::Symbol; 3] = [sym::BinaryHeap, sym::HashMap, sym::HashSet]; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, arg: Option<&Expr<'_>>) { + if let Some(arg) = arg { + if match_acceptable_type(cx, recv, &ACCEPTABLE_TYPES_WITH_ARG) + && let ExprKind::Path(QPath::Resolved(None, container_path)) = recv.kind + && is_range_full(cx, arg, Some(container_path)) + { + suggest(cx, expr, recv, span); + } + } else if match_acceptable_type(cx, recv, &ACCEPTABLE_TYPES_WITHOUT_ARG) { + suggest(cx, expr, recv, span); + } +} + +fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, types: &[rustc_span::Symbol]) -> bool { + let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); + types.iter().any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty)) + // String type is a lang item but not a diagnostic item for now so we need a separate check + || is_type_lang_item(cx, expr_ty, LangItem::String) +} + +fn suggest(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span) { + if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def() + // Use `opt_item_name` while `String` is not a diagnostic item + && let Some(ty_name) = cx.tcx.opt_item_name(adt.did()) + { + span_lint_and_sugg( + cx, + CLEAR_WITH_DRAIN, + span.with_hi(expr.span.hi()), + &format!("`drain` used to clear a `{ty_name}`"), + "try", + "clear()".to_string(), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index a22285058d4..92d21bb8932 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn}; +use clippy_utils::macros::{find_format_args, 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; @@ -136,18 +136,19 @@ pub(super) fn check<'tcx>( if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) { return; } - let Some(format_args) = FormatArgsExpn::find_nested(cx, arg_root, macro_call.expn) else { return }; - let span = format_args.inputs_span(); - let sugg = snippet_with_applicability(cx, span, "..", &mut applicability); - span_lint_and_sugg( - cx, - EXPECT_FUN_CALL, - span_replace_word, - &format!("use of `{name}` followed by a function call"), - "try this", - format!("unwrap_or_else({closure_args} panic!({sugg}))"), - applicability, - ); + find_format_args(cx, arg_root, macro_call.expn, |format_args| { + let span = format_args_inputs_span(format_args); + let sugg = snippet_with_applicability(cx, span, "..", &mut applicability); + span_lint_and_sugg( + cx, + EXPECT_FUN_CALL, + span_replace_word, + &format!("use of `{name}` followed by a function call"), + "try this", + format!("unwrap_or_else({closure_args} panic!({sugg}))"), + applicability, + ); + }); return; } diff --git a/clippy_lints/src/methods/iter_with_drain.rs b/clippy_lints/src/methods/iter_with_drain.rs index 3da230e12d7..f6772c5c6b3 100644 --- a/clippy_lints/src/methods/iter_with_drain.rs +++ b/clippy_lints/src/methods/iter_with_drain.rs @@ -1,7 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher::Range; -use clippy_utils::is_integer_const; -use rustc_ast::ast::RangeLimits; +use clippy_utils::is_range_full; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::LateContext; @@ -15,8 +13,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span && let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def() && let Some(ty_name) = cx.tcx.get_diagnostic_name(adt.did()) && matches!(ty_name, sym::Vec | sym::VecDeque) - && let Some(range) = Range::hir(arg) - && is_full_range(cx, recv, range) + && let ExprKind::Path(QPath::Resolved(None, container_path)) = recv.kind + && is_range_full(cx, arg, Some(container_path)) { span_lint_and_sugg( cx, @@ -29,19 +27,3 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span ); }; } - -fn is_full_range(cx: &LateContext<'_>, container: &Expr<'_>, range: Range<'_>) -> bool { - range.start.map_or(true, |e| is_integer_const(cx, e, 0)) - && range.end.map_or(true, |e| { - if range.limits == RangeLimits::HalfOpen - && let ExprKind::Path(QPath::Resolved(None, container_path)) = container.kind - && let ExprKind::MethodCall(name, self_arg, [], _) = e.kind - && name.ident.name == sym::len - && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind - { - container_path.res == path.res - } else { - false - } - }) -} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 56e3988bf09..64bf55ba24c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -9,6 +9,7 @@ mod chars_last_cmp; mod chars_last_cmp_with_unwrap; mod chars_next_cmp; mod chars_next_cmp_with_unwrap; +mod clear_with_drain; mod clone_on_copy; mod clone_on_ref_ptr; mod cloned_instead_of_copied; @@ -110,7 +111,7 @@ use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_ use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, return_ty}; use if_chain::if_chain; use rustc_hir as hir; -use rustc_hir::{Expr, ExprKind, TraitItem, TraitItemKind}; +use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind}; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; @@ -3190,6 +3191,31 @@ declare_clippy_lint! { "single command line argument that looks like it should be multiple arguments" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `.drain(..)` for the sole purpose of clearing a container. + /// + /// ### Why is this bad? + /// This creates an unnecessary iterator that is dropped immediately. + /// + /// Calling `.clear()` also makes the intent clearer. + /// + /// ### Example + /// ```rust + /// let mut v = vec![1, 2, 3]; + /// v.drain(..); + /// ``` + /// Use instead: + /// ```rust + /// let mut v = vec![1, 2, 3]; + /// v.clear(); + /// ``` + #[clippy::version = "1.69.0"] + pub CLEAR_WITH_DRAIN, + nursery, + "calling `drain` in order to `clear` a container" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -3318,6 +3344,7 @@ impl_lint_pass!(Methods => [ SEEK_TO_START_INSTEAD_OF_REWIND, NEEDLESS_COLLECT, SUSPICIOUS_COMMAND_ARG_SPACE, + CLEAR_WITH_DRAIN, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -3562,8 +3589,15 @@ impl Methods { Some(("bytes", recv2, [], _, _)) => bytes_count_to_len::check(cx, expr, recv, recv2), _ => {}, }, - ("drain", [arg]) => { - iter_with_drain::check(cx, expr, recv, span, arg); + ("drain", ..) => { + if let Node::Stmt(Stmt { hir_id: _, kind, .. }) = cx.tcx.hir().get_parent(expr.hir_id) + && matches!(kind, StmtKind::Semi(_)) + && args.len() <= 1 + { + clear_with_drain::check(cx, expr, recv, span, args.first()); + } else if let [arg] = args { + iter_with_drain::check(cx, expr, recv, span, arg); + } }, ("ends_with", [arg]) => { if let ExprKind::MethodCall(.., span) = expr.kind { diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 87bd007a26a..f1831a30461 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -41,6 +41,7 @@ declare_clippy_lint! { /// can't be const as it calls a non-const function. Making `a` const and running Clippy again, /// will suggest to make `b` const, too. /// + /// If you are marking a public function with `const`, removing it again will break API compatibility. /// ### Example /// ```rust /// # struct Foo { diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 25e8de94863..e5713735672 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -154,10 +154,18 @@ impl ArithmeticSideEffects { Self::literal_integer(cx, actual_rhs), ) { (None, None) => false, - (None, Some(n)) | (Some(n), None) => match (&op.node, n) { + (None, Some(n)) => match (&op.node, n) { // Division and module are always valid if applied to non-zero integers (hir::BinOpKind::Div | hir::BinOpKind::Rem, local_n) if local_n != 0 => true, - // Addition or subtracting zeros is always a no-op + // Adding or subtracting zeros is always a no-op + (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0) + // Multiplication by 1 or 0 will never overflow + | (hir::BinOpKind::Mul, 0 | 1) + => true, + _ => false, + }, + (Some(n), None) => match (&op.node, n) { + // Adding or subtracting zeros is always a no-op (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0) // Multiplication by 1 or 0 will never overflow | (hir::BinOpKind::Mul, 0 | 1) diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index 5ac203665d0..a0f831764d0 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -1,8 +1,15 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet}; -use rustc_ast::ast::{Expr, ExprKind, Stmt, StmtKind}; -use rustc_ast::visit::Visitor as AstVisitor; +use std::ops::ControlFlow; + +use clippy_utils::{ + diagnostics::span_lint_and_sugg, + peel_blocks, + source::{snippet, walk_span_to_context}, + visitors::for_each_expr, +}; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_hir::{AsyncGeneratorKind, Closure, Expr, ExprKind, GeneratorKind, MatchSource}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::{lint::in_external_macro, ty::UpvarCapture}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -14,106 +21,88 @@ declare_clippy_lint! { /// /// ### Example /// ```rust - /// async fn f() -> i32 { - /// 1 + 2 - /// } - /// + /// let f = async { + /// 1 + 2 + /// }; /// let fut = async { - /// f().await + /// f.await /// }; /// ``` /// Use instead: /// ```rust - /// async fn f() -> i32 { - /// 1 + 2 - /// } - /// - /// let fut = f(); + /// let f = async { + /// 1 + 2 + /// }; + /// let fut = f; /// ``` #[clippy::version = "1.69.0"] pub REDUNDANT_ASYNC_BLOCK, - nursery, + complexity, "`async { future.await }` can be replaced by `future`" } declare_lint_pass!(RedundantAsyncBlock => [REDUNDANT_ASYNC_BLOCK]); -impl EarlyLintPass for RedundantAsyncBlock { - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if expr.span.from_expansion() { - return; - } - if let ExprKind::Async(_, block) = &expr.kind && block.stmts.len() == 1 && - let Some(Stmt { kind: StmtKind::Expr(last), .. }) = block.stmts.last() && - let ExprKind::Await(future) = &last.kind && - !future.span.from_expansion() && - !await_in_expr(future) +impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + let span = expr.span; + if !in_external_macro(cx.tcx.sess, span) && + let Some(body_expr) = desugar_async_block(cx, expr) && + let Some(expr) = desugar_await(peel_blocks(body_expr)) && + // The await prefix must not come from a macro as its content could change in the future. + expr.span.ctxt() == body_expr.span.ctxt() && + // An async block does not have immediate side-effects from a `.await` point-of-view. + (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) && + let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt()) { - if captures_value(last) { - // If the async block captures variables then there is no equivalence. - return; - } - span_lint_and_sugg( cx, REDUNDANT_ASYNC_BLOCK, - expr.span, + span, "this async expression only awaits a single future", "you can reduce it to", - snippet(cx, future.span, "..").into_owned(), + snippet(cx, shortened_span, "..").into_owned(), Applicability::MachineApplicable, ); } } } -/// Check whether an expression contains `.await` -fn await_in_expr(expr: &Expr) -> bool { - let mut detector = AwaitDetector::default(); - detector.visit_expr(expr); - detector.await_found -} - -#[derive(Default)] -struct AwaitDetector { - await_found: bool, -} - -impl<'ast> AstVisitor<'ast> for AwaitDetector { - fn visit_expr(&mut self, ex: &'ast Expr) { - match (&ex.kind, self.await_found) { - (ExprKind::Await(_), _) => self.await_found = true, - (_, false) => rustc_ast::visit::walk_expr(self, ex), - _ => (), - } +/// If `expr` is a desugared `async` block, return the original expression if it does not capture +/// any variable by ref. +fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Closure(Closure { body, def_id, .. }) = expr.kind && + let body = cx.tcx.hir().body(*body) && + matches!(body.generator_kind, Some(GeneratorKind::Async(AsyncGeneratorKind::Block))) + { + cx + .typeck_results() + .closure_min_captures + .get(def_id) + .map_or(true, |m| { + m.values().all(|places| { + places + .iter() + .all(|place| matches!(place.info.capture_kind, UpvarCapture::ByValue)) + }) + }) + .then_some(body.value) + } else { + None } } -/// Check whether an expression may have captured a local variable. -/// This is done by looking for paths with only one segment, except as -/// a prefix of `.await` since this would be captured by value. -/// -/// This function will sometimes return `true` even tough there are no -/// captures happening: at the AST level, it is impossible to -/// dinstinguish a function call from a call to a closure which comes -/// from the local environment. -fn captures_value(expr: &Expr) -> bool { - let mut detector = CaptureDetector::default(); - detector.visit_expr(expr); - detector.capture_found -} - -#[derive(Default)] -struct CaptureDetector { - capture_found: bool, -} - -impl<'ast> AstVisitor<'ast> for CaptureDetector { - fn visit_expr(&mut self, ex: &'ast Expr) { - match (&ex.kind, self.capture_found) { - (ExprKind::Await(fut), _) if matches!(fut.kind, ExprKind::Path(..)) => (), - (ExprKind::Path(_, path), _) if path.segments.len() == 1 => self.capture_found = true, - (_, false) => rustc_ast::visit::walk_expr(self, ex), - _ => (), - } +/// If `expr` is a desugared `.await`, return the original expression if it does not come from a +/// macro expansion. +fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if let ExprKind::Match(match_value, _, MatchSource::AwaitDesugar) = expr.kind && + let ExprKind::Call(_, [into_future_arg]) = match_value.kind && + let ctxt = expr.span.ctxt() && + for_each_expr(into_future_arg, |e| + walk_span_to_context(e.span, ctxt) + .map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(()))).is_none() + { + Some(into_future_arg) + } else { + None } } diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 11b908e7e53..038dfe8e480 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; -use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, StaticItem, ConstItem}; +use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -106,7 +106,7 @@ impl EarlyLintPass for RedundantStaticLifetimes { // #2438) } - if let ItemKind::Static(box StaticItem { ty: ref var_type,.. }) = item.kind { + if let ItemKind::Static(box StaticItem { ty: ref var_type, .. }) = item.kind { Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime"); } } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index f0d7dd23a67..df126d7617e 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -9,7 +9,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, MatchSource, PatKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::source_map::Span; @@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { } else { RetReplacement::Empty }; - check_final_expr(cx, body.value, vec![], replacement); + check_final_expr(cx, body.value, vec![], replacement, None); }, FnKind::ItemFn(..) | FnKind::Method(..) => { check_block_return(cx, &body.value.kind, sp, vec![]); @@ -188,11 +188,11 @@ impl<'tcx> LateLintPass<'tcx> for Return { fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, sp: Span, mut semi_spans: Vec) { if let ExprKind::Block(block, _) = expr_kind { if let Some(block_expr) = block.expr { - check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty); + check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty, None); } else if let Some(stmt) = block.stmts.iter().last() { match stmt.kind { StmtKind::Expr(expr) => { - check_final_expr(cx, expr, semi_spans, RetReplacement::Empty); + check_final_expr(cx, expr, semi_spans, RetReplacement::Empty, None); }, StmtKind::Semi(semi_expr) => { // Remove ending semicolons and any whitespace ' ' in between. @@ -202,7 +202,7 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, span_find_starting_semi(cx.sess().source_map(), semi_span.with_hi(sp.hi())); semi_spans.push(semi_span_to_remove); } - check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty); + check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty, None); }, _ => (), } @@ -216,6 +216,7 @@ fn check_final_expr<'tcx>( semi_spans: Vec, /* containing all the places where we would need to remove semicolons if finding an * needless return */ replacement: RetReplacement<'tcx>, + match_ty_opt: Option>, ) { let peeled_drop_expr = expr.peel_drop_temps(); match &peeled_drop_expr.kind { @@ -244,7 +245,22 @@ fn check_final_expr<'tcx>( RetReplacement::Expr(snippet, applicability) } } else { - replacement + match match_ty_opt { + Some(match_ty) => { + match match_ty.kind() { + // If the code got till here with + // tuple not getting detected before it, + // then we are sure it's going to be Unit + // type + ty::Tuple(_) => RetReplacement::Unit, + // We don't want to anything in this case + // cause we can't predict what the user would + // want here + _ => return, + } + }, + None => replacement, + } }; if !cx.tcx.hir().attrs(expr.hir_id).is_empty() { @@ -268,8 +284,9 @@ fn check_final_expr<'tcx>( // note, if without else is going to be a type checking error anyways // (except for unit type functions) so we don't match it ExprKind::Match(_, arms, MatchSource::Normal) => { + let match_ty = cx.typeck_results().expr_ty(peeled_drop_expr); for arm in arms.iter() { - check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit); + check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit, Some(match_ty)); } }, // if it's a whole block, check it @@ -293,6 +310,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec, if ret_span.from_expansion() { return; } + let applicability = replacement.applicability().unwrap_or(Applicability::MachineApplicable); let return_replacement = replacement.to_string(); let sugg_help = replacement.sugg_help(); diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs index d46f6a6352c..5743dd21c28 100644 --- a/clippy_lints/src/single_component_path_imports.rs +++ b/clippy_lints/src/single_component_path_imports.rs @@ -1,6 +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, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind}; +use rustc_ast::visit::{walk_expr, Visitor}; +use rustc_ast::{ptr::P, Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -55,7 +56,7 @@ impl EarlyLintPass for SingleComponentPathImports { return; } - self.check_mod(cx, &krate.items); + self.check_mod(&krate.items); } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { @@ -84,8 +85,43 @@ impl EarlyLintPass for SingleComponentPathImports { } } +#[derive(Default)] +struct ImportUsageVisitor { + // keep track of imports reused with `self` keyword, such as `self::std` in the example below. + // Removing the `use std;` would make this a compile error (#10549) + // ``` + // use std; + // + // fn main() { + // let _ = self::std::io::stdout(); + // } + // ``` + imports_referenced_with_self: Vec, +} + +impl<'tcx> Visitor<'tcx> for ImportUsageVisitor { + fn visit_expr(&mut self, expr: &Expr) { + if let ExprKind::Path(_, path) = &expr.kind + && path.segments.len() > 1 + && path.segments[0].ident.name == kw::SelfLower + { + self.imports_referenced_with_self.push(path.segments[1].ident.name); + } + walk_expr(self, expr); + } + + fn visit_ty(&mut self, ty: &Ty) { + if let TyKind::Path(_, path) = &ty.kind + && path.segments.len() > 1 + && path.segments[0].ident.name == kw::SelfLower + { + self.imports_referenced_with_self.push(path.segments[1].ident.name); + } + } +} + impl SingleComponentPathImports { - fn check_mod(&mut self, cx: &EarlyContext<'_>, items: &[P]) { + fn check_mod(&mut self, items: &[P]) { // keep track of imports reused with `self` keyword, such as `self::crypto_hash` in the example // below. Removing the `use crypto_hash;` would make this a compile error // ``` @@ -108,18 +144,16 @@ impl SingleComponentPathImports { // ``` let mut macros = Vec::new(); + let mut import_usage_visitor = ImportUsageVisitor::default(); for item in items { - self.track_uses( - cx, - item, - &mut imports_reused_with_self, - &mut single_use_usages, - &mut macros, - ); + self.track_uses(item, &mut imports_reused_with_self, &mut single_use_usages, &mut macros); + import_usage_visitor.visit_item(item); } for usage in single_use_usages { - if !imports_reused_with_self.contains(&usage.name) { + if !imports_reused_with_self.contains(&usage.name) + && !import_usage_visitor.imports_referenced_with_self.contains(&usage.name) + { self.found.entry(usage.item_id).or_default().push(usage); } } @@ -127,7 +161,6 @@ impl SingleComponentPathImports { fn track_uses( &mut self, - cx: &EarlyContext<'_>, item: &Item, imports_reused_with_self: &mut Vec, single_use_usages: &mut Vec, @@ -139,7 +172,7 @@ impl SingleComponentPathImports { match &item.kind { ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => { - self.check_mod(cx, items); + self.check_mod(items); }, ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => { macros.push(item.ident.name); diff --git a/clippy_lints/src/suspicious_doc_comments.rs b/clippy_lints/src/suspicious_doc_comments.rs new file mode 100644 index 00000000000..e5746ca99ca --- /dev/null +++ b/clippy_lints/src/suspicious_doc_comments.rs @@ -0,0 +1,94 @@ +use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}; +use if_chain::if_chain; +use rustc_ast::{token::CommentKind, AttrKind, AttrStyle, Attribute, Item}; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!` + /// + /// ### Why is this bad? + /// Triple-slash comments (known as "outer doc comments") apply to items that follow it. + /// An outer doc comment followed by a bang (i.e. `///!`) has no specific meaning. + /// + /// The user most likely meant to write an inner doc comment (`//!`, `/*!`), which + /// applies to the parent item (i.e. the item that the comment is contained in, + /// usually a module or crate). + /// + /// ### Known problems + /// Inner doc comments can only appear before items, so there are certain cases where the suggestion + /// made by this lint is not valid code. For example: + /// ```rs + /// fn foo() {} + /// ///! + /// fn bar() {} + /// ``` + /// This lint detects the doc comment and suggests changing it to `//!`, but an inner doc comment + /// is not valid at that position. + /// + /// ### Example + /// In this example, the doc comment is attached to the *function*, rather than the *module*. + /// ```rust + /// pub mod util { + /// ///! This module contains utility functions. + /// + /// pub fn dummy() {} + /// } + /// ``` + /// + /// Use instead: + /// ```rust + /// pub mod util { + /// //! This module contains utility functions. + /// + /// pub fn dummy() {} + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub SUSPICIOUS_DOC_COMMENTS, + suspicious, + "suspicious usage of (outer) doc comments" +} +declare_lint_pass!(SuspiciousDocComments => [SUSPICIOUS_DOC_COMMENTS]); + +const WARNING: &str = "this is an outer doc comment and does not apply to the parent module or crate"; +const HELP: &str = "use an inner doc comment to document the parent module or crate"; + +impl EarlyLintPass for SuspiciousDocComments { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + let replacements = collect_doc_comment_replacements(&item.attrs); + + if let Some(((lo_span, _), (hi_span, _))) = replacements.first().zip(replacements.last()) { + let span = lo_span.to(*hi_span); + + span_lint_and_then(cx, SUSPICIOUS_DOC_COMMENTS, span, WARNING, |diag| { + multispan_sugg_with_applicability(diag, HELP, Applicability::MaybeIncorrect, replacements); + }); + } + } +} + +fn collect_doc_comment_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> { + attrs + .iter() + .filter_map(|attr| { + if_chain! { + if let AttrKind::DocComment(com_kind, sym) = attr.kind; + if let AttrStyle::Outer = attr.style; + if let Some(com) = sym.as_str().strip_prefix('!'); + then { + let sugg = match com_kind { + CommentKind::Line => format!("//!{com}"), + CommentKind::Block => format!("/*!{com}*/") + }; + Some((attr.span, sugg)) + } else { + None + } + } + }) + .collect() +} diff --git a/clippy_lints/src/tests_outside_test_module.rs b/clippy_lints/src/tests_outside_test_module.rs new file mode 100644 index 00000000000..0a0a77082e0 --- /dev/null +++ b/clippy_lints/src/tests_outside_test_module.rs @@ -0,0 +1,71 @@ +use clippy_utils::{diagnostics::span_lint_and_note, is_in_cfg_test, is_in_test_function}; +use rustc_hir::{intravisit::FnKind, Body, FnDecl}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{def_id::LocalDefId, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module + /// (marked with `#[cfg(test)]`). + /// ### Why is this bad? + /// The idiomatic (and more performant) way of writing tests is inside a testing module (flagged with `#[cfg(test)]`), + /// having test functions outside of this module is confusing and may lead to them being "hidden". + /// ### Example + /// ```rust + /// #[test] + /// fn my_cool_test() { + /// // [...] + /// } + /// + /// #[cfg(test)] + /// mod tests { + /// // [...] + /// } + /// + /// ``` + /// Use instead: + /// ```rust + /// #[cfg(test)] + /// mod tests { + /// #[test] + /// fn my_cool_test() { + /// // [...] + /// } + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub TESTS_OUTSIDE_TEST_MODULE, + restriction, + "A test function is outside the testing module." +} + +declare_lint_pass!(TestsOutsideTestModule => [TESTS_OUTSIDE_TEST_MODULE]); + +impl LateLintPass<'_> for TestsOutsideTestModule { + fn check_fn( + &mut self, + cx: &LateContext<'_>, + kind: FnKind<'_>, + _: &FnDecl<'_>, + body: &Body<'_>, + sp: Span, + _: LocalDefId, + ) { + if_chain! { + if !matches!(kind, FnKind::Closure); + if is_in_test_function(cx.tcx, body.id().hir_id); + if !is_in_cfg_test(cx.tcx, body.id().hir_id); + then { + span_lint_and_note( + cx, + TESTS_OUTSIDE_TEST_MODULE, + sp, + "this function marked with #[test] is outside a #[cfg(test)] module", + None, + "move it to a testing module marked with #[cfg(test)]", + ); + } + } + } +} diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 8530b43243f..85cd74f23ef 100644 --- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -2,8 +2,9 @@ use super::utils::check_cast; use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; +use rustc_ast::ExprPrecedence; use rustc_errors::Applicability; -use rustc_hir::Expr; +use rustc_hir::{Expr, Node}; use rustc_lint::LateContext; use rustc_middle::ty::{cast::CastKind, Ty}; @@ -19,7 +20,7 @@ pub(super) fn check<'tcx>( ) -> bool { use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast}; let mut app = Applicability::MachineApplicable; - let sugg = match check_cast(cx, e, from_ty, to_ty) { + let mut sugg = match check_cast(cx, e, from_ty, to_ty) { Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => { Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app) .as_ty(to_ty.to_string()) @@ -39,6 +40,12 @@ pub(super) fn check<'tcx>( _ => return false, }; + if let Node::Expr(parent) = cx.tcx.hir().get_parent(e.hir_id) + && parent.precedence().order() > ExprPrecedence::Cast.order() + { + sugg = format!("({sugg})"); + } + span_lint_and_sugg( cx, TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs new file mode 100644 index 00000000000..912bcda630b --- /dev/null +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -0,0 +1,120 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_errors::Applicability; +use rustc_hir::{def_id::LocalDefId, FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::Symbol; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for a return type containing a `Box` where `T` implements `Sized` + /// + /// ### Why is this bad? + /// + /// It's better to just return `T` in these cases. The caller may not need + /// the value to be boxed, and it's expensive to free the memory once the + /// `Box` been dropped. + /// + /// ### Example + /// ```rust + /// fn foo() -> Box { + /// Box::new(String::from("Hello, world!")) + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn foo() -> String { + /// String::from("Hello, world!") + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub UNNECESSARY_BOX_RETURNS, + pedantic, + "Needlessly returning a Box" +} + +pub struct UnnecessaryBoxReturns { + avoid_breaking_exported_api: bool, +} + +impl_lint_pass!(UnnecessaryBoxReturns => [UNNECESSARY_BOX_RETURNS]); + +impl UnnecessaryBoxReturns { + pub fn new(avoid_breaking_exported_api: bool) -> Self { + Self { + avoid_breaking_exported_api, + } + } + + fn check_fn_item(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, def_id: LocalDefId, name: Symbol) { + // we don't want to tell someone to break an exported function if they ask us not to + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) { + return; + } + + // functions which contain the word "box" are exempt from this lint + if name.as_str().contains("box") { + return; + } + + let FnRetTy::Return(return_ty_hir) = &decl.output else { return }; + + let return_ty = cx + .tcx + .erase_late_bound_regions(cx.tcx.fn_sig(def_id).skip_binder()) + .output(); + + if !return_ty.is_box() { + return; + } + + let boxed_ty = return_ty.boxed_ty(); + + // it's sometimes useful to return Box if T is unsized, so don't lint those + if boxed_ty.is_sized(cx.tcx, cx.param_env) { + span_lint_and_then( + cx, + UNNECESSARY_BOX_RETURNS, + return_ty_hir.span, + format!("boxed return of the sized type `{boxed_ty}`").as_str(), + |diagnostic| { + diagnostic.span_suggestion( + return_ty_hir.span, + "try", + boxed_ty.to_string(), + // the return value and function callers also needs to + // be changed, so this can't be MachineApplicable + Applicability::Unspecified, + ); + diagnostic.help("changing this also requires a change to the return expressions in this function"); + }, + ); + } + } +} + +impl LateLintPass<'_> for UnnecessaryBoxReturns { + fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { + let TraitItemKind::Fn(signature, _) = &item.kind else { return }; + self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name); + } + + fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) { + // Ignore implementations of traits, because the lint should be on the + // trait, not on the implmentation of it. + let Node::Item(parent) = cx.tcx.hir().get_parent(item.hir_id()) else { return }; + let ItemKind::Impl(parent) = parent.kind else { return }; + if parent.of_trait.is_some() { + return; + } + + let ImplItemKind::Fn(signature, ..) = &item.kind else { return }; + self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name); + } + + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + let ItemKind::Fn(signature, ..) = &item.kind else { return }; + self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name); + } +} diff --git a/clippy_lints/src/unnecessary_struct_initialization.rs b/clippy_lints/src/unnecessary_struct_initialization.rs index af0b4b1592f..084b031982d 100644 --- a/clippy_lints/src/unnecessary_struct_initialization.rs +++ b/clippy_lints/src/unnecessary_struct_initialization.rs @@ -9,7 +9,7 @@ declare_clippy_lint! { /// any field. /// /// ### Why is this bad? - /// Readibility suffers from unnecessary struct building. + /// Readability suffers from unnecessary struct building. /// /// ### Example /// ```rust @@ -25,9 +25,13 @@ declare_clippy_lint! { /// let a = S { s: String::from("Hello, world!") }; /// let b = a; /// ``` + /// + /// ### Known Problems + /// Has false positives when the base is a place expression that cannot be + /// moved out of, see [#10547](https://github.com/rust-lang/rust-clippy/issues/10547). #[clippy::version = "1.70.0"] pub UNNECESSARY_STRUCT_INITIALIZATION, - complexity, + nursery, "struct built from a base that can be written mode concisely" } declare_lint_pass!(UnnecessaryStruct => [UNNECESSARY_STRUCT_INITIALIZATION]); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 7dfb0956077..5a02987453c 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -10,8 +10,8 @@ use rustc_hir::{ def::{CtorOf, DefKind, Res}, def_id::LocalDefId, intravisit::{walk_inf, walk_ty, Visitor}, - Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, ImplItemKind, Item, - ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, + Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, + ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, }; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 8ba252425a3..896a01af37d 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -249,7 +249,7 @@ define_Conf! { /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] /// ``` (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet = <_>::default()), - /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX. + /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS. /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), @@ -275,13 +275,13 @@ define_Conf! { /// /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the - /// default configuration of Clippy. By default any configuration will replace the default value. + /// default configuration of Clippy. By default, any configuration will replace the default value. (disallowed_names: Vec = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()), /// Lint: DOC_MARKDOWN. /// /// The list of words this lint should not consider as identifiers needing ticks. The value /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the - /// default configuration of Clippy. By default any configuraction will replace the default value. For example: + /// default configuration of Clippy. By default, any configuration will replace the default value. For example: /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. /// @@ -390,7 +390,7 @@ define_Conf! { /// Enforce the named macros always use the braces specified. /// /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro - /// is could be used with a full path two `MacroMatcher`s have to be added one with the full path + /// could be used with a full path two `MacroMatcher`s have to be added one with the full path /// `crate_name::macro_name` and one with just the macro name. (standard_macro_braces: Vec = Vec::new()), /// Lint: MISSING_ENFORCED_IMPORT_RENAMES. @@ -408,7 +408,7 @@ define_Conf! { /// Lint: INDEX_REFUTABLE_SLICE. /// /// When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in - /// the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed. + /// the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. /// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. (max_suggested_slice_pattern_length: u64 = 3), /// Lint: AWAIT_HOLDING_INVALID_TYPE. @@ -459,6 +459,10 @@ define_Conf! { /// Whether to **only** check for missing documentation in items visible within the current /// crate. For example, `pub(crate)` items. (missing_docs_in_crate_items: bool = false), + /// Lint: LARGE_FUTURES. + /// + /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint + (future_size_threshold: u64 = 16 * 1024), } /// Search for the configuration file. @@ -466,7 +470,7 @@ define_Conf! { /// # Errors /// /// Returns any unexpected filesystem error encountered when searching for the config file -pub fn lookup_conf_file() -> io::Result> { +pub fn lookup_conf_file() -> io::Result<(Option, Vec)> { /// Possible filename to search for. const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"]; @@ -474,9 +478,11 @@ pub fn lookup_conf_file() -> io::Result> { // If neither of those exist, use ".". let mut current = env::var_os("CLIPPY_CONF_DIR") .or_else(|| env::var_os("CARGO_MANIFEST_DIR")) - .map_or_else(|| PathBuf::from("."), PathBuf::from); + .map_or_else(|| PathBuf::from("."), PathBuf::from) + .canonicalize()?; let mut found_config: Option = None; + let mut warnings = vec![]; loop { for config_file_name in &CONFIG_FILE_NAMES { @@ -487,12 +493,12 @@ pub fn lookup_conf_file() -> io::Result> { Ok(md) if md.is_dir() => {}, Ok(_) => { // warn if we happen to find two config files #8323 - if let Some(ref found_config_) = found_config { - eprintln!( - "Using config file `{}`\nWarning: `{}` will be ignored.", - found_config_.display(), - config_file.display(), - ); + if let Some(ref found_config) = found_config { + warnings.push(format!( + "using config file `{}`, `{}` will be ignored", + found_config.display(), + config_file.display() + )); } else { found_config = Some(config_file); } @@ -502,12 +508,12 @@ pub fn lookup_conf_file() -> io::Result> { } if found_config.is_some() { - return Ok(found_config); + return Ok((found_config, warnings)); } // If the current directory has no parent, we're done searching. if !current.pop() { - return Ok(None); + return Ok((None, warnings)); } } } diff --git a/clippy_lints/src/utils/format_args_collector.rs b/clippy_lints/src/utils/format_args_collector.rs index be56b842b98..09fcb82c37c 100644 --- a/clippy_lints/src/utils/format_args_collector.rs +++ b/clippy_lints/src/utils/format_args_collector.rs @@ -1,7 +1,12 @@ use clippy_utils::macros::collect_ast_format_args; -use rustc_ast::{Expr, ExprKind}; +use clippy_utils::source::snippet_opt; +use itertools::Itertools; +use rustc_ast::{Expr, ExprKind, FormatArgs}; +use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::hygiene; +use std::iter::once; declare_clippy_lint! { /// ### What it does @@ -15,9 +20,79 @@ declare_clippy_lint! { declare_lint_pass!(FormatArgsCollector => [FORMAT_ARGS_COLLECTOR]); impl EarlyLintPass for FormatArgsCollector { - fn check_expr(&mut self, _: &EarlyContext<'_>, expr: &Expr) { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::FormatArgs(args) = &expr.kind { + if has_span_from_proc_macro(cx, args) { + return; + } + collect_ast_format_args(expr.span, args); } } } + +/// Detects if the format string or an argument has its span set by a proc macro to something inside +/// a macro callsite, e.g. +/// +/// ```ignore +/// println!(some_proc_macro!("input {}"), a); +/// ``` +/// +/// Where `some_proc_macro` expands to +/// +/// ```ignore +/// println!("output {}", a); +/// ``` +/// +/// But with the span of `"output {}"` set to the macro input +/// +/// ```ignore +/// println!(some_proc_macro!("input {}"), a); +/// // ^^^^^^^^^^ +/// ``` +fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool { + let ctxt = args.span.ctxt(); + + // `format!("{} {} {c}", "one", "two", c = "three")` + // ^^^^^ ^^^^^ ^^^^^^^ + let argument_span = args + .arguments + .explicit_args() + .iter() + .map(|argument| hygiene::walk_chain(argument.expr.span, ctxt)); + + // `format!("{} {} {c}", "one", "two", c = "three")` + // ^^ ^^ ^^^^^^ + let between_spans = once(args.span) + .chain(argument_span) + .tuple_windows() + .map(|(start, end)| start.between(end)); + + for between_span in between_spans { + let mut seen_comma = false; + + let Some(snippet) = snippet_opt(cx, between_span) else { return true }; + for token in tokenize(&snippet) { + match token.kind { + TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {}, + TokenKind::Comma if !seen_comma => seen_comma = true, + // named arguments, `start_val, name = end_val` + // ^^^^^^^^^ between_span + TokenKind::Ident | TokenKind::Eq if seen_comma => {}, + // An unexpected token usually indicates that we crossed a macro boundary + // + // `println!(some_proc_macro!("input {}"), a)` + // ^^^ between_span + // `println!("{}", val!(x))` + // ^^^^^^^ between_span + _ => return true, + } + } + + if !seen_comma { + return true; + } + } + + false +} diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 8114a8463fa..d7c94b909bd 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -463,12 +463,18 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { && let Some(value_string) = snippet_opt(cx, arg.expr.span) { let (replacement, replace_raw) = match lit.kind { - LitKind::Str | LitKind::StrRaw(_) => extract_str_literal(&value_string), + LitKind::Str | LitKind::StrRaw(_) => match extract_str_literal(&value_string) { + Some(extracted) => extracted, + None => return, + }, LitKind::Char => ( match lit.symbol.as_str() { "\"" => "\\\"", "\\'" => "'", - _ => &value_string[1..value_string.len() - 1], + _ => match value_string.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) { + Some(stripped) => stripped, + None => return, + }, } .to_string(), false, @@ -533,13 +539,13 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) { /// `r#"a"#` -> (`a`, true) /// /// `"b"` -> (`b`, false) -fn extract_str_literal(literal: &str) -> (String, bool) { +fn extract_str_literal(literal: &str) -> Option<(String, bool)> { let (literal, raw) = match literal.strip_prefix('r') { Some(stripped) => (stripped.trim_matches('#'), true), None => (literal, false), }; - (literal[1..literal.len() - 1].to_string(), raw) + Some((literal.strip_prefix('"')?.strip_suffix('"')?.to_string(), raw)) } enum UnescapeErr { diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index c5b58b0c060..1f15598db36 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -286,8 +286,30 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { match (l, r) { (ExternCrate(l), ExternCrate(r)) => l == r, (Use(l), Use(r)) => eq_use_tree(l, r), - (Static(box ast::StaticItem { ty: lt, mutability: lm, expr: le}), Static(box ast::StaticItem { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), - (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re} )) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + ( + Static(box ast::StaticItem { + ty: lt, + mutability: lm, + expr: le, + }), + Static(box ast::StaticItem { + ty: rt, + mutability: rm, + expr: re, + }), + ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + ( + Const(box ast::ConstItem { + defaultness: ld, + ty: lt, + expr: le, + }), + Const(box ast::ConstItem { + defaultness: rd, + ty: rt, + expr: re, + }), + ) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, @@ -451,7 +473,18 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { use AssocItemKind::*; match (l, r) { - (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re})) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), + ( + Const(box ast::ConstItem { + defaultness: ld, + ty: lt, + expr: le, + }), + Const(box ast::ConstItem { + defaultness: rd, + ty: rt, + expr: re, + }), + ) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Fn(box ast::Fn { defaultness: ld, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9051cf51658..6b677df4641 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -32,7 +32,6 @@ extern crate rustc_lexer; extern crate rustc_lint; extern crate rustc_middle; extern crate rustc_mir_dataflow; -extern crate rustc_parse_format; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; @@ -77,7 +76,7 @@ use std::sync::OnceLock; use std::sync::{Mutex, MutexGuard}; use if_chain::if_chain; -use rustc_ast::ast::{self, LitKind}; +use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; @@ -95,6 +94,7 @@ use rustc_hir::{ use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; +use rustc_middle::mir::ConstantKind; use rustc_middle::ty as rustc_ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::binding::BindingMode; @@ -113,7 +113,8 @@ use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::Span; use rustc_target::abi::Integer; -use crate::consts::{constant, Constant}; +use crate::consts::{constant, miri_to_const, Constant}; +use crate::higher::Range; use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param}; use crate::visitors::for_each_expr; @@ -1490,6 +1491,68 @@ pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { } } +/// Checks whether the given `Expr` is a range equivalent to a `RangeFull`. +/// For the lower bound, this means that: +/// - either there is none +/// - or it is the smallest value that can be represented by the range's integer type +/// For the upper bound, this means that: +/// - either there is none +/// - or it is the largest value that can be represented by the range's integer type and is +/// inclusive +/// - or it is a call to some container's `len` method and is exclusive, and the range is passed to +/// a method call on that same container (e.g. `v.drain(..v.len())`) +/// If the given `Expr` is not some kind of range, the function returns `false`. +pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool { + let ty = cx.typeck_results().expr_ty(expr); + if let Some(Range { start, end, limits }) = Range::hir(expr) { + let start_is_none_or_min = start.map_or(true, |start| { + if let rustc_ty::Adt(_, subst) = ty.kind() + && let bnd_ty = subst.type_at(0) + && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) + && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree())) + && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty) + && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind) + && let Some((start_const, _)) = constant(cx, cx.typeck_results(), start) + { + start_const == min_const + } else { + false + } + }); + let end_is_none_or_max = end.map_or(true, |end| { + match limits { + RangeLimits::Closed => { + if let rustc_ty::Adt(_, subst) = ty.kind() + && let bnd_ty = subst.type_at(0) + && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) + && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree())) + && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty) + && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind) + && let Some((end_const, _)) = constant(cx, cx.typeck_results(), end) + { + end_const == max_const + } else { + false + } + }, + RangeLimits::HalfOpen => { + if let Some(container_path) = container_path + && let ExprKind::MethodCall(name, self_arg, [], _) = end.kind + && name.ident.name == sym::len + && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind + { + container_path.res == path.res + } else { + false + } + }, + } + }); + return start_is_none_or_min && end_is_none_or_max; + } + false +} + /// Checks whether the given expression is a constant integer of the given value. /// unlike `is_integer_literal`, this version does const folding pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool { @@ -2104,8 +2167,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); traits::impossible_predicates( cx.tcx, - traits::elaborate(cx.tcx, predicates) - .collect::>(), + traits::elaborate(cx.tcx, predicates).collect::>(), ) } diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index c0e32068eca..62d388a5ece 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -1,24 +1,16 @@ #![allow(clippy::similar_names)] // `expr` and `expn` -use crate::source::snippet_opt; use crate::visitors::{for_each_expr, Descend}; use arrayvec::ArrayVec; -use itertools::{izip, Either, Itertools}; -use rustc_ast::ast::LitKind; -use rustc_ast::FormatArgs; +use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::intravisit::{walk_expr, Visitor}; -use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, LangItem, Node, QPath, TyKind}; -use rustc_lexer::unescape::unescape_literal; -use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind}; +use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; use rustc_lint::LateContext; -use rustc_parse_format::{self as rpf, Alignment}; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; -use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Pos, Span, SpanData, Symbol}; +use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, Symbol}; use std::cell::RefCell; -use std::iter::{once, zip}; use std::ops::ControlFlow; use std::sync::atomic::{AtomicBool, Ordering}; @@ -226,11 +218,11 @@ pub enum PanicExpn<'a> { /// A single argument that implements `Display` - `panic!("{}", object)` Display(&'a Expr<'a>), /// Anything else - `panic!("error {}: {}", a, b)` - Format(FormatArgsExpn<'a>), + Format(&'a Expr<'a>), } impl<'a> PanicExpn<'a> { - pub fn parse(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option { + pub fn parse(expr: &'a Expr<'a>) -> Option { let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else { return None }; let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else { return None }; let result = match path.segments.last().unwrap().ident.as_str() { @@ -240,7 +232,7 @@ impl<'a> PanicExpn<'a> { let ExprKind::AddrOf(_, _, e) = &arg.kind else { return None }; Self::Display(e) }, - "panic_fmt" => Self::Format(FormatArgsExpn::parse(cx, arg)?), + "panic_fmt" => Self::Format(arg), // Since Rust 1.52, `assert_{eq,ne}` macros expand to use: // `core::panicking::assert_failed(.., left_val, right_val, None | Some(format_args!(..)));` "assert_failed" => { @@ -252,7 +244,7 @@ impl<'a> PanicExpn<'a> { // `msg_arg` is either `None` (no custom message) or `Some(format_args!(..))` (custom message) let msg_arg = &rest[2]; match msg_arg.kind { - ExprKind::Call(_, [fmt_arg]) => Self::Format(FormatArgsExpn::parse(cx, fmt_arg)?), + ExprKind::Call(_, [fmt_arg]) => Self::Format(fmt_arg), _ => Self::Empty, } }, @@ -304,7 +296,7 @@ fn find_assert_args_inner<'a, const N: usize>( let mut args = ArrayVec::new(); let panic_expn = for_each_expr(expr, |e| { if args.is_full() { - match PanicExpn::parse(cx, e) { + match PanicExpn::parse(e) { Some(expn) => ControlFlow::Break(expn), None => ControlFlow::Continue(Descend::Yes), } @@ -391,30 +383,82 @@ pub fn collect_ast_format_args(span: Span, format_args: &FormatArgs) { }); } -/// Calls `callback` with an AST [`FormatArgs`] node if one is found +/// Calls `callback` with an AST [`FormatArgs`] node if a `format_args` expansion is found as a +/// descendant of `expn_id` pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId, callback: impl FnOnce(&FormatArgs)) { let format_args_expr = for_each_expr(start, |expr| { let ctxt = expr.span.ctxt(); - if ctxt == start.span.ctxt() { - ControlFlow::Continue(Descend::Yes) - } else if ctxt.outer_expn().is_descendant_of(expn_id) - && macro_backtrace(expr.span) + if ctxt.outer_expn().is_descendant_of(expn_id) { + if macro_backtrace(expr.span) .map(|macro_call| cx.tcx.item_name(macro_call.def_id)) .any(|name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl)) - { - ControlFlow::Break(expr) + { + ControlFlow::Break(expr) + } else { + ControlFlow::Continue(Descend::Yes) + } } else { ControlFlow::Continue(Descend::No) } }); - if let Some(format_args_expr) = format_args_expr { + if let Some(expr) = format_args_expr { AST_FORMAT_ARGS.with(|ast_format_args| { - ast_format_args.borrow().get(&format_args_expr.span).map(callback); + ast_format_args.borrow().get(&expr.span).map(callback); }); } } +/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if +/// it cannot be found it will return the [`rustc_ast::Expr`]. +pub fn find_format_arg_expr<'hir, 'ast>( + start: &'hir Expr<'hir>, + target: &'ast FormatArgument, +) -> Result<&'hir rustc_hir::Expr<'hir>, &'ast rustc_ast::Expr> { + for_each_expr(start, |expr| { + if expr.span == target.expr.span { + ControlFlow::Break(expr) + } else { + ControlFlow::Continue(()) + } + }) + .ok_or(&target.expr) +} + +/// Span of the `:` and format specifiers +/// +/// ```ignore +/// format!("{:.}"), format!("{foo:.}") +/// ^^ ^^ +/// ``` +pub fn format_placeholder_format_span(placeholder: &FormatPlaceholder) -> Option { + let base = placeholder.span?.data(); + + // `base.hi` is `{...}|`, subtract 1 byte (the length of '}') so that it points before the closing + // brace `{...|}` + Some(Span::new( + placeholder.argument.span?.hi(), + base.hi - BytePos(1), + base.ctxt, + base.parent, + )) +} + +/// Span covering the format string and values +/// +/// ```ignore +/// format("{}.{}", 10, 11) +/// // ^^^^^^^^^^^^^^^ +/// ``` +pub fn format_args_inputs_span(format_args: &FormatArgs) -> Span { + match format_args.arguments.explicit_args() { + [] => format_args.span, + [.., last] => format_args + .span + .to(hygiene::walk_chain(last.expr.span, format_args.span.ctxt())), + } +} + /// Returns the [`Span`] of the value at `index` extended to the previous comma, e.g. for the value /// `10` /// @@ -436,251 +480,6 @@ pub fn format_arg_removal_span(format_args: &FormatArgs, index: usize) -> Option Some(current.with_lo(prev.hi())) } -/// The format string doesn't exist in the HIR, so we reassemble it from source code -#[derive(Debug)] -pub struct FormatString { - /// Span of the whole format string literal, including `[r#]"`. - pub span: Span, - /// Snippet of the whole format string literal, including `[r#]"`. - pub snippet: String, - /// If the string is raw `r"..."`/`r#""#`, how many `#`s does it have on each side. - pub style: Option, - /// The unescaped value of the format string, e.g. `"val – {}"` for the literal - /// `"val \u{2013} {}"`. - pub unescaped: String, - /// The format string split by format args like `{..}`. - pub parts: Vec, -} - -impl FormatString { - fn new(cx: &LateContext<'_>, pieces: &Expr<'_>) -> Option { - // format_args!(r"a {} b \", 1); - // - // expands to - // - // ::core::fmt::Arguments::new_v1(&["a ", " b \\"], - // &[::core::fmt::ArgumentV1::new_display(&1)]); - // - // where `pieces` is the expression `&["a ", " b \\"]`. It has the span of `r"a {} b \"` - let span = pieces.span; - let snippet = snippet_opt(cx, span)?; - - let (inner, style) = match tokenize(&snippet).next()?.kind { - TokenKind::Literal { kind, .. } => { - let style = match kind { - LiteralKind::Str { .. } => None, - LiteralKind::RawStr { n_hashes: Some(n), .. } => Some(n.into()), - _ => return None, - }; - - let start = style.map_or(1, |n| 2 + n); - let end = snippet.len() - style.map_or(1, |n| 1 + n); - - (&snippet[start..end], style) - }, - _ => return None, - }; - - let mode = if style.is_some() { - unescape::Mode::RawStr - } else { - unescape::Mode::Str - }; - - let mut unescaped = String::with_capacity(inner.len()); - // Sometimes the original string comes from a macro which accepts a malformed string, such as in a - // #[display(""somestring)] attribute (accepted by the `displaythis` crate). Reconstructing the - // string from the span will not be possible, so we will just return None here. - let mut unparsable = false; - unescape_literal(inner, mode, &mut |_, ch| match ch { - Ok(ch) => unescaped.push(ch), - Err(e) if !e.is_fatal() => (), - Err(_) => unparsable = true, - }); - if unparsable { - return None; - } - - let mut parts = Vec::new(); - let _: Option = for_each_expr(pieces, |expr| { - if let ExprKind::Lit(lit) = &expr.kind - && let LitKind::Str(symbol, _) = lit.node - { - parts.push(symbol); - } - ControlFlow::Continue(()) - }); - - Some(Self { - span, - snippet, - style, - unescaped, - parts, - }) - } -} - -struct FormatArgsValues<'tcx> { - /// Values passed after the format string and implicit captures. `[1, z + 2, x]` for - /// `format!("{x} {} {}", 1, z + 2)`. - value_args: Vec<&'tcx Expr<'tcx>>, - /// Maps an `rt::v1::Argument::position` or an `rt::v1::Count::Param` to its index in - /// `value_args` - pos_to_value_index: Vec, - /// Used to check if a value is declared inline & to resolve `InnerSpan`s. - format_string_span: SpanData, -} - -impl<'tcx> FormatArgsValues<'tcx> { - fn new_empty(format_string_span: SpanData) -> Self { - Self { - value_args: Vec::new(), - pos_to_value_index: Vec::new(), - format_string_span, - } - } - - fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self { - let mut pos_to_value_index = Vec::new(); - let mut value_args = Vec::new(); - let _: Option = for_each_expr(args, |expr| { - if expr.span.ctxt() == args.span.ctxt() { - // ArgumentV1::new_() - // ArgumentV1::from_usize() - if let ExprKind::Call(callee, [val]) = expr.kind - && let ExprKind::Path(QPath::TypeRelative(ty, _)) = callee.kind - && let TyKind::Path(QPath::LangItem(LangItem::FormatArgument, _, _)) = ty.kind - { - let val_idx = if val.span.ctxt() == expr.span.ctxt() - && let ExprKind::Field(_, field) = val.kind - && let Ok(idx) = field.name.as_str().parse() - { - // tuple index - idx - } else { - // assume the value expression is passed directly - pos_to_value_index.len() - }; - - pos_to_value_index.push(val_idx); - } - ControlFlow::Continue(Descend::Yes) - } else { - // assume that any expr with a differing span is a value - value_args.push(expr); - ControlFlow::Continue(Descend::No) - } - }); - - Self { - value_args, - pos_to_value_index, - format_string_span, - } - } -} - -/// The positions of a format argument's value, precision and width -/// -/// A position is an index into the second argument of `Arguments::new_v1[_formatted]` -#[derive(Debug, Default, Copy, Clone)] -struct ParamPosition { - /// The position stored in `rt::v1::Argument::position`. - value: usize, - /// The position stored in `rt::v1::FormatSpec::width` if it is a `Count::Param`. - width: Option, - /// The position stored in `rt::v1::FormatSpec::precision` if it is a `Count::Param`. - precision: Option, -} - -impl<'tcx> Visitor<'tcx> for ParamPosition { - fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) { - match field.ident.name { - sym::position => { - if let ExprKind::Lit(lit) = &field.expr.kind - && let LitKind::Int(pos, _) = lit.node - { - self.value = pos as usize; - } - }, - sym::precision => { - self.precision = parse_count(field.expr); - }, - sym::width => { - self.width = parse_count(field.expr); - }, - _ => walk_expr(self, field.expr), - } - } -} - -fn parse_count(expr: &Expr<'_>) -> Option { - // <::core::fmt::rt::v1::Count>::Param(1usize), - if let ExprKind::Call(ctor, [val]) = expr.kind - && let ExprKind::Path(QPath::TypeRelative(_, path)) = ctor.kind - && path.ident.name == sym::Param - && let ExprKind::Lit(lit) = &val.kind - && let LitKind::Int(pos, _) = lit.node - { - Some(pos as usize) - } else { - None - } -} - -/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)` -fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option + 'tcx> { - if let ExprKind::AddrOf(.., array) = fmt_arg.kind - && let ExprKind::Array(specs) = array.kind - { - Some(specs.iter().map(|spec| { - if let ExprKind::Call(f, args) = spec.kind - && let ExprKind::Path(QPath::TypeRelative(ty, f)) = f.kind - && let TyKind::Path(QPath::LangItem(LangItem::FormatPlaceholder, _, _)) = ty.kind - && f.ident.name == sym::new - && let [position, _fill, _align, _flags, precision, width] = args - && let ExprKind::Lit(position) = &position.kind - && let LitKind::Int(position, _) = position.node { - ParamPosition { - value: position as usize, - width: parse_count(width), - precision: parse_count(precision), - } - } else { - ParamPosition::default() - } - })) - } else { - None - } -} - -/// `Span::from_inner`, but for `rustc_parse_format`'s `InnerSpan` -fn span_from_inner(base: SpanData, inner: rpf::InnerSpan) -> Span { - Span::new( - base.lo + BytePos::from_usize(inner.start), - base.lo + BytePos::from_usize(inner.end), - base.ctxt, - base.parent, - ) -} - -/// How a format parameter is used in the format string -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum FormatParamKind { - /// An implicit parameter , such as `{}` or `{:?}`. - Implicit, - /// A parameter with an explicit number, e.g. `{1}`, `{0:?}`, or `{:.0$}` - Numbered, - /// A parameter with an asterisk precision. e.g. `{:.*}`. - Starred, - /// A named parameter with a named `value_arg`, such as the `x` in `format!("{x}", x = 1)`. - Named(Symbol), - /// An implicit named parameter, such as the `y` in `format!("{y}")`. - NamedInline(Symbol), -} - /// Where a format parameter is being used in the format string #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum FormatParamUsage { @@ -692,467 +491,6 @@ pub enum FormatParamUsage { Precision, } -/// A `FormatParam` is any place in a `FormatArgument` that refers to a supplied value, e.g. -/// -/// ``` -/// let precision = 2; -/// format!("{:.precision$}", 0.1234); -/// ``` -/// -/// has two `FormatParam`s, a [`FormatParamKind::Implicit`] `.kind` with a `.value` of `0.1234` -/// and a [`FormatParamKind::NamedInline("precision")`] `.kind` with a `.value` of `2` -#[derive(Debug, Copy, Clone)] -pub struct FormatParam<'tcx> { - /// The expression this parameter refers to. - pub value: &'tcx Expr<'tcx>, - /// How this parameter refers to its `value`. - pub kind: FormatParamKind, - /// Where this format param is being used - argument/width/precision - pub usage: FormatParamUsage, - /// Span of the parameter, may be zero width. Includes the whitespace of implicit parameters. - /// - /// ```text - /// format!("{}, { }, {0}, {name}", ...); - /// ^ ~~ ~ ~~~~ - /// ``` - pub span: Span, -} - -impl<'tcx> FormatParam<'tcx> { - fn new( - mut kind: FormatParamKind, - usage: FormatParamUsage, - position: usize, - inner: rpf::InnerSpan, - values: &FormatArgsValues<'tcx>, - ) -> Option { - let value_index = *values.pos_to_value_index.get(position)?; - let value = *values.value_args.get(value_index)?; - let span = span_from_inner(values.format_string_span, inner); - - // if a param is declared inline, e.g. `format!("{x}")`, the generated expr's span points - // into the format string - if let FormatParamKind::Named(name) = kind && values.format_string_span.contains(value.span.data()) { - kind = FormatParamKind::NamedInline(name); - } - - Some(Self { - value, - kind, - usage, - span, - }) - } -} - -/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and -/// [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers. -#[derive(Debug, Copy, Clone)] -pub enum Count<'tcx> { - /// Specified with a literal number, stores the value. - Is(usize, Span), - /// Specified using `$` and `*` syntaxes. The `*` format is still considered to be - /// `FormatParamKind::Numbered`. - Param(FormatParam<'tcx>), - /// Not specified. - Implied(Option), -} - -impl<'tcx> Count<'tcx> { - fn new( - usage: FormatParamUsage, - count: rpf::Count<'_>, - position: Option, - inner: Option, - values: &FormatArgsValues<'tcx>, - ) -> Option { - let span = inner.map(|inner| span_from_inner(values.format_string_span, inner)); - - Some(match count { - rpf::Count::CountIs(val) => Self::Is(val, span?), - rpf::Count::CountIsName(name, _) => Self::Param(FormatParam::new( - FormatParamKind::Named(Symbol::intern(name)), - usage, - position?, - inner?, - values, - )?), - rpf::Count::CountIsParam(_) => Self::Param(FormatParam::new( - FormatParamKind::Numbered, - usage, - position?, - inner?, - values, - )?), - rpf::Count::CountIsStar(_) => Self::Param(FormatParam::new( - FormatParamKind::Starred, - usage, - position?, - inner?, - values, - )?), - rpf::Count::CountImplied => Self::Implied(span), - }) - } - - pub fn is_implied(self) -> bool { - matches!(self, Count::Implied(_)) - } - - pub fn param(self) -> Option> { - match self { - Count::Param(param) => Some(param), - _ => None, - } - } - - pub fn span(self) -> Option { - match self { - Count::Is(_, span) => Some(span), - Count::Param(param) => Some(param.span), - Count::Implied(span) => span, - } - } -} - -/// Specification for the formatting of an argument in the format string. See -/// for the precise meanings. -#[derive(Debug)] -pub struct FormatSpec<'tcx> { - /// Optionally specified character to fill alignment with. - pub fill: Option, - /// Optionally specified alignment. - pub align: Alignment, - /// Whether all flag options are set to default (no flags specified). - pub no_flags: bool, - /// Represents either the maximum width or the integer precision. - pub precision: Count<'tcx>, - /// The minimum width, will be padded according to `width`/`align` - pub width: Count<'tcx>, - /// The formatting trait used by the argument, e.g. `sym::Display` for `{}`, `sym::Debug` for - /// `{:?}`. - pub r#trait: Symbol, - pub trait_span: Option, -} - -impl<'tcx> FormatSpec<'tcx> { - fn new(spec: rpf::FormatSpec<'_>, positions: ParamPosition, values: &FormatArgsValues<'tcx>) -> Option { - Some(Self { - fill: spec.fill, - align: spec.align, - no_flags: spec.sign.is_none() && !spec.alternate && !spec.zero_pad && spec.debug_hex.is_none(), - precision: Count::new( - FormatParamUsage::Precision, - spec.precision, - positions.precision, - spec.precision_span, - values, - )?, - width: Count::new( - FormatParamUsage::Width, - spec.width, - positions.width, - spec.width_span, - values, - )?, - r#trait: match spec.ty { - "" => sym::Display, - "?" => sym::Debug, - "o" => sym!(Octal), - "x" => sym!(LowerHex), - "X" => sym!(UpperHex), - "p" => sym::Pointer, - "b" => sym!(Binary), - "e" => sym!(LowerExp), - "E" => sym!(UpperExp), - _ => return None, - }, - trait_span: spec - .ty_span - .map(|span| span_from_inner(values.format_string_span, span)), - }) - } - - /// Returns true if this format spec is unchanged from the default. e.g. returns true for `{}`, - /// `{foo}` and `{2}`, but false for `{:?}`, `{foo:5}` and `{3:.5}` - pub fn is_default(&self) -> bool { - self.r#trait == sym::Display && self.is_default_for_trait() - } - - /// Has no other formatting specifiers than setting the format trait. returns true for `{}`, - /// `{foo}`, `{:?}`, but false for `{foo:5}`, `{3:.5?}` - pub fn is_default_for_trait(&self) -> bool { - self.width.is_implied() && self.precision.is_implied() && self.align == Alignment::AlignUnknown && self.no_flags - } -} - -/// A format argument, such as `{}`, `{foo:?}`. -#[derive(Debug)] -pub struct FormatArg<'tcx> { - /// The parameter the argument refers to. - pub param: FormatParam<'tcx>, - /// How to format `param`. - pub format: FormatSpec<'tcx>, - /// span of the whole argument, `{..}`. - pub span: Span, -} - -impl<'tcx> FormatArg<'tcx> { - /// Span of the `:` and format specifiers - /// - /// ```ignore - /// format!("{:.}"), format!("{foo:.}") - /// ^^ ^^ - /// ``` - pub fn format_span(&self) -> Span { - let base = self.span.data(); - - // `base.hi` is `{...}|`, subtract 1 byte (the length of '}') so that it points before the closing - // brace `{...|}` - Span::new(self.param.span.hi(), base.hi - BytePos(1), base.ctxt, base.parent) - } -} - -/// A parsed `format_args!` expansion. -#[derive(Debug)] -pub struct FormatArgsExpn<'tcx> { - /// The format string literal. - pub format_string: FormatString, - /// The format arguments, such as `{:?}`. - pub args: Vec>, - /// Has an added newline due to `println!()`/`writeln!()`/etc. The last format string part will - /// include this added newline. - pub newline: bool, - /// Spans of the commas between the format string and explicit values, excluding any trailing - /// comma - /// - /// ```ignore - /// format!("..", 1, 2, 3,) - /// // ^ ^ ^ - /// ``` - comma_spans: Vec, - /// Explicit values passed after the format string, ignoring implicit captures. `[1, z + 2]` for - /// `format!("{x} {} {y}", 1, z + 2)`. - explicit_values: Vec<&'tcx Expr<'tcx>>, -} - -impl<'tcx> FormatArgsExpn<'tcx> { - /// Gets the spans of the commas inbetween the format string and explicit args, not including - /// any trailing comma - /// - /// ```ignore - /// format!("{} {}", a, b) - /// // ^ ^ - /// ``` - /// - /// Ensures that the format string and values aren't coming from a proc macro that sets the - /// output span to that of its input - fn comma_spans(cx: &LateContext<'_>, explicit_values: &[&Expr<'_>], fmt_span: Span) -> Option> { - // `format!("{} {} {c}", "one", "two", c = "three")` - // ^^^^^ ^^^^^ ^^^^^^^ - let value_spans = explicit_values - .iter() - .map(|val| hygiene::walk_chain(val.span, fmt_span.ctxt())); - - // `format!("{} {} {c}", "one", "two", c = "three")` - // ^^ ^^ ^^^^^^ - let between_spans = once(fmt_span) - .chain(value_spans) - .tuple_windows() - .map(|(start, end)| start.between(end)); - - let mut comma_spans = Vec::new(); - for between_span in between_spans { - let mut offset = 0; - let mut seen_comma = false; - - for token in tokenize(&snippet_opt(cx, between_span)?) { - match token.kind { - TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {}, - TokenKind::Comma if !seen_comma => { - seen_comma = true; - - let base = between_span.data(); - comma_spans.push(Span::new( - base.lo + BytePos(offset), - base.lo + BytePos(offset + 1), - base.ctxt, - base.parent, - )); - }, - // named arguments, `start_val, name = end_val` - // ^^^^^^^^^ between_span - TokenKind::Ident | TokenKind::Eq if seen_comma => {}, - // An unexpected token usually indicates the format string or a value came from a proc macro output - // that sets the span of its output to an input, e.g. `println!(some_proc_macro!("input"), ..)` that - // emits a string literal with the span set to that of `"input"` - _ => return None, - } - offset += token.len; - } - - if !seen_comma { - return None; - } - } - - Some(comma_spans) - } - - pub fn parse(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option { - let macro_name = macro_backtrace(expr.span) - .map(|macro_call| cx.tcx.item_name(macro_call.def_id)) - .find(|&name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))?; - let newline = macro_name == sym::format_args_nl; - - // ::core::fmt::Arguments::new_const(pieces) - // ::core::fmt::Arguments::new_v1(pieces, args) - // ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg) - if let ExprKind::Call(callee, [pieces, rest @ ..]) = expr.kind - && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind - && let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind - && matches!(seg.ident.as_str(), "new_const" | "new_v1" | "new_v1_formatted") - { - let format_string = FormatString::new(cx, pieces)?; - - let mut parser = rpf::Parser::new( - &format_string.unescaped, - format_string.style, - Some(format_string.snippet.clone()), - // `format_string.unescaped` does not contain the appended newline - false, - rpf::ParseMode::Format, - ); - - let parsed_args = parser - .by_ref() - .filter_map(|piece| match piece { - rpf::Piece::NextArgument(a) => Some(a), - rpf::Piece::String(_) => None, - }) - .collect_vec(); - if !parser.errors.is_empty() { - return None; - } - - let positions = if let Some(fmt_arg) = rest.get(1) { - // If the argument contains format specs, `new_v1_formatted(_, _, fmt, _)`, parse - // them. - - Either::Left(parse_rt_fmt(fmt_arg)?) - } else { - // If no format specs are given, the positions are in the given order and there are - // no `precision`/`width`s to consider. - - Either::Right((0..).map(|n| ParamPosition { - value: n, - width: None, - precision: None, - })) - }; - - let values = if let Some(args) = rest.first() { - FormatArgsValues::new(args, format_string.span.data()) - } else { - FormatArgsValues::new_empty(format_string.span.data()) - }; - - let args = izip!(positions, parsed_args, parser.arg_places) - .map(|(position, parsed_arg, arg_span)| { - Some(FormatArg { - param: FormatParam::new( - match parsed_arg.position { - rpf::Position::ArgumentImplicitlyIs(_) => FormatParamKind::Implicit, - rpf::Position::ArgumentIs(_) => FormatParamKind::Numbered, - // NamedInline is handled by `FormatParam::new()` - rpf::Position::ArgumentNamed(name) => FormatParamKind::Named(Symbol::intern(name)), - }, - FormatParamUsage::Argument, - position.value, - parsed_arg.position_span, - &values, - )?, - format: FormatSpec::new(parsed_arg.format, position, &values)?, - span: span_from_inner(values.format_string_span, arg_span), - }) - }) - .collect::>>()?; - - let mut explicit_values = values.value_args; - // remove values generated for implicitly captured vars - let len = explicit_values - .iter() - .take_while(|val| !format_string.span.contains(val.span)) - .count(); - explicit_values.truncate(len); - - let comma_spans = Self::comma_spans(cx, &explicit_values, format_string.span)?; - - Some(Self { - format_string, - args, - newline, - comma_spans, - explicit_values, - }) - } else { - None - } - } - - pub fn find_nested(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expn_id: ExpnId) -> Option { - for_each_expr(expr, |e| { - let e_ctxt = e.span.ctxt(); - if e_ctxt == expr.span.ctxt() { - ControlFlow::Continue(Descend::Yes) - } else if e_ctxt.outer_expn().is_descendant_of(expn_id) { - if let Some(args) = FormatArgsExpn::parse(cx, e) { - ControlFlow::Break(args) - } else { - ControlFlow::Continue(Descend::No) - } - } else { - ControlFlow::Continue(Descend::No) - } - }) - } - - /// Source callsite span of all inputs - pub fn inputs_span(&self) -> Span { - match *self.explicit_values { - [] => self.format_string.span, - [.., last] => self - .format_string - .span - .to(hygiene::walk_chain(last.span, self.format_string.span.ctxt())), - } - } - - /// Get the span of a value expanded to the previous comma, e.g. for the value `10` - /// - /// ```ignore - /// format("{}.{}", 10, 11) - /// // ^^^^ - /// ``` - pub fn value_with_prev_comma_span(&self, value_id: HirId) -> Option { - for (comma_span, value) in zip(&self.comma_spans, &self.explicit_values) { - if value.hir_id == value_id { - return Some(comma_span.to(hygiene::walk_chain(value.span, comma_span.ctxt()))); - } - } - - None - } - - /// Iterator of all format params, both values and those referenced by `width`/`precision`s. - pub fn params(&'tcx self) -> impl Iterator> { - self.args - .iter() - .flat_map(|arg| [Some(arg.param), arg.format.precision.param(), arg.format.width.param()]) - .flatten() - } -} - /// A node with a `HirId` and a `Span` pub trait HirNode { fn hir_id(&self) -> HirId; diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index c919575bfe9..9be2d0eae80 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -23,6 +23,7 @@ pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"]; pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"]; pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"]; pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"]; +pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"]; pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"]; @@ -113,6 +114,7 @@ pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"]; pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"]; pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"]; +pub const STD_IO_LINES: [&str; 3] = ["std", "io", "Lines"]; pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"]; pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"]; pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"]; diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 0b47234647f..9449f0b5567 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -541,9 +541,25 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { cx.tcx .check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty))) - // For types containing generic parameters we cannot get a layout to check. - // Therefore, we are conservative and assume that they don't allow uninit. - .unwrap_or(false) + .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty)) +} + +/// A fallback for polymorphic types, which are not supported by `check_validity_requirement`. +fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + match *ty.kind() { + // The array length may be polymorphic, let's try the inner type. + ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, component), + // Peek through tuples and try their fallbacks. + 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(), + // For the rest, conservatively assume that they cannot be uninit. + _ => false, + } } /// Gets an iterator over all predicates which apply to the given item. diff --git a/etc/relicense/RELICENSE_DOCUMENTATION.md b/etc/relicense/RELICENSE_DOCUMENTATION.md index fcd7abbf3f1..ffb99cde4f8 100644 --- a/etc/relicense/RELICENSE_DOCUMENTATION.md +++ b/etc/relicense/RELICENSE_DOCUMENTATION.md @@ -35,7 +35,7 @@ relicensing are archived on GitHub. We also have saved Wayback Machine copies of The usernames of commenters on these issues can be found in relicense_comments.txt -There are a couple people in relicense_comments.txt who are not found in contributors.txt: +There are a few people in relicense_comments.txt who are not found in contributors.txt: - @EpocSquadron has [made minor text contributions to the README](https://github.com/rust-lang/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and @@ -55,7 +55,7 @@ There are a couple people in relicense_comments.txt who are not found in contrib we rewrote (see below) -Two of these contributors had nonminor contributions (#2184, #427) requiring a rewrite, carried out in #3251 +Two of these contributors had non-minor contributions (#2184, #427) requiring a rewrite, carried out in #3251 ([archive](http://web.archive.org/web/20181005192411/https://github.com/rust-lang-nursery/rust-clippy/pull/3251), [screenshot](https://user-images.githubusercontent.com/1617736/46573515-5cb69580-c94b-11e8-86e5-b456452121b2.png)) diff --git a/lintcheck/README.md b/lintcheck/README.md index e997eb47e32..faf3ce9093a 100644 --- a/lintcheck/README.md +++ b/lintcheck/README.md @@ -16,7 +16,7 @@ or cargo lintcheck ``` -By default the logs will be saved into +By default, the logs will be saved into `lintcheck-logs/lintcheck_crates_logs.txt`. You can set a custom sources.toml by adding `--crates-toml custom.toml` or using diff --git a/rust-toolchain b/rust-toolchain index 0b2458ea007..91e8ccea1f4 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-03-24" +channel = "nightly-2023-04-06" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/driver.rs b/src/driver.rs index 9e0822404b6..718bc41fb99 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -130,7 +130,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { #[allow(rustc::bad_opt_access)] fn config(&mut self, config: &mut interface::Config) { let conf_path = clippy_lints::lookup_conf_file(); - let conf_path_string = if let Ok(Some(path)) = &conf_path { + let conf_path_string = if let Ok((Some(path), _)) = &conf_path { path.to_str().map(String::from) } else { None diff --git a/tests/ui-cargo/multiple_config_files/warn/src/main.stderr b/tests/ui-cargo/multiple_config_files/warn/src/main.stderr index 98697e001f9..aa1b3c638a0 100644 --- a/tests/ui-cargo/multiple_config_files/warn/src/main.stderr +++ b/tests/ui-cargo/multiple_config_files/warn/src/main.stderr @@ -1,2 +1,4 @@ -Using config file `$SRC_DIR/.clippy.toml` -Warning: `$SRC_DIR/clippy.toml` will be ignored. +warning: using config file `$SRC_DIR/.clippy.toml`, `$SRC_DIR/clippy.toml` will be ignored + +warning: 1 warning emitted + diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr index ee941762196..1be0cda12fc 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr @@ -11,29 +11,29 @@ LL - println!("val='{}'", local_i32); LL + println!("val='{local_i32}'"); | -error: literal with an empty format string - --> $DIR/uninlined_format_args.rs:10:35 +error: variables can be used directly in the `format!` string + --> $DIR/uninlined_format_args.rs:10:5 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); - | ^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D clippy::print-literal` implied by `-D warnings` -help: try this +help: change this to | LL - println!("Hello {} is {:.*}", "x", local_i32, local_f64); -LL + println!("Hello x is {:.*}", local_i32, local_f64); +LL + println!("Hello {} is {local_f64:.local_i32$}", "x"); | -error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:10:5 +error: literal with an empty format string + --> $DIR/uninlined_format_args.rs:10:35 | LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ | -help: change this to + = note: `-D clippy::print-literal` implied by `-D warnings` +help: try this | LL - println!("Hello {} is {:.*}", "x", local_i32, local_f64); -LL + println!("Hello {} is {local_f64:.local_i32$}", "x"); +LL + println!("Hello x is {:.*}", local_i32, local_f64); | error: variables can be used directly in the `format!` string diff --git a/tests/ui-toml/extra_unused_type_parameters/clippy.toml b/tests/ui-toml/extra_unused_type_parameters/clippy.toml new file mode 100644 index 00000000000..5f304987aa9 --- /dev/null +++ b/tests/ui-toml/extra_unused_type_parameters/clippy.toml @@ -0,0 +1 @@ +avoid-breaking-exported-api = true diff --git a/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs b/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs new file mode 100644 index 00000000000..5655232455c --- /dev/null +++ b/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs @@ -0,0 +1,9 @@ +pub struct S; + +impl S { + pub fn exported_fn() { + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui-toml/large_futures/clippy.toml b/tests/ui-toml/large_futures/clippy.toml new file mode 100644 index 00000000000..61bb17fdf6b --- /dev/null +++ b/tests/ui-toml/large_futures/clippy.toml @@ -0,0 +1 @@ +future-size-threshold = 1024 diff --git a/tests/ui-toml/large_futures/large_futures.rs b/tests/ui-toml/large_futures/large_futures.rs new file mode 100644 index 00000000000..4158df8b5ff --- /dev/null +++ b/tests/ui-toml/large_futures/large_futures.rs @@ -0,0 +1,27 @@ +#![warn(clippy::large_futures)] + +fn main() {} + +pub async fn should_warn() { + let x = [0u8; 1024]; + async {}.await; + dbg!(x); +} + +pub async fn should_not_warn() { + let x = [0u8; 1020]; + async {}.await; + dbg!(x); +} + +pub async fn bar() { + should_warn().await; + + async { + let x = [0u8; 1024]; + dbg!(x); + } + .await; + + should_not_warn().await; +} diff --git a/tests/ui-toml/large_futures/large_futures.stderr b/tests/ui-toml/large_futures/large_futures.stderr new file mode 100644 index 00000000000..b92734de2f0 --- /dev/null +++ b/tests/ui-toml/large_futures/large_futures.stderr @@ -0,0 +1,10 @@ +error: large future with a size of 1026 bytes + --> $DIR/large_futures.rs:18:5 + | +LL | should_warn().await; + | ^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(should_warn())` + | + = note: `-D clippy::large-futures` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 6a246afac76..8447c31722d 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -24,6 +24,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie enforced-import-renames enum-variant-name-threshold enum-variant-size-threshold + future-size-threshold ignore-interior-mutability large-error-threshold literal-representation-threshold diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index ee7d2ba444b..3c06676d722 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -425,4 +425,8 @@ pub fn integer_arithmetic() { i ^= i; } +pub fn issue_10583(a: u16) -> u16 { + 10 / a +} + fn main() {} diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index 3895f08964c..2c8ee2884e7 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -576,6 +576,12 @@ error: arithmetic operation that can potentially result in unexpected side-effec LL | i * 2; | ^^^^^ +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:394:5 + | +LL | 1 % i / 2; + | ^^^^^ + error: arithmetic operation that can potentially result in unexpected side-effects --> $DIR/arithmetic_side_effects.rs:395:5 | @@ -642,5 +648,11 @@ error: arithmetic operation that can potentially result in unexpected side-effec LL | i %= var2; | ^^^^^^^^^ -error: aborting due to 107 previous errors +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:429:5 + | +LL | 10 / a + | ^^^^^^ + +error: aborting due to 109 previous errors diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 325be83a0d7..3d5beab1eff 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -63,7 +63,7 @@ fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Gro /// Token used to escape the following token from the macro's span rules. const ESCAPE_CHAR: char = '$'; -/// Takes a single token followed by a sequence tokens. Returns the sequence of tokens with their +/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their /// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`. #[proc_macro] pub fn with_span(input: TokenStream) -> TokenStream { diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 8b2673c2a7f..a86b85706a3 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -29,6 +29,12 @@ fn main() { 1f64 as isize; 1f64 as usize; 1f32 as u32 as u16; + { + let _x: i8 = 1i32 as _; + 1f32 as i32; + 1f64 as i32; + 1f32 as u8; + } // Test clippy::cast_possible_wrap 1u8 as i8; 1u16 as i16; diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 451078de23b..65ecf1aa37a 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -44,10 +44,6 @@ LL | 1f32 as i32; | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` -help: ... or use `try_from` and handle the error accordingly - | -LL | i32::try_from(1f32); - | ~~~~~~~~~~~~~~~~~~~ error: casting `f32` to `u32` may truncate the value --> $DIR/cast.rs:25:5 @@ -56,10 +52,6 @@ LL | 1f32 as u32; | ^^^^^^^^^^^ | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... -help: ... or use `try_from` and handle the error accordingly - | -LL | u32::try_from(1f32); - | ~~~~~~~~~~~~~~~~~~~ error: casting `f32` to `u32` may lose the sign of the value --> $DIR/cast.rs:25:5 @@ -76,10 +68,6 @@ LL | 1f64 as f32; | ^^^^^^^^^^^ | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... -help: ... or use `try_from` and handle the error accordingly - | -LL | f32::try_from(1f64); - | ~~~~~~~~~~~~~~~~~~~ error: casting `i32` to `i8` may truncate the value --> $DIR/cast.rs:27:5 @@ -112,10 +100,6 @@ LL | 1f64 as isize; | ^^^^^^^^^^^^^ | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... -help: ... or use `try_from` and handle the error accordingly - | -LL | isize::try_from(1f64); - | ~~~~~~~~~~~~~~~~~~~~~ error: casting `f64` to `usize` may truncate the value --> $DIR/cast.rs:30:5 @@ -124,10 +108,6 @@ LL | 1f64 as usize; | ^^^^^^^^^^^^^ | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... -help: ... or use `try_from` and handle the error accordingly - | -LL | usize::try_from(1f64); - | ~~~~~~~~~~~~~~~~~~~~~ error: casting `f64` to `usize` may lose the sign of the value --> $DIR/cast.rs:30:5 @@ -154,10 +134,6 @@ LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... -help: ... or use `try_from` and handle the error accordingly - | -LL | u32::try_from(1f32) as u16; - | ~~~~~~~~~~~~~~~~~~~ error: casting `f32` to `u32` may lose the sign of the value --> $DIR/cast.rs:31:5 @@ -165,8 +141,50 @@ error: casting `f32` to `u32` may lose the sign of the value LL | 1f32 as u32 as u16; | ^^^^^^^^^^^ +error: casting `i32` to `i8` may truncate the value + --> $DIR/cast.rs:33:22 + | +LL | let _x: i8 = 1i32 as _; + | ^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | let _x: i8 = 1i32.try_into(); + | ~~~~~~~~~~~~~~~ + +error: casting `f32` to `i32` may truncate the value + --> $DIR/cast.rs:34:9 + | +LL | 1f32 as i32; + | ^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... + +error: casting `f64` to `i32` may truncate the value + --> $DIR/cast.rs:35:9 + | +LL | 1f64 as i32; + | ^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... + +error: casting `f32` to `u8` may truncate the value + --> $DIR/cast.rs:36:9 + | +LL | 1f32 as u8; + | ^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... + +error: casting `f32` to `u8` may lose the sign of the value + --> $DIR/cast.rs:36:9 + | +LL | 1f32 as u8; + | ^^^^^^^^^^ + error: casting `u8` to `i8` may wrap around the value - --> $DIR/cast.rs:33:5 + --> $DIR/cast.rs:39:5 | LL | 1u8 as i8; | ^^^^^^^^^ @@ -174,43 +192,43 @@ LL | 1u8 as i8; = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting `u16` to `i16` may wrap around the value - --> $DIR/cast.rs:34:5 + --> $DIR/cast.rs:40:5 | LL | 1u16 as i16; | ^^^^^^^^^^^ error: casting `u32` to `i32` may wrap around the value - --> $DIR/cast.rs:35:5 + --> $DIR/cast.rs:41:5 | LL | 1u32 as i32; | ^^^^^^^^^^^ error: casting `u64` to `i64` may wrap around the value - --> $DIR/cast.rs:36:5 + --> $DIR/cast.rs:42:5 | LL | 1u64 as i64; | ^^^^^^^^^^^ error: casting `usize` to `isize` may wrap around the value - --> $DIR/cast.rs:37:5 + --> $DIR/cast.rs:43:5 | LL | 1usize as isize; | ^^^^^^^^^^^^^^^ error: casting `i32` to `u32` may lose the sign of the value - --> $DIR/cast.rs:40:5 + --> $DIR/cast.rs:46:5 | LL | -1i32 as u32; | ^^^^^^^^^^^^ error: casting `isize` to `usize` may lose the sign of the value - --> $DIR/cast.rs:42:5 + --> $DIR/cast.rs:48:5 | LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ error: casting `i64` to `i8` may truncate the value - --> $DIR/cast.rs:109:5 + --> $DIR/cast.rs:115:5 | LL | (-99999999999i64).min(1) as i8; // should be linted because signed | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +240,7 @@ LL | i8::try_from((-99999999999i64).min(1)); // should be linted because sig | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `u8` may truncate the value - --> $DIR/cast.rs:121:5 + --> $DIR/cast.rs:127:5 | LL | 999999u64.clamp(0, 256) as u8; // should still be linted | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -234,7 +252,7 @@ LL | u8::try_from(999999u64.clamp(0, 256)); // should still be linted | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E2` to `u8` may truncate the value - --> $DIR/cast.rs:142:21 + --> $DIR/cast.rs:148:21 | LL | let _ = self as u8; | ^^^^^^^^^^ @@ -246,7 +264,7 @@ LL | let _ = u8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E2::B` to `u8` will truncate the value - --> $DIR/cast.rs:143:21 + --> $DIR/cast.rs:149:21 | LL | let _ = Self::B as u8; | ^^^^^^^^^^^^^ @@ -254,7 +272,7 @@ LL | let _ = Self::B as u8; = note: `-D clippy::cast-enum-truncation` implied by `-D warnings` error: casting `main::E5` to `i8` may truncate the value - --> $DIR/cast.rs:179:21 + --> $DIR/cast.rs:185:21 | LL | let _ = self as i8; | ^^^^^^^^^^ @@ -266,13 +284,13 @@ LL | let _ = i8::try_from(self); | ~~~~~~~~~~~~~~~~~~ error: casting `main::E5::A` to `i8` will truncate the value - --> $DIR/cast.rs:180:21 + --> $DIR/cast.rs:186:21 | LL | let _ = Self::A as i8; | ^^^^^^^^^^^^^ error: casting `main::E6` to `i16` may truncate the value - --> $DIR/cast.rs:194:21 + --> $DIR/cast.rs:200:21 | LL | let _ = self as i16; | ^^^^^^^^^^^ @@ -284,7 +302,7 @@ LL | let _ = i16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast.rs:209:21 + --> $DIR/cast.rs:215:21 | LL | let _ = self as usize; | ^^^^^^^^^^^^^ @@ -296,7 +314,7 @@ LL | let _ = usize::try_from(self); | ~~~~~~~~~~~~~~~~~~~~~ error: casting `main::E10` to `u16` may truncate the value - --> $DIR/cast.rs:250:21 + --> $DIR/cast.rs:256:21 | LL | let _ = self as u16; | ^^^^^^^^^^^ @@ -308,7 +326,7 @@ LL | let _ = u16::try_from(self); | ~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:258:13 + --> $DIR/cast.rs:264:13 | LL | let c = (q >> 16) as u8; | ^^^^^^^^^^^^^^^ @@ -316,11 +334,11 @@ LL | let c = (q >> 16) as u8; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | let c = u8::try_from((q >> 16)); - | ~~~~~~~~~~~~~~~~~~~~~~~ +LL | let c = u8::try_from(q >> 16); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `u8` may truncate the value - --> $DIR/cast.rs:261:13 + --> $DIR/cast.rs:267:13 | LL | let c = (q / 1000) as u8; | ^^^^^^^^^^^^^^^^ @@ -328,8 +346,8 @@ LL | let c = (q / 1000) as u8; = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... help: ... or use `try_from` and handle the error accordingly | -LL | let c = u8::try_from((q / 1000)); - | ~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let c = u8::try_from(q / 1000); + | ~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 36 previous errors +error: aborting due to 41 previous errors diff --git a/tests/ui/clear_with_drain.fixed b/tests/ui/clear_with_drain.fixed new file mode 100644 index 00000000000..2d9545eeed1 --- /dev/null +++ b/tests/ui/clear_with_drain.fixed @@ -0,0 +1,358 @@ +// run-rustfix +#![allow(unused)] +#![warn(clippy::clear_with_drain)] + +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn vec_range() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(0..v.len()); + + // Do not lint because iterator is used + let mut v = vec![1, 2, 3]; + let n = v.drain(0..v.len()).count(); + + // Do not lint because iterator is assigned and used + let mut v = vec![1, 2, 3]; + let iter = v.drain(usize::MIN..v.len()); + let n = iter.count(); + + // Do lint + let mut v = vec![1, 2, 3]; + v.clear(); + + // Do lint + let mut v = vec![1, 2, 3]; + v.clear(); +} + +fn vec_range_from() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(0..); + + // Do not lint because iterator is assigned and used + let mut v = vec![1, 2, 3]; + let mut iter = v.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut v = vec![1, 2, 3]; + let next = v.drain(usize::MIN..).next(); + + // Do lint + let mut v = vec![1, 2, 3]; + v.clear(); + + // Do lint + let mut v = vec![1, 2, 3]; + v.clear(); +} + +fn vec_range_full() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(..); + + // Do not lint because iterator is used + let mut v = vec![1, 2, 3]; + for x in v.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut v = vec![1, 2, 3]; + v.clear(); +} + +fn vec_range_to() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(..v.len()); + + // Do not lint because iterator is assigned and used + let mut v = vec![1, 2, 3]; + let iter = v.drain(..v.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut v = vec![1, 2, 3]; + v.clear(); +} + +fn vec_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut v = vec![1, 2, 3]; + v.drain(1..); + let mut v = vec![1, 2, 3]; + v.drain(1..).max(); + + let mut v = vec![1, 2, 3]; + v.drain(..v.len() - 1); + let mut v = vec![1, 2, 3]; + v.drain(..v.len() - 1).min(); + + let mut v = vec![1, 2, 3]; + v.drain(1..v.len() - 1); + let mut v = vec![1, 2, 3]; + let w: Vec = v.drain(1..v.len() - 1).collect(); +} + +fn vec_deque_range() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..deque.len()); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let n = deque.drain(0..deque.len()).count(); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(usize::MIN..deque.len()); + let n = iter.count(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_range_from() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let mut iter = deque.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let next = deque.drain(usize::MIN..).next(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_range_full() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + for x in deque.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_range_to() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.clear(); +} + +fn vec_deque_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..).max(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1).min(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + let w: Vec = deque.drain(1..deque.len() - 1).collect(); +} + +fn string_range() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..s.len()); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let n = s.drain(0..s.len()).count(); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(usize::MIN..s.len()); + let n = iter.count(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_range_from() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let mut iter = s.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let next = s.drain(usize::MIN..).next(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_range_full() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + for x in s.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_range_to() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.clear(); +} + +fn string_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut s = String::from("Hello, world!"); + s.drain(1..); + let mut s = String::from("Hello, world!"); + s.drain(1..).max(); + + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1); + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1).min(); + + let mut s = String::from("Hello, world!"); + s.drain(1..s.len() - 1); + let mut s = String::from("Hello, world!"); + let w: String = s.drain(1..s.len() - 1).collect(); +} + +fn hash_set() { + // Do not lint because iterator is assigned + let mut set = HashSet::from([1, 2, 3]); + let iter = set.drain(); + + // Do not lint because iterator is assigned and used + let mut set = HashSet::from([1, 2, 3]); + let mut iter = set.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut set = HashSet::from([1, 2, 3]); + let next = set.drain().next(); + + // Do lint + let mut set = HashSet::from([1, 2, 3]); + set.clear(); +} + +fn hash_map() { + // Do not lint because iterator is assigned + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let iter = map.drain(); + + // Do not lint because iterator is assigned and used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let mut iter = map.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let next = map.drain().next(); + + // Do lint + let mut map = HashMap::from([(1, "a"), (2, "b")]); + map.clear(); +} + +fn binary_heap() { + // Do not lint because iterator is assigned + let mut heap = BinaryHeap::from([1, 2]); + let iter = heap.drain(); + + // Do not lint because iterator is assigned and used + let mut heap = BinaryHeap::from([1, 2]); + let mut iter = heap.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut heap = BinaryHeap::from([1, 2]); + let next = heap.drain().next(); + + // Do lint + let mut heap = BinaryHeap::from([1, 2]); + heap.clear(); +} + +fn main() {} diff --git a/tests/ui/clear_with_drain.rs b/tests/ui/clear_with_drain.rs new file mode 100644 index 00000000000..4d60ee46e18 --- /dev/null +++ b/tests/ui/clear_with_drain.rs @@ -0,0 +1,358 @@ +// run-rustfix +#![allow(unused)] +#![warn(clippy::clear_with_drain)] + +use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque}; + +fn vec_range() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(0..v.len()); + + // Do not lint because iterator is used + let mut v = vec![1, 2, 3]; + let n = v.drain(0..v.len()).count(); + + // Do not lint because iterator is assigned and used + let mut v = vec![1, 2, 3]; + let iter = v.drain(usize::MIN..v.len()); + let n = iter.count(); + + // Do lint + let mut v = vec![1, 2, 3]; + v.drain(0..v.len()); + + // Do lint + let mut v = vec![1, 2, 3]; + v.drain(usize::MIN..v.len()); +} + +fn vec_range_from() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(0..); + + // Do not lint because iterator is assigned and used + let mut v = vec![1, 2, 3]; + let mut iter = v.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut v = vec![1, 2, 3]; + let next = v.drain(usize::MIN..).next(); + + // Do lint + let mut v = vec![1, 2, 3]; + v.drain(0..); + + // Do lint + let mut v = vec![1, 2, 3]; + v.drain(usize::MIN..); +} + +fn vec_range_full() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(..); + + // Do not lint because iterator is used + let mut v = vec![1, 2, 3]; + for x in v.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut v = vec![1, 2, 3]; + v.drain(..); +} + +fn vec_range_to() { + // Do not lint because iterator is assigned + let mut v = vec![1, 2, 3]; + let iter = v.drain(..v.len()); + + // Do not lint because iterator is assigned and used + let mut v = vec![1, 2, 3]; + let iter = v.drain(..v.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut v = vec![1, 2, 3]; + v.drain(..v.len()); +} + +fn vec_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut v = vec![1, 2, 3]; + v.drain(1..); + let mut v = vec![1, 2, 3]; + v.drain(1..).max(); + + let mut v = vec![1, 2, 3]; + v.drain(..v.len() - 1); + let mut v = vec![1, 2, 3]; + v.drain(..v.len() - 1).min(); + + let mut v = vec![1, 2, 3]; + v.drain(1..v.len() - 1); + let mut v = vec![1, 2, 3]; + let w: Vec = v.drain(1..v.len() - 1).collect(); +} + +fn vec_deque_range() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..deque.len()); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let n = deque.drain(0..deque.len()).count(); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(usize::MIN..deque.len()); + let n = iter.count(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(0..deque.len()); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(usize::MIN..deque.len()); +} + +fn vec_deque_range_from() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(0..); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let mut iter = deque.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + let next = deque.drain(usize::MIN..).next(); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(0..); + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(usize::MIN..); +} + +fn vec_deque_range_full() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..); + + // Do not lint because iterator is used + let mut deque = VecDeque::from([1, 2, 3]); + for x in deque.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..); +} + +fn vec_deque_range_to() { + // Do not lint because iterator is assigned + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + + // Do not lint because iterator is assigned and used + let mut deque = VecDeque::from([1, 2, 3]); + let iter = deque.drain(..deque.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len()); +} + +fn vec_deque_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..).max(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(..deque.len() - 1).min(); + + let mut deque = VecDeque::from([1, 2, 3]); + deque.drain(1..deque.len() - 1); + let mut deque = VecDeque::from([1, 2, 3]); + let w: Vec = deque.drain(1..deque.len() - 1).collect(); +} + +fn string_range() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..s.len()); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let n = s.drain(0..s.len()).count(); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(usize::MIN..s.len()); + let n = iter.count(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(0..s.len()); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(usize::MIN..s.len()); +} + +fn string_range_from() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(0..); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let mut iter = s.drain(0..); + let next = iter.next(); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + let next = s.drain(usize::MIN..).next(); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(0..); + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(usize::MIN..); +} + +fn string_range_full() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..); + + // Do not lint because iterator is used + let mut s = String::from("Hello, world!"); + for x in s.drain(..) { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(..); +} + +fn string_range_to() { + // Do not lint because iterator is assigned + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + + // Do not lint because iterator is assigned and used + let mut s = String::from("Hello, world!"); + let iter = s.drain(..s.len()); + for x in iter { + let y = format!("x = {x}"); + } + + // Do lint + let mut s = String::from("Hello, world!"); + s.drain(..s.len()); +} + +fn string_partial_drains() { + // Do not lint any of these because the ranges are not full + + let mut s = String::from("Hello, world!"); + s.drain(1..); + let mut s = String::from("Hello, world!"); + s.drain(1..).max(); + + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1); + let mut s = String::from("Hello, world!"); + s.drain(..s.len() - 1).min(); + + let mut s = String::from("Hello, world!"); + s.drain(1..s.len() - 1); + let mut s = String::from("Hello, world!"); + let w: String = s.drain(1..s.len() - 1).collect(); +} + +fn hash_set() { + // Do not lint because iterator is assigned + let mut set = HashSet::from([1, 2, 3]); + let iter = set.drain(); + + // Do not lint because iterator is assigned and used + let mut set = HashSet::from([1, 2, 3]); + let mut iter = set.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut set = HashSet::from([1, 2, 3]); + let next = set.drain().next(); + + // Do lint + let mut set = HashSet::from([1, 2, 3]); + set.drain(); +} + +fn hash_map() { + // Do not lint because iterator is assigned + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let iter = map.drain(); + + // Do not lint because iterator is assigned and used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let mut iter = map.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut map = HashMap::from([(1, "a"), (2, "b")]); + let next = map.drain().next(); + + // Do lint + let mut map = HashMap::from([(1, "a"), (2, "b")]); + map.drain(); +} + +fn binary_heap() { + // Do not lint because iterator is assigned + let mut heap = BinaryHeap::from([1, 2]); + let iter = heap.drain(); + + // Do not lint because iterator is assigned and used + let mut heap = BinaryHeap::from([1, 2]); + let mut iter = heap.drain(); + let next = iter.next(); + + // Do not lint because iterator is used + let mut heap = BinaryHeap::from([1, 2]); + let next = heap.drain().next(); + + // Do lint + let mut heap = BinaryHeap::from([1, 2]); + heap.drain(); +} + +fn main() {} diff --git a/tests/ui/clear_with_drain.stderr b/tests/ui/clear_with_drain.stderr new file mode 100644 index 00000000000..20158da1121 --- /dev/null +++ b/tests/ui/clear_with_drain.stderr @@ -0,0 +1,130 @@ +error: `drain` used to clear a `Vec` + --> $DIR/clear_with_drain.rs:23:7 + | +LL | v.drain(0..v.len()); + | ^^^^^^^^^^^^^^^^^ help: try: `clear()` + | + = note: `-D clippy::clear-with-drain` implied by `-D warnings` + +error: `drain` used to clear a `Vec` + --> $DIR/clear_with_drain.rs:27:7 + | +LL | v.drain(usize::MIN..v.len()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `Vec` + --> $DIR/clear_with_drain.rs:46:7 + | +LL | v.drain(0..); + | ^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `Vec` + --> $DIR/clear_with_drain.rs:50:7 + | +LL | v.drain(usize::MIN..); + | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `Vec` + --> $DIR/clear_with_drain.rs:66:7 + | +LL | v.drain(..); + | ^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `Vec` + --> $DIR/clear_with_drain.rs:83:7 + | +LL | v.drain(..v.len()); + | ^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:121:11 + | +LL | deque.drain(0..deque.len()); + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:125:11 + | +LL | deque.drain(usize::MIN..deque.len()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:144:11 + | +LL | deque.drain(0..); + | ^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:148:11 + | +LL | deque.drain(usize::MIN..); + | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:164:11 + | +LL | deque.drain(..); + | ^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `VecDeque` + --> $DIR/clear_with_drain.rs:181:11 + | +LL | deque.drain(..deque.len()); + | ^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:219:7 + | +LL | s.drain(0..s.len()); + | ^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:223:7 + | +LL | s.drain(usize::MIN..s.len()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:242:7 + | +LL | s.drain(0..); + | ^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:246:7 + | +LL | s.drain(usize::MIN..); + | ^^^^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:262:7 + | +LL | s.drain(..); + | ^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `String` + --> $DIR/clear_with_drain.rs:279:7 + | +LL | s.drain(..s.len()); + | ^^^^^^^^^^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `HashSet` + --> $DIR/clear_with_drain.rs:317:9 + | +LL | set.drain(); + | ^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `HashMap` + --> $DIR/clear_with_drain.rs:336:9 + | +LL | map.drain(); + | ^^^^^^^ help: try: `clear()` + +error: `drain` used to clear a `BinaryHeap` + --> $DIR/clear_with_drain.rs:355:10 + | +LL | heap.drain(); + | ^^^^^^^ help: try: `clear()` + +error: aborting due to 21 previous errors + diff --git a/tests/ui/collection_is_never_read.rs b/tests/ui/collection_is_never_read.rs index 068a49486cf..01259a983ab 100644 --- a/tests/ui/collection_is_never_read.rs +++ b/tests/ui/collection_is_never_read.rs @@ -84,13 +84,18 @@ fn shadowing_2() { } #[allow(clippy::let_unit_value)] -fn fake_read() { - let mut x = vec![1, 2, 3]; // Ok +fn fake_read_1() { + let mut x = vec![1, 2, 3]; // WARNING x.reverse(); - // `collection_is_never_read` gets fooled, but other lints should catch this. let _: () = x.clear(); } +fn fake_read_2() { + let mut x = vec![1, 2, 3]; // WARNING + x.reverse(); + println!("{:?}", x.push(5)); +} + fn assignment() { let mut x = vec![1, 2, 3]; // WARNING let y = vec![4, 5, 6]; // Ok @@ -163,3 +168,23 @@ fn function_argument() { let x = vec![1, 2, 3]; // Ok foo(&x); } + +fn string() { + // Do lint (write without read) + let mut s = String::new(); + s.push_str("Hello, World!"); + + // Do not lint (read without write) + let mut s = String::from("Hello, World!"); + let _ = s.len(); + + // Do not lint (write and read) + let mut s = String::from("Hello, World!"); + s.push_str("foo, bar"); + let _ = s.len(); + + // Do lint the first line, but not the second + let mut s = String::from("Hello, World!"); + let t = String::from("foo, bar"); + s = t; +} diff --git a/tests/ui/collection_is_never_read.stderr b/tests/ui/collection_is_never_read.stderr index 7654b74be3d..cf51a53686f 100644 --- a/tests/ui/collection_is_never_read.stderr +++ b/tests/ui/collection_is_never_read.stderr @@ -25,28 +25,52 @@ LL | let mut x = HashMap::new(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> $DIR/collection_is_never_read.rs:95:5 + --> $DIR/collection_is_never_read.rs:88:5 | LL | let mut x = vec![1, 2, 3]; // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> $DIR/collection_is_never_read.rs:102:5 + --> $DIR/collection_is_never_read.rs:94:5 | LL | let mut x = vec![1, 2, 3]; // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> $DIR/collection_is_never_read.rs:119:5 + --> $DIR/collection_is_never_read.rs:100:5 + | +LL | let mut x = vec![1, 2, 3]; // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:107:5 + | +LL | let mut x = vec![1, 2, 3]; // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:124:5 | LL | let mut x = HashSet::new(); // WARNING | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> $DIR/collection_is_never_read.rs:133:5 + --> $DIR/collection_is_never_read.rs:138:5 | LL | let x = vec![1, 2, 3]; // WARNING | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: collection is never read + --> $DIR/collection_is_never_read.rs:174:5 + | +LL | let mut s = String::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:187:5 + | +LL | let mut s = String::from("Hello, World!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors diff --git a/tests/ui/double_must_use.rs b/tests/ui/double_must_use.rs index 05e087b08bc..26a387b3cf0 100644 --- a/tests/ui/double_must_use.rs +++ b/tests/ui/double_must_use.rs @@ -21,6 +21,17 @@ pub fn must_use_with_note() -> Result<(), ()> { unimplemented!(); } +// vvvv Should not lint (#10486) +#[must_use] +async fn async_must_use() -> usize { + unimplemented!(); +} + +#[must_use] +async fn async_must_use_result() -> Result<(), ()> { + Ok(()) +} + fn main() { must_use_result(); must_use_tuple(); diff --git a/tests/ui/double_must_use.stderr b/tests/ui/double_must_use.stderr index 3d34557a881..49ab2ea3e12 100644 --- a/tests/ui/double_must_use.stderr +++ b/tests/ui/double_must_use.stderr @@ -23,5 +23,13 @@ LL | pub fn must_use_array() -> [Result<(), ()>; 1] { | = help: either add some descriptive text or remove the attribute -error: aborting due to 3 previous errors +error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]` + --> $DIR/double_must_use.rs:31:1 + | +LL | async fn async_must_use_result() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: either add some descriptive text or remove the attribute + +error: aborting due to 4 previous errors diff --git a/tests/ui/extra_unused_type_parameters.fixed b/tests/ui/extra_unused_type_parameters.fixed new file mode 100644 index 00000000000..19e71862558 --- /dev/null +++ b/tests/ui/extra_unused_type_parameters.fixed @@ -0,0 +1,105 @@ +// run-rustfix + +#![allow(unused, clippy::needless_lifetimes)] +#![warn(clippy::extra_unused_type_parameters)] + +fn unused_ty(x: u8) { + unimplemented!() +} + +fn unused_multi(x: u8) { + unimplemented!() +} + +fn unused_with_lt<'a>(x: &'a u8) { + unimplemented!() +} + +fn used_ty(x: T, y: u8) {} + +fn used_ref<'a, T>(x: &'a T) {} + +fn used_ret(x: u8) -> T { + T::default() +} + +fn unused_bounded(x: U) { + unimplemented!(); +} + +fn some_unused(b: B, c: C) { + unimplemented!(); +} + +fn used_opaque(iter: impl Iterator) -> usize { + iter.count() +} + +fn used_ret_opaque() -> impl Iterator { + std::iter::empty() +} + +fn used_vec_box(x: Vec>) {} + +fn used_body() -> String { + T::default().to_string() +} + +fn used_closure() -> impl Fn() { + || println!("{}", T::default().to_string()) +} + +struct S; + +impl S { + fn unused_ty_impl(&self) { + unimplemented!() + } +} + +// Don't lint on trait methods +trait Foo { + fn bar(&self); +} + +impl Foo for S { + fn bar(&self) {} +} + +fn skip_index(iter: Iter, index: usize) -> impl Iterator +where + Iter: Iterator, +{ + iter.enumerate() + .filter_map(move |(i, a)| if i == index { None } else { Some(a) }) +} + +fn unused_opaque(dummy: impl Default) { + unimplemented!() +} + +mod unexported_trait_bounds { + mod private { + pub trait Private {} + } + + fn priv_trait_bound() { + unimplemented!(); + } + + fn unused_with_priv_trait_bound() { + unimplemented!(); + } +} + +mod issue10319 { + fn assert_send() {} + + fn assert_send_where() + where + T: Send, + { + } +} + +fn main() {} diff --git a/tests/ui/extra_unused_type_parameters.rs b/tests/ui/extra_unused_type_parameters.rs index 48017434276..e53bb587e89 100644 --- a/tests/ui/extra_unused_type_parameters.rs +++ b/tests/ui/extra_unused_type_parameters.rs @@ -1,3 +1,5 @@ +// run-rustfix + #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] @@ -21,14 +23,7 @@ fn used_ret(x: u8) -> T { T::default() } -fn unused_bounded(x: U) { - unimplemented!(); -} - -fn unused_where_clause(x: U) -where - T: Default, -{ +fn unused_bounded(x: U) { unimplemented!(); } diff --git a/tests/ui/extra_unused_type_parameters.stderr b/tests/ui/extra_unused_type_parameters.stderr index 86c88fc9bf0..c042a5a2290 100644 --- a/tests/ui/extra_unused_type_parameters.stderr +++ b/tests/ui/extra_unused_type_parameters.stderr @@ -1,75 +1,64 @@ -error: type parameter goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:4:13 +error: type parameter `T` goes unused in function definition + --> $DIR/extra_unused_type_parameters.rs:6:13 | LL | fn unused_ty(x: u8) { - | ^^^ + | ^^^ help: consider removing the parameter | - = help: consider removing the parameter = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings` -error: type parameters go unused in function definition - --> $DIR/extra_unused_type_parameters.rs:8:16 +error: type parameters go unused in function definition: T, U + --> $DIR/extra_unused_type_parameters.rs:10:16 | LL | fn unused_multi(x: u8) { - | ^^^^^^ - | - = help: consider removing the parameters + | ^^^^^^ help: consider removing the parameters -error: type parameter goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:12:23 +error: type parameter `T` goes unused in function definition + --> $DIR/extra_unused_type_parameters.rs:14:21 | LL | fn unused_with_lt<'a, T>(x: &'a u8) { - | ^ - | - = help: consider removing the parameter + | ^^^ help: consider removing the parameter -error: type parameter goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:24:19 +error: type parameters go unused in function definition: T, V + --> $DIR/extra_unused_type_parameters.rs:26:19 | -LL | fn unused_bounded(x: U) { - | ^^^^^^^^^^^ +LL | fn unused_bounded(x: U) { + | ^^^^^^^^^^^^ ^^^^^^^^^^^^ | - = help: consider removing the parameter - -error: type parameter goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:28:24 +help: consider removing the parameters | -LL | fn unused_where_clause(x: U) - | ^^ +LL - fn unused_bounded(x: U) { +LL + fn unused_bounded(x: U) { | - = help: consider removing the parameter -error: type parameters go unused in function definition - --> $DIR/extra_unused_type_parameters.rs:35:16 +error: type parameters go unused in function definition: A, D, E + --> $DIR/extra_unused_type_parameters.rs:30:16 | LL | fn some_unused, E>(b: B, c: C) { - | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider removing the parameters + | +LL - fn some_unused, E>(b: B, c: C) { +LL + fn some_unused(b: B, c: C) { | - = help: consider removing the parameters -error: type parameter goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:60:22 +error: type parameter `T` goes unused in function definition + --> $DIR/extra_unused_type_parameters.rs:55:22 | LL | fn unused_ty_impl(&self) { - | ^^^ - | - = help: consider removing the parameter + | ^^^ help: consider removing the parameter -error: type parameters go unused in function definition - --> $DIR/extra_unused_type_parameters.rs:82:17 +error: type parameters go unused in function definition: A, B + --> $DIR/extra_unused_type_parameters.rs:77:17 | LL | fn unused_opaque(dummy: impl Default) { - | ^^^^^^ - | - = help: consider removing the parameters + | ^^^^^^ help: consider removing the parameters -error: type parameter goes unused in function definition - --> $DIR/extra_unused_type_parameters.rs:95:58 +error: type parameter `U` goes unused in function definition + --> $DIR/extra_unused_type_parameters.rs:90:56 | LL | fn unused_with_priv_trait_bound() { - | ^ - | - = help: consider removing the parameter + | ^^^ help: consider removing the parameter -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/extra_unused_type_parameters_unfixable.rs b/tests/ui/extra_unused_type_parameters_unfixable.rs new file mode 100644 index 00000000000..10b39aa8f2c --- /dev/null +++ b/tests/ui/extra_unused_type_parameters_unfixable.rs @@ -0,0 +1,24 @@ +#![warn(clippy::extra_unused_type_parameters)] + +fn unused_where_clause(x: U) +where + T: Default, +{ + unimplemented!(); +} + +fn unused_multi_where_clause(x: U) +where + T: Default, +{ + unimplemented!(); +} + +fn unused_all_where_clause() +where + T: Default, +{ + unimplemented!(); +} + +fn main() {} diff --git a/tests/ui/extra_unused_type_parameters_unfixable.stderr b/tests/ui/extra_unused_type_parameters_unfixable.stderr new file mode 100644 index 00000000000..a9580cc894f --- /dev/null +++ b/tests/ui/extra_unused_type_parameters_unfixable.stderr @@ -0,0 +1,27 @@ +error: type parameter `T` goes unused in function definition + --> $DIR/extra_unused_type_parameters_unfixable.rs:3:24 + | +LL | fn unused_where_clause(x: U) + | ^ + | + = help: consider removing the parameter + = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings` + +error: type parameters go unused in function definition: T, V + --> $DIR/extra_unused_type_parameters_unfixable.rs:10:30 + | +LL | fn unused_multi_where_clause(x: U) + | ^ ^^^^^^^^^^ + | + = help: consider removing the parameters + +error: type parameters go unused in function definition: T, U, V + --> $DIR/extra_unused_type_parameters_unfixable.rs:17:28 + | +LL | fn unused_all_where_clause() + | ^ ^^^^^^^^^^ ^^^^^^^^^^ + | + = help: consider removing the parameters + +error: aborting due to 3 previous errors + diff --git a/tests/ui/format_args_unfixable.rs b/tests/ui/format_args_unfixable.rs index eb0ac15bfbf..423bfaf9796 100644 --- a/tests/ui/format_args_unfixable.rs +++ b/tests/ui/format_args_unfixable.rs @@ -1,4 +1,5 @@ #![warn(clippy::format_in_format_args, clippy::to_string_in_format_args)] +#![allow(unused)] #![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)] use std::io::{stdout, Error, ErrorKind, Write}; @@ -57,3 +58,46 @@ fn main() { my_macro!(); println!("error: {}", my_other_macro!()); } + +macro_rules! _internal { + ($($args:tt)*) => { + println!("{}", format_args!($($args)*)) + }; +} + +macro_rules! my_println2 { + ($target:expr, $($args:tt)+) => {{ + if $target { + _internal!($($args)+) + } + }}; +} + +macro_rules! my_println2_args { + ($target:expr, $($args:tt)+) => {{ + if $target { + _internal!("foo: {}", format_args!($($args)+)) + } + }}; +} + +fn test2() { + let error = Error::new(ErrorKind::Other, "bad thing"); + + // None of these should be linted without the config change + my_println2!(true, "error: {}", format!("something failed at {}", Location::caller())); + my_println2!( + true, + "{}: {}", + error, + format!("something failed at {}", Location::caller()) + ); + + my_println2_args!(true, "error: {}", format!("something failed at {}", Location::caller())); + my_println2_args!( + true, + "{}: {}", + error, + format!("something failed at {}", Location::caller()) + ); +} diff --git a/tests/ui/format_args_unfixable.stderr b/tests/ui/format_args_unfixable.stderr index b291d475ad9..c1be48c3b72 100644 --- a/tests/ui/format_args_unfixable.stderr +++ b/tests/ui/format_args_unfixable.stderr @@ -1,5 +1,5 @@ error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:25:5 + --> $DIR/format_args_unfixable.rs:26:5 | LL | println!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | println!("error: {}", format!("something failed at {}", Location::calle = note: `-D clippy::format-in-format-args` implied by `-D warnings` error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:26:5 + --> $DIR/format_args_unfixable.rs:27:5 | LL | println!("{}: {}", error, format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | println!("{}: {}", error, format!("something failed at {}", Location::c = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:27:5 + --> $DIR/format_args_unfixable.rs:28:5 | LL | println!("{:?}: {}", error, format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | println!("{:?}: {}", error, format!("something failed at {}", Location: = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:28:5 + --> $DIR/format_args_unfixable.rs:29:5 | LL | println!("{{}}: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | println!("{{}}: {}", format!("something failed at {}", Location::caller = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:29:5 + --> $DIR/format_args_unfixable.rs:30:5 | LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | println!(r#"error: "{}""#, format!("something failed at {}", Location:: = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:30:5 + --> $DIR/format_args_unfixable.rs:31:5 | LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | println!("error: {}", format!(r#"something failed at "{}""#, Location:: = help: or consider changing `format!` to `format_args!` error: `format!` in `println!` args - --> $DIR/format_args_unfixable.rs:31:5 + --> $DIR/format_args_unfixable.rs:32:5 | LL | println!("error: {}", format!("something failed at {} {0}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | println!("error: {}", format!("something failed at {} {0}", Location::c = help: or consider changing `format!` to `format_args!` error: `format!` in `format!` args - --> $DIR/format_args_unfixable.rs:32:13 + --> $DIR/format_args_unfixable.rs:33:13 | LL | let _ = format!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = format!("error: {}", format!("something failed at {}", Location = help: or consider changing `format!` to `format_args!` error: `format!` in `write!` args - --> $DIR/format_args_unfixable.rs:33:13 + --> $DIR/format_args_unfixable.rs:34:13 | LL | let _ = write!( | _____________^ @@ -86,7 +86,7 @@ LL | | ); = help: or consider changing `format!` to `format_args!` error: `format!` in `writeln!` args - --> $DIR/format_args_unfixable.rs:38:13 + --> $DIR/format_args_unfixable.rs:39:13 | LL | let _ = writeln!( | _____________^ @@ -100,7 +100,7 @@ LL | | ); = help: or consider changing `format!` to `format_args!` error: `format!` in `print!` args - --> $DIR/format_args_unfixable.rs:43:5 + --> $DIR/format_args_unfixable.rs:44:5 | LL | print!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | print!("error: {}", format!("something failed at {}", Location::caller( = help: or consider changing `format!` to `format_args!` error: `format!` in `eprint!` args - --> $DIR/format_args_unfixable.rs:44:5 + --> $DIR/format_args_unfixable.rs:45:5 | LL | eprint!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | eprint!("error: {}", format!("something failed at {}", Location::caller = help: or consider changing `format!` to `format_args!` error: `format!` in `eprintln!` args - --> $DIR/format_args_unfixable.rs:45:5 + --> $DIR/format_args_unfixable.rs:46:5 | LL | eprintln!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | eprintln!("error: {}", format!("something failed at {}", Location::call = help: or consider changing `format!` to `format_args!` error: `format!` in `format_args!` args - --> $DIR/format_args_unfixable.rs:46:13 + --> $DIR/format_args_unfixable.rs:47:13 | LL | let _ = format_args!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | let _ = format_args!("error: {}", format!("something failed at {}", Loc = help: or consider changing `format!` to `format_args!` error: `format!` in `assert!` args - --> $DIR/format_args_unfixable.rs:47:5 + --> $DIR/format_args_unfixable.rs:48:5 | LL | assert!(true, "error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL | assert!(true, "error: {}", format!("something failed at {}", Location:: = help: or consider changing `format!` to `format_args!` error: `format!` in `assert_eq!` args - --> $DIR/format_args_unfixable.rs:48:5 + --> $DIR/format_args_unfixable.rs:49:5 | LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -154,7 +154,7 @@ LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Locatio = help: or consider changing `format!` to `format_args!` error: `format!` in `assert_ne!` args - --> $DIR/format_args_unfixable.rs:49:5 + --> $DIR/format_args_unfixable.rs:50:5 | LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -163,7 +163,7 @@ LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Locatio = help: or consider changing `format!` to `format_args!` error: `format!` in `panic!` args - --> $DIR/format_args_unfixable.rs:50:5 + --> $DIR/format_args_unfixable.rs:51:5 | LL | panic!("error: {}", format!("something failed at {}", Location::caller())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/item_after_statement.rs b/tests/ui/item_after_statement.rs deleted file mode 100644 index 5e92dcab1f5..00000000000 --- a/tests/ui/item_after_statement.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![warn(clippy::items_after_statements)] -#![allow(clippy::uninlined_format_args)] - -fn ok() { - fn foo() { - println!("foo"); - } - foo(); -} - -fn last() { - foo(); - fn foo() { - println!("foo"); - } -} - -fn main() { - foo(); - fn foo() { - println!("foo"); - } - foo(); -} - -fn mac() { - let mut a = 5; - println!("{}", a); - // do not lint this, because it needs to be after `a` - macro_rules! b { - () => {{ - a = 6; - fn say_something() { - println!("something"); - } - }}; - } - b!(); - println!("{}", a); -} - -fn semicolon() { - struct S { - a: u32, - }; - impl S { - fn new(a: u32) -> Self { - Self { a } - } - } - - let _ = S::new(3); -} diff --git a/tests/ui/item_after_statement.stderr b/tests/ui/item_after_statement.stderr deleted file mode 100644 index 2523c53ac53..00000000000 --- a/tests/ui/item_after_statement.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:13:5 - | -LL | / fn foo() { -LL | | println!("foo"); -LL | | } - | |_____^ - | - = note: `-D clippy::items-after-statements` implied by `-D warnings` - -error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:20:5 - | -LL | / fn foo() { -LL | | println!("foo"); -LL | | } - | |_____^ - -error: adding items after statements is confusing, since items exist from the start of the scope - --> $DIR/item_after_statement.rs:33:13 - | -LL | / fn say_something() { -LL | | println!("something"); -LL | | } - | |_____________^ -... -LL | b!(); - | ---- in this macro invocation - | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 3 previous errors - diff --git a/tests/ui/items_after_statement.rs b/tests/ui/items_after_statement.rs new file mode 100644 index 00000000000..f12cb8f22e2 --- /dev/null +++ b/tests/ui/items_after_statement.rs @@ -0,0 +1,70 @@ +#![warn(clippy::items_after_statements)] +#![allow(clippy::uninlined_format_args)] + +fn ok() { + fn foo() { + println!("foo"); + } + foo(); +} + +fn last() { + foo(); + fn foo() { + println!("foo"); + } +} + +fn main() { + foo(); + fn foo() { + println!("foo"); + } + foo(); +} + +fn mac() { + let mut a = 5; + println!("{}", a); + // do not lint this, because it needs to be after `a` + macro_rules! b { + () => {{ + a = 6; + fn say_something() { + println!("something"); + } + }}; + } + b!(); + println!("{}", a); +} + +fn semicolon() { + struct S { + a: u32, + }; + impl S { + fn new(a: u32) -> Self { + Self { a } + } + } + + let _ = S::new(3); +} + +fn item_from_macro() { + macro_rules! static_assert_size { + ($ty:ty, $size:expr) => { + const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; + }; + } + + let _ = 1; + static_assert_size!(u32, 4); +} + +fn allow_attribute() { + let _ = 1; + #[allow(clippy::items_after_statements)] + const _: usize = 1; +} diff --git a/tests/ui/items_after_statement.stderr b/tests/ui/items_after_statement.stderr new file mode 100644 index 00000000000..f69635a977b --- /dev/null +++ b/tests/ui/items_after_statement.stderr @@ -0,0 +1,33 @@ +error: adding items after statements is confusing, since items exist from the start of the scope + --> $DIR/items_after_statement.rs:13:5 + | +LL | / fn foo() { +LL | | println!("foo"); +LL | | } + | |_____^ + | + = note: `-D clippy::items-after-statements` implied by `-D warnings` + +error: adding items after statements is confusing, since items exist from the start of the scope + --> $DIR/items_after_statement.rs:20:5 + | +LL | / fn foo() { +LL | | println!("foo"); +LL | | } + | |_____^ + +error: adding items after statements is confusing, since items exist from the start of the scope + --> $DIR/items_after_statement.rs:33:13 + | +LL | / fn say_something() { +LL | | println!("something"); +LL | | } + | |_____________^ +... +LL | b!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/large_futures.rs b/tests/ui/large_futures.rs new file mode 100644 index 00000000000..4a8ba995da5 --- /dev/null +++ b/tests/ui/large_futures.rs @@ -0,0 +1,61 @@ +#![feature(generators)] +#![warn(clippy::large_futures)] +#![allow(clippy::future_not_send)] +#![allow(clippy::manual_async_fn)] + +async fn big_fut(_arg: [u8; 1024 * 16]) {} + +async fn wait() { + let f = async { + big_fut([0u8; 1024 * 16]).await; + }; + f.await +} +async fn calls_fut(fut: impl std::future::Future) { + loop { + wait().await; + if true { + return fut.await; + } else { + wait().await; + } + } +} + +pub async fn test() { + let fut = big_fut([0u8; 1024 * 16]); + foo().await; + calls_fut(fut).await; +} + +pub fn foo() -> impl std::future::Future { + async { + let x = [0i32; 1024 * 16]; + async {}.await; + dbg!(x); + } +} + +pub async fn lines() { + async { + let x = [0i32; 1024 * 16]; + async {}.await; + println!("{:?}", x); + } + .await; +} + +pub async fn macro_expn() { + macro_rules! macro_ { + () => { + async { + let x = [0i32; 1024 * 16]; + async {}.await; + println!("macro: {:?}", x); + } + }; + } + macro_!().await +} + +fn main() {} diff --git a/tests/ui/large_futures.stderr b/tests/ui/large_futures.stderr new file mode 100644 index 00000000000..67e0fceff6e --- /dev/null +++ b/tests/ui/large_futures.stderr @@ -0,0 +1,82 @@ +error: large future with a size of 16385 bytes + --> $DIR/large_futures.rs:10:9 + | +LL | big_fut([0u8; 1024 * 16]).await; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))` + | + = note: `-D clippy::large-futures` implied by `-D warnings` + +error: large future with a size of 16386 bytes + --> $DIR/large_futures.rs:12:5 + | +LL | f.await + | ^ help: consider `Box::pin` on it: `Box::pin(f)` + +error: large future with a size of 16387 bytes + --> $DIR/large_futures.rs:16:9 + | +LL | wait().await; + | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` + +error: large future with a size of 16387 bytes + --> $DIR/large_futures.rs:20:13 + | +LL | wait().await; + | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` + +error: large future with a size of 65540 bytes + --> $DIR/large_futures.rs:27:5 + | +LL | foo().await; + | ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())` + +error: large future with a size of 49159 bytes + --> $DIR/large_futures.rs:28:5 + | +LL | calls_fut(fut).await; + | ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))` + +error: large future with a size of 65540 bytes + --> $DIR/large_futures.rs:40:5 + | +LL | / async { +LL | | let x = [0i32; 1024 * 16]; +LL | | async {}.await; +LL | | println!("{:?}", x); +LL | | } + | |_____^ + | +help: consider `Box::pin` on it + | +LL ~ Box::pin(async { +LL + let x = [0i32; 1024 * 16]; +LL + async {}.await; +LL + println!("{:?}", x); +LL + }) + | + +error: large future with a size of 65540 bytes + --> $DIR/large_futures.rs:51:13 + | +LL | / async { +LL | | let x = [0i32; 1024 * 16]; +LL | | async {}.await; +LL | | println!("macro: {:?}", x); +LL | | } + | |_____________^ +... +LL | macro_!().await + | --------- in this macro invocation + | + = note: this error originates in the macro `macro_` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider `Box::pin` on it + | +LL ~ Box::pin(async { +LL + let x = [0i32; 1024 * 16]; +LL + async {}.await; +LL + println!("macro: {:?}", x); +LL + }) + | + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lines_filter_map_ok.fixed b/tests/ui/lines_filter_map_ok.fixed new file mode 100644 index 00000000000..f4033cd8ed8 --- /dev/null +++ b/tests/ui/lines_filter_map_ok.fixed @@ -0,0 +1,29 @@ +// run-rustfix + +#![allow(unused, clippy::map_identity)] +#![warn(clippy::lines_filter_map_ok)] + +use std::io::{self, BufRead, BufReader}; + +fn main() -> io::Result<()> { + let f = std::fs::File::open("/")?; + // Lint + BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + // Lint + let f = std::fs::File::open("/")?; + BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ()); + let s = "foo\nbar\nbaz\n"; + // Lint + io::stdin().lines().map_while(Result::ok).for_each(|_| ()); + // Lint + io::stdin().lines().map_while(Result::ok).for_each(|_| ()); + // Do not lint (not a `Lines` iterator) + io::stdin() + .lines() + .map(std::convert::identity) + .filter_map(|x| x.ok()) + .for_each(|_| ()); + // Do not lint (not a `Result::ok()` extractor) + io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ()); + Ok(()) +} diff --git a/tests/ui/lines_filter_map_ok.rs b/tests/ui/lines_filter_map_ok.rs new file mode 100644 index 00000000000..7e11816b2ac --- /dev/null +++ b/tests/ui/lines_filter_map_ok.rs @@ -0,0 +1,29 @@ +// run-rustfix + +#![allow(unused, clippy::map_identity)] +#![warn(clippy::lines_filter_map_ok)] + +use std::io::{self, BufRead, BufReader}; + +fn main() -> io::Result<()> { + let f = std::fs::File::open("/")?; + // Lint + BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ()); + // Lint + let f = std::fs::File::open("/")?; + BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); + let s = "foo\nbar\nbaz\n"; + // Lint + io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); + // Lint + io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); + // Do not lint (not a `Lines` iterator) + io::stdin() + .lines() + .map(std::convert::identity) + .filter_map(|x| x.ok()) + .for_each(|_| ()); + // Do not lint (not a `Result::ok()` extractor) + io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ()); + Ok(()) +} diff --git a/tests/ui/lines_filter_map_ok.stderr b/tests/ui/lines_filter_map_ok.stderr new file mode 100644 index 00000000000..cddd403d589 --- /dev/null +++ b/tests/ui/lines_filter_map_ok.stderr @@ -0,0 +1,51 @@ +error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` + --> $DIR/lines_filter_map_ok.rs:11:31 + | +LL | BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` + | +note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error + --> $DIR/lines_filter_map_ok.rs:11:5 + | +LL | BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::lines-filter-map-ok` implied by `-D warnings` + +error: `flat_map()` will run forever if the iterator repeatedly produces an `Err` + --> $DIR/lines_filter_map_ok.rs:14:31 + | +LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` + | +note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error + --> $DIR/lines_filter_map_ok.rs:14:5 + | +LL | BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` + --> $DIR/lines_filter_map_ok.rs:17:25 + | +LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` + | +note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error + --> $DIR/lines_filter_map_ok.rs:17:5 + | +LL | io::stdin().lines().filter_map(Result::ok).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^ + +error: `filter_map()` will run forever if the iterator repeatedly produces an `Err` + --> $DIR/lines_filter_map_ok.rs:19:25 + | +LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)` + | +note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error + --> $DIR/lines_filter_map_ok.rs:19:5 + | +LL | io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ()); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs new file mode 100644 index 00000000000..5082f931f3c --- /dev/null +++ b/tests/ui/manual_slice_size_calculation.rs @@ -0,0 +1,36 @@ +#![allow(unused)] +#![warn(clippy::manual_slice_size_calculation)] + +use core::mem::{align_of, size_of}; + +fn main() { + let v_i32 = Vec::::new(); + let s_i32 = v_i32.as_slice(); + + // True positives: + let _ = s_i32.len() * size_of::(); // WARNING + let _ = size_of::() * s_i32.len(); // WARNING + let _ = size_of::() * s_i32.len() * 5; // WARNING + + let len = s_i32.len(); + let size = size_of::(); + let _ = len * size_of::(); // WARNING + let _ = s_i32.len() * size; // WARNING + let _ = len * size; // WARNING + + // True negatives: + let _ = size_of::() + s_i32.len(); // Ok, not a multiplication + let _ = size_of::() * s_i32.partition_point(|_| true); // Ok, not len() + let _ = size_of::() * v_i32.len(); // Ok, not a slice + let _ = align_of::() * s_i32.len(); // Ok, not size_of() + let _ = size_of::() * s_i32.len(); // Ok, different types + + // False negatives: + let _ = 5 * size_of::() * s_i32.len(); // Ok (MISSED OPPORTUNITY) + let _ = size_of::() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY) +} + +const fn _const(s_i32: &[i32]) { + // True negative: + let _ = s_i32.len() * size_of::(); // Ok, can't use size_of_val in const +} diff --git a/tests/ui/manual_slice_size_calculation.stderr b/tests/ui/manual_slice_size_calculation.stderr new file mode 100644 index 00000000000..4a24fc60a0f --- /dev/null +++ b/tests/ui/manual_slice_size_calculation.stderr @@ -0,0 +1,51 @@ +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:11:13 + | +LL | let _ = s_i32.len() * size_of::(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using std::mem::size_of_value instead + = note: `-D clippy::manual-slice-size-calculation` implied by `-D warnings` + +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:12:13 + | +LL | let _ = size_of::() * s_i32.len(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using std::mem::size_of_value instead + +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:13:13 + | +LL | let _ = size_of::() * s_i32.len() * 5; // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using std::mem::size_of_value instead + +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:17:13 + | +LL | let _ = len * size_of::(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using std::mem::size_of_value instead + +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:18:13 + | +LL | let _ = s_i32.len() * size; // WARNING + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider using std::mem::size_of_value instead + +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:19:13 + | +LL | let _ = len * size; // WARNING + | ^^^^^^^^^^ + | + = help: consider using std::mem::size_of_value instead + +error: aborting due to 6 previous errors + diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index 874d5584330..7fd340173af 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -90,3 +90,37 @@ fn msrv_1_40() { let mut s = String::from("foo"); let _ = std::mem::take(&mut s); } + +fn issue9824() { + struct Foo<'a>(Option<&'a str>); + impl<'a> std::ops::Deref for Foo<'a> { + type Target = Option<&'a str>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl<'a> std::ops::DerefMut for Foo<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + struct Bar { + opt: Option, + val: String, + } + + let mut f = Foo(Some("foo")); + let mut b = Bar { + opt: Some(1), + val: String::from("bar"), + }; + + // replace option with none + let _ = f.0.take(); + let _ = (*f).take(); + let _ = b.opt.take(); + // replace with default + let _ = std::mem::take(&mut b.val); +} diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index f4f3bff5144..fa2903addbc 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -90,3 +90,37 @@ fn msrv_1_40() { let mut s = String::from("foo"); let _ = std::mem::replace(&mut s, String::default()); } + +fn issue9824() { + struct Foo<'a>(Option<&'a str>); + impl<'a> std::ops::Deref for Foo<'a> { + type Target = Option<&'a str>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl<'a> std::ops::DerefMut for Foo<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + struct Bar { + opt: Option, + val: String, + } + + let mut f = Foo(Some("foo")); + let mut b = Bar { + opt: Some(1), + val: String::from("bar"), + }; + + // replace option with none + let _ = std::mem::replace(&mut f.0, None); + let _ = std::mem::replace(&mut *f, None); + let _ = std::mem::replace(&mut b.opt, None); + // replace with default + let _ = std::mem::replace(&mut b.val, String::default()); +} diff --git a/tests/ui/mem_replace.stderr b/tests/ui/mem_replace.stderr index caa127f76ee..58b57be7507 100644 --- a/tests/ui/mem_replace.stderr +++ b/tests/ui/mem_replace.stderr @@ -122,5 +122,29 @@ error: replacing a value of type `T` with `T::default()` is better expressed usi LL | let _ = std::mem::replace(&mut s, String::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)` -error: aborting due to 20 previous errors +error: replacing an `Option` with `None` + --> $DIR/mem_replace.rs:121:13 + | +LL | let _ = std::mem::replace(&mut f.0, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()` + +error: replacing an `Option` with `None` + --> $DIR/mem_replace.rs:122:13 + | +LL | let _ = std::mem::replace(&mut *f, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()` + +error: replacing an `Option` with `None` + --> $DIR/mem_replace.rs:123:13 + | +LL | let _ = std::mem::replace(&mut b.opt, None); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()` + +error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take` + --> $DIR/mem_replace.rs:125:13 + | +LL | let _ = std::mem::replace(&mut b.val, String::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut b.val)` + +error: aborting due to 24 previous errors diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index 0f525dd294c..57c08996ce2 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -307,4 +307,13 @@ mod issue10049 { } } +fn test_match_as_stmt() { + let x = 9; + match x { + 1 => 2, + 2 => return, + _ => 0, + }; +} + fn main() {} diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index a1db8375d95..7c1feefbe32 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -317,4 +317,13 @@ mod issue10049 { } } +fn test_match_as_stmt() { + let x = 9; + match x { + 1 => 2, + 2 => return, + _ => 0, + }; +} + fn main() {} diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index 3b5a374b4a7..80cc7c60f56 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -92,3 +92,21 @@ fn issue_10523_2() { } if a!() {} } + +fn issue_10435() { + let x = vec![0]; + let y = vec![1]; + let z = vec![2]; + + // vvv Should not lint + #[allow(clippy::nonminimal_bool)] + if !x.is_empty() && !(y.is_empty() || z.is_empty()) { + println!("{}", line!()); + } + + // vvv Should not lint (#10435 talks about a bug where it lints) + #[allow(clippy::nonminimal_bool)] + if !(x == [0]) { + println!("{}", line!()); + } +} diff --git a/tests/ui/print_literal.rs b/tests/ui/print_literal.rs index 86f908f66b8..538513e9156 100644 --- a/tests/ui/print_literal.rs +++ b/tests/ui/print_literal.rs @@ -38,4 +38,8 @@ fn main() { // named args shouldn't change anything either println!("{foo} {bar}", foo = "hello", bar = "world"); println!("{bar} {foo}", foo = "hello", bar = "world"); + + // The string literal from `file!()` has a callsite span that isn't marked as coming from an + // expansion + println!("file: {}", file!()); } diff --git a/tests/ui/redundant_async_block.fixed b/tests/ui/redundant_async_block.fixed index d26b7a332cb..ad96993c4a7 100644 --- a/tests/ui/redundant_async_block.fixed +++ b/tests/ui/redundant_async_block.fixed @@ -1,6 +1,6 @@ // run-rustfix -#![allow(unused)] +#![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] use std::future::Future; @@ -16,40 +16,16 @@ async fn func2() -> String { x.await } -macro_rules! await_in_macro { - ($e:expr) => { - std::convert::identity($e).await - }; -} - -async fn func3(n: usize) -> usize { - // Do not lint (suggestion would be `std::convert::identity(func1(n))` - // which copies code from inside the macro) - async move { await_in_macro!(func1(n)) }.await -} - -// This macro should never be linted as `$e` might contain `.await` -macro_rules! async_await_parameter_in_macro { - ($e:expr) => { - async { $e.await } - }; -} - -// MISSED OPPORTUNITY: this macro could be linted as the `async` block does not -// contain code coming from the parameters -macro_rules! async_await_in_macro { - ($f:expr) => { - ($f)(async { func2().await }) - }; -} - fn main() { let fut1 = async { 17 }; + // Lint let fut2 = fut1; let fut1 = async { 25 }; + // Lint let fut2 = fut1; + // Lint let fut = async { 42 }; // Do not lint: not a single expression @@ -60,15 +36,12 @@ fn main() { // Do not lint: expression contains `.await` let fut = async { func1(func2().await.len()).await }; - - let fut = async_await_parameter_in_macro!(func2()); - let fut = async_await_in_macro!(std::convert::identity); } #[allow(clippy::let_and_return)] fn capture_local() -> impl Future { - // Lint let fut = async { 17 }; + // Lint fut } @@ -80,11 +53,39 @@ fn capture_local_closure(s: &str) -> impl Future { #[allow(clippy::let_and_return)] fn capture_arg(s: &str) -> impl Future { - // Lint let fut = async move { s }; + // Lint fut } +fn capture_future_arg(f: impl Future) -> impl Future { + // Lint + f +} + +fn capture_func_result(f: FN) -> impl Future +where + F: Future, + FN: FnOnce() -> F, +{ + // Do not lint, as f() would be evaluated prematurely + async { f().await } +} + +fn double_future(f: impl Future>) -> impl Future { + // Do not lint, we will get a `.await` outside a `.async` + async { f.await.await } +} + +fn await_in_async(f: F) -> impl Future +where + F: FnOnce() -> R, + R: Future, +{ + // Lint + async { f().await + 1 } +} + #[derive(Debug, Clone)] struct F {} @@ -109,3 +110,84 @@ fn capture() { // Do not lint: `val` would not live long enough spawn(async { work(&{ val }).await }); } + +fn await_from_macro() -> impl Future { + macro_rules! mac { + ($e:expr) => { + $e.await + }; + } + // Do not lint: the macro may change in the future + // or return different things depending on its argument + async { mac!(async { 42 }) } +} + +fn async_expr_from_macro() -> impl Future { + macro_rules! mac { + () => { + async { 42 } + }; + } + // Do not lint: the macro may change in the future + async { mac!().await } +} + +fn async_expr_from_macro_deep() -> impl Future { + macro_rules! mac { + () => { + async { 42 } + }; + } + // Do not lint: the macro may change in the future + async { ({ mac!() }).await } +} + +fn all_from_macro() -> impl Future { + macro_rules! mac { + () => { + // Lint + async { 42 } + }; + } + mac!() +} + +fn parts_from_macro() -> impl Future { + macro_rules! mac { + ($e: expr) => { + // Do not lint: `$e` might not always be side-effect free + async { $e.await } + }; + } + mac!(async { 42 }) +} + +fn safe_parts_from_macro() -> impl Future { + macro_rules! mac { + ($e: expr) => { + // Lint + async { $e } + }; + } + mac!(42) +} + +fn parts_from_macro_deep() -> impl Future { + macro_rules! mac { + ($e: expr) => { + // Do not lint: `$e` might not always be side-effect free + async { ($e,).0.await } + }; + } + let f = std::future::ready(42); + mac!(f) +} + +fn await_from_macro_deep() -> impl Future { + macro_rules! mac { + ($e:expr) => {{ $e }.await}; + } + // Do not lint: the macro may change in the future + // or return different things depending on its argument + async { mac!(async { 42 }) } +} diff --git a/tests/ui/redundant_async_block.rs b/tests/ui/redundant_async_block.rs index 04726e62805..7ae23558369 100644 --- a/tests/ui/redundant_async_block.rs +++ b/tests/ui/redundant_async_block.rs @@ -1,6 +1,6 @@ // run-rustfix -#![allow(unused)] +#![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] use std::future::Future; @@ -16,40 +16,16 @@ async fn func2() -> String { x.await } -macro_rules! await_in_macro { - ($e:expr) => { - std::convert::identity($e).await - }; -} - -async fn func3(n: usize) -> usize { - // Do not lint (suggestion would be `std::convert::identity(func1(n))` - // which copies code from inside the macro) - async move { await_in_macro!(func1(n)) }.await -} - -// This macro should never be linted as `$e` might contain `.await` -macro_rules! async_await_parameter_in_macro { - ($e:expr) => { - async { $e.await } - }; -} - -// MISSED OPPORTUNITY: this macro could be linted as the `async` block does not -// contain code coming from the parameters -macro_rules! async_await_in_macro { - ($f:expr) => { - ($f)(async { func2().await }) - }; -} - fn main() { let fut1 = async { 17 }; + // Lint let fut2 = async { fut1.await }; let fut1 = async { 25 }; + // Lint let fut2 = async move { fut1.await }; + // Lint let fut = async { async { 42 }.await }; // Do not lint: not a single expression @@ -60,15 +36,12 @@ fn main() { // Do not lint: expression contains `.await` let fut = async { func1(func2().await.len()).await }; - - let fut = async_await_parameter_in_macro!(func2()); - let fut = async_await_in_macro!(std::convert::identity); } #[allow(clippy::let_and_return)] fn capture_local() -> impl Future { - // Lint let fut = async { 17 }; + // Lint async move { fut.await } } @@ -80,11 +53,39 @@ fn capture_local_closure(s: &str) -> impl Future { #[allow(clippy::let_and_return)] fn capture_arg(s: &str) -> impl Future { - // Lint let fut = async move { s }; + // Lint async move { fut.await } } +fn capture_future_arg(f: impl Future) -> impl Future { + // Lint + async { f.await } +} + +fn capture_func_result(f: FN) -> impl Future +where + F: Future, + FN: FnOnce() -> F, +{ + // Do not lint, as f() would be evaluated prematurely + async { f().await } +} + +fn double_future(f: impl Future>) -> impl Future { + // Do not lint, we will get a `.await` outside a `.async` + async { f.await.await } +} + +fn await_in_async(f: F) -> impl Future +where + F: FnOnce() -> R, + R: Future, +{ + // Lint + async { async { f().await + 1 }.await } +} + #[derive(Debug, Clone)] struct F {} @@ -109,3 +110,84 @@ fn capture() { // Do not lint: `val` would not live long enough spawn(async { work(&{ val }).await }); } + +fn await_from_macro() -> impl Future { + macro_rules! mac { + ($e:expr) => { + $e.await + }; + } + // Do not lint: the macro may change in the future + // or return different things depending on its argument + async { mac!(async { 42 }) } +} + +fn async_expr_from_macro() -> impl Future { + macro_rules! mac { + () => { + async { 42 } + }; + } + // Do not lint: the macro may change in the future + async { mac!().await } +} + +fn async_expr_from_macro_deep() -> impl Future { + macro_rules! mac { + () => { + async { 42 } + }; + } + // Do not lint: the macro may change in the future + async { ({ mac!() }).await } +} + +fn all_from_macro() -> impl Future { + macro_rules! mac { + () => { + // Lint + async { async { 42 }.await } + }; + } + mac!() +} + +fn parts_from_macro() -> impl Future { + macro_rules! mac { + ($e: expr) => { + // Do not lint: `$e` might not always be side-effect free + async { $e.await } + }; + } + mac!(async { 42 }) +} + +fn safe_parts_from_macro() -> impl Future { + macro_rules! mac { + ($e: expr) => { + // Lint + async { async { $e }.await } + }; + } + mac!(42) +} + +fn parts_from_macro_deep() -> impl Future { + macro_rules! mac { + ($e: expr) => { + // Do not lint: `$e` might not always be side-effect free + async { ($e,).0.await } + }; + } + let f = std::future::ready(42); + mac!(f) +} + +fn await_from_macro_deep() -> impl Future { + macro_rules! mac { + ($e:expr) => {{ $e }.await}; + } + // Do not lint: the macro may change in the future + // or return different things depending on its argument + async { mac!(async { 42 }) } +} diff --git a/tests/ui/redundant_async_block.stderr b/tests/ui/redundant_async_block.stderr index 1a1c1603e08..f3dcb09b444 100644 --- a/tests/ui/redundant_async_block.stderr +++ b/tests/ui/redundant_async_block.stderr @@ -7,34 +7,68 @@ LL | let x = async { f.await }; = note: `-D clippy::redundant-async-block` implied by `-D warnings` error: this async expression only awaits a single future - --> $DIR/redundant_async_block.rs:48:16 + --> $DIR/redundant_async_block.rs:22:16 | LL | let fut2 = async { fut1.await }; | ^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1` error: this async expression only awaits a single future - --> $DIR/redundant_async_block.rs:51:16 + --> $DIR/redundant_async_block.rs:26:16 | LL | let fut2 = async move { fut1.await }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1` error: this async expression only awaits a single future - --> $DIR/redundant_async_block.rs:53:15 + --> $DIR/redundant_async_block.rs:29:15 | LL | let fut = async { async { 42 }.await }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }` error: this async expression only awaits a single future - --> $DIR/redundant_async_block.rs:72:5 + --> $DIR/redundant_async_block.rs:45:5 | LL | async move { fut.await } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut` error: this async expression only awaits a single future - --> $DIR/redundant_async_block.rs:85:5 + --> $DIR/redundant_async_block.rs:58:5 | LL | async move { fut.await } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut` -error: aborting due to 6 previous errors +error: this async expression only awaits a single future + --> $DIR/redundant_async_block.rs:63:5 + | +LL | async { f.await } + | ^^^^^^^^^^^^^^^^^ help: you can reduce it to: `f` + +error: this async expression only awaits a single future + --> $DIR/redundant_async_block.rs:86:5 + | +LL | async { async { f().await + 1 }.await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { f().await + 1 }` + +error: this async expression only awaits a single future + --> $DIR/redundant_async_block.rs:149:13 + | +LL | async { async { 42 }.await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }` +... +LL | mac!() + | ------ in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: this async expression only awaits a single future + --> $DIR/redundant_async_block.rs:169:13 + | +LL | async { async { $e }.await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { $e }` +... +LL | mac!(42) + | -------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed index 4c40739d6f5..8c96c4715d3 100644 --- a/tests/ui/single_component_path_imports.fixed +++ b/tests/ui/single_component_path_imports.fixed @@ -2,9 +2,11 @@ #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] +use core; use serde as edres; pub use serde; +use std; macro_rules! m { () => { @@ -17,6 +19,10 @@ fn main() { // False positive #5154, shouldn't trigger lint. m!(); + + // False positive #10549 + let _ = self::std::io::stdout(); + let _ = 0 as self::core::ffi::c_uint; } mod hello_mod { diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs index 9280bab3c71..8434bf7eaf1 100644 --- a/tests/ui/single_component_path_imports.rs +++ b/tests/ui/single_component_path_imports.rs @@ -2,9 +2,11 @@ #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] +use core; use regex; use serde as edres; pub use serde; +use std; macro_rules! m { () => { @@ -17,6 +19,10 @@ fn main() { // False positive #5154, shouldn't trigger lint. m!(); + + // False positive #10549 + let _ = self::std::io::stdout(); + let _ = 0 as self::core::ffi::c_uint; } mod hello_mod { diff --git a/tests/ui/single_component_path_imports.stderr b/tests/ui/single_component_path_imports.stderr index 71dcc25d6e5..d69a86470a5 100644 --- a/tests/ui/single_component_path_imports.stderr +++ b/tests/ui/single_component_path_imports.stderr @@ -1,5 +1,5 @@ error: this import is redundant - --> $DIR/single_component_path_imports.rs:5:1 + --> $DIR/single_component_path_imports.rs:6:1 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely @@ -7,7 +7,7 @@ LL | use regex; = note: `-D clippy::single-component-path-imports` implied by `-D warnings` error: this import is redundant - --> $DIR/single_component_path_imports.rs:23:5 + --> $DIR/single_component_path_imports.rs:29:5 | LL | use regex; | ^^^^^^^^^^ help: remove it entirely diff --git a/tests/ui/suspicious_doc_comments.fixed b/tests/ui/suspicious_doc_comments.fixed new file mode 100644 index 00000000000..b404df94d3c --- /dev/null +++ b/tests/ui/suspicious_doc_comments.fixed @@ -0,0 +1,81 @@ +// run-rustfix +#![allow(unused)] +#![warn(clippy::suspicious_doc_comments)] + +//! Real module documentation. +//! Fake module documentation. +fn baz() {} + +pub mod singleline_outer_doc { + //! This module contains useful functions. + + pub fn bar() {} +} + +pub mod singleline_inner_doc { + //! This module contains useful functions. + + pub fn bar() {} +} + +pub mod multiline_outer_doc { + /*! This module contains useful functions. + */ + + pub fn bar() {} +} + +pub mod multiline_inner_doc { + /*! This module contains useful functions. + */ + + pub fn bar() {} +} + +pub mod multiline_outer_doc2 { + //! This module + //! contains + //! useful functions. + + pub fn bar() {} +} + +pub mod multiline_outer_doc3 { + //! a + //! b + + /// c + pub fn bar() {} +} + +pub mod multiline_outer_doc4 { + //! a + /// b + pub fn bar() {} +} + +pub mod multiline_outer_doc_gap { + //! a + + //! b + pub fn bar() {} +} + +pub mod multiline_outer_doc_commented { + /////! This outer doc comment was commented out. + pub fn bar() {} +} + +pub mod outer_doc_macro { + //! Very cool macro + macro_rules! x { + () => {}; + } +} + +pub mod useless_outer_doc { + //! Huh. + use std::mem; +} + +fn main() {} diff --git a/tests/ui/suspicious_doc_comments.rs b/tests/ui/suspicious_doc_comments.rs new file mode 100644 index 00000000000..46eff51e220 --- /dev/null +++ b/tests/ui/suspicious_doc_comments.rs @@ -0,0 +1,81 @@ +// run-rustfix +#![allow(unused)] +#![warn(clippy::suspicious_doc_comments)] + +//! Real module documentation. +///! Fake module documentation. +fn baz() {} + +pub mod singleline_outer_doc { + ///! This module contains useful functions. + + pub fn bar() {} +} + +pub mod singleline_inner_doc { + //! This module contains useful functions. + + pub fn bar() {} +} + +pub mod multiline_outer_doc { + /**! This module contains useful functions. + */ + + pub fn bar() {} +} + +pub mod multiline_inner_doc { + /*! This module contains useful functions. + */ + + pub fn bar() {} +} + +pub mod multiline_outer_doc2 { + ///! This module + ///! contains + ///! useful functions. + + pub fn bar() {} +} + +pub mod multiline_outer_doc3 { + ///! a + ///! b + + /// c + pub fn bar() {} +} + +pub mod multiline_outer_doc4 { + ///! a + /// b + pub fn bar() {} +} + +pub mod multiline_outer_doc_gap { + ///! a + + ///! b + pub fn bar() {} +} + +pub mod multiline_outer_doc_commented { + /////! This outer doc comment was commented out. + pub fn bar() {} +} + +pub mod outer_doc_macro { + ///! Very cool macro + macro_rules! x { + () => {}; + } +} + +pub mod useless_outer_doc { + ///! Huh. + use std::mem; +} + +fn main() {} diff --git a/tests/ui/suspicious_doc_comments.stderr b/tests/ui/suspicious_doc_comments.stderr new file mode 100644 index 00000000000..6c167df2787 --- /dev/null +++ b/tests/ui/suspicious_doc_comments.stderr @@ -0,0 +1,114 @@ +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:6:1 + | +LL | ///! Fake module documentation. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::suspicious-doc-comments` implied by `-D warnings` +help: use an inner doc comment to document the parent module or crate + | +LL | //! Fake module documentation. + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:10:5 + | +LL | ///! This module contains useful functions. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use an inner doc comment to document the parent module or crate + | +LL | //! This module contains useful functions. + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:22:5 + | +LL | / /**! This module contains useful functions. +LL | | */ + | |_______^ + | +help: use an inner doc comment to document the parent module or crate + | +LL ~ /*! This module contains useful functions. +LL + */ + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:36:5 + | +LL | / ///! This module +LL | | ///! contains +LL | | ///! useful functions. + | |__________________________^ + | +help: use an inner doc comment to document the parent module or crate + | +LL ~ //! This module +LL ~ //! contains +LL ~ //! useful functions. + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:44:5 + | +LL | / ///! a +LL | | ///! b + | |__________^ + | +help: use an inner doc comment to document the parent module or crate + | +LL ~ //! a +LL ~ //! b + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:52:5 + | +LL | ///! a + | ^^^^^^ + | +help: use an inner doc comment to document the parent module or crate + | +LL | //! a + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:58:5 + | +LL | / ///! a +LL | | +LL | | ///! b + | |__________^ + | +help: use an inner doc comment to document the parent module or crate + | +LL ~ //! a +LL | +LL ~ //! b + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:70:5 + | +LL | ///! Very cool macro + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use an inner doc comment to document the parent module or crate + | +LL | //! Very cool macro + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments.rs:77:5 + | +LL | ///! Huh. + | ^^^^^^^^^ + | +help: use an inner doc comment to document the parent module or crate + | +LL | //! Huh. + | + +error: aborting due to 9 previous errors + diff --git a/tests/ui/suspicious_doc_comments_unfixable.rs b/tests/ui/suspicious_doc_comments_unfixable.rs new file mode 100644 index 00000000000..ad98c7f4966 --- /dev/null +++ b/tests/ui/suspicious_doc_comments_unfixable.rs @@ -0,0 +1,16 @@ +#![allow(unused)] +#![warn(clippy::suspicious_doc_comments)] + +///! a +///! b +/// c +///! d +pub fn foo() {} + +///! a +///! b +/// c +///! d +use std::mem; + +fn main() {} diff --git a/tests/ui/suspicious_doc_comments_unfixable.stderr b/tests/ui/suspicious_doc_comments_unfixable.stderr new file mode 100644 index 00000000000..f89146dad36 --- /dev/null +++ b/tests/ui/suspicious_doc_comments_unfixable.stderr @@ -0,0 +1,37 @@ +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments_unfixable.rs:4:1 + | +LL | / ///! a +LL | | ///! b +LL | | /// c +LL | | ///! d + | |______^ + | + = note: `-D clippy::suspicious-doc-comments` implied by `-D warnings` +help: use an inner doc comment to document the parent module or crate + | +LL + //! a +LL + //! b +LL | /// c +LL + //! d + | + +error: this is an outer doc comment and does not apply to the parent module or crate + --> $DIR/suspicious_doc_comments_unfixable.rs:10:1 + | +LL | / ///! a +LL | | ///! b +LL | | /// c +LL | | ///! d + | |______^ + | +help: use an inner doc comment to document the parent module or crate + | +LL + //! a +LL + //! b +LL | /// c +LL + //! d + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/tests_outside_test_module.rs b/tests/ui/tests_outside_test_module.rs new file mode 100644 index 00000000000..1982b1d0107 --- /dev/null +++ b/tests/ui/tests_outside_test_module.rs @@ -0,0 +1,18 @@ +// compile-flags: --test +#![allow(unused)] +#![warn(clippy::tests_outside_test_module)] + +fn main() { + // test code goes here +} + +// Should lint +#[test] +fn my_test() {} + +#[cfg(test)] +mod tests { + // Should not lint + #[test] + fn my_test() {} +} diff --git a/tests/ui/tests_outside_test_module.stderr b/tests/ui/tests_outside_test_module.stderr new file mode 100644 index 00000000000..125a79d6edf --- /dev/null +++ b/tests/ui/tests_outside_test_module.stderr @@ -0,0 +1,11 @@ +error: this function marked with #[test] is outside a #[cfg(test)] module + --> $DIR/tests_outside_test_module.rs:11:1 + | +LL | fn my_test() {} + | ^^^^^^^^^^^^^^^ + | + = note: move it to a testing module marked with #[cfg(test)] + = note: `-D clippy::tests-outside-test-module` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 55307506eb3..cc84ba25bd0 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -4,7 +4,7 @@ // would otherwise be responsible for #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)] +#![allow(unused, clippy::borrow_as_ptr)] use std::mem::{size_of, transmute}; @@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair { unsafe { transmute::(in_param) } } + +fn issue_10449() { + fn f() {} + + let _x: u8 = unsafe { *(f as *const u8) }; +} diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs index e7360f3f9dc..aa65ab4dd24 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -4,7 +4,7 @@ // would otherwise be responsible for #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)] +#![allow(unused, clippy::borrow_as_ptr)] use std::mem::{size_of, transmute}; @@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair { unsafe { transmute::(in_param) } } + +fn issue_10449() { + fn f() {} + + let _x: u8 = unsafe { *std::mem::transmute::(f) }; +} diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/tests/ui/transmutes_expressible_as_ptr_casts.stderr index e862fcb67a4..58f5162c78e 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -58,5 +58,11 @@ error: transmute from a reference to a pointer LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` -error: aborting due to 9 previous errors +error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead + --> $DIR/transmutes_expressible_as_ptr_casts.rs:84:28 + | +LL | let _x: u8 = unsafe { *std::mem::transmute::(f) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)` + +error: aborting due to 10 previous errors diff --git a/tests/ui/uninit.rs b/tests/ui/uninit.rs index 412b36b4ee8..c996de89422 100644 --- a/tests/ui/uninit.rs +++ b/tests/ui/uninit.rs @@ -1,7 +1,7 @@ #![feature(stmt_expr_attributes)] #![allow(clippy::let_unit_value, invalid_value)] -use std::mem::{self, MaybeUninit}; +use std::mem::MaybeUninit; union MyOwnMaybeUninit { value: u8, @@ -30,12 +30,24 @@ fn main() { let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() }; // Was a false negative. - let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() }; + let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; polymorphic::<()>(); + polymorphic_maybe_uninit_array::<10>(); + polymorphic_maybe_uninit::(); fn polymorphic() { // We are conservative around polymorphic types. - let _: T = unsafe { mem::MaybeUninit::uninit().assume_init() }; + let _: T = unsafe { MaybeUninit::uninit().assume_init() }; + } + + fn polymorphic_maybe_uninit_array() { + // While the type is polymorphic, MaybeUninit is not. + let _: [MaybeUninit; N] = unsafe { MaybeUninit::uninit().assume_init() }; + } + + fn polymorphic_maybe_uninit() { + // The entire type is polymorphic, but it's wrapped in a MaybeUninit. + let _: MaybeUninit = unsafe { MaybeUninit::uninit().assume_init() }; } } diff --git a/tests/ui/uninit.stderr b/tests/ui/uninit.stderr index 9e01b9a4aa8..248de56da76 100644 --- a/tests/ui/uninit.stderr +++ b/tests/ui/uninit.stderr @@ -9,14 +9,14 @@ LL | let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; error: this call for this type may be undefined behavior --> $DIR/uninit.rs:33:29 | -LL | let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call for this type may be undefined behavior - --> $DIR/uninit.rs:39:29 + --> $DIR/uninit.rs:41:29 | -LL | let _: T = unsafe { mem::MaybeUninit::uninit().assume_init() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: T = unsafe { MaybeUninit::uninit().assume_init() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/uninit_vec.rs b/tests/ui/uninit_vec.rs index 59ec64a7ab1..79effc82fdf 100644 --- a/tests/ui/uninit_vec.rs +++ b/tests/ui/uninit_vec.rs @@ -124,4 +124,12 @@ fn main() { vec.set_len(10); } } + + fn poly_maybe_uninit() { + // We are conservative around polymorphic types. + let mut vec: Vec> = Vec::with_capacity(1000); + unsafe { + vec.set_len(10); + } + } } diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 1475d781c67..3122081a44f 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -1,7 +1,7 @@ // aux-build:proc_macros.rs // run-rustfix #![warn(clippy::uninlined_format_args)] -#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)] +#![allow(named_arguments_used_positionally, unused)] #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] extern crate proc_macros; @@ -119,7 +119,7 @@ fn tester(fn_arg: i32) { println!("Width = {local_i32}, value with width = {local_f64:local_i32$}"); println!("{local_i32:width$.prec$}"); println!("{width:width$.prec$}"); - println!("{}", format!("{local_i32}")); + println!("{}", format!("{}", local_i32)); my_println!("{}", local_i32); my_println_args!("{}", local_i32); @@ -178,3 +178,87 @@ fn _meets_msrv() { fn _do_not_fire() { println!("{:?}", None::<()>); } + +macro_rules! _internal { + ($($args:tt)*) => { + println!("{}", format_args!($($args)*)) + }; +} + +macro_rules! my_println2 { + ($target:expr, $($args:tt)+) => {{ + if $target { + _internal!($($args)+) + } + }}; +} + +macro_rules! my_println2_args { + ($target:expr, $($args:tt)+) => {{ + if $target { + _internal!("foo: {}", format_args!($($args)+)) + } + }}; +} + +macro_rules! my_concat { + ($fmt:literal $(, $e:expr)*) => { + println!(concat!("ERROR: ", $fmt), $($e,)*) + } +} + +macro_rules! my_good_macro { + ($fmt:literal $(, $e:expr)* $(,)?) => { + println!($fmt $(, $e)*) + } +} + +macro_rules! my_bad_macro { + ($fmt:literal, $($e:expr),*) => { + println!($fmt, $($e,)*) + } +} + +macro_rules! my_bad_macro2 { + ($fmt:literal) => { + let s = $fmt.clone(); + println!("{}", s); + }; + ($fmt:literal, $($e:expr)+) => { + println!($fmt, $($e,)*) + }; +} + +// This abomination was suggested by @Alexendoo, may the Rust gods have mercy on their soul... +// https://github.com/rust-lang/rust-clippy/pull/9948#issuecomment-1327965962 +macro_rules! used_twice { + ( + large = $large:literal, + small = $small:literal, + $val:expr, + ) => { + if $val < 5 { + println!($small, $val); + } else { + println!($large, $val); + } + }; +} + +fn tester2() { + let local_i32 = 1; + my_println2_args!(true, "{}", local_i32); + my_println2!(true, "{}", local_i32); + my_concat!("{}", local_i32); + my_good_macro!("{}", local_i32); + my_good_macro!("{}", local_i32,); + + // FIXME: Broken false positives, currently unhandled + my_bad_macro!("{}", local_i32); + my_bad_macro2!("{}", local_i32); + used_twice! { + large = "large value: {}", + small = "small value: {}", + local_i32, + }; +} diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 835afac393f..b153ef256e0 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -1,7 +1,7 @@ // aux-build:proc_macros.rs // run-rustfix #![warn(clippy::uninlined_format_args)] -#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)] +#![allow(named_arguments_used_positionally, unused)] #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] extern crate proc_macros; @@ -183,3 +183,87 @@ fn _meets_msrv() { fn _do_not_fire() { println!("{:?}", None::<()>); } + +macro_rules! _internal { + ($($args:tt)*) => { + println!("{}", format_args!($($args)*)) + }; +} + +macro_rules! my_println2 { + ($target:expr, $($args:tt)+) => {{ + if $target { + _internal!($($args)+) + } + }}; +} + +macro_rules! my_println2_args { + ($target:expr, $($args:tt)+) => {{ + if $target { + _internal!("foo: {}", format_args!($($args)+)) + } + }}; +} + +macro_rules! my_concat { + ($fmt:literal $(, $e:expr)*) => { + println!(concat!("ERROR: ", $fmt), $($e,)*) + } +} + +macro_rules! my_good_macro { + ($fmt:literal $(, $e:expr)* $(,)?) => { + println!($fmt $(, $e)*) + } +} + +macro_rules! my_bad_macro { + ($fmt:literal, $($e:expr),*) => { + println!($fmt, $($e,)*) + } +} + +macro_rules! my_bad_macro2 { + ($fmt:literal) => { + let s = $fmt.clone(); + println!("{}", s); + }; + ($fmt:literal, $($e:expr)+) => { + println!($fmt, $($e,)*) + }; +} + +// This abomination was suggested by @Alexendoo, may the Rust gods have mercy on their soul... +// https://github.com/rust-lang/rust-clippy/pull/9948#issuecomment-1327965962 +macro_rules! used_twice { + ( + large = $large:literal, + small = $small:literal, + $val:expr, + ) => { + if $val < 5 { + println!($small, $val); + } else { + println!($large, $val); + } + }; +} + +fn tester2() { + let local_i32 = 1; + my_println2_args!(true, "{}", local_i32); + my_println2!(true, "{}", local_i32); + my_concat!("{}", local_i32); + my_good_macro!("{}", local_i32); + my_good_macro!("{}", local_i32,); + + // FIXME: Broken false positives, currently unhandled + my_bad_macro!("{}", local_i32); + my_bad_macro2!("{}", local_i32); + used_twice! { + large = "large value: {}", + small = "small value: {}", + local_i32, + }; +} diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index a12abf8bef8..dc4af6ef42e 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -774,18 +774,6 @@ LL - println!("{:w$.p$}", w = width, p = prec); LL + println!("{width:width$.prec$}"); | -error: variables can be used directly in the `format!` string - --> $DIR/uninlined_format_args.rs:125:20 - | -LL | println!("{}", format!("{}", local_i32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: change this to - | -LL - println!("{}", format!("{}", local_i32)); -LL + println!("{}", format!("{local_i32}")); - | - error: variables can be used directly in the `format!` string --> $DIR/uninlined_format_args.rs:143:5 | @@ -856,5 +844,5 @@ LL - println!("expand='{}'", local_i32); LL + println!("expand='{local_i32}'"); | -error: aborting due to 72 previous errors +error: aborting due to 71 previous errors diff --git a/tests/ui/unnecessary_box_returns.rs b/tests/ui/unnecessary_box_returns.rs new file mode 100644 index 00000000000..fe60d929759 --- /dev/null +++ b/tests/ui/unnecessary_box_returns.rs @@ -0,0 +1,60 @@ +#![warn(clippy::unnecessary_box_returns)] + +trait Bar { + // lint + fn baz(&self) -> Box; +} + +pub struct Foo {} + +impl Bar for Foo { + // don't lint: this is a problem with the trait, not the implementation + fn baz(&self) -> Box { + Box::new(42) + } +} + +impl Foo { + fn baz(&self) -> Box { + // lint + Box::new(13) + } +} + +// lint +fn bxed_usize() -> Box { + Box::new(5) +} + +// lint +fn _bxed_foo() -> Box { + Box::new(Foo {}) +} + +// don't lint: this is exported +pub fn bxed_foo() -> Box { + Box::new(Foo {}) +} + +// don't lint: str is unsized +fn bxed_str() -> Box { + "Hello, world!".to_string().into_boxed_str() +} + +// don't lint: function contains the word, "box" +fn boxed_usize() -> Box { + Box::new(7) +} + +// don't lint: this has an unspecified return type +fn default() {} + +// don't lint: this doesn't return a Box +fn string() -> String { + String::from("Hello, world") +} + +fn main() { + // don't lint: this is a closure + let a = || -> Box { Box::new(5) }; +} diff --git a/tests/ui/unnecessary_box_returns.stderr b/tests/ui/unnecessary_box_returns.stderr new file mode 100644 index 00000000000..b17512c10a1 --- /dev/null +++ b/tests/ui/unnecessary_box_returns.stderr @@ -0,0 +1,35 @@ +error: boxed return of the sized type `usize` + --> $DIR/unnecessary_box_returns.rs:5:22 + | +LL | fn baz(&self) -> Box; + | ^^^^^^^^^^ help: try: `usize` + | + = help: changing this also requires a change to the return expressions in this function + = note: `-D clippy::unnecessary-box-returns` implied by `-D warnings` + +error: boxed return of the sized type `usize` + --> $DIR/unnecessary_box_returns.rs:18:22 + | +LL | fn baz(&self) -> Box { + | ^^^^^^^^^^ help: try: `usize` + | + = help: changing this also requires a change to the return expressions in this function + +error: boxed return of the sized type `usize` + --> $DIR/unnecessary_box_returns.rs:25:20 + | +LL | fn bxed_usize() -> Box { + | ^^^^^^^^^^ help: try: `usize` + | + = help: changing this also requires a change to the return expressions in this function + +error: boxed return of the sized type `Foo` + --> $DIR/unnecessary_box_returns.rs:30:19 + | +LL | fn _bxed_foo() -> Box { + | ^^^^^^^^ help: try: `Foo` + | + = help: changing this also requires a change to the return expressions in this function + +error: aborting due to 4 previous errors + diff --git a/tests/ui/unused_format_specs.fixed b/tests/ui/unused_format_specs.fixed deleted file mode 100644 index 2930722b42d..00000000000 --- a/tests/ui/unused_format_specs.fixed +++ /dev/null @@ -1,18 +0,0 @@ -// run-rustfix - -#![warn(clippy::unused_format_specs)] -#![allow(unused)] - -fn main() { - let f = 1.0f64; - println!("{}", 1.0); - println!("{f} {f:?}"); - - println!("{}", 1); -} - -fn should_not_lint() { - let f = 1.0f64; - println!("{:.1}", 1.0); - println!("{f:.w$} {f:.*?}", 3, w = 2); -} diff --git a/tests/ui/unused_format_specs.rs b/tests/ui/unused_format_specs.rs deleted file mode 100644 index ee192a000d4..00000000000 --- a/tests/ui/unused_format_specs.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-rustfix - -#![warn(clippy::unused_format_specs)] -#![allow(unused)] - -fn main() { - let f = 1.0f64; - println!("{:.}", 1.0); - println!("{f:.} {f:.?}"); - - println!("{:.}", 1); -} - -fn should_not_lint() { - let f = 1.0f64; - println!("{:.1}", 1.0); - println!("{f:.w$} {f:.*?}", 3, w = 2); -} diff --git a/tests/ui/unused_format_specs.stderr b/tests/ui/unused_format_specs.stderr deleted file mode 100644 index 7231c17e74c..00000000000 --- a/tests/ui/unused_format_specs.stderr +++ /dev/null @@ -1,54 +0,0 @@ -error: empty precision specifier has no effect - --> $DIR/unused_format_specs.rs:8:17 - | -LL | println!("{:.}", 1.0); - | ^ - | - = note: a precision specifier is not required to format floats - = note: `-D clippy::unused-format-specs` implied by `-D warnings` -help: remove the `.` - | -LL - println!("{:.}", 1.0); -LL + println!("{}", 1.0); - | - -error: empty precision specifier has no effect - --> $DIR/unused_format_specs.rs:9:18 - | -LL | println!("{f:.} {f:.?}"); - | ^ - | - = note: a precision specifier is not required to format floats -help: remove the `.` - | -LL - println!("{f:.} {f:.?}"); -LL + println!("{f} {f:.?}"); - | - -error: empty precision specifier has no effect - --> $DIR/unused_format_specs.rs:9:24 - | -LL | println!("{f:.} {f:.?}"); - | ^ - | - = note: a precision specifier is not required to format floats -help: remove the `.` - | -LL - println!("{f:.} {f:.?}"); -LL + println!("{f:.} {f:?}"); - | - -error: empty precision specifier has no effect - --> $DIR/unused_format_specs.rs:11:17 - | -LL | println!("{:.}", 1); - | ^ - | -help: remove the `.` - | -LL - println!("{:.}", 1); -LL + println!("{}", 1); - | - -error: aborting due to 4 previous errors - diff --git a/tests/ui/unused_format_specs_unfixable.stderr b/tests/ui/unused_format_specs_unfixable.stderr index 9f1890282e6..cb7156b6baf 100644 --- a/tests/ui/unused_format_specs_unfixable.stderr +++ b/tests/ui/unused_format_specs_unfixable.stderr @@ -37,11 +37,7 @@ error: format specifiers have no effect on `format_args!()` LL | println!("{:5}.", format_args_from_macro!()); | ^^^^ | -help: for the width to apply consider using `format!()` - --> $DIR/unused_format_specs_unfixable.rs:16:17 - | -LL | println!("{:5}.", format_args_from_macro!()); - | ^ + = help: for the width to apply consider using `format!()` help: if the current behavior is intentional, remove the format specifiers | LL - println!("{:5}.", format_args_from_macro!()); @@ -54,11 +50,7 @@ error: format specifiers have no effect on `format_args!()` LL | println!("{args:5}"); | ^^^^^^^^ | -help: for the width to apply consider using `format!()` - --> $DIR/unused_format_specs_unfixable.rs:19:21 - | -LL | println!("{args:5}"); - | ^ + = help: for the width to apply consider using `format!()` help: if the current behavior is intentional, remove the format specifiers | LL - println!("{args:5}"); -- cgit 1.4.1-3-g733a5 From 5989400e2e068aec0ecc12e53dddc1d8b0c0e585 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 10 Apr 2023 19:07:57 +0300 Subject: resolve: Pre-compute non-reexport module children Instead of repeating the same logic by walking HIR during metadata encoding. The only difference is that we are no longer encoding `macro_rules` items, but we never currently need them as a part of this list. They can be encoded separately if this need ever arises. `module_reexports` is also un-querified, because I don't see any reasons to make it a query, only overhead. --- tests/ui/macro_use_imports.fixed | 2 +- tests/ui/macro_use_imports.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index 15f7a099a7d..a395e4f5653 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -16,7 +16,7 @@ extern crate macro_use_helper as mac; extern crate proc_macro_derive as mini_mac; mod a { - use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro}; + use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro}; use mac; use mini_mac::ClippyMiniMacroTest; use mini_mac; diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr index 68d558dede0..6fd338cef86 100644 --- a/tests/ui/macro_use_imports.stderr +++ b/tests/ui/macro_use_imports.stderr @@ -22,7 +22,7 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition --> $DIR/macro_use_imports.rs:19:5 | LL | #[macro_use] - | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, function_macro, ty_macro, inner_mod_macro, pub_in_private_macro};` + | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 7a0fb902bc3c02f7832f8fed074d8dfd21bf7ea8 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sat, 18 Mar 2023 02:18:39 +0000 Subject: Tweak output for 'add line' suggestion --- tests/ui/crashes/ice-6252.stderr | 9 ++++++--- tests/ui/derivable_impls.stderr | 24 ++++++++++++++++-------- tests/ui/new_without_default.stderr | 6 ++++++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/tests/ui/crashes/ice-6252.stderr b/tests/ui/crashes/ice-6252.stderr index efdd56dd47d..3c7e08ebeae 100644 --- a/tests/ui/crashes/ice-6252.stderr +++ b/tests/ui/crashes/ice-6252.stderr @@ -6,11 +6,14 @@ LL | _n: PhantomData, | help: consider importing one of these items | -LL | use core::marker::PhantomData; +LL + use core::marker::PhantomData; +LL | trait TypeVal { | -LL | use serde::__private::PhantomData; +LL + use serde::__private::PhantomData; +LL | trait TypeVal { | -LL | use std::marker::PhantomData; +LL + use std::marker::PhantomData; +LL | trait TypeVal { | error[E0412]: cannot find type `VAL` in this scope diff --git a/tests/ui/derivable_impls.stderr b/tests/ui/derivable_impls.stderr index 81963c3be5b..8089f5ea0fc 100644 --- a/tests/ui/derivable_impls.stderr +++ b/tests/ui/derivable_impls.stderr @@ -14,7 +14,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | struct FooDefault<'a> { | error: this `impl` can be derived @@ -30,7 +31,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | struct TupleDefault(bool, i32, u64); | error: this `impl` can be derived @@ -46,7 +48,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | struct StrDefault<'a>(&'a str); | error: this `impl` can be derived @@ -62,7 +65,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | struct Y(u32); | error: this `impl` can be derived @@ -78,7 +82,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | struct WithoutSelfCurly { | error: this `impl` can be derived @@ -94,7 +99,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | struct WithoutSelfParan(bool); | error: this `impl` can be derived @@ -110,7 +116,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | pub struct RepeatDefault1 { | error: this `impl` can be derived @@ -126,7 +133,8 @@ LL | | } = help: remove the manual implementation... help: ...and instead derive it... | -LL | #[derive(Default)] +LL + #[derive(Default)] +LL | pub enum SimpleEnum { | help: ...and mark the default variant | diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 583dd327d6a..9b0a2f6ca5b 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -14,6 +14,7 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } +LL | impl Foo { | error: you should consider adding a `Default` implementation for `Bar` @@ -31,6 +32,7 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } +LL | impl Bar { | error: you should consider adding a `Default` implementation for `LtKo<'c>` @@ -48,6 +50,7 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } +LL | impl<'c> LtKo<'c> { | error: you should consider adding a `Default` implementation for `NewNotEqualToDerive` @@ -65,6 +68,7 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } +LL | impl NewNotEqualToDerive { | error: you should consider adding a `Default` implementation for `FooGenerics` @@ -82,6 +86,7 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } +LL | impl FooGenerics { | error: you should consider adding a `Default` implementation for `BarGenerics` @@ -99,6 +104,7 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } +LL | impl BarGenerics { | error: you should consider adding a `Default` implementation for `Foo` -- cgit 1.4.1-3-g733a5 From 4680aa2fd07876a4d2f7059defef2595e3184038 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 10 Apr 2023 16:46:12 +0000 Subject: Special-case item attributes in the suggestion output --- tests/ui/crashes/ice-6252.stderr | 3 --- tests/ui/new_without_default.stderr | 6 ------ 2 files changed, 9 deletions(-) diff --git a/tests/ui/crashes/ice-6252.stderr b/tests/ui/crashes/ice-6252.stderr index 3c7e08ebeae..4787282f504 100644 --- a/tests/ui/crashes/ice-6252.stderr +++ b/tests/ui/crashes/ice-6252.stderr @@ -7,13 +7,10 @@ LL | _n: PhantomData, help: consider importing one of these items | LL + use core::marker::PhantomData; -LL | trait TypeVal { | LL + use serde::__private::PhantomData; -LL | trait TypeVal { | LL + use std::marker::PhantomData; -LL | trait TypeVal { | error[E0412]: cannot find type `VAL` in this scope diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 9b0a2f6ca5b..583dd327d6a 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -14,7 +14,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl Foo { | error: you should consider adding a `Default` implementation for `Bar` @@ -32,7 +31,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl Bar { | error: you should consider adding a `Default` implementation for `LtKo<'c>` @@ -50,7 +48,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl<'c> LtKo<'c> { | error: you should consider adding a `Default` implementation for `NewNotEqualToDerive` @@ -68,7 +65,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl NewNotEqualToDerive { | error: you should consider adding a `Default` implementation for `FooGenerics` @@ -86,7 +82,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl FooGenerics { | error: you should consider adding a `Default` implementation for `BarGenerics` @@ -104,7 +99,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl BarGenerics { | error: you should consider adding a `Default` implementation for `Foo` -- cgit 1.4.1-3-g733a5 From 8f53926232c43aa9d03e88c24460411542a244ed Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 25 Mar 2023 10:12:35 +0000 Subject: Alloc `hir::Lit` in an arena to remove the destructor from `Expr` This allows allocating `Expr`s into a dropless arena, which is useful for using length prefixed thing slices in HIR, since these can only be allocated in the dropless arena and not in a typed arena. This is something I'm working on. --- clippy_lints/src/bool_assert_comparison.rs | 2 +- clippy_lints/src/manual_strip.rs | 2 +- clippy_lints/src/matches/match_like_matches.rs | 2 +- clippy_lints/src/methods/open_options.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs index 1d9096ea64d..8c3ad24eeed 100644 --- a/clippy_lints/src/bool_assert_comparison.rs +++ b/clippy_lints/src/bool_assert_comparison.rs @@ -41,7 +41,7 @@ fn extract_bool_lit(e: &Expr<'_>) -> Option { }) = e.kind && !e.span.from_expansion() { - Some(b) + Some(*b) } else { None } diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index c795c1d9a16..7d28c111624 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -159,7 +159,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t .. }) = expr.kind { - constant_length(cx, pattern).map_or(false, |length| length == n) + constant_length(cx, pattern).map_or(false, |length| length == *n) } else { len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg)) } diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index 107fad32393..33bc20dad6b 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -162,7 +162,7 @@ fn find_bool_lit(ex: &ExprKind<'_>) -> Option { node: LitKind::Bool(b), .. }) = exp.kind { - Some(b) + Some(*b) } else { None } diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index c6a27cdd6fa..23d23f25f14 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -48,7 +48,7 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec .. } = *span { - if lit { Argument::True } else { Argument::False } + if *lit { Argument::True } else { Argument::False } } else { // The function is called with a literal which is not a boolean literal. // This is theoretically possible, but not very likely. diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index bc4adf1596d..2dac807c420 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Unary(UnOp::{op:?}, {inner})"); self.expr(inner); }, - ExprKind::Lit(ref lit) => { + ExprKind::Lit(lit) => { bind!(self, lit); kind!("Lit(ref {lit})"); self.lit(lit); -- cgit 1.4.1-3-g733a5 From 0a81f8257e2317b019406c42575d10bbd33c7268 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 16 Apr 2023 23:30:00 -0500 Subject: add `semicolon_outside_block_if_singleline` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/semicolon_block.rs | 92 +++++++++++++++++++++- .../ui/semicolon_outside_block_if_singleline.fixed | 85 ++++++++++++++++++++ tests/ui/semicolon_outside_block_if_singleline.rs | 85 ++++++++++++++++++++ .../semicolon_outside_block_if_singleline.stderr | 54 +++++++++++++ 6 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 tests/ui/semicolon_outside_block_if_singleline.fixed create mode 100644 tests/ui/semicolon_outside_block_if_singleline.rs create mode 100644 tests/ui/semicolon_outside_block_if_singleline.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 559b560dde4..a0a7780f4c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4884,6 +4884,7 @@ Released 2018-09-13 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned [`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block [`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block +[`semicolon_outside_block_if_singleline`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block_if_singleline [`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index f24dab62780..70379b6caf1 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -546,6 +546,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO, crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO, crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO, + crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE_INFO, crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO, crate::serde_api::SERDE_API_MISUSE_INFO, crate::shadow::SHADOW_REUSE_INFO, diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index 34a3e5ddf4f..d791100b9b9 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -64,7 +64,48 @@ declare_clippy_lint! { restriction, "add a semicolon outside the block" } -declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]); +declare_clippy_lint! { + /// ### What it does + /// + /// Suggests moving the semicolon from a block's final expression outside of + /// the block if it's singleline, and inside the block if it's multiline. + /// + /// ### Why is this bad? + /// + /// Some may prefer if the semicolon is outside if a block is only one + /// expression, as this allows rustfmt to make it singleline. In the case that + /// it isn't, it should be inside. + /// Take a look at both `semicolon_inside_block` and `semicolon_outside_block` for alternatives. + /// + /// ### Example + /// + /// ```rust + /// # fn f(_: u32) {} + /// # let x = 0; + /// unsafe { f(x); } + /// + /// unsafe { + /// let x = 1; + /// f(x) + /// }; + /// ``` + /// Use instead: + /// ```rust + /// # fn f(_: u32) {} + /// # let x = 0; + /// unsafe { f(x) }; + /// + /// unsafe { + /// let x = 1; + /// f(x); + /// } + /// ``` + #[clippy::version = "1.68.0"] + pub SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, + restriction, + "add a semicolon inside the block if it's singleline, otherwise outside" +} +declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE]); impl LateLintPass<'_> for SemicolonBlock { fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { @@ -98,6 +139,8 @@ fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<' let insert_span = tail.span.source_callsite().shrink_to_hi(); let remove_span = semi_span.with_lo(block.span.hi()); + check_semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, true, "inside"); + span_lint_and_then( cx, SEMICOLON_INSIDE_BLOCK, @@ -120,6 +163,8 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); + check_semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, false, "outside"); + span_lint_and_then( cx, SEMICOLON_OUTSIDE_BLOCK, @@ -135,3 +180,48 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex }, ); } + +fn check_semicolon_outside_block_if_singleline( + cx: &LateContext<'_>, + block: &Block<'_>, + remove_span: Span, + insert_span: Span, + inequality: bool, + ty: &str, +) { + let remove_line = cx + .sess() + .source_map() + .lookup_line(remove_span.lo()) + .expect("failed to get `remove_span`'s line") + .line; + let insert_line = cx + .sess() + .source_map() + .lookup_line(insert_span.lo()) + .expect("failed to get `insert_span`'s line") + .line; + + let eq = if inequality { + remove_line != insert_line + } else { + remove_line == insert_line + }; + + if eq { + span_lint_and_then( + cx, + SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, + block.span, + &format!("consider moving the `;` {ty} the block for consistent formatting"), + |diag| { + multispan_sugg_with_applicability( + diag, + "put the `;` here", + Applicability::MachineApplicable, + [(remove_span, String::new()), (insert_span, ";".to_owned())], + ); + }, + ); + } +} diff --git a/tests/ui/semicolon_outside_block_if_singleline.fixed b/tests/ui/semicolon_outside_block_if_singleline.fixed new file mode 100644 index 00000000000..592f9c49ed7 --- /dev/null +++ b/tests/ui/semicolon_outside_block_if_singleline.fixed @@ -0,0 +1,85 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_outside_block_if_singleline)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()) }; + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} \ No newline at end of file diff --git a/tests/ui/semicolon_outside_block_if_singleline.rs b/tests/ui/semicolon_outside_block_if_singleline.rs new file mode 100644 index 00000000000..21dd61445a5 --- /dev/null +++ b/tests/ui/semicolon_outside_block_if_singleline.rs @@ -0,0 +1,85 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_outside_block_if_singleline)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); } + unsafe { unit_fn_block(); } + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block() + }; + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()); } + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} \ No newline at end of file diff --git a/tests/ui/semicolon_outside_block_if_singleline.stderr b/tests/ui/semicolon_outside_block_if_singleline.stderr new file mode 100644 index 00000000000..dda083f2be3 --- /dev/null +++ b/tests/ui/semicolon_outside_block_if_singleline.stderr @@ -0,0 +1,54 @@ +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/semicolon_outside_block_if_singleline.rs:42:5 + | +LL | { unit_fn_block(); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::semicolon-outside-block-if-singleline` implied by `-D warnings` +help: put the `;` here + | +LL - { unit_fn_block(); } +LL + { unit_fn_block() }; + | + +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/semicolon_outside_block_if_singleline.rs:43:5 + | +LL | unsafe { unit_fn_block(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: put the `;` here + | +LL - unsafe { unit_fn_block(); } +LL + unsafe { unit_fn_block() }; + | + +error: consider moving the `;` inside the block for consistent formatting + --> $DIR/semicolon_outside_block_if_singleline.rs:48:5 + | +LL | / { +LL | | unit_fn_block(); +LL | | unit_fn_block() +LL | | }; + | |_____^ + | +help: put the `;` here + | +LL ~ unit_fn_block(); +LL ~ } + | + +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/semicolon_outside_block_if_singleline.rs:62:5 + | +LL | { m!(()); } + | ^^^^^^^^^^^ + | +help: put the `;` here + | +LL - { m!(()); } +LL + { m!(()) }; + | + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From dfccebe3e01e8c63ea0fc2833550123e45091e5b Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 16 Apr 2023 23:36:01 -0500 Subject: make cargo test pass --- clippy_lints/src/semicolon_block.rs | 4 ++-- tests/ui/semicolon_outside_block_if_singleline.fixed | 2 +- tests/ui/semicolon_outside_block_if_singleline.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index d791100b9b9..eabe0e4619f 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -83,7 +83,7 @@ declare_clippy_lint! { /// # fn f(_: u32) {} /// # let x = 0; /// unsafe { f(x); } - /// + /// /// unsafe { /// let x = 1; /// f(x) @@ -94,7 +94,7 @@ declare_clippy_lint! { /// # fn f(_: u32) {} /// # let x = 0; /// unsafe { f(x) }; - /// + /// /// unsafe { /// let x = 1; /// f(x); diff --git a/tests/ui/semicolon_outside_block_if_singleline.fixed b/tests/ui/semicolon_outside_block_if_singleline.fixed index 592f9c49ed7..e1ecbf8588d 100644 --- a/tests/ui/semicolon_outside_block_if_singleline.fixed +++ b/tests/ui/semicolon_outside_block_if_singleline.fixed @@ -82,4 +82,4 @@ fn main() { { unit_fn_block(); }; unit_fn_block() -} \ No newline at end of file +} diff --git a/tests/ui/semicolon_outside_block_if_singleline.rs b/tests/ui/semicolon_outside_block_if_singleline.rs index 21dd61445a5..80fbb4ce2d5 100644 --- a/tests/ui/semicolon_outside_block_if_singleline.rs +++ b/tests/ui/semicolon_outside_block_if_singleline.rs @@ -82,4 +82,4 @@ fn main() { { unit_fn_block(); }; unit_fn_block() -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From a7c3301b5884b33fc87f2e498f28426dfbcb1a84 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 16 Apr 2023 23:56:21 -0500 Subject: refactor --- clippy_lints/src/semicolon_block.rs | 90 +++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index eabe0e4619f..d85d3b58305 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -125,11 +125,15 @@ impl LateLintPass<'_> for SemicolonBlock { .. } = stmt else { return }; semicolon_outside_block(cx, block, expr, span); + semicolon_outside_block_if_singleline_check_outside(cx, block, expr, stmt.span) }, StmtKind::Semi(Expr { kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _), .. - }) if !block.span.from_expansion() => semicolon_inside_block(cx, block, tail, stmt.span), + }) if !block.span.from_expansion() => { + semicolon_inside_block(cx, block, tail, stmt.span); + semicolon_outside_block_if_singleline_check_inside(cx, block, tail, stmt.span) + }, _ => (), } } @@ -139,8 +143,6 @@ fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<' let insert_span = tail.span.source_callsite().shrink_to_hi(); let remove_span = semi_span.with_lo(block.span.hi()); - check_semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, true, "inside"); - span_lint_and_then( cx, SEMICOLON_INSIDE_BLOCK, @@ -163,8 +165,6 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); - check_semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, false, "outside"); - span_lint_and_then( cx, SEMICOLON_OUTSIDE_BLOCK, @@ -181,39 +181,54 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex ); } -fn check_semicolon_outside_block_if_singleline( +fn semicolon_outside_block_if_singleline_check_inside( cx: &LateContext<'_>, block: &Block<'_>, - remove_span: Span, - insert_span: Span, - inequality: bool, - ty: &str, + tail: &Expr<'_>, + semi_span: Span, ) { - let remove_line = cx - .sess() - .source_map() - .lookup_line(remove_span.lo()) - .expect("failed to get `remove_span`'s line") - .line; - let insert_line = cx - .sess() - .source_map() - .lookup_line(insert_span.lo()) - .expect("failed to get `insert_span`'s line") - .line; + let insert_span = tail.span.source_callsite().shrink_to_hi(); + let remove_span = semi_span.with_lo(block.span.hi()); + + let (remove_line, insert_line) = get_line(cx, remove_span, insert_span); + + if insert_line != remove_line { + span_lint_and_then( + cx, + SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, + block.span, + &format!("consider moving the `;` inside the block for consistent formatting"), + |diag| { + multispan_sugg_with_applicability( + diag, + "put the `;` here", + Applicability::MachineApplicable, + [(remove_span, String::new()), (insert_span, ";".to_owned())], + ); + }, + ); + } +} - let eq = if inequality { - remove_line != insert_line - } else { - remove_line == insert_line - }; +fn semicolon_outside_block_if_singleline_check_outside( + cx: &LateContext<'_>, + block: &Block<'_>, + tail_stmt_expr: &Expr<'_>, + semi_span: Span, +) { + let insert_span = block.span.with_lo(block.span.hi()); + // account for macro calls + let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); + let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); + + let (remove_line, insert_line) = get_line(cx, remove_span, insert_span); - if eq { + if remove_line == insert_line { span_lint_and_then( cx, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, block.span, - &format!("consider moving the `;` {ty} the block for consistent formatting"), + &format!("consider moving the `;` outside the block for consistent formatting"), |diag| { multispan_sugg_with_applicability( diag, @@ -225,3 +240,20 @@ fn check_semicolon_outside_block_if_singleline( ); } } + +fn get_line(cx: &LateContext<'_>, remove_span: Span, insert_span: Span) -> (usize, usize) { + let remove_line = cx + .sess() + .source_map() + .lookup_line(remove_span.lo()) + .expect("failed to get `remove_span`'s line") + .line; + let insert_line = cx + .sess() + .source_map() + .lookup_line(insert_span.lo()) + .expect("failed to get `insert_span`'s line") + .line; + + (remove_line, insert_line) +} -- cgit 1.4.1-3-g733a5 From a57445d4d6c14adfd2103796a577805a04bb4db5 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Sun, 16 Apr 2023 23:59:31 -0500 Subject: make cargo test pass, again --- clippy_lints/src/semicolon_block.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index d85d3b58305..c9689454c63 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -72,7 +72,7 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// - /// Some may prefer if the semicolon is outside if a block is only one + /// Some may prefer if the semicolon is outside if a block is only one /// expression, as this allows rustfmt to make it singleline. In the case that /// it isn't, it should be inside. /// Take a look at both `semicolon_inside_block` and `semicolon_outside_block` for alternatives. @@ -125,14 +125,14 @@ impl LateLintPass<'_> for SemicolonBlock { .. } = stmt else { return }; semicolon_outside_block(cx, block, expr, span); - semicolon_outside_block_if_singleline_check_outside(cx, block, expr, stmt.span) + semicolon_outside_block_if_singleline_check_outside(cx, block, expr, stmt.span); }, StmtKind::Semi(Expr { kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _), .. }) if !block.span.from_expansion() => { semicolon_inside_block(cx, block, tail, stmt.span); - semicolon_outside_block_if_singleline_check_inside(cx, block, tail, stmt.span) + semicolon_outside_block_if_singleline_check_inside(cx, block, tail, stmt.span); }, _ => (), } @@ -197,7 +197,7 @@ fn semicolon_outside_block_if_singleline_check_inside( cx, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, block.span, - &format!("consider moving the `;` inside the block for consistent formatting"), + "consider moving the `;` inside the block for consistent formatting", |diag| { multispan_sugg_with_applicability( diag, @@ -228,7 +228,7 @@ fn semicolon_outside_block_if_singleline_check_outside( cx, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, block.span, - &format!("consider moving the `;` outside the block for consistent formatting"), + "consider moving the `;` outside the block for consistent formatting", |diag| { multispan_sugg_with_applicability( diag, -- cgit 1.4.1-3-g733a5 From 80707aa95faae4acf8b35abf0daf4626afdb446e Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 17 Apr 2023 00:37:43 -0500 Subject: improve description a bit --- clippy_lints/src/semicolon_block.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index c9689454c63..8cdfbd5c495 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -72,10 +72,11 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// - /// Some may prefer if the semicolon is outside if a block is only one - /// expression, as this allows rustfmt to make it singleline. In the case that - /// it isn't, it should be inside. - /// Take a look at both `semicolon_inside_block` and `semicolon_outside_block` for alternatives. + /// Some may prefer if the semicolon is outside of a block if it is only one + /// expression, as this allows rustfmt to make it singleline (and may just be + /// more readable). In the case that it isn't, it should be inside. + /// Take a look at both `semicolon_inside_block` and `semicolon_outside_block` + /// for alternatives. /// /// ### Example /// -- cgit 1.4.1-3-g733a5 From 89f0aaaec60f5e67604fd2f98b1e43500c1a0578 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 17 Apr 2023 13:45:11 +0200 Subject: Force -Zflatten-format-args=no in Clippy. --- src/driver.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/driver.rs b/src/driver.rs index 718bc41fb99..205905d5091 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -160,6 +160,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks { // MIR passes can be enabled / disabled separately, we should figure out, what passes to // use for Clippy. config.opts.unstable_opts.mir_opt_level = Some(0); + + // Disable flattening and inlining of format_args!(), so the HIR matches with the AST. + config.opts.unstable_opts.flatten_format_args = false; } } -- cgit 1.4.1-3-g733a5 From fa1efa8b104c71721d8317ae59819f6abf2d0ac8 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 17 Apr 2023 20:57:56 -0500 Subject: refactor --- clippy_lints/src/semicolon_block.rs | 77 +++++++++++-------------------------- 1 file changed, 22 insertions(+), 55 deletions(-) diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index 8cdfbd5c495..7113f0c55d4 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -126,14 +126,12 @@ impl LateLintPass<'_> for SemicolonBlock { .. } = stmt else { return }; semicolon_outside_block(cx, block, expr, span); - semicolon_outside_block_if_singleline_check_outside(cx, block, expr, stmt.span); }, StmtKind::Semi(Expr { kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _), .. }) if !block.span.from_expansion() => { semicolon_inside_block(cx, block, tail, stmt.span); - semicolon_outside_block_if_singleline_check_inside(cx, block, tail, stmt.span); }, _ => (), } @@ -144,6 +142,8 @@ fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<' let insert_span = tail.span.source_callsite().shrink_to_hi(); let remove_span = semi_span.with_lo(block.span.hi()); + semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, true, "inside"); + span_lint_and_then( cx, SEMICOLON_INSIDE_BLOCK, @@ -166,6 +166,8 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); + semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, false, "outside"); + span_lint_and_then( cx, SEMICOLON_OUTSIDE_BLOCK, @@ -182,23 +184,28 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex ); } -fn semicolon_outside_block_if_singleline_check_inside( +fn semicolon_outside_block_if_singleline( cx: &LateContext<'_>, block: &Block<'_>, - tail: &Expr<'_>, - semi_span: Span, + remove_span: Span, + insert_span: Span, + inequality: bool, + ty: &str, ) { - let insert_span = tail.span.source_callsite().shrink_to_hi(); - let remove_span = semi_span.with_lo(block.span.hi()); + let (remove_line, insert_line) = (get_line(cx, remove_span), get_line(cx, insert_span)); - let (remove_line, insert_line) = get_line(cx, remove_span, insert_span); + let eq = if inequality { + remove_line != insert_line + } else { + remove_line == insert_line + }; - if insert_line != remove_line { + if eq { span_lint_and_then( cx, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, block.span, - "consider moving the `;` inside the block for consistent formatting", + &format!("consider moving the `;` {ty} the block for consistent formatting"), |diag| { multispan_sugg_with_applicability( diag, @@ -211,50 +218,10 @@ fn semicolon_outside_block_if_singleline_check_inside( } } -fn semicolon_outside_block_if_singleline_check_outside( - cx: &LateContext<'_>, - block: &Block<'_>, - tail_stmt_expr: &Expr<'_>, - semi_span: Span, -) { - let insert_span = block.span.with_lo(block.span.hi()); - // account for macro calls - let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); - let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); - - let (remove_line, insert_line) = get_line(cx, remove_span, insert_span); - - if remove_line == insert_line { - span_lint_and_then( - cx, - SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, - block.span, - "consider moving the `;` outside the block for consistent formatting", - |diag| { - multispan_sugg_with_applicability( - diag, - "put the `;` here", - Applicability::MachineApplicable, - [(remove_span, String::new()), (insert_span, ";".to_owned())], - ); - }, - ); - } -} - -fn get_line(cx: &LateContext<'_>, remove_span: Span, insert_span: Span) -> (usize, usize) { - let remove_line = cx - .sess() - .source_map() - .lookup_line(remove_span.lo()) - .expect("failed to get `remove_span`'s line") - .line; - let insert_line = cx - .sess() +fn get_line(cx: &LateContext<'_>, span: Span) -> usize { + cx.sess() .source_map() - .lookup_line(insert_span.lo()) - .expect("failed to get `insert_span`'s line") - .line; - - (remove_line, insert_line) + .lookup_line(span.lo()) + .expect("failed to get span's line") + .line } -- cgit 1.4.1-3-g733a5 From 2ebfbc5753529cd50611605f87386c517a4a3f83 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 18 Apr 2023 17:39:08 +0000 Subject: Remove very useless `as_substs` usage from clippy --- clippy_utils/src/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 9449f0b5567..8b996c18816 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -975,7 +975,7 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 { } match (cx.layout_of(ty).map(|layout| layout.size.bytes()), ty.kind()) { (Ok(size), _) => size, - (Err(_), ty::Tuple(list)) => list.as_substs().types().map(|t| approx_ty_size(cx, t)).sum(), + (Err(_), ty::Tuple(list)) => list.iter().map(|t| approx_ty_size(cx, t)).sum(), (Err(_), ty::Array(t, n)) => { n.try_eval_target_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t) }, -- cgit 1.4.1-3-g733a5 From 1dfc231b10baa850b072a6c5f3d845f2e0a19d07 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Tue, 18 Apr 2023 18:15:06 +0200 Subject: clippy: add test for https://github.com/rust-lang/rust-clippy/issues/10645 --- tests/ui/crashes/ice-5207.rs | 5 ++++- tests/ui/crashes/ice-5207.stderr | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/ui/crashes/ice-5207.stderr diff --git a/tests/ui/crashes/ice-5207.rs b/tests/ui/crashes/ice-5207.rs index f463f78a99a..893c15f5d73 100644 --- a/tests/ui/crashes/ice-5207.rs +++ b/tests/ui/crashes/ice-5207.rs @@ -1,5 +1,8 @@ -// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207 +// compile-flags: --cap-lints=warn +// ^ for https://github.com/rust-lang/rust-clippy/issues/10645 +// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207 +#![warn(clippy::future_not_send)] pub async fn bar<'a, T: 'a>(_: T) {} fn main() {} diff --git a/tests/ui/crashes/ice-5207.stderr b/tests/ui/crashes/ice-5207.stderr new file mode 100644 index 00000000000..367e9a08b75 --- /dev/null +++ b/tests/ui/crashes/ice-5207.stderr @@ -0,0 +1,16 @@ +warning: future cannot be sent between threads safely + --> $DIR/ice-5207.rs:6:35 + | +LL | pub async fn bar<'a, T: 'a>(_: T) {} + | ^ future returned by `bar` is not `Send` + | +note: captured value is not `Send` + --> $DIR/ice-5207.rs:6:29 + | +LL | pub async fn bar<'a, T: 'a>(_: T) {} + | ^ has type `T` which is not `Send` + = note: `T` doesn't implement `std::marker::Send` + = note: `-D clippy::future-not-send` implied by `-D warnings` + +warning: 1 warning emitted + -- cgit 1.4.1-3-g733a5 From 2745c878423dd120b5e17ec6260db455f81a6b71 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Wed, 19 Apr 2023 20:04:17 +0200 Subject: Dont suggest suboptimal_flops unavailable in nostd Fixes #10634 --- clippy_lints/src/floating_point_arithmetic.rs | 13 ++++++++--- tests/ui/floating_point_arithmetic_nostd.rs | 31 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 tests/ui/floating_point_arithmetic_nostd.rs diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index f95b628e6c3..b50e47e5a1c 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -2,9 +2,10 @@ use clippy_utils::consts::{ constant, constant_simple, Constant, Constant::{Int, F32, F64}, }; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; -use clippy_utils::{eq_expr_value, get_parent_expr, in_constant, numeric_literal, peel_blocks, sugg}; +use clippy_utils::{ + diagnostics::span_lint_and_sugg, eq_expr_value, get_parent_expr, higher, in_constant, is_no_std_crate, + numeric_literal, peel_blocks, sugg, +}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; @@ -452,6 +453,9 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&' // TODO: Fix rust-lang/rust-clippy#4735 fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { + if is_no_std_crate(cx) { + return; // The suggested methods are not available in core + } if let ExprKind::Binary( Spanned { node: op @ (BinOpKind::Add | BinOpKind::Sub), @@ -566,6 +570,9 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a } fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { + if is_no_std_crate(cx) { + return; // The suggested methods are not available in core + } if_chain! { if let Some(higher::If { cond, then, r#else: Some(r#else) }) = higher::If::hir(expr); let if_body_expr = peel_blocks(then); diff --git a/tests/ui/floating_point_arithmetic_nostd.rs b/tests/ui/floating_point_arithmetic_nostd.rs new file mode 100644 index 00000000000..a42c6383cce --- /dev/null +++ b/tests/ui/floating_point_arithmetic_nostd.rs @@ -0,0 +1,31 @@ +#![feature(lang_items, start)] +#![warn(clippy::imprecise_flops)] +#![warn(clippy::suboptimal_flops)] +#![no_std] + +// The following should not lint, as the suggested methods {f32,f64}.mul_add() +// and {f32,f64}::abs() are not available in no_std + +pub fn mul_add() { + let a: f64 = 1234.567; + let b: f64 = 45.67834; + let c: f64 = 0.0004; + let _ = a * b + c; +} + +fn fake_abs1(num: f64) -> f64 { + if num >= 0.0 { num } else { -num } +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} -- cgit 1.4.1-3-g733a5 From a3aeec4f75dd0049f6632e26df5aa174b55e730f Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 19 Apr 2023 21:46:13 -0500 Subject: config instead of new lint and don't panic --- CHANGELOG.md | 1 - clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/lib.rs | 9 +- clippy_lints/src/semicolon_block.rs | 127 +++++++-------------- clippy_lints/src/utils/conf.rs | 8 ++ tests/ui-toml/semicolon_block/both.fixed | 86 ++++++++++++++ tests/ui-toml/semicolon_block/both.rs | 86 ++++++++++++++ tests/ui-toml/semicolon_block/both.stderr | 55 +++++++++ tests/ui-toml/semicolon_block/clippy.toml | 2 + .../semicolon_block/semicolon_inside_block.fixed | 85 ++++++++++++++ .../semicolon_block/semicolon_inside_block.rs | 85 ++++++++++++++ .../semicolon_block/semicolon_inside_block.stderr | 18 +++ .../semicolon_block/semicolon_outside_block.fixed | 85 ++++++++++++++ .../semicolon_block/semicolon_outside_block.rs | 85 ++++++++++++++ .../semicolon_block/semicolon_outside_block.stderr | 39 +++++++ .../toml_unknown_key/conf_unknown_key.stderr | 2 + .../ui/semicolon_outside_block_if_singleline.fixed | 85 -------------- tests/ui/semicolon_outside_block_if_singleline.rs | 85 -------------- .../semicolon_outside_block_if_singleline.stderr | 54 --------- 19 files changed, 684 insertions(+), 314 deletions(-) create mode 100644 tests/ui-toml/semicolon_block/both.fixed create mode 100644 tests/ui-toml/semicolon_block/both.rs create mode 100644 tests/ui-toml/semicolon_block/both.stderr create mode 100644 tests/ui-toml/semicolon_block/clippy.toml create mode 100644 tests/ui-toml/semicolon_block/semicolon_inside_block.fixed create mode 100644 tests/ui-toml/semicolon_block/semicolon_inside_block.rs create mode 100644 tests/ui-toml/semicolon_block/semicolon_inside_block.stderr create mode 100644 tests/ui-toml/semicolon_block/semicolon_outside_block.fixed create mode 100644 tests/ui-toml/semicolon_block/semicolon_outside_block.rs create mode 100644 tests/ui-toml/semicolon_block/semicolon_outside_block.stderr delete mode 100644 tests/ui/semicolon_outside_block_if_singleline.fixed delete mode 100644 tests/ui/semicolon_outside_block_if_singleline.rs delete mode 100644 tests/ui/semicolon_outside_block_if_singleline.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index a0a7780f4c2..559b560dde4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4884,7 +4884,6 @@ Released 2018-09-13 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned [`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block [`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block -[`semicolon_outside_block_if_singleline`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block_if_singleline [`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 70379b6caf1..f24dab62780 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -546,7 +546,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO, crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO, crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO, - crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE_INFO, crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO, crate::serde_api::SERDE_API_MISUSE_INFO, crate::shadow::SHADOW_REUSE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b0ec14855e7..cb223ce9d16 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -932,7 +932,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr)); store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv()))); - store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock)); + let semicolon_inside_block_if_multiline = conf.semicolon_inside_block_if_multiline; + let semicolon_outside_block_if_singleline = conf.semicolon_outside_block_if_singleline; + store.register_late_pass(move |_| { + Box::new(semicolon_block::SemicolonBlock::new( + semicolon_inside_block_if_multiline, + semicolon_outside_block_if_singleline, + )) + }); store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck)); store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse)); store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef)); diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index 7113f0c55d4..6be43033712 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; declare_clippy_lint! { @@ -64,49 +64,22 @@ declare_clippy_lint! { restriction, "add a semicolon outside the block" } -declare_clippy_lint! { - /// ### What it does - /// - /// Suggests moving the semicolon from a block's final expression outside of - /// the block if it's singleline, and inside the block if it's multiline. - /// - /// ### Why is this bad? - /// - /// Some may prefer if the semicolon is outside of a block if it is only one - /// expression, as this allows rustfmt to make it singleline (and may just be - /// more readable). In the case that it isn't, it should be inside. - /// Take a look at both `semicolon_inside_block` and `semicolon_outside_block` - /// for alternatives. - /// - /// ### Example - /// - /// ```rust - /// # fn f(_: u32) {} - /// # let x = 0; - /// unsafe { f(x); } - /// - /// unsafe { - /// let x = 1; - /// f(x) - /// }; - /// ``` - /// Use instead: - /// ```rust - /// # fn f(_: u32) {} - /// # let x = 0; - /// unsafe { f(x) }; - /// - /// unsafe { - /// let x = 1; - /// f(x); - /// } - /// ``` - #[clippy::version = "1.68.0"] - pub SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, - restriction, - "add a semicolon inside the block if it's singleline, otherwise outside" +impl_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]); + +#[derive(Copy, Clone)] +pub struct SemicolonBlock { + semicolon_inside_block_if_multiline: bool, + semicolon_outside_block_if_singleline: bool, +} + +impl SemicolonBlock { + pub fn new(semicolon_inside_block_if_multiline: bool, semicolon_outside_block_if_singleline: bool) -> Self { + Self { + semicolon_inside_block_if_multiline, + semicolon_outside_block_if_singleline, + } + } } -declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE]); impl LateLintPass<'_> for SemicolonBlock { fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { @@ -125,24 +98,34 @@ impl LateLintPass<'_> for SemicolonBlock { span, .. } = stmt else { return }; - semicolon_outside_block(cx, block, expr, span); + semicolon_outside_block(self, cx, block, expr, span); }, StmtKind::Semi(Expr { kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _), .. }) if !block.span.from_expansion() => { - semicolon_inside_block(cx, block, tail, stmt.span); + semicolon_inside_block(self, cx, block, tail, stmt.span); }, _ => (), } } } -fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) { +fn semicolon_inside_block( + conf: &mut SemicolonBlock, + cx: &LateContext<'_>, + block: &Block<'_>, + tail: &Expr<'_>, + semi_span: Span, +) { let insert_span = tail.span.source_callsite().shrink_to_hi(); let remove_span = semi_span.with_lo(block.span.hi()); - semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, true, "inside"); + if conf.semicolon_inside_block_if_multiline { + if get_line(cx, remove_span) == get_line(cx, insert_span) { + return; + } + } span_lint_and_then( cx, @@ -160,13 +143,17 @@ fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<' ); } -fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) { +fn semicolon_outside_block(conf: &mut SemicolonBlock, cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) { let insert_span = block.span.with_lo(block.span.hi()); // account for macro calls let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); - semicolon_outside_block_if_singleline(cx, block, remove_span, insert_span, false, "outside"); + if conf.semicolon_outside_block_if_singleline { + if get_line(cx, remove_span) != get_line(cx, insert_span) { + return; + } + } span_lint_and_then( cx, @@ -184,44 +171,10 @@ fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_ex ); } -fn semicolon_outside_block_if_singleline( - cx: &LateContext<'_>, - block: &Block<'_>, - remove_span: Span, - insert_span: Span, - inequality: bool, - ty: &str, -) { - let (remove_line, insert_line) = (get_line(cx, remove_span), get_line(cx, insert_span)); - - let eq = if inequality { - remove_line != insert_line - } else { - remove_line == insert_line - }; - - if eq { - span_lint_and_then( - cx, - SEMICOLON_OUTSIDE_BLOCK_IF_SINGLELINE, - block.span, - &format!("consider moving the `;` {ty} the block for consistent formatting"), - |diag| { - multispan_sugg_with_applicability( - diag, - "put the `;` here", - Applicability::MachineApplicable, - [(remove_span, String::new()), (insert_span, ";".to_owned())], - ); - }, - ); +fn get_line(cx: &LateContext<'_>, span: Span) -> Option { + if let Ok(line) = cx.sess().source_map().lookup_line(span.lo()) { + return Some(line.line); } -} -fn get_line(cx: &LateContext<'_>, span: Span) -> usize { - cx.sess() - .source_map() - .lookup_line(span.lo()) - .expect("failed to get span's line") - .line + None } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 896a01af37d..26123549b94 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -463,6 +463,14 @@ define_Conf! { /// /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint (future_size_threshold: u64 = 16 * 1024), + /// Lint: SEMICOLON_INSIDE_BLOCK. + /// + /// Whether to lint only if it's multiline. + (semicolon_inside_block_if_multiline: bool = false), + /// Lint: SEMICOLON_OUTSIDE_BLOCK. + /// + /// Whether to lint only if it's singleline. + (semicolon_outside_block_if_singleline: bool = false), } /// Search for the configuration file. diff --git a/tests/ui-toml/semicolon_block/both.fixed b/tests/ui-toml/semicolon_block/both.fixed new file mode 100644 index 00000000000..981b661bc78 --- /dev/null +++ b/tests/ui-toml/semicolon_block/both.fixed @@ -0,0 +1,86 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_inside_block)] +#![warn(clippy::semicolon_outside_block)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()) }; + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} diff --git a/tests/ui-toml/semicolon_block/both.rs b/tests/ui-toml/semicolon_block/both.rs new file mode 100644 index 00000000000..d4dcd6e7240 --- /dev/null +++ b/tests/ui-toml/semicolon_block/both.rs @@ -0,0 +1,86 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_inside_block)] +#![warn(clippy::semicolon_outside_block)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); } + unsafe { unit_fn_block(); } + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block() + }; + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()); } + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} diff --git a/tests/ui-toml/semicolon_block/both.stderr b/tests/ui-toml/semicolon_block/both.stderr new file mode 100644 index 00000000000..2f58842eab0 --- /dev/null +++ b/tests/ui-toml/semicolon_block/both.stderr @@ -0,0 +1,55 @@ +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/both.rs:43:5 + | +LL | { unit_fn_block(); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::semicolon-outside-block` implied by `-D warnings` +help: put the `;` here + | +LL - { unit_fn_block(); } +LL + { unit_fn_block() }; + | + +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/both.rs:44:5 + | +LL | unsafe { unit_fn_block(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: put the `;` here + | +LL - unsafe { unit_fn_block(); } +LL + unsafe { unit_fn_block() }; + | + +error: consider moving the `;` inside the block for consistent formatting + --> $DIR/both.rs:49:5 + | +LL | / { +LL | | unit_fn_block(); +LL | | unit_fn_block() +LL | | }; + | |______^ + | + = note: `-D clippy::semicolon-inside-block` implied by `-D warnings` +help: put the `;` here + | +LL ~ unit_fn_block(); +LL ~ } + | + +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/both.rs:63:5 + | +LL | { m!(()); } + | ^^^^^^^^^^^ + | +help: put the `;` here + | +LL - { m!(()); } +LL + { m!(()) }; + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui-toml/semicolon_block/clippy.toml b/tests/ui-toml/semicolon_block/clippy.toml new file mode 100644 index 00000000000..cc3bc8cae14 --- /dev/null +++ b/tests/ui-toml/semicolon_block/clippy.toml @@ -0,0 +1,2 @@ +semicolon-inside-block-if-multiline = true +semicolon-outside-block-if-singleline = true diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed b/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed new file mode 100644 index 00000000000..6a08bc905b1 --- /dev/null +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed @@ -0,0 +1,85 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_inside_block)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); } + unsafe { unit_fn_block(); } + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()); } + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.rs b/tests/ui-toml/semicolon_block/semicolon_inside_block.rs new file mode 100644 index 00000000000..f40848f702e --- /dev/null +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.rs @@ -0,0 +1,85 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_inside_block)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); } + unsafe { unit_fn_block(); } + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block() + }; + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()); } + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr b/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr new file mode 100644 index 00000000000..2569dc4b4e4 --- /dev/null +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.stderr @@ -0,0 +1,18 @@ +error: consider moving the `;` inside the block for consistent formatting + --> $DIR/semicolon_inside_block.rs:48:5 + | +LL | / { +LL | | unit_fn_block(); +LL | | unit_fn_block() +LL | | }; + | |______^ + | + = note: `-D clippy::semicolon-inside-block` implied by `-D warnings` +help: put the `;` here + | +LL ~ unit_fn_block(); +LL ~ } + | + +error: aborting due to previous error + diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed b/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed new file mode 100644 index 00000000000..e2d653dc3c3 --- /dev/null +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed @@ -0,0 +1,85 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_outside_block)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block() + }; + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()) }; + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.rs b/tests/ui-toml/semicolon_block/semicolon_outside_block.rs new file mode 100644 index 00000000000..7ce46431fac --- /dev/null +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.rs @@ -0,0 +1,85 @@ +// run-rustfix +#![allow( + unused, + clippy::unused_unit, + clippy::unnecessary_operation, + clippy::no_effect, + clippy::single_element_loop +)] +#![warn(clippy::semicolon_outside_block)] + +macro_rules! m { + (()) => { + () + }; + (0) => {{ + 0 + };}; + (1) => {{ + 1; + }}; + (2) => {{ + 2; + }}; +} + +fn unit_fn_block() { + () +} + +#[rustfmt::skip] +fn main() { + { unit_fn_block() } + unsafe { unit_fn_block() } + + { + unit_fn_block() + } + + { unit_fn_block() }; + unsafe { unit_fn_block() }; + + { unit_fn_block(); } + unsafe { unit_fn_block(); } + + { unit_fn_block(); }; + unsafe { unit_fn_block(); }; + + { + unit_fn_block(); + unit_fn_block() + }; + { + unit_fn_block(); + unit_fn_block(); + } + { + unit_fn_block(); + unit_fn_block(); + }; + + { m!(()) }; + { m!(()); } + { m!(()); }; + m!(0); + m!(1); + m!(2); + + for _ in [()] { + unit_fn_block(); + } + for _ in [()] { + unit_fn_block() + } + + let _d = || { + unit_fn_block(); + }; + let _d = || { + unit_fn_block() + }; + + { unit_fn_block(); }; + + unit_fn_block() +} diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr b/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr new file mode 100644 index 00000000000..6dd3577dd09 --- /dev/null +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.stderr @@ -0,0 +1,39 @@ +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/semicolon_outside_block.rs:42:5 + | +LL | { unit_fn_block(); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::semicolon-outside-block` implied by `-D warnings` +help: put the `;` here + | +LL - { unit_fn_block(); } +LL + { unit_fn_block() }; + | + +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/semicolon_outside_block.rs:43:5 + | +LL | unsafe { unit_fn_block(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: put the `;` here + | +LL - unsafe { unit_fn_block(); } +LL + unsafe { unit_fn_block() }; + | + +error: consider moving the `;` outside the block for consistent formatting + --> $DIR/semicolon_outside_block.rs:62:5 + | +LL | { m!(()); } + | ^^^^^^^^^^^ + | +help: put the `;` here + | +LL - { m!(()); } +LL + { m!(()) }; + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 8447c31722d..c49c9087946 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -37,6 +37,8 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie missing-docs-in-crate-items msrv pass-by-value-size-limit + semicolon-inside-block-if-multiline + semicolon-outside-block-if-singleline single-char-binding-names-threshold standard-macro-braces suppress-restriction-lint-in-const diff --git a/tests/ui/semicolon_outside_block_if_singleline.fixed b/tests/ui/semicolon_outside_block_if_singleline.fixed deleted file mode 100644 index e1ecbf8588d..00000000000 --- a/tests/ui/semicolon_outside_block_if_singleline.fixed +++ /dev/null @@ -1,85 +0,0 @@ -// run-rustfix -#![allow( - unused, - clippy::unused_unit, - clippy::unnecessary_operation, - clippy::no_effect, - clippy::single_element_loop -)] -#![warn(clippy::semicolon_outside_block_if_singleline)] - -macro_rules! m { - (()) => { - () - }; - (0) => {{ - 0 - };}; - (1) => {{ - 1; - }}; - (2) => {{ - 2; - }}; -} - -fn unit_fn_block() { - () -} - -#[rustfmt::skip] -fn main() { - { unit_fn_block() } - unsafe { unit_fn_block() } - - { - unit_fn_block() - } - - { unit_fn_block() }; - unsafe { unit_fn_block() }; - - { unit_fn_block() }; - unsafe { unit_fn_block() }; - - { unit_fn_block(); }; - unsafe { unit_fn_block(); }; - - { - unit_fn_block(); - unit_fn_block(); - } - { - unit_fn_block(); - unit_fn_block(); - } - { - unit_fn_block(); - unit_fn_block(); - }; - - { m!(()) }; - { m!(()) }; - { m!(()); }; - m!(0); - m!(1); - m!(2); - - for _ in [()] { - unit_fn_block(); - } - for _ in [()] { - unit_fn_block() - } - - let _d = || { - unit_fn_block(); - }; - let _d = || { - unit_fn_block() - }; - - { unit_fn_block(); }; - - unit_fn_block() -} diff --git a/tests/ui/semicolon_outside_block_if_singleline.rs b/tests/ui/semicolon_outside_block_if_singleline.rs deleted file mode 100644 index 80fbb4ce2d5..00000000000 --- a/tests/ui/semicolon_outside_block_if_singleline.rs +++ /dev/null @@ -1,85 +0,0 @@ -// run-rustfix -#![allow( - unused, - clippy::unused_unit, - clippy::unnecessary_operation, - clippy::no_effect, - clippy::single_element_loop -)] -#![warn(clippy::semicolon_outside_block_if_singleline)] - -macro_rules! m { - (()) => { - () - }; - (0) => {{ - 0 - };}; - (1) => {{ - 1; - }}; - (2) => {{ - 2; - }}; -} - -fn unit_fn_block() { - () -} - -#[rustfmt::skip] -fn main() { - { unit_fn_block() } - unsafe { unit_fn_block() } - - { - unit_fn_block() - } - - { unit_fn_block() }; - unsafe { unit_fn_block() }; - - { unit_fn_block(); } - unsafe { unit_fn_block(); } - - { unit_fn_block(); }; - unsafe { unit_fn_block(); }; - - { - unit_fn_block(); - unit_fn_block() - }; - { - unit_fn_block(); - unit_fn_block(); - } - { - unit_fn_block(); - unit_fn_block(); - }; - - { m!(()) }; - { m!(()); } - { m!(()); }; - m!(0); - m!(1); - m!(2); - - for _ in [()] { - unit_fn_block(); - } - for _ in [()] { - unit_fn_block() - } - - let _d = || { - unit_fn_block(); - }; - let _d = || { - unit_fn_block() - }; - - { unit_fn_block(); }; - - unit_fn_block() -} diff --git a/tests/ui/semicolon_outside_block_if_singleline.stderr b/tests/ui/semicolon_outside_block_if_singleline.stderr deleted file mode 100644 index dda083f2be3..00000000000 --- a/tests/ui/semicolon_outside_block_if_singleline.stderr +++ /dev/null @@ -1,54 +0,0 @@ -error: consider moving the `;` outside the block for consistent formatting - --> $DIR/semicolon_outside_block_if_singleline.rs:42:5 - | -LL | { unit_fn_block(); } - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::semicolon-outside-block-if-singleline` implied by `-D warnings` -help: put the `;` here - | -LL - { unit_fn_block(); } -LL + { unit_fn_block() }; - | - -error: consider moving the `;` outside the block for consistent formatting - --> $DIR/semicolon_outside_block_if_singleline.rs:43:5 - | -LL | unsafe { unit_fn_block(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: put the `;` here - | -LL - unsafe { unit_fn_block(); } -LL + unsafe { unit_fn_block() }; - | - -error: consider moving the `;` inside the block for consistent formatting - --> $DIR/semicolon_outside_block_if_singleline.rs:48:5 - | -LL | / { -LL | | unit_fn_block(); -LL | | unit_fn_block() -LL | | }; - | |_____^ - | -help: put the `;` here - | -LL ~ unit_fn_block(); -LL ~ } - | - -error: consider moving the `;` outside the block for consistent formatting - --> $DIR/semicolon_outside_block_if_singleline.rs:62:5 - | -LL | { m!(()); } - | ^^^^^^^^^^^ - | -help: put the `;` here - | -LL - { m!(()); } -LL + { m!(()) }; - | - -error: aborting due to 4 previous errors - -- cgit 1.4.1-3-g733a5 From 41f6d88be588b191d7c49547819671c11c9a84e9 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 19 Apr 2023 21:51:58 -0500 Subject: make cargo test pass --- clippy_lints/src/semicolon_block.rs | 20 +++++++++++--------- clippy_lints/src/utils/conf.rs | 16 ++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index 6be43033712..c1c0325b786 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -121,10 +121,8 @@ fn semicolon_inside_block( let insert_span = tail.span.source_callsite().shrink_to_hi(); let remove_span = semi_span.with_lo(block.span.hi()); - if conf.semicolon_inside_block_if_multiline { - if get_line(cx, remove_span) == get_line(cx, insert_span) { - return; - } + if conf.semicolon_inside_block_if_multiline && get_line(cx, remove_span) == get_line(cx, insert_span) { + return; } span_lint_and_then( @@ -143,16 +141,20 @@ fn semicolon_inside_block( ); } -fn semicolon_outside_block(conf: &mut SemicolonBlock, cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) { +fn semicolon_outside_block( + conf: &mut SemicolonBlock, + cx: &LateContext<'_>, + block: &Block<'_>, + tail_stmt_expr: &Expr<'_>, + semi_span: Span, +) { let insert_span = block.span.with_lo(block.span.hi()); // account for macro calls let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); - if conf.semicolon_outside_block_if_singleline { - if get_line(cx, remove_span) != get_line(cx, insert_span) { - return; - } + if conf.semicolon_outside_block_if_singleline && get_line(cx, remove_span) != get_line(cx, insert_span) { + return; } span_lint_and_then( diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 26123549b94..939f6cd5f1f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -277,6 +277,14 @@ define_Conf! { /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the /// default configuration of Clippy. By default, any configuration will replace the default value. (disallowed_names: Vec = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()), + /// Lint: SEMICOLON_INSIDE_BLOCK. + /// + /// Whether to lint only if it's multiline. + (semicolon_inside_block_if_multiline: bool = false), + /// Lint: SEMICOLON_OUTSIDE_BLOCK. + /// + /// Whether to lint only if it's singleline. + (semicolon_outside_block_if_singleline: bool = false), /// Lint: DOC_MARKDOWN. /// /// The list of words this lint should not consider as identifiers needing ticks. The value @@ -463,14 +471,6 @@ define_Conf! { /// /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint (future_size_threshold: u64 = 16 * 1024), - /// Lint: SEMICOLON_INSIDE_BLOCK. - /// - /// Whether to lint only if it's multiline. - (semicolon_inside_block_if_multiline: bool = false), - /// Lint: SEMICOLON_OUTSIDE_BLOCK. - /// - /// Whether to lint only if it's singleline. - (semicolon_outside_block_if_singleline: bool = false), } /// Search for the configuration file. -- cgit 1.4.1-3-g733a5 From 8ead58c67bb4cc0c23e5f3c9d335a2b6e90d1854 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 8 May 2022 15:53:19 +0200 Subject: Remove WithOptconstParam. --- clippy_lints/src/non_copy_const.rs | 8 +++----- clippy_utils/src/consts.rs | 6 +----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 0bedab05eec..eed0f1f1991 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -196,11 +196,9 @@ fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty< fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let substs = cx.typeck_results().node_substs(hir_id); - let result = cx.tcx.const_eval_resolve( - cx.param_env, - mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs), - None, - ); + let result = cx + .tcx + .const_eval_resolve(cx.param_env, mir::UnevaluatedConst::new(def_id, substs), None); is_value_unfrozen_raw(cx, result, ty) } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index bb8890dcaf9..99bfc4b5717 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -450,11 +450,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { let result = self .lcx .tcx - .const_eval_resolve( - self.param_env, - mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs), - None, - ) + .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None) .ok() .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?; let result = miri_to_const(self.lcx.tcx, result); -- cgit 1.4.1-3-g733a5 From afa28e63044649230671635e78b649e8cdfe3b3a Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 17 Apr 2023 15:57:29 -0600 Subject: change usages of explicit_item_bounds to bound_explicit_item_bounds --- clippy_lints/src/future_not_send.rs | 7 +++---- clippy_utils/src/ty.rs | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index ed0bd58c770..73ae2406f9d 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind}; +use rustc_middle::ty::{self, AliasTy, Clause, PredicateKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -64,10 +64,9 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner()); if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() { - let preds = cx.tcx.explicit_item_bounds(def_id); + let preds = cx.tcx.bound_explicit_item_bounds(def_id); let mut is_future = false; - for &(p, _span) in preds { - let p = EarlyBinder(p).subst(cx.tcx, substs); + for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) { if let Some(trait_pred) = p.to_opt_poly_trait_pred() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 8b996c18816..058f6b0306d 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -90,7 +90,8 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { + for bound in cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() { + let (predicate, _span) = bound.map_bound(|b| *b).subst_identity(); match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substituions to find `U`. @@ -267,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { + for (predicate, _) in cx.tcx.bound_explicit_item_bounds(*def_id).skip_binder() { if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; -- cgit 1.4.1-3-g733a5 From 097309c10f6bdfa0f8540d063e6e64942fd53204 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 17 Apr 2023 16:43:46 -0600 Subject: add EarlyBinder to output of explicit_item_bounds; replace bound_explicit_item_bounds usages; remove bound_explicit_item_bounds query --- clippy_lints/src/future_not_send.rs | 2 +- clippy_utils/src/ty.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index 73ae2406f9d..ff838c2d56e 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner()); if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() { - let preds = cx.tcx.bound_explicit_item_bounds(def_id); + let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) { if let Some(trait_pred) = p.to_opt_poly_trait_pred() { diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 058f6b0306d..5f768928adf 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -90,7 +90,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for bound in cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() { + for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { let (predicate, _span) = bound.map_bound(|b| *b).subst_identity(); match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through @@ -268,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.bound_explicit_item_bounds(*def_id).skip_binder() { + for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() { if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; @@ -744,7 +744,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option for (pred, _) in cx .tcx - .bound_explicit_item_bounds(ty.def_id) + .explicit_item_bounds(ty.def_id) .subst_iter_copied(cx.tcx, ty.substs) { match pred.kind().skip_binder() { -- cgit 1.4.1-3-g733a5 From 55d814633423c801034fca46f4f391d0c5fd3899 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 17 Apr 2023 17:19:08 -0600 Subject: add subst_identity_iter and subst_identity_iter_copied methods on EarlyBinder; use this to simplify some EarlyBinder noise around explicit_item_bounds calls --- clippy_utils/src/ty.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 5f768928adf..cb700126c2b 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -90,8 +90,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { - let (predicate, _span) = bound.map_bound(|b| *b).subst_identity(); + for (predicate, _span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() { match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substituions to find `U`. -- cgit 1.4.1-3-g733a5 From 654d12ff8930a332a4cdcfccc6c1c34700e2f3b7 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 20 Apr 2023 22:43:59 +0200 Subject: use is_inside_const_context query for in_constant --- clippy_utils/src/lib.rs | 32 ++++---------------------------- tests/ui/bool_to_int_with_if.fixed | 9 ++++++++- tests/ui/bool_to_int_with_if.rs | 9 ++++++++- tests/ui/bool_to_int_with_if.stderr | 2 +- 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index f1d2ae220f8..98d6f29765f 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -86,10 +86,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ - self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, Destination, - Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local, + self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, + ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, - TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, + TraitItem, TraitItemRef, TraitRef, TyKind, UnOp, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -197,31 +197,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option< /// } /// ``` pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool { - let parent_id = cx.tcx.hir().get_parent_item(id).def_id; - match cx.tcx.hir().get_by_def_id(parent_id) { - Node::Item(&Item { - kind: ItemKind::Const(..) | ItemKind::Static(..) | ItemKind::Enum(..), - .. - }) - | Node::TraitItem(&TraitItem { - kind: TraitItemKind::Const(..), - .. - }) - | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Const(..), - .. - }) - | Node::AnonConst(_) => true, - Node::Item(&Item { - kind: ItemKind::Fn(ref sig, ..), - .. - }) - | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Fn(ref sig, _), - .. - }) => sig.header.constness == Constness::Const, - _ => false, - } + cx.tcx.hir().is_inside_const_context(id) } /// Checks if a `Res` refers to a constructor of a `LangItem` diff --git a/tests/ui/bool_to_int_with_if.fixed b/tests/ui/bool_to_int_with_if.fixed index 9831c3373d4..fbb10a133e2 100644 --- a/tests/ui/bool_to_int_with_if.fixed +++ b/tests/ui/bool_to_int_with_if.fixed @@ -1,6 +1,6 @@ //@run-rustfix -#![feature(let_chains)] +#![feature(let_chains, inline_const)] #![warn(clippy::bool_to_int_with_if)] #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)] @@ -79,6 +79,13 @@ fn main() { pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 }; + // https://github.com/rust-lang/rust-clippy/issues/10452 + let should_not_lint = [(); if true { 1 } else { 0 }]; + + let should_not_lint = const { + if true { 1 } else { 0 } + }; + some_fn(a); } diff --git a/tests/ui/bool_to_int_with_if.rs b/tests/ui/bool_to_int_with_if.rs index 5e3047bb32c..709a18d63e4 100644 --- a/tests/ui/bool_to_int_with_if.rs +++ b/tests/ui/bool_to_int_with_if.rs @@ -1,6 +1,6 @@ //@run-rustfix -#![feature(let_chains)] +#![feature(let_chains, inline_const)] #![warn(clippy::bool_to_int_with_if)] #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)] @@ -111,6 +111,13 @@ fn main() { pub const SHOULD_NOT_LINT: usize = if true { 1 } else { 0 }; + // https://github.com/rust-lang/rust-clippy/issues/10452 + let should_not_lint = [(); if true { 1 } else { 0 }]; + + let should_not_lint = const { + if true { 1 } else { 0 } + }; + some_fn(a); } diff --git a/tests/ui/bool_to_int_with_if.stderr b/tests/ui/bool_to_int_with_if.stderr index 5cfb75cc0df..3bdae75cad2 100644 --- a/tests/ui/bool_to_int_with_if.stderr +++ b/tests/ui/bool_to_int_with_if.stderr @@ -98,7 +98,7 @@ LL | | }; = note: `!b as i32` or `(!b).into()` can also be valid options error: boolean to int conversion using if - --> $DIR/bool_to_int_with_if.rs:119:5 + --> $DIR/bool_to_int_with_if.rs:126:5 | LL | if a { 1 } else { 0 } | ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)` -- cgit 1.4.1-3-g733a5 From 68c4776b4603f453d17b772e4598fee77c48dde8 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Sun, 11 Sep 2022 00:37:49 -0700 Subject: offset_of --- clippy_lints/src/loops/never_loop.rs | 3 ++- clippy_lints/src/matches/significant_drop_in_scrutinee.rs | 1 + clippy_lints/src/utils/author.rs | 4 ++++ clippy_utils/src/eager_or_lazy.rs | 3 ++- clippy_utils/src/hir_utils.rs | 9 +++++++++ clippy_utils/src/qualify_min_const_fn.rs | 2 +- clippy_utils/src/sugg.rs | 2 ++ clippy_utils/src/visitors.rs | 1 + 8 files changed, 22 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index f0a1b1dfe56..5f1fdf00be8 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -226,7 +226,8 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec, main_loop_id: H | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise, }) .fold(NeverLoopResult::Otherwise, combine_seq), - ExprKind::Yield(_, _) + ExprKind::OffsetOf(_, _) + | ExprKind::Yield(_, _) | ExprKind::Closure { .. } | ExprKind::Path(_) | ExprKind::ConstBlock(_) diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 04225beeb70..7945275393c 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -342,6 +342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { ExprKind::DropTemps(_) | ExprKind::Err(_) | ExprKind::InlineAsm(_) | + ExprKind::OffsetOf(_, _) | ExprKind::Let(_) | ExprKind::Lit(_) | ExprKind::Loop(_, _, _, _) | diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 2dac807c420..01927b6b5f1 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -558,6 +558,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("InlineAsm(_)"); out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); }, + ExprKind::OffsetOf(container, ref fields) => { + bind!(self, container, fields); + kind!("OffsetOf({container}, {fields})"); + } ExprKind::Struct(qpath, fields, base) => { bind!(self, qpath, fields); opt_bind!(self, base); diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 28c85717061..3df40942e7b 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -218,7 +218,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS | ExprKind::AddrOf(..) | ExprKind::Struct(..) | ExprKind::Repeat(..) - | ExprKind::Block(Block { stmts: [], .. }, _) => (), + | ExprKind::Block(Block { stmts: [], .. }, _) + | ExprKind::OffsetOf(..) => (), // Assignment might be to a local defined earlier, so don't eagerly evaluate. // Blocks with multiple statements might be expensive, so don't eagerly evaluate. diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 3ee7147828b..d972ed82c25 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -301,6 +301,9 @@ impl HirEqInterExpr<'_, '_, '_> { (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re), (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r), (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re), + (&ExprKind::OffsetOf(l_container, ref l_fields), &ExprKind::OffsetOf(r_container, ref r_fields)) => { + self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name) + }, _ => false, }; (is_eq && (!self.should_ignore(left) || !self.should_ignore(right))) @@ -701,6 +704,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } }, + ExprKind::OffsetOf(container, fields) => { + self.hash_ty(container); + for field in fields { + self.hash_name(field.name); + } + }, ExprKind::Let(Let { pat, init, ty, .. }) => { self.hash_expr(init); if let Some(ty) = ty { diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 354b6d71aa4..ecd712f32dc 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -194,7 +194,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()), + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); if ty.is_integral() || ty.is_bool() { diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index a5a4a921d94..e81eadceec0 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -139,6 +139,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Field(..) | hir::ExprKind::Index(..) | hir::ExprKind::InlineAsm(..) + | hir::ExprKind::OffsetOf(..) | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Loop(..) @@ -197,6 +198,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::ForLoop(..) | ast::ExprKind::Index(..) | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::OffsetOf(..) | ast::ExprKind::ConstBlock(..) | ast::ExprKind::Lit(..) | ast::ExprKind::IncludedBytes(..) diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 1dc19bac984..5dcd71cef12 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -662,6 +662,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( | ExprKind::Path(_) | ExprKind::Continue(_) | ExprKind::InlineAsm(_) + | ExprKind::OffsetOf(..) | ExprKind::Err(_) => (), } ControlFlow::Continue(()) -- cgit 1.4.1-3-g733a5 From 85d7de25a987b72ffb6552e852a4c8f661dfb1c8 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Fri, 21 Apr 2023 05:12:14 -0500 Subject: fix false positive --- clippy_lints/src/allow_attributes.rs | 4 +++- tests/ui/allow_attributes_false_positive.rs | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/ui/allow_attributes_false_positive.rs diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index b984132acf5..add73d0aeee 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -2,7 +2,8 @@ use ast::AttrStyle; use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_ast as ast; use rustc_errors::Applicability; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -51,6 +52,7 @@ impl LateLintPass<'_> for AllowAttribute { // Separate each crate's features. fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { if_chain! { + if !in_external_macro(cx.sess(), attr.span); if cx.tcx.features().lint_reasons; if let AttrStyle::Outer = attr.style; if let Some(ident) = attr.ident(); diff --git a/tests/ui/allow_attributes_false_positive.rs b/tests/ui/allow_attributes_false_positive.rs new file mode 100644 index 00000000000..a34a5d91ef5 --- /dev/null +++ b/tests/ui/allow_attributes_false_positive.rs @@ -0,0 +1,6 @@ +#![allow(unused)] +#![warn(clippy::allow_attributes)] +#![feature(lint_reasons)] +#![crate_type = "proc-macro"] + +fn main() {} -- cgit 1.4.1-3-g733a5 From cb3e0fbb5999429f4f4c30e505c4904c9999cdf8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 24 Nov 2022 19:09:27 +0000 Subject: Evaluate place expression in `PlaceMention`. --- tests/ui/option_if_let_else.fixed | 4 ++-- tests/ui/option_if_let_else.rs | 4 ++-- tests/ui/option_if_let_else.stderr | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 0456005dce4..35ce89c7986 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -25,7 +25,7 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> { fn unop_bad(string: &Option<&str>, mut num: Option) { let _ = string.map_or(0, |s| s.len()); let _ = num.as_ref().map_or(&0, |s| s); - let _ = num.as_mut().map_or(&mut 0, |s| { + let _ = num.as_mut().map_or(&0, |s| { *s += 1; s }); @@ -34,7 +34,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option) { s += 1; s }); - let _ = num.as_mut().map_or(&mut 0, |s| { + let _ = num.as_mut().map_or(&0, |s| { *s += 1; s }); diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 23b148752cb..c8683e5aae2 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -33,7 +33,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option) { *s += 1; s } else { - &mut 0 + &0 }; let _ = if let Some(ref s) = num { s } else { &0 }; let _ = if let Some(mut s) = num { @@ -46,7 +46,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option) { *s += 1; s } else { - &mut 0 + &0 }; } diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index a5dbf6e1f22..f5e4affb672 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -30,13 +30,13 @@ LL | let _ = if let Some(s) = &mut num { LL | | *s += 1; LL | | s LL | | } else { -LL | | &mut 0 +LL | | &0 LL | | }; | |_____^ | help: try | -LL ~ let _ = num.as_mut().map_or(&mut 0, |s| { +LL ~ let _ = num.as_mut().map_or(&0, |s| { LL + *s += 1; LL + s LL ~ }); @@ -76,13 +76,13 @@ LL | let _ = if let Some(ref mut s) = num { LL | | *s += 1; LL | | s LL | | } else { -LL | | &mut 0 +LL | | &0 LL | | }; | |_____^ | help: try | -LL ~ let _ = num.as_mut().map_or(&mut 0, |s| { +LL ~ let _ = num.as_mut().map_or(&0, |s| { LL + *s += 1; LL + s LL ~ }); -- cgit 1.4.1-3-g733a5 From 7f13e6d8a54f58d51f159ddb97eb94b14a72ac79 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 16 Feb 2023 09:25:11 +0000 Subject: Allow `LocalDefId` as the argument to `def_path_str` --- clippy_lints/src/default_union_representation.rs | 2 +- clippy_lints/src/trailing_empty_array.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index dec357ab75c..03b5a2d6d08 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation { None, &format!( "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout", - cx.tcx.def_path_str(item.owner_id.to_def_id()) + cx.tcx.def_path_str(item.owner_id) ), ); } diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs index 1382c1a40da..98f5b47f7a0 100644 --- a/clippy_lints/src/trailing_empty_array.rs +++ b/clippy_lints/src/trailing_empty_array.rs @@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { None, &format!( "consider annotating `{}` with `#[repr(C)]` or another `repr` attribute", - cx.tcx.def_path_str(item.owner_id.to_def_id()) + cx.tcx.def_path_str(item.owner_id) ), ); } -- cgit 1.4.1-3-g733a5 From 628605e07a2a9a546ba698f1a50311b16832f227 Mon Sep 17 00:00:00 2001 From: Renato Lochetti Date: Sat, 22 Apr 2023 20:28:08 +0100 Subject: Ignore `shadow` warns in code from macro expansions --- clippy_lints/src/shadow.rs | 2 +- tests/ui/shadow.rs | 12 ++++++ tests/ui/shadow.stderr | 92 +++++++++++++++++++++++----------------------- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index ae7d19624ba..993f9373d85 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { let PatKind::Binding(_, id, ident, _) = pat.kind else { return }; - if pat.span.desugaring_kind().is_some() { + if pat.span.desugaring_kind().is_some() || pat.span.from_expansion() { return; } diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 03337ec3564..2c0fc3e3fd8 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -8,6 +8,12 @@ extern crate proc_macro_derive; #[derive(proc_macro_derive::ShadowDerive)] pub struct Nothing; +macro_rules! reuse { + ($v:ident) => { + let $v = $v + 1; + }; +} + fn shadow_same() { let x = 1; let x = x; @@ -33,6 +39,12 @@ fn shadow_reuse() -> Option<()> { None } +fn shadow_reuse_macro() { + let x = 1; + // this should not warn + reuse!(x); +} + fn shadow_unrelated() { let x = 1; let x = 2; diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index 92bb937d086..8321f6df224 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,278 +1,278 @@ error: `x` is shadowed by itself in `x` - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:19:9 | LL | let x = x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:12:9 + --> $DIR/shadow.rs:18:9 | LL | let x = 1; | ^ = note: `-D clippy::shadow-same` implied by `-D warnings` error: `mut x` is shadowed by itself in `&x` - --> $DIR/shadow.rs:14:13 + --> $DIR/shadow.rs:20:13 | LL | let mut x = &x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:19:9 | LL | let x = x; | ^ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:21:9 | LL | let x = &mut x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:20:9 | LL | let mut x = &x; | ^^^^^ error: `x` is shadowed by itself in `*x` - --> $DIR/shadow.rs:16:9 + --> $DIR/shadow.rs:22:9 | LL | let x = *x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:21:9 | LL | let x = &mut x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:27:9 | LL | let x = x.0; | ^ | note: previous binding is here - --> $DIR/shadow.rs:20:9 + --> $DIR/shadow.rs:26:9 | LL | let x = ([[0]], ()); | ^ = note: `-D clippy::shadow-reuse` implied by `-D warnings` error: `x` is shadowed - --> $DIR/shadow.rs:22:9 + --> $DIR/shadow.rs:28:9 | LL | let x = x[0]; | ^ | note: previous binding is here - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:27:9 | LL | let x = x.0; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:23:10 + --> $DIR/shadow.rs:29:10 | LL | let [x] = x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:22:9 + --> $DIR/shadow.rs:28:9 | LL | let x = x[0]; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:24:9 + --> $DIR/shadow.rs:30:9 | LL | let x = Some(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:23:10 + --> $DIR/shadow.rs:29:10 | LL | let [x] = x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:25:9 + --> $DIR/shadow.rs:31:9 | LL | let x = foo(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:24:9 + --> $DIR/shadow.rs:30:9 | LL | let x = Some(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:26:9 + --> $DIR/shadow.rs:32:9 | LL | let x = || x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:25:9 + --> $DIR/shadow.rs:31:9 | LL | let x = foo(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:27:9 + --> $DIR/shadow.rs:33:9 | LL | let x = Some(1).map(|_| x)?; | ^ | note: previous binding is here - --> $DIR/shadow.rs:26:9 + --> $DIR/shadow.rs:32:9 | LL | let x = || x; | ^ error: `y` is shadowed - --> $DIR/shadow.rs:29:9 + --> $DIR/shadow.rs:35:9 | LL | let y = match y { | ^ | note: previous binding is here - --> $DIR/shadow.rs:28:9 + --> $DIR/shadow.rs:34:9 | LL | let y = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:50:9 | LL | let x = 2; | ^ | note: previous binding is here - --> $DIR/shadow.rs:37:9 + --> $DIR/shadow.rs:49:9 | LL | let x = 1; | ^ = note: `-D clippy::shadow-unrelated` implied by `-D warnings` error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:43:13 + --> $DIR/shadow.rs:55:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:42:10 + --> $DIR/shadow.rs:54:10 | LL | fn f(x: u32) { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:48:14 + --> $DIR/shadow.rs:60:14 | LL | Some(x) => { | ^ | note: previous binding is here - --> $DIR/shadow.rs:45:9 + --> $DIR/shadow.rs:57:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:49:17 + --> $DIR/shadow.rs:61:17 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:48:14 + --> $DIR/shadow.rs:60:14 | LL | Some(x) => { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:53:17 + --> $DIR/shadow.rs:65:17 | LL | if let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:45:9 + --> $DIR/shadow.rs:57:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:54:20 + --> $DIR/shadow.rs:66:20 | LL | while let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:45:9 + --> $DIR/shadow.rs:57:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:55:15 + --> $DIR/shadow.rs:67:15 | LL | let _ = |[x]: [u32; 1]| { | ^ | note: previous binding is here - --> $DIR/shadow.rs:45:9 + --> $DIR/shadow.rs:57:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:56:13 + --> $DIR/shadow.rs:68:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:55:15 + --> $DIR/shadow.rs:67:15 | LL | let _ = |[x]: [u32; 1]| { | ^ error: `y` is shadowed - --> $DIR/shadow.rs:59:17 + --> $DIR/shadow.rs:71:17 | LL | if let Some(y) = y {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:58:9 + --> $DIR/shadow.rs:70:9 | LL | let y = Some(1); | ^ error: `_b` shadows a previous, unrelated binding - --> $DIR/shadow.rs:95:9 + --> $DIR/shadow.rs:107:9 | LL | let _b = _a; | ^^ | note: previous binding is here - --> $DIR/shadow.rs:94:28 + --> $DIR/shadow.rs:106:28 | LL | pub async fn foo2(_a: i32, _b: i64) { | ^^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:101:21 + --> $DIR/shadow.rs:113:21 | LL | if let Some(x) = Some(1) { x } else { 1 } | ^ | note: previous binding is here - --> $DIR/shadow.rs:100:13 + --> $DIR/shadow.rs:112:13 | LL | let x = 1; | ^ -- cgit 1.4.1-3-g733a5 From 0add5bb0f1c5535a508155e6065d24bf0a8c1dbe Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 23 Apr 2023 03:39:19 -0700 Subject: Bump Clippy version -> 0.1.71 --- Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_utils/Cargo.toml | 2 +- declare_clippy_lint/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4db15ddb283..3c72bb62ed1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.70" +version = "0.1.71" 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/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 5c6040f63f5..a0db69b652d 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.70" +version = "0.1.71" 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/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 124ebd164e6..66a5079fa85 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.70" +version = "0.1.71" edition = "2021" publish = false diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index bd26f4fc913..139102798c4 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.70" +version = "0.1.71" edition = "2021" publish = false -- cgit 1.4.1-3-g733a5 From d5a2c2ba713985d01d2105c43891ba829331ee22 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 23 Apr 2023 03:39:29 -0700 Subject: Bump nightly version -> 2023-04-23 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 91e8ccea1f4..7a6d85f4147 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-04-06" +channel = "nightly-2023-04-23" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] -- cgit 1.4.1-3-g733a5 From 36bf3ef0042397f0d9d21f9de695f551e4e9d3b5 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 23 Apr 2023 03:44:24 -0700 Subject: Fix dogfood test --- tests/dogfood.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 68a878e9a3d..afde31face1 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -39,7 +39,7 @@ fn dogfood_clippy() { assert!( failed_packages.is_empty(), "Dogfood failed for packages `{}`", - failed_packages.iter().format(", "), + failed_packages.iter().join(", "), ); } -- cgit 1.4.1-3-g733a5 From acf50a7dc685ad5267e2fcff5a1545d5e56f5c44 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sun, 23 Apr 2023 12:52:45 +0200 Subject: Improve the help message + add a help span --- clippy_lints/src/let_underscore.rs | 10 ++++++++-- tests/ui/let_underscore_untyped.stderr | 30 +++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 637b7de920e..16772a9d598 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -6,6 +6,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -205,8 +206,13 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { LET_UNDERSCORE_UNTYPED, local.span, "non-binding `let` without a type annotation", - None, - "consider adding a type annotation or removing the `let` keyword", + Some( + Span::new(local.pat.span.hi(), + local.pat.span.hi() + BytePos(1), + local.pat.span.ctxt(), + local.pat.span.parent() + )), + "consider adding a type annotation", ); } } diff --git a/tests/ui/let_underscore_untyped.stderr b/tests/ui/let_underscore_untyped.stderr index 47e76ea1d04..6844cb998f7 100644 --- a/tests/ui/let_underscore_untyped.stderr +++ b/tests/ui/let_underscore_untyped.stderr @@ -4,7 +4,11 @@ error: non-binding `let` without a type annotation LL | let _ = a(); | ^^^^^^^^^^^^ | - = help: consider adding a type annotation or removing the `let` keyword +help: consider adding a type annotation + --> $DIR/let_underscore_untyped.rs:36:10 + | +LL | let _ = a(); + | ^ = note: `-D clippy::let-underscore-untyped` implied by `-D warnings` error: non-binding `let` without a type annotation @@ -13,7 +17,11 @@ error: non-binding `let` without a type annotation LL | let _ = b(1); | ^^^^^^^^^^^^^ | - = help: consider adding a type annotation or removing the `let` keyword +help: consider adding a type annotation + --> $DIR/let_underscore_untyped.rs:37:10 + | +LL | let _ = b(1); + | ^ error: non-binding `let` without a type annotation --> $DIR/let_underscore_untyped.rs:39:5 @@ -21,7 +29,11 @@ error: non-binding `let` without a type annotation LL | let _ = d(&1); | ^^^^^^^^^^^^^^ | - = help: consider adding a type annotation or removing the `let` keyword +help: consider adding a type annotation + --> $DIR/let_underscore_untyped.rs:39:10 + | +LL | let _ = d(&1); + | ^ error: non-binding `let` without a type annotation --> $DIR/let_underscore_untyped.rs:40:5 @@ -29,7 +41,11 @@ error: non-binding `let` without a type annotation LL | let _ = e(); | ^^^^^^^^^^^^ | - = help: consider adding a type annotation or removing the `let` keyword +help: consider adding a type annotation + --> $DIR/let_underscore_untyped.rs:40:10 + | +LL | let _ = e(); + | ^ error: non-binding `let` without a type annotation --> $DIR/let_underscore_untyped.rs:41:5 @@ -37,7 +53,11 @@ error: non-binding `let` without a type annotation LL | let _ = f(); | ^^^^^^^^^^^^ | - = help: consider adding a type annotation or removing the `let` keyword +help: consider adding a type annotation + --> $DIR/let_underscore_untyped.rs:41:10 + | +LL | let _ = f(); + | ^ error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From a1b75c5108514504c8382ac70d56f9a2a9aee7c4 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sun, 23 Apr 2023 13:03:09 +0200 Subject: Merge commit 'a3ed905928a03b6e433d0b429190bf3a847128b3' into clippyup --- CHANGELOG.md | 120 ++++++++- Cargo.toml | 5 +- book/src/SUMMARY.md | 2 + book/src/development/README.md | 22 ++ book/src/development/adding_lints.md | 2 +- book/src/development/lint_passes.md | 114 +++++++++ book/src/development/macro_expansions.md | 158 ++++++++++++ book/src/development/type_checking.md | 25 +- book/src/lint_configuration.md | 9 + clippy_dev/src/update_lints.rs | 2 +- clippy_lints/src/allow_attributes.rs | 2 +- clippy_lints/src/casts/mod.rs | 10 +- clippy_lints/src/crate_in_macro_def.rs | 2 +- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/entry.rs | 2 +- clippy_lints/src/enum_variants.rs | 8 +- clippy_lints/src/format_impl.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/functions/mod.rs | 2 +- clippy_lints/src/items_after_test_module.rs | 83 +++++++ clippy_lints/src/len_zero.rs | 22 +- clippy_lints/src/let_underscore.rs | 15 +- clippy_lints/src/lib.rs | 4 + clippy_lints/src/lines_filter_map_ok.rs | 2 +- clippy_lints/src/manual_bits.rs | 2 +- clippy_lints/src/manual_slice_size_calculation.rs | 28 ++- clippy_lints/src/matches/mod.rs | 6 +- clippy_lints/src/methods/mod.rs | 34 +-- clippy_lints/src/methods/obfuscated_if_else.rs | 2 - clippy_lints/src/multiple_unsafe_ops_per_block.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 6 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/octal_escapes.rs | 94 ++++---- .../src/operators/arithmetic_side_effects.rs | 42 +++- clippy_lints/src/operators/mod.rs | 2 +- clippy_lints/src/operators/numeric_arithmetic.rs | 10 +- clippy_lints/src/question_mark_used.rs | 2 +- clippy_lints/src/significant_drop_tightening.rs | 4 +- clippy_lints/src/types/mod.rs | 10 +- clippy_lints/src/unnecessary_box_returns.rs | 15 +- clippy_lints/src/utils/conf.rs | 4 + .../utils/internal_lints/unnecessary_def_path.rs | 2 +- clippy_lints/src/write.rs | 2 +- declare_clippy_lint/Cargo.toml | 2 +- declare_clippy_lint/src/lib.rs | 8 +- tests/compile-test.rs | 3 +- .../cargo_common_metadata/fail/src/main.rs | 2 +- .../cargo_common_metadata/fail_publish/src/main.rs | 2 +- .../fail_publish_true/src/main.rs | 2 +- .../cargo_common_metadata/pass/src/main.rs | 2 +- .../pass_publish_empty/src/main.rs | 2 +- .../pass_publish_false/src/main.rs | 2 +- tests/ui-cargo/feature_name/fail/src/main.rs | 2 +- tests/ui-cargo/feature_name/pass/src/main.rs | 2 +- .../module_style/fail_mod_remap/src/main.rs | 2 +- .../5041_allow_dev_build/src/main.rs | 2 +- .../multiple_crate_versions/fail/src/main.rs | 2 +- .../multiple_crate_versions/pass/src/main.rs | 2 +- .../wildcard_dependencies/fail/src/main.rs | 2 +- .../wildcard_dependencies/pass/src/main.rs | 2 +- .../ui-internal/collapsible_span_lint_calls.fixed | 2 +- tests/ui-internal/collapsible_span_lint_calls.rs | 2 +- tests/ui-internal/custom_ice_message.rs | 12 +- tests/ui-internal/interning_defined_symbol.fixed | 2 +- tests/ui-internal/interning_defined_symbol.rs | 2 +- tests/ui-internal/invalid_msrv_attr_impl.fixed | 2 +- tests/ui-internal/invalid_msrv_attr_impl.rs | 2 +- tests/ui-internal/outer_expn_data.fixed | 2 +- tests/ui-internal/outer_expn_data.rs | 2 +- tests/ui-internal/unnecessary_def_path.fixed | 4 +- tests/ui-internal/unnecessary_def_path.rs | 4 +- tests/ui-internal/unnecessary_symbol_str.fixed | 2 +- tests/ui-internal/unnecessary_symbol_str.rs | 2 +- .../uninlined_format_args.fixed | 2 +- .../uninlined_format_args.rs | 2 +- tests/ui-toml/dbg_macro/dbg_macro.rs | 2 +- .../ui-toml/disallowed_macros/disallowed_macros.rs | 2 +- tests/ui-toml/expect_used/expect_used.rs | 2 +- tests/ui-toml/mut_key/mut_key.rs | 2 +- .../auxiliary/proc_macro_derive.rs | 4 +- .../conf_nonstandard_macro_braces.fixed | 4 +- .../conf_nonstandard_macro_braces.rs | 4 +- tests/ui-toml/print_macro/print_macro.rs | 2 +- .../conf_disallowed_methods.rs | 2 +- tests/ui-toml/toml_trivially_copy/test.rs | 4 +- tests/ui-toml/toml_unknown_key/conf_unknown_key.rs | 2 + .../toml_unknown_key/conf_unknown_key.stderr | 1 + tests/ui-toml/unwrap_used/unwrap_used.rs | 2 +- tests/ui/allow_attributes.fixed | 2 +- tests/ui/allow_attributes.rs | 2 +- tests/ui/almost_complete_range.fixed | 6 +- tests/ui/almost_complete_range.rs | 6 +- tests/ui/arithmetic_side_effects.rs | 29 +++ tests/ui/arithmetic_side_effects.stderr | 268 ++++++++++++--------- tests/ui/as_conversions.rs | 2 +- tests/ui/as_underscore.fixed | 2 +- tests/ui/as_underscore.rs | 2 +- tests/ui/asm_syntax.rs | 4 +- tests/ui/assertions_on_result_states.fixed | 2 +- tests/ui/assertions_on_result_states.rs | 2 +- tests/ui/assign_ops.fixed | 2 +- tests/ui/assign_ops.rs | 2 +- tests/ui/async_yields_async.fixed | 2 +- tests/ui/async_yields_async.rs | 2 +- tests/ui/author/blocks.rs | 2 +- tests/ui/auxiliary/proc_macro_attr.rs | 8 +- tests/ui/auxiliary/proc_macro_derive.rs | 77 +++++- .../proc_macro_suspicious_else_formatting.rs | 4 +- tests/ui/auxiliary/proc_macro_unsafe.rs | 4 +- tests/ui/auxiliary/proc_macros.rs | 4 +- tests/ui/bind_instead_of_map.fixed | 2 +- tests/ui/bind_instead_of_map.rs | 2 +- tests/ui/bind_instead_of_map_multipart.fixed | 2 +- tests/ui/bind_instead_of_map_multipart.rs | 2 +- tests/ui/blanket_clippy_restriction_lints.rs | 2 +- tests/ui/blocks_in_if_conditions.fixed | 2 +- tests/ui/blocks_in_if_conditions.rs | 2 +- tests/ui/bool_assert_comparison.fixed | 2 +- tests/ui/bool_assert_comparison.rs | 2 +- tests/ui/bool_comparison.fixed | 2 +- tests/ui/bool_comparison.rs | 2 +- tests/ui/bool_to_int_with_if.fixed | 2 +- tests/ui/bool_to_int_with_if.rs | 2 +- tests/ui/borrow_as_ptr.fixed | 2 +- tests/ui/borrow_as_ptr.rs | 2 +- tests/ui/borrow_as_ptr_no_std.fixed | 2 +- tests/ui/borrow_as_ptr_no_std.rs | 2 +- tests/ui/borrow_deref_ref.fixed | 2 +- tests/ui/borrow_deref_ref.rs | 2 +- tests/ui/borrow_interior_mutable_const/enums.rs | 2 +- tests/ui/box_default.fixed | 2 +- tests/ui/box_default.rs | 2 +- tests/ui/bytes_count_to_len.fixed | 2 +- tests/ui/bytes_count_to_len.rs | 2 +- tests/ui/bytes_nth.fixed | 2 +- tests/ui/bytes_nth.rs | 2 +- ...case_sensitive_file_extension_comparisons.fixed | 2 +- .../case_sensitive_file_extension_comparisons.rs | 2 +- tests/ui/cast_abs_to_unsigned.fixed | 2 +- tests/ui/cast_abs_to_unsigned.rs | 2 +- tests/ui/cast_lossless_bool.fixed | 2 +- tests/ui/cast_lossless_bool.rs | 2 +- tests/ui/cast_lossless_float.fixed | 2 +- tests/ui/cast_lossless_float.rs | 2 +- tests/ui/cast_lossless_integer.fixed | 2 +- tests/ui/cast_lossless_integer.rs | 2 +- tests/ui/cast_raw_slice_pointer_cast.fixed | 2 +- tests/ui/cast_raw_slice_pointer_cast.rs | 2 +- tests/ui/cast_size.rs | 2 +- tests/ui/cast_size_32bit.rs | 2 +- tests/ui/cast_size_32bit.stderr | 53 ++++ tests/ui/cfg_attr_rustfmt.fixed | 2 +- tests/ui/cfg_attr_rustfmt.rs | 2 +- tests/ui/char_lit_as_u8_suggestions.fixed | 2 +- tests/ui/char_lit_as_u8_suggestions.rs | 2 +- tests/ui/checked_conversions.fixed | 2 +- tests/ui/checked_conversions.rs | 2 +- tests/ui/clear_with_drain.fixed | 2 +- tests/ui/clear_with_drain.rs | 2 +- tests/ui/clone_on_copy.fixed | 2 +- tests/ui/clone_on_copy.rs | 2 +- tests/ui/cloned_instead_of_copied.fixed | 2 +- tests/ui/cloned_instead_of_copied.rs | 2 +- tests/ui/cmp_owned/asymmetric_partial_eq.fixed | 2 +- tests/ui/cmp_owned/asymmetric_partial_eq.rs | 2 +- tests/ui/cmp_owned/comparison_flip.fixed | 2 +- tests/ui/cmp_owned/comparison_flip.rs | 2 +- tests/ui/cmp_owned/with_suggestion.fixed | 2 +- tests/ui/cmp_owned/with_suggestion.rs | 2 +- tests/ui/collapsible_else_if.fixed | 2 +- tests/ui/collapsible_else_if.rs | 2 +- tests/ui/collapsible_if.fixed | 2 +- tests/ui/collapsible_if.rs | 2 +- tests/ui/collapsible_str_replace.fixed | 2 +- tests/ui/collapsible_str_replace.rs | 2 +- tests/ui/collection_is_never_read.rs | 49 ++-- tests/ui/collection_is_never_read.stderr | 62 ++++- tests/ui/comparison_to_empty.fixed | 2 +- tests/ui/comparison_to_empty.rs | 2 +- tests/ui/crashes/auxiliary/proc_macro_crash.rs | 4 +- tests/ui/crashes/ice-10148.rs | 2 +- tests/ui/crashes/ice-3741.rs | 2 +- tests/ui/crashes/ice-4968.rs | 2 +- tests/ui/crashes/ice-5207.stderr | 4 +- tests/ui/crashes/ice-7272.rs | 2 +- tests/ui/crashes/ice-7410.rs | 6 +- tests/ui/crashes/ice-8681.rs | 2 +- tests/ui/crate_in_macro_def.fixed | 2 +- tests/ui/crate_in_macro_def.rs | 2 +- .../ui/crate_level_checks/entrypoint_recursion.rs | 2 +- .../ui/crate_level_checks/no_std_main_recursion.rs | 4 +- tests/ui/create_dir.fixed | 2 +- tests/ui/create_dir.rs | 2 +- tests/ui/dbg_macro.rs | 2 +- tests/ui/decimal_literal_representation.fixed | 2 +- tests/ui/decimal_literal_representation.rs | 2 +- tests/ui/def_id_nocore.rs | 2 +- tests/ui/default_instead_of_iter_empty.fixed | 2 +- tests/ui/default_instead_of_iter_empty.rs | 2 +- tests/ui/default_numeric_fallback_f64.fixed | 4 +- tests/ui/default_numeric_fallback_f64.rs | 4 +- tests/ui/default_numeric_fallback_i32.fixed | 4 +- tests/ui/default_numeric_fallback_i32.rs | 4 +- tests/ui/default_trait_access.fixed | 4 +- tests/ui/default_trait_access.rs | 4 +- tests/ui/deref_addrof.fixed | 4 +- tests/ui/deref_addrof.rs | 4 +- tests/ui/deref_addrof_macro.rs | 2 +- tests/ui/deref_by_slicing.fixed | 2 +- tests/ui/deref_by_slicing.rs | 2 +- tests/ui/derivable_impls.fixed | 2 +- tests/ui/derivable_impls.rs | 2 +- tests/ui/derive_partial_eq_without_eq.fixed | 2 +- tests/ui/derive_partial_eq_without_eq.rs | 2 +- tests/ui/doc/doc-fixable.fixed | 2 +- tests/ui/doc/doc-fixable.rs | 2 +- tests/ui/doc_unsafe.rs | 2 +- tests/ui/double_comparison.fixed | 2 +- tests/ui/double_comparison.rs | 2 +- tests/ui/duration_subsec.fixed | 2 +- tests/ui/duration_subsec.rs | 2 +- tests/ui/empty_drop.fixed | 2 +- tests/ui/empty_drop.rs | 2 +- tests/ui/empty_line_after_outer_attribute.rs | 2 +- tests/ui/empty_loop.rs | 2 +- tests/ui/empty_loop_no_std.rs | 4 +- tests/ui/empty_structs_with_brackets.fixed | 2 +- tests/ui/empty_structs_with_brackets.rs | 2 +- tests/ui/entry.fixed | 4 +- tests/ui/entry.rs | 4 +- tests/ui/entry_btree.fixed | 2 +- tests/ui/entry_btree.rs | 2 +- tests/ui/entry_with_else.fixed | 2 +- tests/ui/entry_with_else.rs | 2 +- tests/ui/enum_clike_unportable_variant.rs | 2 +- tests/ui/enum_glob_use.fixed | 2 +- tests/ui/enum_glob_use.rs | 2 +- tests/ui/enum_variants.rs | 10 + tests/ui/eq_op.rs | 2 +- tests/ui/equatable_if_let.fixed | 4 +- tests/ui/equatable_if_let.rs | 4 +- tests/ui/err_expect.fixed | 2 +- tests/ui/err_expect.rs | 2 +- tests/ui/eta.fixed | 2 +- tests/ui/eta.rs | 2 +- tests/ui/excessive_precision.fixed | 2 +- tests/ui/excessive_precision.rs | 2 +- tests/ui/exhaustive_items.fixed | 2 +- tests/ui/exhaustive_items.rs | 2 +- tests/ui/expect_fun_call.fixed | 2 +- tests/ui/expect_fun_call.rs | 2 +- tests/ui/explicit_auto_deref.fixed | 2 +- tests/ui/explicit_auto_deref.rs | 2 +- tests/ui/explicit_deref_methods.fixed | 2 +- tests/ui/explicit_deref_methods.rs | 2 +- tests/ui/explicit_write.fixed | 2 +- tests/ui/explicit_write.rs | 2 +- tests/ui/extend_with_drain.fixed | 2 +- tests/ui/extend_with_drain.rs | 2 +- tests/ui/extra_unused_lifetimes.rs | 2 +- tests/ui/extra_unused_type_parameters.fixed | 2 +- tests/ui/extra_unused_type_parameters.rs | 2 +- tests/ui/field_reassign_with_default.rs | 4 +- tests/ui/filter_map_identity.fixed | 2 +- tests/ui/filter_map_identity.rs | 2 +- tests/ui/filter_map_next_fixable.fixed | 2 +- tests/ui/filter_map_next_fixable.rs | 2 +- tests/ui/flat_map_identity.fixed | 2 +- tests/ui/flat_map_identity.rs | 2 +- tests/ui/flat_map_option.fixed | 2 +- tests/ui/flat_map_option.rs | 2 +- tests/ui/floating_point_abs.fixed | 2 +- tests/ui/floating_point_abs.rs | 2 +- tests/ui/floating_point_exp.fixed | 2 +- tests/ui/floating_point_exp.rs | 2 +- tests/ui/floating_point_hypot.fixed | 2 +- tests/ui/floating_point_hypot.rs | 2 +- tests/ui/floating_point_log.fixed | 2 +- tests/ui/floating_point_log.rs | 2 +- tests/ui/floating_point_logbase.fixed | 2 +- tests/ui/floating_point_logbase.rs | 2 +- tests/ui/floating_point_mul_add.fixed | 2 +- tests/ui/floating_point_mul_add.rs | 2 +- tests/ui/floating_point_powf.fixed | 2 +- tests/ui/floating_point_powf.rs | 2 +- tests/ui/floating_point_powi.fixed | 2 +- tests/ui/floating_point_powi.rs | 2 +- tests/ui/floating_point_rad.fixed | 2 +- tests/ui/floating_point_rad.rs | 2 +- tests/ui/fn_to_numeric_cast.rs | 2 +- tests/ui/fn_to_numeric_cast_32bit.rs | 2 +- tests/ui/fn_to_numeric_cast_32bit.stderr | 14 +- tests/ui/for_loop_fixable.fixed | 2 +- tests/ui/for_loop_fixable.rs | 2 +- tests/ui/format.fixed | 2 +- tests/ui/format.rs | 2 +- tests/ui/format_args.fixed | 2 +- tests/ui/format_args.rs | 2 +- tests/ui/from_iter_instead_of_collect.fixed | 2 +- tests/ui/from_iter_instead_of_collect.rs | 2 +- tests/ui/from_over_into.fixed | 2 +- tests/ui/from_over_into.rs | 2 +- tests/ui/get_first.fixed | 2 +- tests/ui/get_first.rs | 2 +- tests/ui/get_last_with_len.fixed | 2 +- tests/ui/get_last_with_len.rs | 2 +- tests/ui/get_unwrap.fixed | 2 +- tests/ui/get_unwrap.rs | 2 +- tests/ui/identity_op.fixed | 2 +- tests/ui/identity_op.rs | 2 +- tests/ui/implicit_clone.fixed | 2 +- tests/ui/implicit_clone.rs | 2 +- tests/ui/implicit_hasher.rs | 2 +- tests/ui/implicit_return.fixed | 2 +- tests/ui/implicit_return.rs | 2 +- tests/ui/implicit_saturating_add.fixed | 2 +- tests/ui/implicit_saturating_add.rs | 2 +- tests/ui/implicit_saturating_sub.fixed | 2 +- tests/ui/implicit_saturating_sub.rs | 2 +- tests/ui/inconsistent_digit_grouping.fixed | 2 +- tests/ui/inconsistent_digit_grouping.rs | 2 +- tests/ui/inconsistent_struct_constructor.fixed | 4 +- tests/ui/inconsistent_struct_constructor.rs | 4 +- tests/ui/inefficient_to_string.fixed | 2 +- tests/ui/inefficient_to_string.rs | 2 +- tests/ui/infallible_destructuring_match.fixed | 2 +- tests/ui/infallible_destructuring_match.rs | 2 +- tests/ui/inline_fn_without_body.fixed | 2 +- tests/ui/inline_fn_without_body.rs | 2 +- tests/ui/int_plus_one.fixed | 2 +- tests/ui/int_plus_one.rs | 2 +- tests/ui/integer_arithmetic.rs | 7 + tests/ui/integer_arithmetic.stderr | 54 ++--- tests/ui/into_iter_on_ref.fixed | 2 +- tests/ui/into_iter_on_ref.rs | 2 +- tests/ui/invalid_null_ptr_usage.fixed | 2 +- tests/ui/invalid_null_ptr_usage.rs | 2 +- tests/ui/is_digit_ascii_radix.fixed | 2 +- tests/ui/is_digit_ascii_radix.rs | 2 +- tests/ui/issue_2356.fixed | 2 +- tests/ui/issue_2356.rs | 2 +- tests/ui/items_after_test_module.rs | 23 ++ tests/ui/items_after_test_module.stderr | 17 ++ tests/ui/iter_cloned_collect.fixed | 2 +- tests/ui/iter_cloned_collect.rs | 2 +- tests/ui/iter_count.fixed | 4 +- tests/ui/iter_count.rs | 4 +- tests/ui/iter_kv_map.fixed | 2 +- tests/ui/iter_kv_map.rs | 2 +- tests/ui/iter_next_slice.fixed | 2 +- tests/ui/iter_next_slice.rs | 2 +- tests/ui/iter_nth.rs | 2 +- tests/ui/iter_nth_zero.fixed | 2 +- tests/ui/iter_nth_zero.rs | 2 +- tests/ui/iter_on_empty_collections.fixed | 2 +- tests/ui/iter_on_empty_collections.rs | 2 +- tests/ui/iter_on_single_items.fixed | 2 +- tests/ui/iter_on_single_items.rs | 2 +- tests/ui/iter_overeager_cloned.fixed | 2 +- tests/ui/iter_overeager_cloned.rs | 2 +- tests/ui/iter_skip_next.fixed | 4 +- tests/ui/iter_skip_next.rs | 4 +- tests/ui/iter_with_drain.fixed | 2 +- tests/ui/iter_with_drain.rs | 2 +- tests/ui/large_const_arrays.fixed | 2 +- tests/ui/large_const_arrays.rs | 2 +- tests/ui/large_digit_groups.fixed | 2 +- tests/ui/large_digit_groups.rs | 2 +- tests/ui/large_enum_variant.rs | 2 +- tests/ui/large_types_passed_by_value.rs | 4 +- tests/ui/len_zero.fixed | 6 +- tests/ui/len_zero.rs | 6 +- tests/ui/len_zero.stderr | 16 +- tests/ui/len_zero_ranges.fixed | 2 +- tests/ui/len_zero_ranges.rs | 2 +- tests/ui/let_underscore_untyped.rs | 5 + tests/ui/let_underscore_untyped.stderr | 20 +- tests/ui/let_unit.fixed | 2 +- tests/ui/let_unit.rs | 2 +- tests/ui/lines_filter_map_ok.fixed | 2 +- tests/ui/lines_filter_map_ok.rs | 2 +- tests/ui/lossy_float_literal.fixed | 2 +- tests/ui/lossy_float_literal.rs | 2 +- tests/ui/macro_use_imports.fixed | 10 +- tests/ui/macro_use_imports.rs | 10 +- tests/ui/macro_use_imports_expect.rs | 8 +- tests/ui/manual_assert.edition2018.fixed | 8 +- tests/ui/manual_assert.edition2021.fixed | 8 +- tests/ui/manual_assert.rs | 8 +- tests/ui/manual_async_fn.fixed | 2 +- tests/ui/manual_async_fn.rs | 2 +- tests/ui/manual_bits.fixed | 2 +- tests/ui/manual_bits.rs | 2 +- tests/ui/manual_filter.fixed | 2 +- tests/ui/manual_filter.rs | 2 +- tests/ui/manual_filter_map.fixed | 2 +- tests/ui/manual_filter_map.rs | 2 +- tests/ui/manual_find_fixable.fixed | 2 +- tests/ui/manual_find_fixable.rs | 2 +- tests/ui/manual_find_map.fixed | 2 +- tests/ui/manual_find_map.rs | 2 +- tests/ui/manual_instant_elapsed.fixed | 2 +- tests/ui/manual_instant_elapsed.rs | 2 +- tests/ui/manual_is_ascii_check.fixed | 2 +- tests/ui/manual_is_ascii_check.rs | 2 +- tests/ui/manual_main_separator_str.fixed | 2 +- tests/ui/manual_main_separator_str.rs | 2 +- tests/ui/manual_map_option.fixed | 2 +- tests/ui/manual_map_option.rs | 2 +- tests/ui/manual_map_option_2.fixed | 2 +- tests/ui/manual_map_option_2.rs | 2 +- tests/ui/manual_ok_or.fixed | 2 +- tests/ui/manual_ok_or.rs | 2 +- tests/ui/manual_rem_euclid.fixed | 4 +- tests/ui/manual_rem_euclid.rs | 4 +- tests/ui/manual_retain.fixed | 2 +- tests/ui/manual_retain.rs | 2 +- tests/ui/manual_saturating_arithmetic.fixed | 2 +- tests/ui/manual_saturating_arithmetic.rs | 2 +- tests/ui/manual_slice_size_calculation.fixed | 46 ++++ tests/ui/manual_slice_size_calculation.rs | 10 + tests/ui/manual_slice_size_calculation.stderr | 41 ++-- tests/ui/manual_split_once.fixed | 2 +- tests/ui/manual_split_once.rs | 2 +- tests/ui/manual_str_repeat.fixed | 2 +- tests/ui/manual_str_repeat.rs | 2 +- tests/ui/manual_string_new.fixed | 2 +- tests/ui/manual_string_new.rs | 2 +- tests/ui/manual_unwrap_or.fixed | 2 +- tests/ui/manual_unwrap_or.rs | 2 +- tests/ui/map_clone.fixed | 2 +- tests/ui/map_clone.rs | 2 +- tests/ui/map_collect_result_unit.fixed | 2 +- tests/ui/map_collect_result_unit.rs | 2 +- tests/ui/map_flatten_fixable.fixed | 2 +- tests/ui/map_flatten_fixable.rs | 2 +- tests/ui/map_identity.fixed | 2 +- tests/ui/map_identity.rs | 2 +- tests/ui/map_unwrap_or.rs | 2 +- tests/ui/map_unwrap_or_fixable.fixed | 4 +- tests/ui/map_unwrap_or_fixable.rs | 4 +- tests/ui/match_as_ref.fixed | 2 +- tests/ui/match_as_ref.rs | 2 +- tests/ui/match_expr_like_matches_macro.fixed | 2 +- tests/ui/match_expr_like_matches_macro.rs | 2 +- tests/ui/match_ref_pats.fixed | 2 +- tests/ui/match_ref_pats.rs | 2 +- tests/ui/match_result_ok.fixed | 2 +- tests/ui/match_result_ok.rs | 2 +- tests/ui/match_single_binding.fixed | 2 +- tests/ui/match_single_binding.rs | 2 +- tests/ui/match_single_binding2.fixed | 2 +- tests/ui/match_single_binding2.rs | 2 +- tests/ui/match_str_case_mismatch.fixed | 2 +- tests/ui/match_str_case_mismatch.rs | 2 +- tests/ui/match_wildcard_for_single_variants.fixed | 2 +- tests/ui/match_wildcard_for_single_variants.rs | 2 +- tests/ui/mem_replace.fixed | 2 +- tests/ui/mem_replace.rs | 2 +- tests/ui/mem_replace_macro.rs | 2 +- tests/ui/methods.rs | 2 +- tests/ui/methods_fixable.fixed | 2 +- tests/ui/methods_fixable.rs | 2 +- tests/ui/mismatched_target_os_non_unix.fixed | 2 +- tests/ui/mismatched_target_os_non_unix.rs | 2 +- tests/ui/mismatched_target_os_unix.fixed | 2 +- tests/ui/mismatched_target_os_unix.rs | 2 +- tests/ui/missing_const_for_fn/cant_be_const.rs | 4 +- tests/ui/missing_doc.rs | 4 +- tests/ui/missing_doc_impl.rs | 2 +- tests/ui/missing_spin_loop.fixed | 2 +- tests/ui/missing_spin_loop.rs | 2 +- tests/ui/missing_spin_loop_no_std.fixed | 2 +- tests/ui/missing_spin_loop_no_std.rs | 2 +- tests/ui/mistyped_literal_suffix.fixed | 4 +- tests/ui/mistyped_literal_suffix.rs | 4 +- tests/ui/module_name_repetitions.rs | 2 +- tests/ui/multiple_unsafe_ops_per_block.rs | 2 +- tests/ui/must_use_candidates.fixed | 2 +- tests/ui/must_use_candidates.rs | 2 +- tests/ui/must_use_unit.fixed | 4 +- tests/ui/must_use_unit.rs | 4 +- tests/ui/mut_mut.rs | 2 +- tests/ui/mut_mutex_lock.fixed | 2 +- tests/ui/mut_mutex_lock.rs | 2 +- tests/ui/needless_arbitrary_self_type.fixed | 2 +- tests/ui/needless_arbitrary_self_type.rs | 2 +- tests/ui/needless_arbitrary_self_type_unfixable.rs | 2 +- .../needless_arbitrary_self_type_unfixable.stderr | 2 +- tests/ui/needless_bitwise_bool.fixed | 2 +- tests/ui/needless_bitwise_bool.rs | 2 +- tests/ui/needless_bool/fixable.fixed | 2 +- tests/ui/needless_bool/fixable.rs | 2 +- tests/ui/needless_borrow.fixed | 2 +- tests/ui/needless_borrow.rs | 2 +- tests/ui/needless_borrowed_ref.fixed | 2 +- tests/ui/needless_borrowed_ref.rs | 2 +- tests/ui/needless_collect.fixed | 2 +- tests/ui/needless_collect.rs | 2 +- tests/ui/needless_for_each_fixable.fixed | 2 +- tests/ui/needless_for_each_fixable.rs | 2 +- tests/ui/needless_late_init.fixed | 4 +- tests/ui/needless_late_init.rs | 4 +- tests/ui/needless_lifetimes.fixed | 4 +- tests/ui/needless_lifetimes.rs | 4 +- tests/ui/needless_match.fixed | 2 +- tests/ui/needless_match.rs | 2 +- tests/ui/needless_option_as_deref.fixed | 2 +- tests/ui/needless_option_as_deref.rs | 2 +- tests/ui/needless_option_take.fixed | 2 +- tests/ui/needless_option_take.rs | 2 +- tests/ui/needless_parens_on_range_literals.fixed | 4 +- tests/ui/needless_parens_on_range_literals.rs | 4 +- tests/ui/needless_question_mark.fixed | 2 +- tests/ui/needless_question_mark.rs | 2 +- tests/ui/needless_return.fixed | 2 +- tests/ui/needless_return.rs | 2 +- tests/ui/needless_splitn.fixed | 4 +- tests/ui/needless_splitn.rs | 4 +- tests/ui/neg_multiply.fixed | 2 +- tests/ui/neg_multiply.rs | 2 +- tests/ui/non_octal_unix_permissions.fixed | 4 +- tests/ui/non_octal_unix_permissions.rs | 4 +- tests/ui/nonminimal_bool_methods.fixed | 2 +- tests/ui/nonminimal_bool_methods.rs | 2 +- tests/ui/numbered_fields.fixed | 2 +- tests/ui/numbered_fields.rs | 2 +- tests/ui/obfuscated_if_else.fixed | 2 +- tests/ui/obfuscated_if_else.rs | 2 +- tests/ui/octal_escapes.rs | 1 + tests/ui/octal_escapes.stderr | 18 +- tests/ui/option_as_ref_deref.fixed | 2 +- tests/ui/option_as_ref_deref.rs | 2 +- tests/ui/option_env_unwrap.rs | 2 +- tests/ui/option_filter_map.fixed | 2 +- tests/ui/option_filter_map.rs | 2 +- tests/ui/option_if_let_else.fixed | 2 +- tests/ui/option_if_let_else.rs | 2 +- tests/ui/option_map_or_none.fixed | 2 +- tests/ui/option_map_or_none.rs | 2 +- tests/ui/option_map_unit_fn_fixable.fixed | 2 +- tests/ui/option_map_unit_fn_fixable.rs | 2 +- tests/ui/or_fun_call.fixed | 2 +- tests/ui/or_fun_call.rs | 2 +- tests/ui/or_then_unwrap.fixed | 2 +- tests/ui/or_then_unwrap.rs | 2 +- tests/ui/partialeq_to_none.fixed | 2 +- tests/ui/partialeq_to_none.rs | 2 +- tests/ui/path_buf_push_overwrite.fixed | 2 +- tests/ui/path_buf_push_overwrite.rs | 2 +- tests/ui/patterns.fixed | 2 +- tests/ui/patterns.rs | 2 +- tests/ui/precedence.fixed | 2 +- tests/ui/precedence.rs | 2 +- tests/ui/print_stdout_build_script.rs | 2 +- tests/ui/print_with_newline.rs | 2 +- tests/ui/println_empty_string.fixed | 2 +- tests/ui/println_empty_string.rs | 2 +- tests/ui/ptr_as_ptr.fixed | 4 +- tests/ui/ptr_as_ptr.rs | 4 +- tests/ui/ptr_eq.fixed | 2 +- tests/ui/ptr_eq.rs | 2 +- tests/ui/ptr_offset_with_cast.fixed | 2 +- tests/ui/ptr_offset_with_cast.rs | 2 +- tests/ui/question_mark.fixed | 2 +- tests/ui/question_mark.rs | 2 +- tests/ui/range_contains.fixed | 2 +- tests/ui/range_contains.rs | 2 +- tests/ui/range_plus_minus_one.fixed | 2 +- tests/ui/range_plus_minus_one.rs | 2 +- tests/ui/rc_buffer.fixed | 2 +- tests/ui/rc_buffer.rs | 2 +- tests/ui/rc_buffer_arc.fixed | 2 +- tests/ui/rc_buffer_arc.rs | 2 +- tests/ui/redundant_allocation_fixable.fixed | 2 +- tests/ui/redundant_allocation_fixable.rs | 2 +- tests/ui/redundant_async_block.fixed | 2 +- tests/ui/redundant_async_block.rs | 2 +- tests/ui/redundant_clone.fixed | 2 +- tests/ui/redundant_clone.rs | 2 +- tests/ui/redundant_closure_call_fixable.fixed | 2 +- tests/ui/redundant_closure_call_fixable.rs | 2 +- tests/ui/redundant_field_names.fixed | 2 +- tests/ui/redundant_field_names.rs | 2 +- .../ui/redundant_pattern_matching_drop_order.fixed | 2 +- tests/ui/redundant_pattern_matching_drop_order.rs | 2 +- tests/ui/redundant_pattern_matching_ipaddr.fixed | 2 +- tests/ui/redundant_pattern_matching_ipaddr.rs | 2 +- tests/ui/redundant_pattern_matching_option.fixed | 2 +- tests/ui/redundant_pattern_matching_option.rs | 2 +- tests/ui/redundant_pattern_matching_poll.fixed | 2 +- tests/ui/redundant_pattern_matching_poll.rs | 2 +- tests/ui/redundant_pattern_matching_result.fixed | 2 +- tests/ui/redundant_pattern_matching_result.rs | 2 +- tests/ui/redundant_pub_crate.fixed | 2 +- tests/ui/redundant_pub_crate.rs | 2 +- tests/ui/redundant_slicing.fixed | 2 +- tests/ui/redundant_slicing.rs | 2 +- tests/ui/redundant_static_lifetimes.fixed | 2 +- tests/ui/redundant_static_lifetimes.rs | 2 +- tests/ui/rename.fixed | 2 +- tests/ui/rename.rs | 2 +- tests/ui/renamed_builtin_attr.fixed | 2 +- tests/ui/renamed_builtin_attr.rs | 2 +- tests/ui/repeat_once.fixed | 2 +- tests/ui/repeat_once.rs | 2 +- tests/ui/result_map_or_into_option.fixed | 2 +- tests/ui/result_map_or_into_option.rs | 2 +- tests/ui/result_map_unit_fn_fixable.fixed | 2 +- tests/ui/result_map_unit_fn_fixable.rs | 2 +- tests/ui/reversed_empty_ranges_fixable.fixed | 2 +- tests/ui/reversed_empty_ranges_fixable.rs | 2 +- tests/ui/reversed_empty_ranges_loops_fixable.fixed | 2 +- tests/ui/reversed_empty_ranges_loops_fixable.rs | 2 +- tests/ui/same_functions_in_if_condition.rs | 2 +- tests/ui/same_functions_in_if_condition.stderr | 6 +- tests/ui/search_is_some.rs | 2 +- tests/ui/search_is_some_fixable_none.fixed | 2 +- tests/ui/search_is_some_fixable_none.rs | 2 +- tests/ui/search_is_some_fixable_some.fixed | 2 +- tests/ui/search_is_some_fixable_some.rs | 2 +- tests/ui/seek_from_current.fixed | 2 +- tests/ui/seek_from_current.rs | 2 +- tests/ui/seek_to_start_instead_of_rewind.fixed | 2 +- tests/ui/seek_to_start_instead_of_rewind.rs | 2 +- tests/ui/semicolon_inside_block.fixed | 2 +- tests/ui/semicolon_inside_block.rs | 2 +- tests/ui/semicolon_outside_block.fixed | 2 +- tests/ui/semicolon_outside_block.rs | 2 +- tests/ui/shadow.rs | 7 + tests/ui/shadow.stderr | 92 +++---- tests/ui/short_circuit_statement.fixed | 2 +- tests/ui/short_circuit_statement.rs | 2 +- tests/ui/significant_drop_in_scrutinee.rs | 2 +- tests/ui/significant_drop_tightening.fixed | 2 +- tests/ui/significant_drop_tightening.rs | 2 +- tests/ui/single_char_add_str.fixed | 2 +- tests/ui/single_char_add_str.rs | 2 +- tests/ui/single_char_pattern.fixed | 2 +- tests/ui/single_char_pattern.rs | 2 +- tests/ui/single_component_path_imports.fixed | 2 +- tests/ui/single_component_path_imports.rs | 2 +- tests/ui/single_element_loop.fixed | 2 +- tests/ui/single_element_loop.rs | 2 +- tests/ui/single_match_else.rs | 2 +- tests/ui/skip_while_next.rs | 2 +- tests/ui/stable_sort_primitive.fixed | 2 +- tests/ui/stable_sort_primitive.rs | 2 +- tests/ui/starts_ends_with.fixed | 2 +- tests/ui/starts_ends_with.rs | 2 +- tests/ui/string_add.rs | 2 +- tests/ui/string_add_assign.fixed | 2 +- tests/ui/string_add_assign.rs | 2 +- tests/ui/string_extend.fixed | 2 +- tests/ui/string_extend.rs | 2 +- tests/ui/string_from_utf8_as_bytes.fixed | 2 +- tests/ui/string_from_utf8_as_bytes.rs | 2 +- tests/ui/string_lit_as_bytes.fixed | 2 +- tests/ui/string_lit_as_bytes.rs | 2 +- tests/ui/strlen_on_c_strings.fixed | 2 +- tests/ui/strlen_on_c_strings.rs | 2 +- tests/ui/suspicious_doc_comments.fixed | 2 +- tests/ui/suspicious_doc_comments.rs | 2 +- tests/ui/suspicious_else_formatting.rs | 2 +- tests/ui/suspicious_operation_groupings.fixed | 2 +- tests/ui/suspicious_operation_groupings.rs | 2 +- tests/ui/swap.fixed | 4 +- tests/ui/swap.rs | 4 +- tests/ui/swap_ptr_to_ref.fixed | 2 +- tests/ui/swap_ptr_to_ref.rs | 2 +- tests/ui/tabs_in_doc_comments.fixed | 2 +- tests/ui/tabs_in_doc_comments.rs | 2 +- tests/ui/tests_outside_test_module.rs | 2 +- tests/ui/to_digit_is_some.fixed | 2 +- tests/ui/to_digit_is_some.rs | 2 +- tests/ui/toplevel_ref_arg.fixed | 4 +- tests/ui/toplevel_ref_arg.rs | 4 +- tests/ui/toplevel_ref_arg_non_rustfix.rs | 2 +- tests/ui/track-diagnostics.rs | 5 +- tests/ui/trait_duplication_in_bounds.fixed | 2 +- tests/ui/trait_duplication_in_bounds.rs | 2 +- tests/ui/transmute_32bit.rs | 2 +- tests/ui/transmute_32bit.stderr | 29 ++- tests/ui/transmute_64bit.rs | 2 +- tests/ui/transmute_ptr_to_ref.fixed | 2 +- tests/ui/transmute_ptr_to_ref.rs | 2 +- tests/ui/transmutes_expressible_as_ptr_casts.fixed | 2 +- tests/ui/transmutes_expressible_as_ptr_casts.rs | 2 +- tests/ui/trim_split_whitespace.fixed | 2 +- tests/ui/trim_split_whitespace.rs | 2 +- tests/ui/trivially_copy_pass_by_ref.rs | 4 +- tests/ui/try_err.fixed | 4 +- tests/ui/try_err.rs | 4 +- tests/ui/types.fixed | 2 +- tests/ui/types.rs | 2 +- tests/ui/unchecked_duration_subtraction.fixed | 2 +- tests/ui/unchecked_duration_subtraction.rs | 2 +- tests/ui/undocumented_unsafe_blocks.rs | 2 +- tests/ui/unicode.fixed | 4 +- tests/ui/unicode.rs | 4 +- tests/ui/uninlined_format_args.fixed | 4 +- tests/ui/uninlined_format_args.rs | 4 +- .../uninlined_format_args_panic.edition2018.fixed | 8 +- .../uninlined_format_args_panic.edition2021.fixed | 8 +- tests/ui/uninlined_format_args_panic.rs | 8 +- tests/ui/unit_arg.rs | 2 +- tests/ui/unit_arg_empty_blocks.fixed | 2 +- tests/ui/unit_arg_empty_blocks.rs | 2 +- tests/ui/unknown_clippy_lints.fixed | 2 +- tests/ui/unknown_clippy_lints.rs | 2 +- tests/ui/unnecessary_box_returns.rs | 10 + tests/ui/unnecessary_cast.fixed | 2 +- tests/ui/unnecessary_cast.rs | 2 +- tests/ui/unnecessary_fold.fixed | 2 +- tests/ui/unnecessary_fold.rs | 2 +- tests/ui/unnecessary_iter_cloned.fixed | 2 +- tests/ui/unnecessary_iter_cloned.rs | 2 +- tests/ui/unnecessary_join.fixed | 2 +- tests/ui/unnecessary_join.rs | 2 +- tests/ui/unnecessary_lazy_eval.fixed | 4 +- tests/ui/unnecessary_lazy_eval.rs | 4 +- tests/ui/unnecessary_operation.fixed | 2 +- tests/ui/unnecessary_operation.rs | 2 +- tests/ui/unnecessary_owned_empty_strings.fixed | 2 +- tests/ui/unnecessary_owned_empty_strings.rs | 2 +- tests/ui/unnecessary_self_imports.fixed | 2 +- tests/ui/unnecessary_self_imports.rs | 2 +- tests/ui/unnecessary_sort_by.fixed | 2 +- tests/ui/unnecessary_sort_by.rs | 2 +- tests/ui/unnecessary_struct_initialization.fixed | 2 +- tests/ui/unnecessary_struct_initialization.rs | 2 +- tests/ui/unnecessary_to_owned.fixed | 2 +- tests/ui/unnecessary_to_owned.rs | 2 +- tests/ui/unnecessary_unsafety_doc.rs | 2 +- tests/ui/unneeded_wildcard_pattern.fixed | 2 +- tests/ui/unneeded_wildcard_pattern.rs | 2 +- tests/ui/unnested_or_patterns.fixed | 2 +- tests/ui/unnested_or_patterns.rs | 2 +- tests/ui/unnested_or_patterns2.fixed | 2 +- tests/ui/unnested_or_patterns2.rs | 2 +- tests/ui/unreadable_literal.fixed | 2 +- tests/ui/unreadable_literal.rs | 2 +- tests/ui/unseparated_prefix_literals.fixed | 4 +- tests/ui/unseparated_prefix_literals.rs | 4 +- tests/ui/unused_rounding.fixed | 2 +- tests/ui/unused_rounding.rs | 2 +- tests/ui/unused_unit.fixed | 2 +- tests/ui/unused_unit.rs | 2 +- tests/ui/unwrap_or_else_default.fixed | 2 +- tests/ui/unwrap_or_else_default.rs | 2 +- tests/ui/use_self.fixed | 4 +- tests/ui/use_self.rs | 4 +- tests/ui/use_self_trait.fixed | 2 +- tests/ui/use_self_trait.rs | 2 +- tests/ui/used_underscore_binding.rs | 2 +- tests/ui/useless_asref.fixed | 2 +- tests/ui/useless_asref.rs | 2 +- tests/ui/useless_attribute.fixed | 4 +- tests/ui/useless_attribute.rs | 4 +- tests/ui/useless_conversion.fixed | 2 +- tests/ui/useless_conversion.rs | 2 +- tests/ui/vec.fixed | 2 +- tests/ui/vec.rs | 2 +- tests/ui/vec_box_sized.fixed | 2 +- tests/ui/vec_box_sized.rs | 2 +- tests/ui/while_let_on_iterator.fixed | 2 +- tests/ui/while_let_on_iterator.rs | 2 +- tests/ui/wildcard_enum_match_arm.fixed | 4 +- tests/ui/wildcard_enum_match_arm.rs | 4 +- tests/ui/wildcard_imports.fixed | 6 +- tests/ui/wildcard_imports.rs | 6 +- tests/ui/wildcard_imports_2021.edition2018.fixed | 10 +- tests/ui/wildcard_imports_2021.edition2021.fixed | 10 +- tests/ui/wildcard_imports_2021.rs | 10 +- tests/ui/wildcard_imports_2021.stderr | 132 ---------- tests/ui/write_with_newline.rs | 4 +- tests/ui/write_with_newline.stderr | 6 +- tests/ui/writeln_empty_string.fixed | 2 +- tests/ui/writeln_empty_string.rs | 2 +- tests/ui/zero_ptr.fixed | 2 +- tests/ui/zero_ptr.rs | 2 +- tests/ui/zero_ptr_no_std.fixed | 2 +- tests/ui/zero_ptr_no_std.rs | 2 +- 783 files changed, 2304 insertions(+), 1400 deletions(-) create mode 100644 book/src/development/lint_passes.md create mode 100644 book/src/development/macro_expansions.md create mode 100644 clippy_lints/src/items_after_test_module.rs create mode 100644 tests/ui/items_after_test_module.rs create mode 100644 tests/ui/items_after_test_module.stderr create mode 100644 tests/ui/manual_slice_size_calculation.fixed delete mode 100644 tests/ui/wildcard_imports_2021.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 559b560dde4..d7102d2474e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,126 @@ document. ## Unreleased / Beta / In Rust Nightly -[7f27e2e7...master](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...master) +[149392b0...master](https://github.com/rust-lang/rust-clippy/compare/149392b0...master) + +## Rust 1.69 + +Current stable, released 2023-04-20 + +[7f27e2e7...149392b0](https://github.com/rust-lang/rust-clippy/compare/7f27e2e7...149392b0) + +### New Lints + +* [`no_mangle_with_rust_abi`] + [#10369](https://github.com/rust-lang/rust-clippy/pull/10369) +* [`significant_drop_tightening`] + [#10163](https://github.com/rust-lang/rust-clippy/pull/10163) +* [`suspicious_command_arg_space`] + [#10317](https://github.com/rust-lang/rust-clippy/pull/10317) +* [`let_underscore_untyped`] + [#10356](https://github.com/rust-lang/rust-clippy/pull/10356) +* [`question_mark_used`] + [#10342](https://github.com/rust-lang/rust-clippy/pull/10342) +* [`extra_unused_type_parameters`] + [#10028](https://github.com/rust-lang/rust-clippy/pull/10028) +* [`impl_trait_in_params`] + [10197](https://github.com/rust-lang/rust-clippy/pull/10197) +* [`transmute_int_to_non_zero`] + [#10360](https://github.com/rust-lang/rust-clippy/pull/10360) +* [`multiple_unsafe_ops_per_block`] + [#10206](https://github.com/rust-lang/rust-clippy/pull/10206) + +### Moves and Deprecations + +* Moved [`uninlined_format_args`] to `pedantic` (Now allow-by-default) + [#10265](https://github.com/rust-lang/rust-clippy/pull/10265) +* Moved [`unchecked_duration_subtraction`] to `pedantic` (Now allow-by-default) + [#10194](https://github.com/rust-lang/rust-clippy/pull/10194) + +### Enhancements + +* [`arithmetic_side_effects`]: No longer lints, if safe constant values are used. + [#10310](https://github.com/rust-lang/rust-clippy/pull/10310) +* [`needless_lifetimes`]: Now works in local macros + [#10257](https://github.com/rust-lang/rust-clippy/pull/10257) +* [`unused_io_amount`]: Now detects usages of `is_ok` and `is_err` + [#10225](https://github.com/rust-lang/rust-clippy/pull/10225) +* [`missing_docs_in_private_items`]: Added new configuration `missing-docs-in-crate-items` to lint + on items visible within the current crate. For example, `pub(crate)` items. + [#10303](https://github.com/rust-lang/rust-clippy/pull/10303) +* [`almost_swapped`]: Now detects almost swaps using `let` statements + [#10177](https://github.com/rust-lang/rust-clippy/pull/10177) +* [`wildcard_enum_match_arm`]: Now lints missing private variants, for local enums + [#10250](https://github.com/rust-lang/rust-clippy/pull/10250) + +### False Positive Fixes + +* [`explicit_auto_deref`]: Now considers projections, when determining if auto deref is applicable + [#10386](https://github.com/rust-lang/rust-clippy/pull/10386) +* [`manual_let_else`]: Now considers side effects of branches, before linting + [#10336](https://github.com/rust-lang/rust-clippy/pull/10336) +* [`uninlined_format_args`]: No longer lints for arguments with generic parameters + [#10343](https://github.com/rust-lang/rust-clippy/pull/10343) +* [`needless_lifetimes`]: No longer lints signatures in macros, if the lifetime is a metavariable + [#10380](https://github.com/rust-lang/rust-clippy/pull/10380) +* [`len_without_is_empty`]: No longer lints, if `len` as a non-default signature + [#10255](https://github.com/rust-lang/rust-clippy/pull/10255) +* [`unusual_byte_groupings`]: Relaxed the required restrictions for specific sizes, to reduce false + positives + [#10353](https://github.com/rust-lang/rust-clippy/pull/10353) +* [`manual_let_else`]: No longer lints `if-else` blocks if they can divergent + [#10332](https://github.com/rust-lang/rust-clippy/pull/10332) +* [`expect_used`], [`unwrap_used`], [`dbg_macro`], [`print_stdout`], [`print_stderr`]: No longer lint + in test functions, if `allow-expect-in-tests` is set + [#10391](https://github.com/rust-lang/rust-clippy/pull/10391) +* [`unnecessary_safety_comment`]: No longer lints code inside macros + [#10106](https://github.com/rust-lang/rust-clippy/pull/10106) +* [`never_loop`]: No longer lints, for statements following break statements for outer blocks. + [#10311](https://github.com/rust-lang/rust-clippy/pull/10311) + +### Suggestion Fixes/Improvements + +* [`box_default`]: The suggestion now includes the type for trait objects, when needed + [#10382](https://github.com/rust-lang/rust-clippy/pull/10382) +* [`cast_possible_truncation`]: Now suggests using `try_from` or allowing the lint + [#10038](https://github.com/rust-lang/rust-clippy/pull/10038) +* [`invalid_regex`]: Regex errors for non-literals or regular strings containing escape sequences will + now show the complete error + [#10231](https://github.com/rust-lang/rust-clippy/pull/10231) +* [`transmutes_expressible_as_ptr_casts`]: The suggestion now works, if the base type is borrowed + [#10193](https://github.com/rust-lang/rust-clippy/pull/10193) +* [`needless_return`]: Now removes all semicolons on the same line + [#10187](https://github.com/rust-lang/rust-clippy/pull/10187) +* [`suspicious_to_owned`]: The suggestion now shows all options clearly + [#10295](https://github.com/rust-lang/rust-clippy/pull/10295) +* [`bytes_nth`]: Now suggests the correct replacement based on the context + [#10361](https://github.com/rust-lang/rust-clippy/pull/10361) +* [`bool_assert_comparison`]: The suggestion is now machine applicable + [#10218](https://github.com/rust-lang/rust-clippy/pull/10218) +* [`cast_possible_truncation`]: Corrected the lint name in the help message + [#10330](https://github.com/rust-lang/rust-clippy/pull/10330) +* [`needless_return`]: The suggestion now works on if sequences + [#10345](https://github.com/rust-lang/rust-clippy/pull/10345) +* [`needless_lifetimes`]: The suggestion is now machine applicable + [#10222](https://github.com/rust-lang/rust-clippy/pull/10222) +* [`map_entry`]: The suggestion no longer expands macros + [#10346](https://github.com/rust-lang/rust-clippy/pull/10346) + +### ICE Fixes + +* [`needless_pass_by_value`]: Fixed an ICE, caused by how late bounds were handled + [#10328](https://github.com/rust-lang/rust-clippy/pull/10328) +* [`needless_borrow`]: No longer panics on ambiguous projections + [#10403](https://github.com/rust-lang/rust-clippy/pull/10403) + +### Documentation Improvements + +* All configurations are now documented in the Clippy Book + [#10199](https://github.com/rust-lang/rust-clippy/pull/10199) ## Rust 1.68 -Current stable, released 2023-03-09 +Released 2023-03-09 [d822110d...7f27e2e7](https://github.com/rust-lang/rust-clippy/compare/d822110d...7f27e2e7) @@ -4615,6 +4730,7 @@ Released 2018-09-13 [`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 +[`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module [`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect [`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count [`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map diff --git a/Cargo.toml b/Cargo.toml index c35dfcbd8c4..4db15ddb283 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,13 +22,12 @@ path = "src/driver.rs" [dependencies] clippy_lints = { path = "clippy_lints" } -semver = "1.0" rustc_tools_util = "0.3.0" tempfile = { version = "3.2", optional = true } termize = "0.1" [dev-dependencies] -compiletest_rs = { version = "0.9", features = ["tmp"] } +compiletest_rs = { version = "0.10", features = ["tmp"] } tester = "0.9" regex = "1.5" toml = "0.5" @@ -49,7 +48,7 @@ if_chain = "1.0" itertools = "0.10.1" quote = "1.0" serde = { version = "1.0.125", features = ["derive"] } -syn = { version = "1.0", features = ["full"] } +syn = { version = "2.0", features = ["full"] } futures = "0.3" parking_lot = "0.12" tokio = { version = "1", features = ["io-util"] } diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index cbd73376dfa..22fbdce75e8 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -13,7 +13,9 @@ - [Development](development/README.md) - [Basics](development/basics.md) - [Adding Lints](development/adding_lints.md) + - [Lint Passes](development/lint_passes.md) - [Type Checking](development/type_checking.md) + - [Macro Expansions](development/macro_expansions.md) - [Common Tools](development/common_tools_writing_lints.md) - [Infrastructure](development/infrastructure/README.md) - [Syncing changes between Clippy and rust-lang/rust](development/infrastructure/sync.md) diff --git a/book/src/development/README.md b/book/src/development/README.md index 616e6d182b7..8f09f66f595 100644 --- a/book/src/development/README.md +++ b/book/src/development/README.md @@ -13,6 +13,24 @@ If this is your first time contributing to Clippy, you should first read the [Basics docs](basics.md). This will explain the basics on how to get the source code and how to compile and test the code. +## Additional Readings for Beginners + +If a dear reader of this documentation has never taken a class on compilers +and interpreters, it might be confusing as to why AST level deals with only +the language's syntax. And some readers might not even understand what lexing, +parsing, and AST mean. + +This documentation serves by no means as a crash course on compilers or language design. +And for details specifically related to Rust, the [Rustc Development Guide][rustc_dev_guide] +is a far better choice to peruse. + +The [Syntax and AST][ast] chapter and the [High-Level IR][hir] chapter are +great introduction to the concepts mentioned in this chapter. + +Some readers might also find the [introductory chapter][map_of_territory] of +Robert Nystrom's _Crafting Interpreters_ a helpful overview of compiled and +interpreted languages before jumping back to the Rustc guide. + ## Writing code If you have done the basic setup, it's time to start hacking. @@ -37,6 +55,10 @@ book](../lints.md). > - Triage procedure > - Bors and Homu +[ast]: https://rustc-dev-guide.rust-lang.org/syntax-intro.html +[hir]: https://rustc-dev-guide.rust-lang.org/hir.html +[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/ +[map_of_territory]: https://craftinginterpreters.com/a-map-of-the-territory.html [clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md [rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees [rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 9dacaaaae5c..ccae8d37420 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -164,7 +164,7 @@ The process of generating the `.stderr` file is the same, and prepending the ## Rustfix tests If the lint you are working on is making use of structured suggestions, the test -file should include a `// run-rustfix` comment at the top. This will +file should include a `//@run-rustfix` comment at the top. This will additionally run [rustfix] for that test. Rustfix will apply the suggestions from the lint to the code of the test file and compare that to the contents of a `.fixed` file. diff --git a/book/src/development/lint_passes.md b/book/src/development/lint_passes.md new file mode 100644 index 00000000000..c41b6ea0de8 --- /dev/null +++ b/book/src/development/lint_passes.md @@ -0,0 +1,114 @@ +# Lint passes + +Before working on the logic of a new lint, there is an important decision +that every Clippy developer must make: to use +[`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass]. + +In short, the `LateLintPass` has access to type and symbol information while the +`EarlyLintPass` doesn't. If you don't need access to type information, use the +`EarlyLintPass`. + +Let us expand on these two traits more below. + +## `EarlyLintPass` + +If you examine the documentation on [`EarlyLintPass`][early_lint_pass] closely, +you'll see that every method defined for this trait utilizes a +[`EarlyContext`][early_context]. In `EarlyContext`'s documentation, it states: + +> Context for lint checking of the AST, after expansion, before lowering to HIR. + +Voilà. `EarlyLintPass` works only on the Abstract Syntax Tree (AST) level. +And AST is generated during the [lexing and parsing][lexing_and_parsing] phase +of code compilation. Therefore, it doesn't know what a symbol means or information about types, and it should +be our trait choice for a new lint if the lint only deals with syntax-related issues. + +While linting speed has not been a concern for Clippy, +the `EarlyLintPass` is faster, and it should be your choice +if you know for sure a lint does not need type information. + +As a reminder, run the following command to generate boilerplate for lints +that use `EarlyLintPass`: + +```sh +$ cargo dev new_lint --name= --pass=early --category= +``` + +### Example for `EarlyLintPass` + +Take a look at the following code: + +```rust +let x = OurUndefinedType; +x.non_existing_method(); +``` + +From the AST perspective, both lines are "grammatically" correct. +The assignment uses a `let` and ends with a semicolon. The invocation +of a method looks fine, too. As programmers, we might raise a few +questions already, but the parser is okay with it. This is what we +mean when we say `EarlyLintPass` deals with only syntax on the AST level. + +Alternatively, think of the `foo_functions` lint we mentioned in +[define new lints](define_lints.md#name-the-lint) chapter. + +We want the `foo_functions` lint to detect functions with `foo` as their name. +Writing a lint that only checks for the name of a function means that we only +work with the AST and don't have to access the type system at all (the type system is where +`LateLintPass` comes into the picture). + +## `LateLintPass` + +In contrast to `EarlyLintPass`, `LateLintPass` contains type information. + +If you examine the documentation on [`LateLintPass`][late_lint_pass] closely, +you see that every method defined in this trait utilizes a +[`LateContext`][late_context]. + +In `LateContext`'s documentation we will find methods that +deal with type-checking, which do not exist in `EarlyContext`, such as: + +- [`maybe_typeck_results`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#method.maybe_typeck_results) +- [`typeck_results`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#method.typeck_results) + +### Example for `LateLintPass` + +Let us take a look with the following example: + +```rust +let x = OurUndefinedType; +x.non_existing_method(); +``` + +These two lines of code are syntactically correct code from the perspective +of the AST. We have an assignment and invoke a method on the variable that +is of a type. Grammatically, everything is in order for the parser. + +However, going down a level and looking at the type information, +the compiler will notice that both `OurUndefinedType` and `non_existing_method()` +**are undefined**. + +As Clippy developers, to access such type information, we must implement +`LateLintPass` on our lint. +When you browse through Clippy's lints, you will notice that almost every lint +is implemented in a `LateLintPass`, specifically because we often need to check +not only for syntactic issues but also type information. + +Another limitation of the `EarlyLintPass` is that the nodes are only identified +by their position in the AST. This means that you can't just get an `id` and +request a certain node. For most lints that is fine, but we have some lints +that require the inspection of other nodes, which is easier at the HIR level. +In these cases, `LateLintPass` is the better choice. + +As a reminder, run the following command to generate boilerplate for lints +that use `LateLintPass`: + +```sh +$ cargo dev new_lint --name= --pass=late --category= +``` + +[early_context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.EarlyContext.html +[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html +[late_context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html +[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html +[lexing_and_parsing]: https://rustc-dev-guide.rust-lang.org/overview.html#lexing-and-parsing diff --git a/book/src/development/macro_expansions.md b/book/src/development/macro_expansions.md new file mode 100644 index 00000000000..c5eb000272d --- /dev/null +++ b/book/src/development/macro_expansions.md @@ -0,0 +1,158 @@ +# Dealing with macros and expansions + +Sometimes we might encounter Rust macro expansions while working with Clippy. +While macro expansions are not as dramatic and profound as the expansion +of our universe, they can certainly bring chaos to the orderly world +of code and logic. + +The general rule of thumb is that we should ignore code with macro +expansions when working with Clippy because the code can be dynamic +in ways that are difficult or impossible for us to foresee. + +## False Positives + +What exactly do we mean by _dynamic in ways that are difficult to foresee_? + +Macros are [expanded][expansion] in the `EarlyLintPass` level, +so the Abstract Syntax Tree (AST) is generated in place of macros. +This means the code which we work with in Clippy is already expanded. + +If we wrote a new lint, there is a possibility that the lint is +triggered in macro-generated code. Since this expanded macro code +is not written by the macro's user but really by the macro's author, +the user cannot and should not be responsible for fixing the issue +that triggers the lint. + +Besides, a [Span] in a macro can be changed by the macro author. +Therefore, any lint check related to lines or columns should be +avoided since they might be changed at any time and become unreliable +or incorrect information. + +Because of these unforeseeable or unstable behaviors, macro expansion +should often not be regarded as a part of the stable API. +This is also why most lints check if they are inside a macro or not +before emitting suggestions to the end user to avoid false positives. + +## How to Work with Macros + +Several functions are available for working with macros. + +### The `Span.from_expansion` method + +We could utilize a `span`'s [`from_expansion`] method, which +detects if the `span` is from a macro expansion / desugaring. +This is a very common first step in a lint: + +```rust +if expr.span.from_expansion() { + // We most likely want to ignore it. + return; +} +``` + +### `Span.ctxt` method + +The `span`'s context, given by the method [`ctxt`] and returning [SpanContext], +represents if the span is from a macro expansion and, if it is, which +macro call expanded this span. + +Sometimes, it is useful to check if the context of two spans are equal. +For instance, suppose we have the following line of code that would +expand into `1 + 0`: + +```rust +// The following code expands to `1 + 0` for both `EarlyLintPass` and `LateLintPass` +1 + mac!() +``` + +Assuming that we'd collect the `1` expression as a variable `left` and the +`0`/`mac!()` expression as a variable `right`, we can simply compare their +contexts. If the context is different, then we most likely are dealing with a +macro expansion and should just ignore it: + +```rust +if left.span.ctxt() != right.span.ctxt() { + // The code author most likely cannot modify this expression + return; +} +``` + +> **Note**: Code that is not from expansion is in the "root" context. +> So any spans whose `from_expansion` returns `false` can be assumed +> to have the same context. Because of this, using `span.from_expansion()` +> is often sufficient. + +Going a bit deeper, in a simple expression such as `a == b`, +`a` and `b` have the same context. +However, in a `macro_rules!` with `a == $b`, `$b` is expanded to +an expression that contains a different context from `a`. + +Take a look at the following macro `m`: + +```rust +macro_rules! m { + ($a:expr, $b:expr) => { + if $a.is_some() { + $b; + } + } +} + +let x: Option = Some(42); +m!(x, x.unwrap()); +``` + +If the `m!(x, x.unwrapp());` line is expanded, we would get two expanded +expressions: + +- `x.is_some()` (from the `$a.is_some()` line in the `m` macro) +- `x.unwrap()` (corresponding to `$b` in the `m` macro) + +Suppose `x.is_some()` expression's span is associated with the `x_is_some_span` variable +and `x.unwrap()` expression's span is associated with `x_unwrap_span` variable, +we could assume that these two spans do not share the same context: + +```rust +// x.is_some() is from inside the macro +// x.unwrap() is from outside the macro +assert_ne!(x_is_some_span.ctxt(), x_unwrap_span.ctxt()); +``` + +### The `in_external_macro` function + +`rustc_middle::lint` provides a function ([`in_external_macro`]) that can +detect if the given span is from a macro defined in a foreign crate. + +Therefore, if we really want a new lint to work with macro-generated code, +this is the next line of defense to avoid macros not defined inside +the current crate since it is unfair to the user if Clippy lints code +which the user cannot change. + +For example, assume we have the following code that is being examined +by Clippy: + +```rust +#[macro_use] +extern crate a_foreign_crate_with_macros; + +// `foo` macro is defined in `a_foreign_crate_with_macros` +foo!("bar"); +``` + +Also assume that we get the corresponding variable `foo_span` for the +`foo` macro call, we could decide not to lint if `in_external_macro` +results in `true` (note that `cx` can be `EarlyContext` or `LateContext`): + +```rust +if in_external_macro(cx.sess(), foo_span) { + // We should ignore macro from a foreign crate. + return; +} +``` + +[`ctxt`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.ctxt +[expansion]: https://rustc-dev-guide.rust-lang.org/macro-expansion.html#expansion-and-ast-integration +[`from_expansion`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion +[`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html +[Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html +[SpanContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 5ce434b99a1..225de849566 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -51,7 +51,7 @@ impl LateLintPass<'_> for MyStructLint { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { // Get type of `expr` let ty = cx.typeck_results().expr_ty(expr); - + // Check if the `Ty` of this expression is of character type if ty.is_char() { println!("Our expression is a char!"); @@ -70,18 +70,18 @@ pub fn is_char(self) -> bool { } ``` -Indeed, we just discovered `Ty`'s [`kind` method][kind], which provides us +Indeed, we just discovered `Ty`'s [`kind()` method][kind], which provides us with [`TyKind`][TyKind] of a `Ty`. ## `TyKind` `TyKind` defines the kinds of types in Rust's type system. Peeking into [`TyKind` documentation][TyKind], we will see that it is an -enum of 27 variants, including items such as `Bool`, `Int`, `Ref`, etc. +enum of over 25 variants, including items such as `Bool`, `Int`, `Ref`, etc. ### `kind` Usage -The `TyKind` of `Ty` can be returned by calling [`Ty.kind` method][kind]. +The `TyKind` of `Ty` can be returned by calling [`Ty.kind()` method][kind]. We often use this method to perform pattern matching in Clippy. For instance, if we want to check for a `struct`, we could examine if the @@ -107,15 +107,21 @@ impl LateLintPass<'_> for MyStructLint { We've been talking about [`ty::Ty`][middle_ty] this whole time without addressing [`hir::Ty`][hir_ty], but the latter is also important to understand. -`hir::Ty` would represent *what* an user wrote, while `ty::Ty` would understand the meaning of it (because it has more -information). +`hir::Ty` would represent *what* the user wrote, while `ty::Ty` is how the compiler sees the type and has more +information. Example: -**Example: `fn foo(x: u32) -> u32 { x }`** +```rust +fn foo(x: u32) -> u32 { x } +``` Here the HIR sees the types without "thinking" about them, it knows that the function takes an `u32` and returns -an `u32`. But at the `ty::Ty` level the compiler understands that they're the same type, in-depth lifetimes, etc... +an `u32`. As far as `hir::Ty` is concerned those might be different types. But at the `ty::Ty` level the compiler +understands that they're the same type, in-depth lifetimes, etc... + +To get from a `hir::Ty` to a `ty::Ty`, you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function outside of bodies or +outside of bodies the [`TypeckResults::node_type()`][node_type] method. -you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function to convert from a `hir::Ty` to a `ty::Ty` +> **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs. ## Useful Links @@ -130,6 +136,7 @@ in this chapter: [Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt [AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty +[node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type [is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char [is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 78e1a55cff3..a702226e861 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -55,6 +55,7 @@ Please use that command to update the file and do not edit it by hand. | [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` | | [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` | | [future-size-threshold](#future-size-threshold) | `16384` | +| [unnecessary-box-size](#unnecessary-box-size) | `128` | ### arithmetic-side-effects-allowed Suppress checking of the passed type names in all types of operations. @@ -561,4 +562,12 @@ The maximum byte size a `Future` can have, before it triggers the `clippy::large * [large_futures](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) +### unnecessary-box-size +The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint + +**Default Value:** `128` (`u64`) + +* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) + + diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 95222a9acdf..dd90a38f757 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -741,7 +741,7 @@ fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String { fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String { let mut seen_lints = HashSet::new(); let mut res: String = GENERATED_FILE_COMMENT.into(); - res.push_str("// run-rustfix\n\n"); + res.push_str("//@run-rustfix\n\n"); for lint in lints { if seen_lints.insert(&lint.new_name) { writeln!(res, "#![allow({})]", lint.new_name).unwrap(); diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index 15d46e954a9..b984132acf5 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -6,7 +6,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { - /// Detects uses of the `#[allow]` attribute and suggests replacing it with + /// Checks for usage of the `#[allow]` attribute and suggests replacing it with /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) /// /// The expect attribute is still unstable and requires the `lint_reasons` diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 362f70d12d1..d74bd57fe45 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -506,7 +506,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for uses of the `abs()` method that cast the result to unsigned. + /// Checks for usage of the `abs()` method that cast the result to unsigned. /// /// ### Why is this bad? /// The `unsigned_abs()` method avoids panic when called on the MIN value. @@ -625,14 +625,14 @@ declare_clippy_lint! { /// /// ### Example /// ```rust - /// let string = String::with_capacity(1); - /// let ptr = string.as_ptr() as *mut u8; + /// let mut vec = Vec::::with_capacity(1); + /// let ptr = vec.as_ptr() as *mut u8; /// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR /// ``` /// Use instead: /// ```rust - /// let mut string = String::with_capacity(1); - /// let ptr = string.as_mut_ptr(); + /// let mut vec = Vec::::with_capacity(1); + /// let ptr = vec.as_mut_ptr(); /// unsafe { ptr.write(4) }; /// ``` #[clippy::version = "1.66.0"] diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index b2fe0386f94..7436e9ce811 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -9,7 +9,7 @@ use rustc_span::{symbol::sym, Span}; declare_clippy_lint! { /// ### What it does - /// Checks for use of `crate` as opposed to `$crate` in a macro definition. + /// Checks for usage of `crate` as opposed to `$crate` in a macro definition. /// /// ### Why is this bad? /// `crate` refers to the macro call's crate, whereas `$crate` refers to the macro definition's diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index f24dab62780..0c66d36a1d6 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -215,6 +215,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO, crate::invalid_utf8_in_unchecked::INVALID_UTF8_IN_UNCHECKED_INFO, crate::items_after_statements::ITEMS_AFTER_STATEMENTS_INFO, + crate::items_after_test_module::ITEMS_AFTER_TEST_MODULE_INFO, crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO, crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO, crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO, diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 48a54f60253..ee5a875ade7 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -19,7 +19,7 @@ use rustc_span::{Span, SyntaxContext, DUMMY_SP}; declare_clippy_lint! { /// ### What it does - /// Checks for uses of `contains_key` + `insert` on `HashMap` + /// Checks for usage of `contains_key` + `insert` on `HashMap` /// or `BTreeMap`. /// /// ### Why is this bad? diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 4c69dacf381..faac6340419 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -1,6 +1,6 @@ //! lint on enum variants that are prefixed or suffixed by the same characters -use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; use clippy_utils::source::is_present_in_source; use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start}; use rustc_hir::{EnumDef, Item, ItemKind, Variant}; @@ -135,9 +135,10 @@ fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_> && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) { - span_lint( + span_lint_hir( cx, ENUM_VARIANT_NAMES, + variant.hir_id, variant.span, "variant name starts with the enum's name", ); @@ -149,9 +150,10 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>) let item_name_chars = item_name.chars().count(); if count_match_end(item_name, name).char_count == item_name_chars { - span_lint( + span_lint_hir( cx, ENUM_VARIANT_NAMES, + variant.hir_id, variant.span, "variant name ends with the enum's name", ); diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index e3ddbfb5981..3ddee1842a3 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -51,7 +51,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `println`, `print`, `eprintln` or `eprint` in an + /// Checks for usage of `println`, `print`, `eprintln` or `eprint` in an /// implementation of a formatting trait. /// /// ### Why is this bad? diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index a866a68987d..4762b354392 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -10,7 +10,7 @@ use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does - /// Checks for use of the non-existent `=*`, `=!` and `=-` + /// Checks for usage of the non-existent `=*`, `=!` and `=-` /// operators. /// /// ### Why is this bad? diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 7c5e44bb7dc..ac2d253fe83 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -348,7 +348,7 @@ declare_clippy_lint! { /// // [...] /// } /// ``` - #[clippy::version = "1.68.0"] + #[clippy::version = "1.69.0"] pub IMPL_TRAIT_IN_PARAMS, restriction, "`impl Trait` is used in the function's parameters" diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs new file mode 100644 index 00000000000..52d716feea0 --- /dev/null +++ b/clippy_lints/src/items_after_test_module.rs @@ -0,0 +1,83 @@ +use clippy_utils::{diagnostics::span_lint_and_help, is_in_cfg_test}; +use rustc_hir::{HirId, ItemId, ItemKind, Mod}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{sym, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Triggers if an item is declared after the testing module marked with `#[cfg(test)]`. + /// ### Why is this bad? + /// Having items declared after the testing module is confusing and may lead to bad test coverage. + /// ### Example + /// ```rust + /// #[cfg(test)] + /// mod tests { + /// // [...] + /// } + /// + /// fn my_function() { + /// // [...] + /// } + /// ``` + /// Use instead: + /// ```rust + /// fn my_function() { + /// // [...] + /// } + /// + /// #[cfg(test)] + /// mod tests { + /// // [...] + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub ITEMS_AFTER_TEST_MODULE, + style, + "An item was found after the testing module `tests`" +} + +declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]); + +impl LateLintPass<'_> for ItemsAfterTestModule { + fn check_mod(&mut self, cx: &LateContext<'_>, _: &Mod<'_>, _: HirId) { + let mut was_test_mod_visited = false; + let mut test_mod_span: Option = None; + + let hir = cx.tcx.hir(); + let items = hir.items().collect::>(); + + for (i, itid) in items.iter().enumerate() { + let item = hir.item(*itid); + + if_chain! { + if was_test_mod_visited; + if i == (items.len() - 3 /* Weird magic number (HIR-translation behaviour) */); + if cx.sess().source_map().lookup_char_pos(item.span.lo()).file.name_hash + == cx.sess().source_map().lookup_char_pos(test_mod_span.unwrap().lo()).file.name_hash; // Will never fail + if !matches!(item.kind, ItemKind::Mod(_)); + if !is_in_cfg_test(cx.tcx, itid.hir_id()); // The item isn't in the testing module itself + if !in_external_macro(cx.sess(), item.span); + + then { + span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined"); + }}; + + if matches!(item.kind, ItemKind::Mod(_)) { + for attr in cx.tcx.get_attrs(item.owner_id.to_def_id(), sym::cfg) { + if_chain! { + if attr.has_name(sym::cfg); + if let Some(mitems) = attr.meta_item_list(); + if let [mitem] = &*mitems; + if mitem.has_name(sym::test); + then { + was_test_mod_visited = true; + test_mod_span = Some(item.span); + } + } + } + } + } + } +} diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 0805b4b1979..fec9c6f626c 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -168,25 +168,27 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { } if let ExprKind::Binary(Spanned { node: cmp, .. }, left, right) = expr.kind { + // expr.span might contains parenthesis, see issue #10529 + let actual_span = left.span.with_hi(right.span.hi()); match cmp { BinOpKind::Eq => { - check_cmp(cx, expr.span, left, right, "", 0); // len == 0 - check_cmp(cx, expr.span, right, left, "", 0); // 0 == len + check_cmp(cx, actual_span, left, right, "", 0); // len == 0 + check_cmp(cx, actual_span, right, left, "", 0); // 0 == len }, BinOpKind::Ne => { - check_cmp(cx, expr.span, left, right, "!", 0); // len != 0 - check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len + check_cmp(cx, actual_span, left, right, "!", 0); // len != 0 + check_cmp(cx, actual_span, right, left, "!", 0); // 0 != len }, BinOpKind::Gt => { - check_cmp(cx, expr.span, left, right, "!", 0); // len > 0 - check_cmp(cx, expr.span, right, left, "", 1); // 1 > len + check_cmp(cx, actual_span, left, right, "!", 0); // len > 0 + check_cmp(cx, actual_span, right, left, "", 1); // 1 > len }, BinOpKind::Lt => { - check_cmp(cx, expr.span, left, right, "", 1); // len < 1 - check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len + check_cmp(cx, actual_span, left, right, "", 1); // len < 1 + check_cmp(cx, actual_span, right, left, "!", 0); // 0 < len }, - BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1 - BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len + BinOpKind::Ge => check_cmp(cx, actual_span, left, right, "!", 1), // len >= 1 + BinOpKind::Le => check_cmp(cx, actual_span, right, left, "!", 1), // 1 <= len _ => (), } } diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 51b5de27de8..637b7de920e 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; use clippy_utils::{is_must_use_func_call, paths}; -use rustc_hir::{Local, PatKind}; +use rustc_hir::{ExprKind, Local, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; @@ -189,7 +189,18 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { if local.pat.default_binding_modes && local.ty.is_none() { // When `default_binding_modes` is true, the `let` keyword is present. - span_lint_and_help( + + // Ignore function calls that return impl traits... + if let Some(init) = local.init && + matches!(init.kind, ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _)) { + let expr_ty = cx.typeck_results().expr_ty(init); + if expr_ty.is_impl_trait() { + return; + } + } + + + span_lint_and_help( cx, LET_UNDERSCORE_UNTYPED, local.span, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b0ec14855e7..573ffe349ec 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -158,6 +158,7 @@ mod int_plus_one; mod invalid_upcast_comparisons; mod invalid_utf8_in_unchecked; mod items_after_statements; +mod items_after_test_module; mod iter_not_returning_iterator; mod large_const_arrays; mod large_enum_variant; @@ -950,15 +951,18 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute)); store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv()))); store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct)); + let unnecessary_box_size = conf.unnecessary_box_size; store.register_late_pass(move |_| { Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new( avoid_breaking_exported_api, + unnecessary_box_size, )) }); store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk)); store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule)); store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments)); + store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/lines_filter_map_ok.rs b/clippy_lints/src/lines_filter_map_ok.rs index b0f9276475d..bba9bb445a7 100644 --- a/clippy_lints/src/lines_filter_map_ok.rs +++ b/clippy_lints/src/lines_filter_map_ok.rs @@ -10,7 +10,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// Detect uses of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` + /// Checks for usage of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` /// when `lines` has type `std::io::Lines`. /// /// ### Why is this bad? diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index bc815dc4a26..4629b22d171 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -13,7 +13,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// Checks for uses of `std::mem::size_of::() * 8` when + /// Checks for usage of `std::mem::size_of::() * 8` when /// `T::BITS` is available. /// /// ### Why is this bad? diff --git a/clippy_lints/src/manual_slice_size_calculation.rs b/clippy_lints/src/manual_slice_size_calculation.rs index 92ee79453a3..703a6b25840 100644 --- a/clippy_lints/src/manual_slice_size_calculation.rs +++ b/clippy_lints/src/manual_slice_size_calculation.rs @@ -1,5 +1,7 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{expr_or_init, in_constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_context; +use clippy_utils::{expr_or_init, in_constant, std_or_core}; +use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -38,19 +40,27 @@ declare_lint_pass!(ManualSliceSizeCalculation => [MANUAL_SLICE_SIZE_CALCULATION] impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - // Does not apply inside const because size_of_value is not cost in stable. + // Does not apply inside const because size_of_val is not cost in stable. if !in_constant(cx, expr.hir_id) && let ExprKind::Binary(ref op, left, right) = expr.kind && BinOpKind::Mul == op.node - && let Some(_receiver) = simplify(cx, left, right) + && !expr.span.from_expansion() + && let Some(receiver) = simplify(cx, left, right) { - span_lint_and_help( + let ctxt = expr.span.ctxt(); + let mut app = Applicability::MachineApplicable; + let val_name = snippet_with_context(cx, receiver.span, ctxt, "slice", &mut app).0; + let Some(sugg) = std_or_core(cx) else { return }; + + span_lint_and_sugg( cx, MANUAL_SLICE_SIZE_CALCULATION, expr.span, "manual slice size calculation", - None, - "consider using std::mem::size_of_value instead"); + "try", + format!("{sugg}::mem::size_of_val({val_name})"), + app, + ); } } } @@ -71,9 +81,9 @@ fn simplify_half<'tcx>( expr1: &'tcx Expr<'tcx>, expr2: &'tcx Expr<'tcx>, ) -> Option<&'tcx Expr<'tcx>> { - if + if !expr1.span.from_expansion() // expr1 is `[T1].len()`? - let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind + && let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind && method_path.ident.name == sym::len && let receiver_ty = cx.typeck_results().expr_ty(receiver) && let ty::Slice(ty1) = receiver_ty.peel_refs().kind() diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 97ecca450fa..87b63eead25 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -843,7 +843,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `Err(x)?`. + /// Checks for usage of `Err(x)?`. /// /// ### Why is this bad? /// The `?` operator is designed to allow calls that @@ -878,7 +878,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `match` which could be implemented using `map` + /// Checks for usage of `match` which could be implemented using `map` /// /// ### Why is this bad? /// Using the `map` method is clearer and more concise. @@ -902,7 +902,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `match` which could be implemented using `filter` + /// Checks for usage of `match` which could be implemented using `filter` /// /// ### Why is this bad? /// Using the `filter` method is clearer and more concise. diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 64bf55ba24c..9cafbc2e5f5 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -121,7 +121,7 @@ use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does - /// Checks for usages of `cloned()` on an `Iterator` or `Option` where + /// Checks for usage of `cloned()` on an `Iterator` or `Option` where /// `copied()` could be used instead. /// /// ### Why is this bad? @@ -201,7 +201,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `Iterator::flat_map()` where `filter_map()` could be + /// Checks for usage of `Iterator::flat_map()` where `filter_map()` could be /// used instead. /// /// ### Why is this bad? @@ -441,7 +441,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and + /// Checks for usage of `_.unwrap_or_else(Default::default)` on `Option` and /// `Result` values. /// /// ### Why is this bad? @@ -1194,7 +1194,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `.iter().nth()` (and the related + /// Checks for usage of `.iter().nth()` (and the related /// `.iter_mut().nth()`) on standard library types with *O*(1) element access. /// /// ### Why is this bad? @@ -1221,7 +1221,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `.skip(x).next()` on iterators. + /// Checks for usage of `.skip(x).next()` on iterators. /// /// ### Why is this bad? /// `.nth(x)` is cleaner @@ -1246,7 +1246,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `.drain(..)` on `Vec` and `VecDeque` for iteration. + /// Checks for usage of `.drain(..)` on `Vec` and `VecDeque` for iteration. /// /// ### Why is this bad? /// `.into_iter()` is simpler with better performance. @@ -1271,7 +1271,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for using `x.get(x.len() - 1)` instead of + /// Checks for usage of `x.get(x.len() - 1)` instead of /// `x.last()`. /// /// ### Why is this bad? @@ -1304,7 +1304,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `.get().unwrap()` (or + /// Checks for usage of `.get().unwrap()` (or /// `.get_mut().unwrap`) on a standard library type which implements `Index` /// /// ### Why is this bad? @@ -1475,7 +1475,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for using `fold` when a more succinct alternative exists. + /// Checks for usage of `fold` when a more succinct alternative exists. /// Specifically, this checks for `fold`s which could be replaced by `any`, `all`, /// `sum` or `product`. /// @@ -2161,7 +2161,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `str::splitn(2, _)` + /// Checks for usage of `str::splitn(2, _)` /// /// ### Why is this bad? /// `split_once` is both clearer in intent and slightly more efficient. @@ -2197,7 +2197,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same. + /// Checks for usage of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same. /// ### Why is this bad? /// The function `split` is simpler and there is no performance difference in these cases, considering /// that both functions return a lazy iterator. @@ -2251,7 +2251,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `.collect::>().join("")` on iterators. + /// Checks for usage of `.collect::>().join("")` on iterators. /// /// ### Why is this bad? /// `.collect::()` is more concise and might be more performant @@ -2377,7 +2377,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `.then_some(..).unwrap_or(..)` + /// Checks for usage of `.then_some(..).unwrap_or(..)` /// /// ### Why is this bad? /// This can be written more clearly with `if .. else ..` @@ -2553,7 +2553,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for using `x.get(0)` instead of + /// Checks for usage of `x.get(0)` instead of /// `x.first()`. /// /// ### Why is this bad? @@ -2957,7 +2957,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Detects uses of `Vec::sort_by` passing in a closure + /// Checks for usage of `Vec::sort_by` passing in a closure /// which compares the two arguments, either directly or indirectly. /// /// ### Why is this bad? @@ -3013,7 +3013,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of File::read_to_end and File::read_to_string. + /// Checks for usage of File::read_to_end and File::read_to_string. /// /// ### Why is this bad? /// `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values. @@ -3185,7 +3185,7 @@ declare_clippy_lint! { /// ```rust /// std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap(); /// ``` - #[clippy::version = "1.67.0"] + #[clippy::version = "1.69.0"] pub SUSPICIOUS_COMMAND_ARG_SPACE, suspicious, "single command line argument that looks like it should be multiple arguments" diff --git a/clippy_lints/src/methods/obfuscated_if_else.rs b/clippy_lints/src/methods/obfuscated_if_else.rs index 4d7427b2662..eada530d670 100644 --- a/clippy_lints/src/methods/obfuscated_if_else.rs +++ b/clippy_lints/src/methods/obfuscated_if_else.rs @@ -1,5 +1,3 @@ -// run-rustfix - use super::OBFUSCATED_IF_ELSE; use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_with_applicability}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 5418616ded0..2abdfacd276 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -59,7 +59,7 @@ declare_clippy_lint! { /// unsafe { char::from_u32_unchecked(int_value) } /// } /// ``` - #[clippy::version = "1.68.0"] + #[clippy::version = "1.69.0"] pub MULTIPLE_UNSAFE_OPS_PER_BLOCK, restriction, "more than one unsafe operation per `unsafe` block" diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index dc866ab6373..99394b9e5fb 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -1,4 +1,4 @@ -//! Checks for uses of mutex where an atomic value could be used +//! Checks for usage of mutex where an atomic value could be used //! //! This lint is **allow** by default @@ -12,7 +12,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// Checks for usages of `Mutex` where an atomic will do. + /// Checks for usage of `Mutex` where an atomic will do. /// /// ### Why is this bad? /// Using a mutex just to make access to a plain bool or @@ -49,7 +49,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usages of `Mutex` where `X` is an integral + /// Checks for usage of `Mutex` where `X` is an integral /// type. /// /// ### Why is this bad? diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index eed0f1f1991..58590df1fed 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -1,4 +1,4 @@ -//! Checks for uses of const which the type is not `Freeze` (`Cell`-free). +//! Checks for usage of const which the type is not `Freeze` (`Cell`-free). //! //! This lint is **warn** by default. diff --git a/clippy_lints/src/octal_escapes.rs b/clippy_lints/src/octal_escapes.rs index 7376ab0c846..6d3865080a6 100644 --- a/clippy_lints/src/octal_escapes.rs +++ b/clippy_lints/src/octal_escapes.rs @@ -76,8 +76,8 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { if ch == '\\' { if let Some((_, '0')) = iter.next() { // collect up to two further octal digits - if let Some((mut to, '0'..='7')) = iter.next() { - if let Some((_, '0'..='7')) = iter.peek() { + if let Some((mut to, _)) = iter.next_if(|(_, ch)| matches!(ch, '0'..='7')) { + if iter.next_if(|(_, ch)| matches!(ch, '0'..='7')).is_some() { to += 1; } found.push((from, to + 1)); @@ -90,32 +90,6 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { return; } - // construct two suggestion strings, one with \x escapes with octal meaning - // as in C, and one with \x00 for null bytes. - let mut suggest_1 = if is_string { "\"" } else { "b\"" }.to_string(); - let mut suggest_2 = suggest_1.clone(); - let mut index = 0; - for (from, to) in found { - suggest_1.push_str(&contents[index..from]); - suggest_2.push_str(&contents[index..from]); - - // construct a replacement escape - // the maximum value is \077, or \x3f, so u8 is sufficient here - if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) { - write!(suggest_1, "\\x{n:02x}").unwrap(); - } - - // append the null byte as \x00 and the following digits literally - suggest_2.push_str("\\x00"); - suggest_2.push_str(&contents[from + 2..to]); - - index = to; - } - suggest_1.push_str(&contents[index..]); - suggest_1.push('"'); - suggest_2.push_str(&contents[index..]); - suggest_2.push('"'); - span_lint_and_then( cx, OCTAL_ESCAPES, @@ -129,23 +103,53 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { "octal escapes are not supported, `\\0` is always a null {}", if is_string { "character" } else { "byte" } )); - // suggestion 1: equivalent hex escape - diag.span_suggestion( - span, - "if an octal escape was intended, use the hexadecimal representation instead", - suggest_1, - Applicability::MaybeIncorrect, - ); - // suggestion 2: unambiguous null byte - diag.span_suggestion( - span, - format!( - "if the null {} is intended, disambiguate using", - if is_string { "character" } else { "byte" } - ), - suggest_2, - Applicability::MaybeIncorrect, - ); + + // Generate suggestions if the string is not too long (~ 5 lines) + if contents.len() < 400 { + // construct two suggestion strings, one with \x escapes with octal meaning + // as in C, and one with \x00 for null bytes. + let mut suggest_1 = if is_string { "\"" } else { "b\"" }.to_string(); + let mut suggest_2 = suggest_1.clone(); + let mut index = 0; + for (from, to) in found { + suggest_1.push_str(&contents[index..from]); + suggest_2.push_str(&contents[index..from]); + + // construct a replacement escape + // the maximum value is \077, or \x3f, so u8 is sufficient here + if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) { + write!(suggest_1, "\\x{n:02x}").unwrap(); + } + + // append the null byte as \x00 and the following digits literally + suggest_2.push_str("\\x00"); + suggest_2.push_str(&contents[from + 2..to]); + + index = to; + } + suggest_1.push_str(&contents[index..]); + suggest_2.push_str(&contents[index..]); + + suggest_1.push('"'); + suggest_2.push('"'); + // suggestion 1: equivalent hex escape + diag.span_suggestion( + span, + "if an octal escape was intended, use the hexadecimal representation instead", + suggest_1, + Applicability::MaybeIncorrect, + ); + // suggestion 2: unambiguous null byte + diag.span_suggestion( + span, + format!( + "if the null {} is intended, disambiguate using", + if is_string { "character" } else { "byte" } + ), + suggest_2, + Applicability::MaybeIncorrect, + ); + } }, ); } diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index e5713735672..fafcf257094 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -1,4 +1,5 @@ use super::ARITHMETIC_SIDE_EFFECTS; +use clippy_utils::is_from_proc_macro; use clippy_utils::{ consts::{constant, constant_simple, Constant}, diagnostics::span_lint, @@ -10,7 +11,10 @@ use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; -use rustc_span::source_map::{Span, Spanned}; +use rustc_span::{ + source_map::{Span, Spanned}, + Symbol, +}; const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[ ["f32", "f32"], @@ -20,6 +24,7 @@ const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[ ["std::string::String", "&str"], ]; const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"]; +const INTEGER_METHODS: &[&str] = &["saturating_div", "wrapping_div", "wrapping_rem", "wrapping_rem_euclid"]; #[derive(Debug)] pub struct ArithmeticSideEffects { @@ -28,6 +33,7 @@ pub struct ArithmeticSideEffects { // Used to check whether expressions are constants, such as in enum discriminants and consts const_span: Option, expr_span: Option, + integer_methods: FxHashSet, } impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]); @@ -53,6 +59,7 @@ impl ArithmeticSideEffects { allowed_unary, const_span: None, expr_span: None, + integer_methods: INTEGER_METHODS.iter().map(|el| Symbol::intern(el)).collect(), } } @@ -184,6 +191,33 @@ impl ArithmeticSideEffects { } } + /// There are some integer methods like `wrapping_div` that will panic depending on the + /// provided input. + fn manage_method_call<'tcx>( + &mut self, + args: &[hir::Expr<'tcx>], + cx: &LateContext<'tcx>, + ps: &hir::PathSegment<'tcx>, + receiver: &hir::Expr<'tcx>, + ) { + let Some(arg) = args.first() else { return; }; + if constant_simple(cx, cx.typeck_results(), receiver).is_some() { + return; + } + let instance_ty = cx.typeck_results().expr_ty(receiver); + if !Self::is_integral(instance_ty) { + return; + } + if !self.integer_methods.contains(&ps.ident.name) { + return; + } + let (actual_arg, _) = peel_hir_expr_refs(arg); + match Self::literal_integer(cx, actual_arg) { + None | Some(0) => self.issue_lint(cx, arg), + Some(_) => {}, + } + } + fn manage_unary_ops<'tcx>( &mut self, cx: &LateContext<'tcx>, @@ -206,8 +240,9 @@ impl ArithmeticSideEffects { self.issue_lint(cx, expr); } - fn should_skip_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool { is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id) + || is_from_proc_macro(cx, expr) || self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) } @@ -222,6 +257,9 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects { hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => { self.manage_bin_ops(cx, expr, op, lhs, rhs); }, + hir::ExprKind::MethodCall(ps, receiver, args, _) => { + self.manage_method_call(args, cx, ps, receiver); + }, hir::ExprKind::Unary(un_op, un_expr) => { self.manage_unary_ops(cx, expr, un_expr, *un_op); }, diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index eba230da6c3..19599731bd6 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -685,7 +685,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using + /// Checks for usage of bitwise and/or operators between booleans, where performance may be improved by using /// a lazy and. /// /// ### Why is this bad? diff --git a/clippy_lints/src/operators/numeric_arithmetic.rs b/clippy_lints/src/operators/numeric_arithmetic.rs index 777395f452c..77fd45b199a 100644 --- a/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/clippy_lints/src/operators/numeric_arithmetic.rs @@ -1,12 +1,12 @@ +use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC}; use clippy_utils::consts::constant_simple; use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_from_proc_macro; use clippy_utils::is_integer_literal; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_span::source_map::Span; -use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC}; - #[derive(Default)] pub struct Context { expr_id: Option, @@ -47,6 +47,9 @@ impl Context { let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r)); if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() { + if is_from_proc_macro(cx, expr) { + return; + } match op { hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind { hir::ExprKind::Lit(_lit) => (), @@ -79,6 +82,9 @@ impl Context { let ty = cx.typeck_results().expr_ty(arg); if constant_simple(cx, cx.typeck_results(), expr).is_none() { if ty.is_integral() { + if is_from_proc_macro(cx, expr) { + return; + } span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); self.expr_id = Some(expr.hir_id); } else if ty.is_floating_point() { diff --git a/clippy_lints/src/question_mark_used.rs b/clippy_lints/src/question_mark_used.rs index 9b678e8d753..ff66b8a0095 100644 --- a/clippy_lints/src/question_mark_used.rs +++ b/clippy_lints/src/question_mark_used.rs @@ -24,7 +24,7 @@ declare_clippy_lint! { /// ```ignore /// utility_macro!(expr); /// ``` - #[clippy::version = "pre 1.29.0"] + #[clippy::version = "1.69.0"] pub QUESTION_MARK_USED, restriction, "complains if the question mark operator is used" diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index 869358fb1ba..b930b2c8dd7 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -17,7 +17,7 @@ use rustc_span::{symbol::Ident, Span, DUMMY_SP}; declare_clippy_lint! { /// ### What it does /// - /// Searches for elements marked with `#[clippy::significant_drop]` that could be early + /// Searches for elements marked with `#[clippy::has_significant_drop]` that could be early /// dropped but are in fact dropped at the end of their scopes. In other words, enforces the /// "tightening" of their possible lifetimes. /// @@ -46,7 +46,7 @@ declare_clippy_lint! { /// do_heavy_computation_that_takes_time(owned_rslt); /// } /// ``` - #[clippy::version = "1.67.0"] + #[clippy::version = "1.69.0"] pub SIGNIFICANT_DROP_TIGHTENING, nursery, "Searches for elements marked with `#[clippy::has_significant_drop]` that could be early dropped but are in fact dropped at the end of their scopes" diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index c1f228d5f90..c6834a8fdaa 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -22,7 +22,7 @@ use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does - /// Checks for use of `Box` where T is a collection such as Vec anywhere in the code. + /// Checks for usage of `Box` where T is a collection such as Vec anywhere in the code. /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information. /// /// ### Why is this bad? @@ -52,7 +52,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `Vec>` where T: Sized anywhere in the code. + /// Checks for usage of `Vec>` where T: Sized anywhere in the code. /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information. /// /// ### Why is this bad? @@ -85,7 +85,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `Option>` in function signatures and type + /// Checks for usage of `Option>` in function signatures and type /// definitions /// /// ### Why is this bad? @@ -164,7 +164,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `&Box` anywhere in the code. + /// Checks for usage of `&Box` anywhere in the code. /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information. /// /// ### Why is this bad? @@ -190,7 +190,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of redundant allocations anywhere in the code. + /// Checks for usage of redundant allocations anywhere in the code. /// /// ### Why is this bad? /// Expressions such as `Rc<&T>`, `Rc>`, `Rc>`, `Rc>`, `Arc<&T>`, `Arc>`, diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs index 912bcda630b..af1c8d83b4f 100644 --- a/clippy_lints/src/unnecessary_box_returns.rs +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{diagnostics::span_lint_and_then, ty::approx_ty_size}; use rustc_errors::Applicability; use rustc_hir::{def_id::LocalDefId, FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -10,6 +10,9 @@ declare_clippy_lint! { /// /// Checks for a return type containing a `Box` where `T` implements `Sized` /// + /// The lint ignores `Box` where `T` is larger than `unnecessary_box_size`, + /// as returning a large `T` directly may be detrimental to performance. + /// /// ### Why is this bad? /// /// It's better to just return `T` in these cases. The caller may not need @@ -36,14 +39,16 @@ declare_clippy_lint! { pub struct UnnecessaryBoxReturns { avoid_breaking_exported_api: bool, + maximum_size: u64, } impl_lint_pass!(UnnecessaryBoxReturns => [UNNECESSARY_BOX_RETURNS]); impl UnnecessaryBoxReturns { - pub fn new(avoid_breaking_exported_api: bool) -> Self { + pub fn new(avoid_breaking_exported_api: bool, maximum_size: u64) -> Self { Self { avoid_breaking_exported_api, + maximum_size, } } @@ -71,8 +76,10 @@ impl UnnecessaryBoxReturns { let boxed_ty = return_ty.boxed_ty(); - // it's sometimes useful to return Box if T is unsized, so don't lint those - if boxed_ty.is_sized(cx.tcx, cx.param_env) { + // It's sometimes useful to return Box if T is unsized, so don't lint those. + // Also, don't lint if we know that T is very large, in which case returning + // a Box may be beneficial. + if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { span_lint_and_then( cx, UNNECESSARY_BOX_RETURNS, diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 896a01af37d..67bb499c455 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -463,6 +463,10 @@ define_Conf! { /// /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint (future_size_threshold: u64 = 16 * 1024), + /// Lint: UNNECESSARY_BOX_RETURNS. + /// + /// The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint + (unnecessary_box_size: u64 = 128), } /// Search for the configuration file. diff --git a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 14ed1368e03..00842376628 100644 --- a/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -20,7 +20,7 @@ use std::str; declare_clippy_lint! { /// ### What it does - /// Checks for usages of def paths when a diagnostic item or a `LangItem` could be used. + /// Checks for usage of def paths when a diagnostic item or a `LangItem` could be used. /// /// ### Why is this bad? /// The path for an item is subject to change and is less efficient to look up than a diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index d7c94b909bd..f194dc5d4b2 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -104,7 +104,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for use of `Debug` formatting. The purpose of this + /// Checks for usage of `Debug` formatting. The purpose of this /// lint is to catch debugging remnants. /// /// ### Why is this bad? diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 5c9f76dbbc6..bd26f4fc913 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -10,7 +10,7 @@ proc-macro = true [dependencies] itertools = "0.10.1" quote = "1.0.21" -syn = "1.0.100" +syn = "2.0" [features] deny-warnings = [] diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs index 26210556d65..5232e4ab7d7 100644 --- a/declare_clippy_lint/src/lib.rs +++ b/declare_clippy_lint/src/lib.rs @@ -6,16 +6,16 @@ use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::parse::{Parse, ParseStream}; -use syn::{parse_macro_input, Attribute, Error, Ident, Lit, LitStr, Meta, Result, Token}; +use syn::{parse_macro_input, Attribute, Error, Expr, ExprLit, Ident, Lit, LitStr, Meta, Result, Token}; fn parse_attr(path: [&'static str; LEN], attr: &Attribute) -> Option { - if let Meta::NameValue(name_value) = attr.parse_meta().ok()? { + if let Meta::NameValue(name_value) = &attr.meta { let path_idents = name_value.path.segments.iter().map(|segment| &segment.ident); if itertools::equal(path_idents, path) - && let Lit::Str(lit) = name_value.lit + && let Expr::Lit(ExprLit { lit: Lit::Str(s), .. }) = &name_value.value { - return Some(lit); + return Some(s.clone()); } } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 57890ff3173..35d75cc51c2 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -126,6 +126,7 @@ fn base_config(test_dir: &str) -> compiletest::Config { let mut config = compiletest::Config { edition: Some("2021".into()), mode: TestMode::Ui, + strict_headers: true, ..Default::default() }; @@ -424,7 +425,7 @@ fn check_rustfix_coverage() { .binary_search_by_key(&filename, Path::new) .is_ok(), "`{rs_file}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation. \ - Please either add `// run-rustfix` at the top of the file or add the file to \ + Please either add `//@run-rustfix` at the top of the file or add the file to \ `RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS` in `tests/compile-test.rs`.", ); } diff --git a/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs index 27841e18aa9..1a69bb24101 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=cargo_common_metadata +//@compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs b/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs index 27841e18aa9..1a69bb24101 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/fail_publish/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=cargo_common_metadata +//@compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs index 27841e18aa9..1a69bb24101 100644 --- a/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/fail_publish_true/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=cargo_common_metadata +//@compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs index 27841e18aa9..1a69bb24101 100644 --- a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=cargo_common_metadata +//@compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs b/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs index 27841e18aa9..1a69bb24101 100644 --- a/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/pass_publish_empty/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=cargo_common_metadata +//@compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs b/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs index 27841e18aa9..1a69bb24101 100644 --- a/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs +++ b/tests/ui-cargo/cargo_common_metadata/pass_publish_false/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=cargo_common_metadata +//@compile-flags: --crate-name=cargo_common_metadata #![warn(clippy::cargo_common_metadata)] fn main() {} diff --git a/tests/ui-cargo/feature_name/fail/src/main.rs b/tests/ui-cargo/feature_name/fail/src/main.rs index 64f01a98c90..4dd9582aff8 100644 --- a/tests/ui-cargo/feature_name/fail/src/main.rs +++ b/tests/ui-cargo/feature_name/fail/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=feature_name +//@compile-flags: --crate-name=feature_name #![warn(clippy::redundant_feature_names)] #![warn(clippy::negative_feature_names)] diff --git a/tests/ui-cargo/feature_name/pass/src/main.rs b/tests/ui-cargo/feature_name/pass/src/main.rs index 64f01a98c90..4dd9582aff8 100644 --- a/tests/ui-cargo/feature_name/pass/src/main.rs +++ b/tests/ui-cargo/feature_name/pass/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=feature_name +//@compile-flags: --crate-name=feature_name #![warn(clippy::redundant_feature_names)] #![warn(clippy::negative_feature_names)] diff --git a/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs b/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs index ba4c8c873dd..c70d92e359e 100644 --- a/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs +++ b/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --remap-path-prefix {{src-base}}=/remapped +//@compile-flags: --remap-path-prefix {{src-base}}=/remapped #![warn(clippy::self_named_module_files)] diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs index 1b2d3ec9459..ece260b743d 100644 --- a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=multiple_crate_versions +//@compile-flags: --crate-name=multiple_crate_versions #![warn(clippy::multiple_crate_versions)] fn main() {} diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs index 1b2d3ec9459..ece260b743d 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs +++ b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=multiple_crate_versions +//@compile-flags: --crate-name=multiple_crate_versions #![warn(clippy::multiple_crate_versions)] fn main() {} diff --git a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs index 1b2d3ec9459..ece260b743d 100644 --- a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs +++ b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=multiple_crate_versions +//@compile-flags: --crate-name=multiple_crate_versions #![warn(clippy::multiple_crate_versions)] fn main() {} diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs index 581babfeacb..bb3a39d0720 100644 --- a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs +++ b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=wildcard_dependencies +//@compile-flags: --crate-name=wildcard_dependencies #![warn(clippy::wildcard_dependencies)] fn main() {} diff --git a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs index 581babfeacb..bb3a39d0720 100644 --- a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs +++ b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=wildcard_dependencies +//@compile-flags: --crate-name=wildcard_dependencies #![warn(clippy::wildcard_dependencies)] fn main() {} diff --git a/tests/ui-internal/collapsible_span_lint_calls.fixed b/tests/ui-internal/collapsible_span_lint_calls.fixed index 9f299d7dec7..72c04bf80b6 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] #![feature(rustc_private)] diff --git a/tests/ui-internal/collapsible_span_lint_calls.rs b/tests/ui-internal/collapsible_span_lint_calls.rs index 2b113f555e4..76f7c3ce94d 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/tests/ui-internal/collapsible_span_lint_calls.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] #![feature(rustc_private)] diff --git a/tests/ui-internal/custom_ice_message.rs b/tests/ui-internal/custom_ice_message.rs index 837811bdf1e..acb98d7ba98 100644 --- a/tests/ui-internal/custom_ice_message.rs +++ b/tests/ui-internal/custom_ice_message.rs @@ -1,9 +1,9 @@ -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" -// normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs" -// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints" -// normalize-stderr-test: "'rustc'" -> "''" -// normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> "" +//@rustc-env:RUST_BACKTRACE=0 +//@normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" +//@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs" +//@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints" +//@normalize-stderr-test: "'rustc'" -> "''" +//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> "" #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] diff --git a/tests/ui-internal/interning_defined_symbol.fixed b/tests/ui-internal/interning_defined_symbol.fixed index eaea218e128..a1a10c0798e 100644 --- a/tests/ui-internal/interning_defined_symbol.fixed +++ b/tests/ui-internal/interning_defined_symbol.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)] #![feature(rustc_private)] diff --git a/tests/ui-internal/interning_defined_symbol.rs b/tests/ui-internal/interning_defined_symbol.rs index 7efebb8fae4..32dbfe5dcac 100644 --- a/tests/ui-internal/interning_defined_symbol.rs +++ b/tests/ui-internal/interning_defined_symbol.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute, clippy::let_unit_value)] #![feature(rustc_private)] diff --git a/tests/ui-internal/invalid_msrv_attr_impl.fixed b/tests/ui-internal/invalid_msrv_attr_impl.fixed index 08634063a57..ac0752774f3 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] diff --git a/tests/ui-internal/invalid_msrv_attr_impl.rs b/tests/ui-internal/invalid_msrv_attr_impl.rs index f8af77e6d39..56f778621a4 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] diff --git a/tests/ui-internal/outer_expn_data.fixed b/tests/ui-internal/outer_expn_data.fixed index bb82faf0c90..d8a08bc9997 100644 --- a/tests/ui-internal/outer_expn_data.fixed +++ b/tests/ui-internal/outer_expn_data.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] diff --git a/tests/ui-internal/outer_expn_data.rs b/tests/ui-internal/outer_expn_data.rs index 187d468b392..f7af0e9d8be 100644 --- a/tests/ui-internal/outer_expn_data.rs +++ b/tests/ui-internal/outer_expn_data.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::internal)] #![allow(clippy::missing_clippy_version_attribute)] diff --git a/tests/ui-internal/unnecessary_def_path.fixed b/tests/ui-internal/unnecessary_def_path.fixed index e474f370a5d..fce24412f84 100644 --- a/tests/ui-internal/unnecessary_def_path.fixed +++ b/tests/ui-internal/unnecessary_def_path.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:paths.rs +//@run-rustfix +//@aux-build:paths.rs #![deny(clippy::internal)] #![feature(rustc_private)] diff --git a/tests/ui-internal/unnecessary_def_path.rs b/tests/ui-internal/unnecessary_def_path.rs index f17fed6c653..b10bc9e46e2 100644 --- a/tests/ui-internal/unnecessary_def_path.rs +++ b/tests/ui-internal/unnecessary_def_path.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:paths.rs +//@run-rustfix +//@aux-build:paths.rs #![deny(clippy::internal)] #![feature(rustc_private)] diff --git a/tests/ui-internal/unnecessary_symbol_str.fixed b/tests/ui-internal/unnecessary_symbol_str.fixed index 6033d06e4f6..b802de1cbc6 100644 --- a/tests/ui-internal/unnecessary_symbol_str.fixed +++ b/tests/ui-internal/unnecessary_symbol_str.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(rustc_private)] #![deny(clippy::internal)] #![allow( diff --git a/tests/ui-internal/unnecessary_symbol_str.rs b/tests/ui-internal/unnecessary_symbol_str.rs index 1bb5d55f0b6..c1bead5bdc9 100644 --- a/tests/ui-internal/unnecessary_symbol_str.rs +++ b/tests/ui-internal/unnecessary_symbol_str.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(rustc_private)] #![deny(clippy::internal)] #![allow( diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed index aa8b45b5fe7..23e7bc16d23 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::uninlined_format_args)] fn main() { diff --git a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs index ad2e4863ee8..d66b2b8ff6a 100644 --- a/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs +++ b/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::uninlined_format_args)] fn main() { diff --git a/tests/ui-toml/dbg_macro/dbg_macro.rs b/tests/ui-toml/dbg_macro/dbg_macro.rs index 5d9ce18f631..21e4fce26e4 100644 --- a/tests/ui-toml/dbg_macro/dbg_macro.rs +++ b/tests/ui-toml/dbg_macro/dbg_macro.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![warn(clippy::dbg_macro)] fn foo(n: u32) -> u32 { diff --git a/tests/ui-toml/disallowed_macros/disallowed_macros.rs b/tests/ui-toml/disallowed_macros/disallowed_macros.rs index 2bb5376076e..ba919b48788 100644 --- a/tests/ui-toml/disallowed_macros/disallowed_macros.rs +++ b/tests/ui-toml/disallowed_macros/disallowed_macros.rs @@ -1,4 +1,4 @@ -// aux-build:macros.rs +//@aux-build:macros.rs #![allow(unused)] diff --git a/tests/ui-toml/expect_used/expect_used.rs b/tests/ui-toml/expect_used/expect_used.rs index 89f142a150d..9e267c89300 100644 --- a/tests/ui-toml/expect_used/expect_used.rs +++ b/tests/ui-toml/expect_used/expect_used.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![warn(clippy::expect_used)] fn expect_option() { diff --git a/tests/ui-toml/mut_key/mut_key.rs b/tests/ui-toml/mut_key/mut_key.rs index 667c51cb4a3..095e0d15448 100644 --- a/tests/ui-toml/mut_key/mut_key.rs +++ b/tests/ui-toml/mut_key/mut_key.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name mut_key +//@compile-flags: --crate-name mut_key #![warn(clippy::mutable_key_type)] diff --git a/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs b/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs index 6452189a461..f5761c6afeb 100644 --- a/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs +++ b/tests/ui-toml/nonstandard_macro_braces/auxiliary/proc_macro_derive.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic #![crate_type = "proc-macro"] diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed index 01d135764df..e4747bedddb 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed @@ -1,5 +1,5 @@ -// aux-build:proc_macro_derive.rs -// run-rustfix +//@aux-build:proc_macro_derive.rs +//@run-rustfix #![warn(clippy::nonstandard_macro_braces)] diff --git a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs index 72883e8270c..54edded99f4 100644 --- a/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs +++ b/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs @@ -1,5 +1,5 @@ -// aux-build:proc_macro_derive.rs -// run-rustfix +//@aux-build:proc_macro_derive.rs +//@run-rustfix #![warn(clippy::nonstandard_macro_braces)] diff --git a/tests/ui-toml/print_macro/print_macro.rs b/tests/ui-toml/print_macro/print_macro.rs index 5aefb6a6b4d..3a8b30cca36 100644 --- a/tests/ui-toml/print_macro/print_macro.rs +++ b/tests/ui-toml/print_macro/print_macro.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![warn(clippy::print_stdout)] #![warn(clippy::print_stderr)] diff --git a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs index 2f3160c8338..8e1a1710a6c 100644 --- a/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs +++ b/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name conf_disallowed_methods +//@compile-flags: --crate-name conf_disallowed_methods #![warn(clippy::disallowed_methods)] diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index fb0e226f3aa..179b1266169 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,5 +1,5 @@ -// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)" -// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)" +//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)" +//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)" #![deny(clippy::trivially_copy_pass_by_ref)] diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs index f328e4d9d04..569fd2c3553 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs @@ -1 +1,3 @@ +//@error-pattern: unknown field `foobar`, expected one of + fn main() {} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 8447c31722d..36b372b36f4 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -46,6 +46,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie too-many-lines-threshold trivial-copy-size-limit type-complexity-threshold + unnecessary-box-size unreadable-literal-lint-fractions upper-case-acronyms-aggressive vec-box-size-threshold diff --git a/tests/ui-toml/unwrap_used/unwrap_used.rs b/tests/ui-toml/unwrap_used/unwrap_used.rs index 6525ea5bfc3..5d3e800cadd 100644 --- a/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![allow(unused_mut, clippy::get_first, clippy::from_iter_instead_of_collect)] #![warn(clippy::unwrap_used)] diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index b8dd0619e6d..f0936b2608e 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index 295f560906a..2fb9e86126e 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] diff --git a/tests/ui/almost_complete_range.fixed b/tests/ui/almost_complete_range.fixed index a4bf7fe18d5..5cd0dcce6f7 100644 --- a/tests/ui/almost_complete_range.fixed +++ b/tests/ui/almost_complete_range.fixed @@ -1,6 +1,6 @@ -// run-rustfix -// edition:2018 -// aux-build:proc_macros.rs +//@run-rustfix +//@edition:2018 +//@aux-build:proc_macros.rs #![feature(exclusive_range_pattern)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/almost_complete_range.rs b/tests/ui/almost_complete_range.rs index 8237c3a1361..db0bfc8afc3 100644 --- a/tests/ui/almost_complete_range.rs +++ b/tests/ui/almost_complete_range.rs @@ -1,6 +1,6 @@ -// run-rustfix -// edition:2018 -// aux-build:proc_macros.rs +//@run-rustfix +//@edition:2018 +//@aux-build:proc_macros.rs #![feature(exclusive_range_pattern)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index 3c06676d722..ab408bdf261 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -1,3 +1,5 @@ +//@aux-build:proc_macro_derive.rs + #![allow( clippy::assign_op_pattern, clippy::erasing_op, @@ -11,6 +13,8 @@ #![feature(const_mut_refs, inline_const, saturating_int_impl)] #![warn(clippy::arithmetic_side_effects)] +extern crate proc_macro_derive; + use core::num::{Saturating, Wrapping}; const ONE: i32 = 1; @@ -19,6 +23,9 @@ const ZERO: i32 = 0; #[derive(Clone, Copy)] pub struct Custom; +#[derive(proc_macro_derive::ShadowDerive)] +pub struct Nothing; + macro_rules! impl_arith { ( $( $_trait:ident, $lhs:ty, $rhs:ty, $method:ident; )* ) => { $( @@ -269,6 +276,17 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri _n = &1 * _n; _n = 23 + 85; + // Method + _n.saturating_div(1); + _n.wrapping_div(1); + _n.wrapping_rem(1); + _n.wrapping_rem_euclid(1); + + _n.saturating_div(1); + _n.checked_div(1); + _n.checked_rem(1); + _n.checked_rem_euclid(1); + // Unary _n = -2147483647; _n = -i32::MAX; @@ -376,6 +394,17 @@ pub fn unknown_ops_or_runtime_ops_that_can_overflow() { _custom = Custom << _custom; _custom = &Custom << _custom; + // Method + _n.saturating_div(0); + _n.wrapping_div(0); + _n.wrapping_rem(0); + _n.wrapping_rem_euclid(0); + + _n.saturating_div(_n); + _n.wrapping_div(_n); + _n.wrapping_rem(_n); + _n.wrapping_rem_euclid(_n); + // Unary _n = -_n; _n = -&_n; diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index 2c8ee2884e7..e9a626643ff 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -1,5 +1,5 @@ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:286:5 + --> $DIR/arithmetic_side_effects.rs:304:5 | LL | _n += 1; | ^^^^^^^ @@ -7,652 +7,700 @@ LL | _n += 1; = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:287:5 + --> $DIR/arithmetic_side_effects.rs:305:5 | LL | _n += &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:288:5 + --> $DIR/arithmetic_side_effects.rs:306:5 | LL | _n -= 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:289:5 + --> $DIR/arithmetic_side_effects.rs:307:5 | LL | _n -= &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:290:5 + --> $DIR/arithmetic_side_effects.rs:308:5 | LL | _n /= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:291:5 + --> $DIR/arithmetic_side_effects.rs:309:5 | LL | _n /= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:292:5 + --> $DIR/arithmetic_side_effects.rs:310:5 | LL | _n %= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:293:5 + --> $DIR/arithmetic_side_effects.rs:311:5 | LL | _n %= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:294:5 + --> $DIR/arithmetic_side_effects.rs:312:5 | LL | _n *= 2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:295:5 + --> $DIR/arithmetic_side_effects.rs:313:5 | LL | _n *= &2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:296:5 + --> $DIR/arithmetic_side_effects.rs:314:5 | LL | _n += -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:297:5 + --> $DIR/arithmetic_side_effects.rs:315:5 | LL | _n += &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:298:5 + --> $DIR/arithmetic_side_effects.rs:316:5 | LL | _n -= -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:299:5 + --> $DIR/arithmetic_side_effects.rs:317:5 | LL | _n -= &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:300:5 + --> $DIR/arithmetic_side_effects.rs:318:5 | LL | _n /= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:301:5 + --> $DIR/arithmetic_side_effects.rs:319:5 | LL | _n /= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:302:5 + --> $DIR/arithmetic_side_effects.rs:320:5 | LL | _n %= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:303:5 + --> $DIR/arithmetic_side_effects.rs:321:5 | LL | _n %= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:304:5 + --> $DIR/arithmetic_side_effects.rs:322:5 | LL | _n *= -2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:305:5 + --> $DIR/arithmetic_side_effects.rs:323:5 | LL | _n *= &-2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:306:5 + --> $DIR/arithmetic_side_effects.rs:324:5 | LL | _custom += Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:307:5 + --> $DIR/arithmetic_side_effects.rs:325:5 | LL | _custom += &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:308:5 + --> $DIR/arithmetic_side_effects.rs:326:5 | LL | _custom -= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:309:5 + --> $DIR/arithmetic_side_effects.rs:327:5 | LL | _custom -= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:310:5 + --> $DIR/arithmetic_side_effects.rs:328:5 | LL | _custom /= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:311:5 + --> $DIR/arithmetic_side_effects.rs:329:5 | LL | _custom /= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:312:5 + --> $DIR/arithmetic_side_effects.rs:330:5 | LL | _custom %= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:313:5 + --> $DIR/arithmetic_side_effects.rs:331:5 | LL | _custom %= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:314:5 + --> $DIR/arithmetic_side_effects.rs:332:5 | LL | _custom *= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:315:5 + --> $DIR/arithmetic_side_effects.rs:333:5 | LL | _custom *= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:316:5 + --> $DIR/arithmetic_side_effects.rs:334:5 | LL | _custom >>= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:317:5 + --> $DIR/arithmetic_side_effects.rs:335:5 | LL | _custom >>= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:318:5 + --> $DIR/arithmetic_side_effects.rs:336:5 | LL | _custom <<= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:319:5 + --> $DIR/arithmetic_side_effects.rs:337:5 | LL | _custom <<= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:320:5 + --> $DIR/arithmetic_side_effects.rs:338:5 | LL | _custom += -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:321:5 + --> $DIR/arithmetic_side_effects.rs:339:5 | LL | _custom += &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:322:5 + --> $DIR/arithmetic_side_effects.rs:340:5 | LL | _custom -= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:323:5 + --> $DIR/arithmetic_side_effects.rs:341:5 | LL | _custom -= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:324:5 + --> $DIR/arithmetic_side_effects.rs:342:5 | LL | _custom /= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:325:5 + --> $DIR/arithmetic_side_effects.rs:343:5 | LL | _custom /= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:326:5 + --> $DIR/arithmetic_side_effects.rs:344:5 | LL | _custom %= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:327:5 + --> $DIR/arithmetic_side_effects.rs:345:5 | LL | _custom %= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:328:5 + --> $DIR/arithmetic_side_effects.rs:346:5 | LL | _custom *= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:329:5 + --> $DIR/arithmetic_side_effects.rs:347:5 | LL | _custom *= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:330:5 + --> $DIR/arithmetic_side_effects.rs:348:5 | LL | _custom >>= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:331:5 + --> $DIR/arithmetic_side_effects.rs:349:5 | LL | _custom >>= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:332:5 + --> $DIR/arithmetic_side_effects.rs:350:5 | LL | _custom <<= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:333:5 + --> $DIR/arithmetic_side_effects.rs:351:5 | LL | _custom <<= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:336:10 + --> $DIR/arithmetic_side_effects.rs:354:10 | LL | _n = _n + 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:337:10 + --> $DIR/arithmetic_side_effects.rs:355:10 | LL | _n = _n + &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:338:10 + --> $DIR/arithmetic_side_effects.rs:356:10 | LL | _n = 1 + _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:339:10 + --> $DIR/arithmetic_side_effects.rs:357:10 | LL | _n = &1 + _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:340:10 + --> $DIR/arithmetic_side_effects.rs:358:10 | LL | _n = _n - 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:341:10 + --> $DIR/arithmetic_side_effects.rs:359:10 | LL | _n = _n - &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:342:10 + --> $DIR/arithmetic_side_effects.rs:360:10 | LL | _n = 1 - _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:343:10 + --> $DIR/arithmetic_side_effects.rs:361:10 | LL | _n = &1 - _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:344:10 + --> $DIR/arithmetic_side_effects.rs:362:10 | LL | _n = _n / 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:345:10 + --> $DIR/arithmetic_side_effects.rs:363:10 | LL | _n = _n / &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:346:10 + --> $DIR/arithmetic_side_effects.rs:364:10 | LL | _n = _n % 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:347:10 + --> $DIR/arithmetic_side_effects.rs:365:10 | LL | _n = _n % &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:348:10 + --> $DIR/arithmetic_side_effects.rs:366:10 | LL | _n = _n * 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:349:10 + --> $DIR/arithmetic_side_effects.rs:367:10 | LL | _n = _n * &2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:350:10 + --> $DIR/arithmetic_side_effects.rs:368:10 | LL | _n = 2 * _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:351:10 + --> $DIR/arithmetic_side_effects.rs:369:10 | LL | _n = &2 * _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:352:10 + --> $DIR/arithmetic_side_effects.rs:370:10 | LL | _n = 23 + &85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:353:10 + --> $DIR/arithmetic_side_effects.rs:371:10 | LL | _n = &23 + 85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:354:10 + --> $DIR/arithmetic_side_effects.rs:372:10 | LL | _n = &23 + &85; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:355:15 + --> $DIR/arithmetic_side_effects.rs:373:15 | LL | _custom = _custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:356:15 + --> $DIR/arithmetic_side_effects.rs:374:15 | LL | _custom = _custom + &_custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:357:15 + --> $DIR/arithmetic_side_effects.rs:375:15 | LL | _custom = Custom + _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:358:15 + --> $DIR/arithmetic_side_effects.rs:376:15 | LL | _custom = &Custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:359:15 + --> $DIR/arithmetic_side_effects.rs:377:15 | LL | _custom = _custom - Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:360:15 + --> $DIR/arithmetic_side_effects.rs:378:15 | LL | _custom = _custom - &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:361:15 + --> $DIR/arithmetic_side_effects.rs:379:15 | LL | _custom = Custom - _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:362:15 + --> $DIR/arithmetic_side_effects.rs:380:15 | LL | _custom = &Custom - _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:363:15 + --> $DIR/arithmetic_side_effects.rs:381:15 | LL | _custom = _custom / Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:364:15 + --> $DIR/arithmetic_side_effects.rs:382:15 | LL | _custom = _custom / &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:365:15 + --> $DIR/arithmetic_side_effects.rs:383:15 | LL | _custom = _custom % Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:366:15 + --> $DIR/arithmetic_side_effects.rs:384:15 | LL | _custom = _custom % &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:367:15 + --> $DIR/arithmetic_side_effects.rs:385:15 | LL | _custom = _custom * Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:368:15 + --> $DIR/arithmetic_side_effects.rs:386:15 | LL | _custom = _custom * &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:369:15 + --> $DIR/arithmetic_side_effects.rs:387:15 | LL | _custom = Custom * _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:370:15 + --> $DIR/arithmetic_side_effects.rs:388:15 | LL | _custom = &Custom * _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:371:15 + --> $DIR/arithmetic_side_effects.rs:389:15 | LL | _custom = Custom + &Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:372:15 + --> $DIR/arithmetic_side_effects.rs:390:15 | LL | _custom = &Custom + Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:373:15 + --> $DIR/arithmetic_side_effects.rs:391:15 | LL | _custom = &Custom + &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:374:15 + --> $DIR/arithmetic_side_effects.rs:392:15 | LL | _custom = _custom >> _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:375:15 + --> $DIR/arithmetic_side_effects.rs:393:15 | LL | _custom = _custom >> &_custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:376:15 + --> $DIR/arithmetic_side_effects.rs:394:15 | LL | _custom = Custom << _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:377:15 + --> $DIR/arithmetic_side_effects.rs:395:15 | LL | _custom = &Custom << _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:380:10 + --> $DIR/arithmetic_side_effects.rs:398:23 + | +LL | _n.saturating_div(0); + | ^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:399:21 + | +LL | _n.wrapping_div(0); + | ^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:400:21 + | +LL | _n.wrapping_rem(0); + | ^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:401:28 + | +LL | _n.wrapping_rem_euclid(0); + | ^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:403:23 + | +LL | _n.saturating_div(_n); + | ^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:404:21 + | +LL | _n.wrapping_div(_n); + | ^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:405:21 + | +LL | _n.wrapping_rem(_n); + | ^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:406:28 + | +LL | _n.wrapping_rem_euclid(_n); + | ^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> $DIR/arithmetic_side_effects.rs:409:10 | LL | _n = -_n; | ^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:381:10 + --> $DIR/arithmetic_side_effects.rs:410:10 | LL | _n = -&_n; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:382:15 + --> $DIR/arithmetic_side_effects.rs:411:15 | LL | _custom = -_custom; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:383:15 + --> $DIR/arithmetic_side_effects.rs:412:15 | LL | _custom = -&_custom; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:392:5 + --> $DIR/arithmetic_side_effects.rs:421:5 | LL | 1 + i; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:393:5 + --> $DIR/arithmetic_side_effects.rs:422:5 | LL | i * 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:394:5 + --> $DIR/arithmetic_side_effects.rs:423:5 | LL | 1 % i / 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:395:5 + --> $DIR/arithmetic_side_effects.rs:424:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:396:5 + --> $DIR/arithmetic_side_effects.rs:425:5 | LL | -i; | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:407:5 + --> $DIR/arithmetic_side_effects.rs:436:5 | LL | i += 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:408:5 + --> $DIR/arithmetic_side_effects.rs:437:5 | LL | i -= 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:409:5 + --> $DIR/arithmetic_side_effects.rs:438:5 | LL | i *= 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:411:5 + --> $DIR/arithmetic_side_effects.rs:440:5 | LL | i /= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:413:5 + --> $DIR/arithmetic_side_effects.rs:442:5 | LL | i /= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:414:5 + --> $DIR/arithmetic_side_effects.rs:443:5 | LL | i /= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:416:5 + --> $DIR/arithmetic_side_effects.rs:445:5 | LL | i %= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:418:5 + --> $DIR/arithmetic_side_effects.rs:447:5 | LL | i %= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:419:5 + --> $DIR/arithmetic_side_effects.rs:448:5 | LL | i %= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> $DIR/arithmetic_side_effects.rs:429:5 + --> $DIR/arithmetic_side_effects.rs:458:5 | LL | 10 / a | ^^^^^^ -error: aborting due to 109 previous errors +error: aborting due to 117 previous errors diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs index c50d4088b5e..890bf0b0a7e 100644 --- a/tests/ui/as_conversions.rs +++ b/tests/ui/as_conversions.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::as_conversions)] #![allow(clippy::borrow_as_ptr)] diff --git a/tests/ui/as_underscore.fixed b/tests/ui/as_underscore.fixed index 948f6d8e6b1..69af84a0eae 100644 --- a/tests/ui/as_underscore.fixed +++ b/tests/ui/as_underscore.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::as_underscore)] diff --git a/tests/ui/as_underscore.rs b/tests/ui/as_underscore.rs index 97785ed08a8..a8cfb81d9a3 100644 --- a/tests/ui/as_underscore.rs +++ b/tests/ui/as_underscore.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::as_underscore)] diff --git a/tests/ui/asm_syntax.rs b/tests/ui/asm_syntax.rs index 0220bf3331f..c93995f939a 100644 --- a/tests/ui/asm_syntax.rs +++ b/tests/ui/asm_syntax.rs @@ -1,5 +1,5 @@ -// only-x86_64 -// ignore-aarch64 +//@only-x86_64 +//@ignore-aarch64 #[warn(clippy::inline_asm_x86_intel_syntax)] mod warn_intel { diff --git a/tests/ui/assertions_on_result_states.fixed b/tests/ui/assertions_on_result_states.fixed index 2bb755290c5..ea8b895664c 100644 --- a/tests/ui/assertions_on_result_states.fixed +++ b/tests/ui/assertions_on_result_states.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::assertions_on_result_states)] use std::result::Result; diff --git a/tests/ui/assertions_on_result_states.rs b/tests/ui/assertions_on_result_states.rs index d8a9bd2f1c4..6fc20f85988 100644 --- a/tests/ui/assertions_on_result_states.rs +++ b/tests/ui/assertions_on_result_states.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::assertions_on_result_states)] use std::result::Result; diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed index da034b51cfd..b50682ea00c 100644 --- a/tests/ui/assign_ops.fixed +++ b/tests/ui/assign_ops.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix use core::num::Wrapping; diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index 337bb02c8a6..780d2d040f1 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix use core::num::Wrapping; diff --git a/tests/ui/async_yields_async.fixed b/tests/ui/async_yields_async.fixed index 579a63ea477..8d9b023893f 100644 --- a/tests/ui/async_yields_async.fixed +++ b/tests/ui/async_yields_async.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![feature(async_closure)] #![warn(clippy::async_yields_async)] diff --git a/tests/ui/async_yields_async.rs b/tests/ui/async_yields_async.rs index 5aec2fb50f6..bed79062f01 100644 --- a/tests/ui/async_yields_async.rs +++ b/tests/ui/async_yields_async.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![feature(async_closure)] #![warn(clippy::async_yields_async)] diff --git a/tests/ui/author/blocks.rs b/tests/ui/author/blocks.rs index a7335c01baa..164f7d0d9d6 100644 --- a/tests/ui/author/blocks.rs +++ b/tests/ui/author/blocks.rs @@ -1,4 +1,4 @@ -// edition:2018 +//@edition:2018 #![allow(redundant_semicolons, clippy::no_effect)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index 4914f14b58f..92c47b41a38 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic #![crate_type = "proc-macro"] #![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)] @@ -28,7 +28,7 @@ pub fn dummy(_args: TokenStream, input: TokenStream) -> TokenStream { pub fn fake_async_trait(_args: TokenStream, input: TokenStream) -> TokenStream { let mut item = parse_macro_input!(input as ItemTrait); for inner in &mut item.items { - if let TraitItem::Method(method) = inner { + if let TraitItem::Fn(method) = inner { let sig = &method.sig; let block = &mut method.default; if let Some(block) = block { @@ -70,7 +70,7 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea // Look for methods having arbitrary self type taken by &mut ref for inner in &mut item.items { - if let ImplItem::Method(method) = inner { + if let ImplItem::Fn(method) = inner { if let Some(FnArg::Typed(pat_type)) = mut_receiver_of(&mut method.sig) { if let box Type::Reference(reference) = &mut pat_type.ty { // Target only unnamed lifetimes diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index a89a06308d0..5a924ca1830 100644 --- a/tests/ui/auxiliary/proc_macro_derive.rs +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic #![crate_type = "proc-macro"] #![feature(repr128, proc_macro_quote)] @@ -9,7 +9,7 @@ extern crate proc_macro; -use proc_macro::{quote, TokenStream}; +use proc_macro::{quote, Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; #[proc_macro_derive(DeriveSomething)] pub fn derive(_: TokenStream) -> TokenStream { @@ -86,3 +86,74 @@ pub fn extra_lifetime(_input: TokenStream) -> TokenStream { } ) } + +#[allow(unused)] +#[proc_macro_derive(ArithmeticDerive)] +pub fn arithmetic_derive(_: TokenStream) -> TokenStream { + >::from_iter( + [ + Ident::new("fn", Span::call_site()).into(), + Ident::new("_foo", Span::call_site()).into(), + Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), + Group::new( + Delimiter::Brace, + >::from_iter( + [ + Ident::new("let", Span::call_site()).into(), + Ident::new("mut", Span::call_site()).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Literal::i32_unsuffixed(9).into(), + Punct::new(';', Spacing::Alone).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Literal::i32_unsuffixed(9).into(), + Punct::new('/', Spacing::Alone).into(), + Literal::i32_unsuffixed(2).into(), + Punct::new(';', Spacing::Alone).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Punct::new('-', Spacing::Alone).into(), + Ident::new("_n", Span::call_site()).into(), + Punct::new(';', Spacing::Alone).into(), + ] + .into_iter(), + ), + ) + .into(), + ] + .into_iter(), + ) +} + +#[allow(unused)] +#[proc_macro_derive(ShadowDerive)] +pub fn shadow_derive(_: TokenStream) -> TokenStream { + >::from_iter( + [ + Ident::new("fn", Span::call_site()).into(), + Ident::new("_foo", Span::call_site()).into(), + Group::new(Delimiter::Parenthesis, TokenStream::new()).into(), + Group::new( + Delimiter::Brace, + >::from_iter( + [ + Ident::new("let", Span::call_site()).into(), + Ident::new("_x", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Literal::i32_unsuffixed(2).into(), + Punct::new(';', Spacing::Alone).into(), + Ident::new("let", Span::call_site()).into(), + Ident::new("_x", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Ident::new("_x", Span::call_site()).into(), + Punct::new(';', Spacing::Alone).into(), + ] + .into_iter(), + ), + ) + .into(), + ] + .into_iter(), + ) +} diff --git a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs index a2ef0fe827c..f13b76e44b0 100644 --- a/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs +++ b/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic #![crate_type = "proc-macro"] diff --git a/tests/ui/auxiliary/proc_macro_unsafe.rs b/tests/ui/auxiliary/proc_macro_unsafe.rs index 3c40f77469b..c2326678d0d 100644 --- a/tests/ui/auxiliary/proc_macro_unsafe.rs +++ b/tests/ui/auxiliary/proc_macro_unsafe.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic #![crate_type = "proc-macro"] diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs index 3d5beab1eff..94f075ed09c 100644 --- a/tests/ui/auxiliary/proc_macros.rs +++ b/tests/ui/auxiliary/proc_macros.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic #![crate_type = "proc-macro"] #![feature(let_chains)] diff --git a/tests/ui/bind_instead_of_map.fixed b/tests/ui/bind_instead_of_map.fixed index d94e2ac6072..ea2dc2e2293 100644 --- a/tests/ui/bind_instead_of_map.fixed +++ b/tests/ui/bind_instead_of_map.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::bind_instead_of_map)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/bind_instead_of_map.rs b/tests/ui/bind_instead_of_map.rs index 86f31f58284..1db58dae538 100644 --- a/tests/ui/bind_instead_of_map.rs +++ b/tests/ui/bind_instead_of_map.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::bind_instead_of_map)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/bind_instead_of_map_multipart.fixed b/tests/ui/bind_instead_of_map_multipart.fixed index e1589843226..63c7aafcddb 100644 --- a/tests/ui/bind_instead_of_map_multipart.fixed +++ b/tests/ui/bind_instead_of_map_multipart.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::bind_instead_of_map)] #![allow(clippy::blocks_in_if_conditions)] diff --git a/tests/ui/bind_instead_of_map_multipart.rs b/tests/ui/bind_instead_of_map_multipart.rs index 49944403f6d..69b982fa8a2 100644 --- a/tests/ui/bind_instead_of_map_multipart.rs +++ b/tests/ui/bind_instead_of_map_multipart.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::bind_instead_of_map)] #![allow(clippy::blocks_in_if_conditions)] diff --git a/tests/ui/blanket_clippy_restriction_lints.rs b/tests/ui/blanket_clippy_restriction_lints.rs index 554745368bc..e1ff25c54cf 100644 --- a/tests/ui/blanket_clippy_restriction_lints.rs +++ b/tests/ui/blanket_clippy_restriction_lints.rs @@ -1,4 +1,4 @@ -// compile-flags: -W clippy::restriction +//@compile-flags: -W clippy::restriction #![warn(clippy::blanket_clippy_restriction_lints)] diff --git a/tests/ui/blocks_in_if_conditions.fixed b/tests/ui/blocks_in_if_conditions.fixed index e6e40a9948c..a9f18782e58 100644 --- a/tests/ui/blocks_in_if_conditions.fixed +++ b/tests/ui/blocks_in_if_conditions.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::blocks_in_if_conditions)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/blocks_in_if_conditions.rs b/tests/ui/blocks_in_if_conditions.rs index 69387ff5782..0a70317c4d4 100644 --- a/tests/ui/blocks_in_if_conditions.rs +++ b/tests/ui/blocks_in_if_conditions.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::blocks_in_if_conditions)] #![allow(unused, clippy::let_and_return)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/bool_assert_comparison.fixed b/tests/ui/bool_assert_comparison.fixed index b8dd92906c8..53f63444aef 100644 --- a/tests/ui/bool_assert_comparison.fixed +++ b/tests/ui/bool_assert_comparison.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::assertions_on_constants)] #![warn(clippy::bool_assert_comparison)] diff --git a/tests/ui/bool_assert_comparison.rs b/tests/ui/bool_assert_comparison.rs index 0a8ad34fda5..151d93a9233 100644 --- a/tests/ui/bool_assert_comparison.rs +++ b/tests/ui/bool_assert_comparison.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::assertions_on_constants)] #![warn(clippy::bool_assert_comparison)] diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 5a012ff4d27..670eef6a21d 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::bool_comparison)] diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index c534bc25c20..72851be635d 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::bool_comparison)] diff --git a/tests/ui/bool_to_int_with_if.fixed b/tests/ui/bool_to_int_with_if.fixed index 37d3e3286a4..9831c3373d4 100644 --- a/tests/ui/bool_to_int_with_if.fixed +++ b/tests/ui/bool_to_int_with_if.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(let_chains)] #![warn(clippy::bool_to_int_with_if)] diff --git a/tests/ui/bool_to_int_with_if.rs b/tests/ui/bool_to_int_with_if.rs index ebdf86fd185..5e3047bb32c 100644 --- a/tests/ui/bool_to_int_with_if.rs +++ b/tests/ui/bool_to_int_with_if.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(let_chains)] #![warn(clippy::bool_to_int_with_if)] diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed index ff5c6a8c377..3f440ce0045 100644 --- a/tests/ui/borrow_as_ptr.fixed +++ b/tests/ui/borrow_as_ptr.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::borrow_as_ptr)] fn main() { diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs index 0f62ec6ee58..c1ca9180eef 100644 --- a/tests/ui/borrow_as_ptr.rs +++ b/tests/ui/borrow_as_ptr.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::borrow_as_ptr)] fn main() { diff --git a/tests/ui/borrow_as_ptr_no_std.fixed b/tests/ui/borrow_as_ptr_no_std.fixed index eaba3b1c20c..10f2727c793 100644 --- a/tests/ui/borrow_as_ptr_no_std.fixed +++ b/tests/ui/borrow_as_ptr_no_std.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::borrow_as_ptr)] #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/borrow_as_ptr_no_std.rs b/tests/ui/borrow_as_ptr_no_std.rs index d83f9d1f875..311e9341aac 100644 --- a/tests/ui/borrow_as_ptr_no_std.rs +++ b/tests/ui/borrow_as_ptr_no_std.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::borrow_as_ptr)] #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index bf4691c5bc9..165e4bc8272 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_variables)] diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index 28c005fdbef..66c8d69bef9 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_variables)] diff --git a/tests/ui/borrow_interior_mutable_const/enums.rs b/tests/ui/borrow_interior_mutable_const/enums.rs index 5027db44561..29b08ab3643 100644 --- a/tests/ui/borrow_interior_mutable_const/enums.rs +++ b/tests/ui/borrow_interior_mutable_const/enums.rs @@ -1,4 +1,4 @@ -// aux-build:helper.rs +//@aux-build:helper.rs #![warn(clippy::borrow_interior_mutable_const)] #![allow(clippy::declare_interior_mutable_const)] diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed index 59c0baf8718..6afce208769 100644 --- a/tests/ui/box_default.fixed +++ b/tests/ui/box_default.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::box_default)] #[derive(Default)] diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs index f7d832193a3..09365618e63 100644 --- a/tests/ui/box_default.rs +++ b/tests/ui/box_default.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::box_default)] #[derive(Default)] diff --git a/tests/ui/bytes_count_to_len.fixed b/tests/ui/bytes_count_to_len.fixed index 860642363b5..fb3d521badd 100644 --- a/tests/ui/bytes_count_to_len.fixed +++ b/tests/ui/bytes_count_to_len.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::bytes_count_to_len)] use std::fs::File; use std::io::Read; diff --git a/tests/ui/bytes_count_to_len.rs b/tests/ui/bytes_count_to_len.rs index 162730c2842..8e256b8f0b8 100644 --- a/tests/ui/bytes_count_to_len.rs +++ b/tests/ui/bytes_count_to_len.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::bytes_count_to_len)] use std::fs::File; use std::io::Read; diff --git a/tests/ui/bytes_nth.fixed b/tests/ui/bytes_nth.fixed index a35c679afb7..d3e0f676b29 100644 --- a/tests/ui/bytes_nth.fixed +++ b/tests/ui/bytes_nth.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::unnecessary_operation)] #![warn(clippy::bytes_nth)] diff --git a/tests/ui/bytes_nth.rs b/tests/ui/bytes_nth.rs index 1ecffea5303..b7d813fe296 100644 --- a/tests/ui/bytes_nth.rs +++ b/tests/ui/bytes_nth.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::unnecessary_operation)] #![warn(clippy::bytes_nth)] diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed index 5fbaa64db39..d5af22aefe5 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.fixed +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::case_sensitive_file_extension_comparisons)] use std::string::String; diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index 3c0d4821f9f..f5f0a0022a4 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::case_sensitive_file_extension_comparisons)] use std::string::String; diff --git a/tests/ui/cast_abs_to_unsigned.fixed b/tests/ui/cast_abs_to_unsigned.fixed index 8676b562b4f..ef0a93b01d1 100644 --- a/tests/ui/cast_abs_to_unsigned.fixed +++ b/tests/ui/cast_abs_to_unsigned.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::cast_abs_to_unsigned)] #![allow(clippy::uninlined_format_args, unused)] diff --git a/tests/ui/cast_abs_to_unsigned.rs b/tests/ui/cast_abs_to_unsigned.rs index 5775af874f8..96ced670a05 100644 --- a/tests/ui/cast_abs_to_unsigned.rs +++ b/tests/ui/cast_abs_to_unsigned.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::cast_abs_to_unsigned)] #![allow(clippy::uninlined_format_args, unused)] diff --git a/tests/ui/cast_lossless_bool.fixed b/tests/ui/cast_lossless_bool.fixed index 13b3cf838c9..c321cc64437 100644 --- a/tests/ui/cast_lossless_bool.fixed +++ b/tests/ui/cast_lossless_bool.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_bool.rs b/tests/ui/cast_lossless_bool.rs index 3eed2135562..632a718920d 100644 --- a/tests/ui/cast_lossless_bool.rs +++ b/tests/ui/cast_lossless_bool.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed index 32a9c1c4ae1..e72a0096acc 100644 --- a/tests/ui/cast_lossless_float.fixed +++ b/tests/ui/cast_lossless_float.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index 6f5ddcfe09c..dbcbaa9b815 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed index 925cbf25368..7dab02084fc 100644 --- a/tests/ui/cast_lossless_integer.fixed +++ b/tests/ui/cast_lossless_integer.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index c82bd9108d2..c24f73960b0 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/cast_raw_slice_pointer_cast.fixed b/tests/ui/cast_raw_slice_pointer_cast.fixed index b70c1912951..9b6fee270ee 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.fixed +++ b/tests/ui/cast_raw_slice_pointer_cast.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::cast_slice_from_raw_parts)] #[allow(unused_imports, unused_unsafe)] diff --git a/tests/ui/cast_raw_slice_pointer_cast.rs b/tests/ui/cast_raw_slice_pointer_cast.rs index c1b316765c9..c0bb8137990 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.rs +++ b/tests/ui/cast_raw_slice_pointer_cast.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::cast_slice_from_raw_parts)] #[allow(unused_imports, unused_unsafe)] diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index 595109be46b..cd2184aea38 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -1,4 +1,4 @@ -// ignore-32bit +//@ignore-32bit #[warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, diff --git a/tests/ui/cast_size_32bit.rs b/tests/ui/cast_size_32bit.rs index 99aac6deca3..7ca20d3ca4a 100644 --- a/tests/ui/cast_size_32bit.rs +++ b/tests/ui/cast_size_32bit.rs @@ -1,4 +1,4 @@ -// ignore-64bit +//@ignore-64bit #[warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, diff --git a/tests/ui/cast_size_32bit.stderr b/tests/ui/cast_size_32bit.stderr index 8990c3ba739..fb51783a487 100644 --- a/tests/ui/cast_size_32bit.stderr +++ b/tests/ui/cast_size_32bit.stderr @@ -4,7 +4,12 @@ error: casting `isize` to `i8` may truncate the value LL | 1isize as i8; | ^^^^^^^^^^^^ | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` +help: ... or use `try_from` and handle the error accordingly + | +LL | i8::try_from(1isize); + | ~~~~~~~~~~~~~~~~~~~~ error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide) --> $DIR/cast_size_32bit.rs:15:5 @@ -37,24 +42,48 @@ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wi | LL | 1isize as i32; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | i32::try_from(1isize); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size_32bit.rs:20:5 | LL | 1isize as u32; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | u32::try_from(1isize); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size_32bit.rs:21:5 | LL | 1usize as u32; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | u32::try_from(1usize); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers --> $DIR/cast_size_32bit.rs:22:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | i32::try_from(1usize); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers --> $DIR/cast_size_32bit.rs:22:5 @@ -69,18 +98,36 @@ error: casting `i64` to `isize` may truncate the value on targets with 32-bit wi | LL | 1i64 as isize; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | isize::try_from(1i64); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size_32bit.rs:25:5 | LL | 1i64 as usize; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | usize::try_from(1i64); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers --> $DIR/cast_size_32bit.rs:26:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | isize::try_from(1u64); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers --> $DIR/cast_size_32bit.rs:26:5 @@ -93,6 +140,12 @@ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wi | LL | 1u64 as usize; | ^^^^^^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... +help: ... or use `try_from` and handle the error accordingly + | +LL | usize::try_from(1u64); + | ~~~~~~~~~~~~~~~~~~~~~ error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers --> $DIR/cast_size_32bit.rs:28:5 diff --git a/tests/ui/cfg_attr_rustfmt.fixed b/tests/ui/cfg_attr_rustfmt.fixed index b970b1209b6..13aadb7d330 100644 --- a/tests/ui/cfg_attr_rustfmt.fixed +++ b/tests/ui/cfg_attr_rustfmt.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(stmt_expr_attributes)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/cfg_attr_rustfmt.rs b/tests/ui/cfg_attr_rustfmt.rs index 0a8e6a89d8a..769c5d22b9d 100644 --- a/tests/ui/cfg_attr_rustfmt.rs +++ b/tests/ui/cfg_attr_rustfmt.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(stmt_expr_attributes)] #![allow(unused, clippy::no_effect, clippy::unnecessary_operation)] diff --git a/tests/ui/char_lit_as_u8_suggestions.fixed b/tests/ui/char_lit_as_u8_suggestions.fixed index 3dc3cb4e757..ce2f149dc05 100644 --- a/tests/ui/char_lit_as_u8_suggestions.fixed +++ b/tests/ui/char_lit_as_u8_suggestions.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::char_lit_as_u8)] diff --git a/tests/ui/char_lit_as_u8_suggestions.rs b/tests/ui/char_lit_as_u8_suggestions.rs index d379a023494..ffad12fc6f9 100644 --- a/tests/ui/char_lit_as_u8_suggestions.rs +++ b/tests/ui/char_lit_as_u8_suggestions.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::char_lit_as_u8)] diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index e279ba3147b..188e6d97595 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( clippy::cast_lossless, diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index 9d7a40995c3..70f0f0975ac 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( clippy::cast_lossless, diff --git a/tests/ui/clear_with_drain.fixed b/tests/ui/clear_with_drain.fixed index 2d9545eeed1..b68c7d867ec 100644 --- a/tests/ui/clear_with_drain.fixed +++ b/tests/ui/clear_with_drain.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::clear_with_drain)] diff --git a/tests/ui/clear_with_drain.rs b/tests/ui/clear_with_drain.rs index 4d60ee46e18..0f6562ecad5 100644 --- a/tests/ui/clear_with_drain.rs +++ b/tests/ui/clear_with_drain.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::clear_with_drain)] diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed index 72b12227098..a720711585b 100644 --- a/tests/ui/clone_on_copy.fixed +++ b/tests/ui/clone_on_copy.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs index 03e210ebad9..2c5fac8faf5 100644 --- a/tests/ui/clone_on_copy.rs +++ b/tests/ui/clone_on_copy.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, diff --git a/tests/ui/cloned_instead_of_copied.fixed b/tests/ui/cloned_instead_of_copied.fixed index ecbfc1feedf..b6e09ab3190 100644 --- a/tests/ui/cloned_instead_of_copied.fixed +++ b/tests/ui/cloned_instead_of_copied.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] diff --git a/tests/ui/cloned_instead_of_copied.rs b/tests/ui/cloned_instead_of_copied.rs index 163dc3dddce..fa9e1a99613 100644 --- a/tests/ui/cloned_instead_of_copied.rs +++ b/tests/ui/cloned_instead_of_copied.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::cloned_instead_of_copied)] #![allow(unused)] diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed index abd059c2308..3bf3deb9b91 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.fixed +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700 // Define the types in each module to avoid trait impls leaking between modules. diff --git a/tests/ui/cmp_owned/asymmetric_partial_eq.rs b/tests/ui/cmp_owned/asymmetric_partial_eq.rs index 020ef5f840b..10107dc8f86 100644 --- a/tests/ui/cmp_owned/asymmetric_partial_eq.rs +++ b/tests/ui/cmp_owned/asymmetric_partial_eq.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::redundant_clone, clippy::derive_partial_eq_without_eq)] // See #5700 // Define the types in each module to avoid trait impls leaking between modules. diff --git a/tests/ui/cmp_owned/comparison_flip.fixed b/tests/ui/cmp_owned/comparison_flip.fixed index 44e41bdd114..b1133f2a59f 100644 --- a/tests/ui/cmp_owned/comparison_flip.fixed +++ b/tests/ui/cmp_owned/comparison_flip.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix use std::fmt::{self, Display}; diff --git a/tests/ui/cmp_owned/comparison_flip.rs b/tests/ui/cmp_owned/comparison_flip.rs index 662673abb62..091a9aa65c0 100644 --- a/tests/ui/cmp_owned/comparison_flip.rs +++ b/tests/ui/cmp_owned/comparison_flip.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix use std::fmt::{self, Display}; diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index b28c4378e33..76f90ab2a9d 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[warn(clippy::cmp_owned)] #[allow(clippy::unnecessary_operation, clippy::no_effect, unused_must_use, clippy::eq_op)] diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index c1089010fe1..f3f663670eb 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[warn(clippy::cmp_owned)] #[allow(clippy::unnecessary_operation, clippy::no_effect, unused_must_use, clippy::eq_op)] diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index d6a5a785067..8302cec45e7 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] #[rustfmt::skip] diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 4399fc8b2bd..5913dcf41ca 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] #[rustfmt::skip] diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 6bb7682bae9..d2aba2ac59b 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] #[rustfmt::skip] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index e216a9ee54c..e0bef7f9c97 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::assertions_on_constants, clippy::equatable_if_let)] #[rustfmt::skip] diff --git a/tests/ui/collapsible_str_replace.fixed b/tests/ui/collapsible_str_replace.fixed index 9792ae9ed6b..ba6c1769a9a 100644 --- a/tests/ui/collapsible_str_replace.fixed +++ b/tests/ui/collapsible_str_replace.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::collapsible_str_replace)] diff --git a/tests/ui/collapsible_str_replace.rs b/tests/ui/collapsible_str_replace.rs index baee185b79e..f5871be65be 100644 --- a/tests/ui/collapsible_str_replace.rs +++ b/tests/ui/collapsible_str_replace.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::collapsible_str_replace)] diff --git a/tests/ui/collection_is_never_read.rs b/tests/ui/collection_is_never_read.rs index 01259a983ab..2c1a42a72c1 100644 --- a/tests/ui/collection_is_never_read.rs +++ b/tests/ui/collection_is_never_read.rs @@ -169,22 +169,35 @@ fn function_argument() { foo(&x); } -fn string() { - // Do lint (write without read) - let mut s = String::new(); - s.push_str("Hello, World!"); - - // Do not lint (read without write) - let mut s = String::from("Hello, World!"); - let _ = s.len(); - - // Do not lint (write and read) - let mut s = String::from("Hello, World!"); - s.push_str("foo, bar"); - let _ = s.len(); - - // Do lint the first line, but not the second - let mut s = String::from("Hello, World!"); - let t = String::from("foo, bar"); - s = t; +fn supported_types() { + let mut x = std::collections::BTreeMap::new(); // WARNING + x.insert(true, 1); + + let mut x = std::collections::BTreeSet::new(); // WARNING + x.insert(1); + + let mut x = std::collections::BinaryHeap::new(); // WARNING + x.push(1); + + let mut x = std::collections::HashMap::new(); // WARNING + x.insert(1, 2); + + let mut x = std::collections::HashSet::new(); // WARNING + x.insert(1); + + let mut x = std::collections::LinkedList::new(); // WARNING + x.push_front(1); + + let mut x = Some(true); // WARNING + x.insert(false); + + let mut x = String::from("hello"); // WARNING + x.push('!'); + + let mut x = Vec::new(); // WARNING + x.clear(); + x.push(1); + + let mut x = std::collections::VecDeque::new(); // WARNING + x.push_front(1); } diff --git a/tests/ui/collection_is_never_read.stderr b/tests/ui/collection_is_never_read.stderr index cf51a53686f..982cb445534 100644 --- a/tests/ui/collection_is_never_read.stderr +++ b/tests/ui/collection_is_never_read.stderr @@ -61,16 +61,64 @@ LL | let x = vec![1, 2, 3]; // WARNING | ^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> $DIR/collection_is_never_read.rs:174:5 + --> $DIR/collection_is_never_read.rs:173:5 | -LL | let mut s = String::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let mut x = std::collections::BTreeMap::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:176:5 + | +LL | let mut x = std::collections::BTreeSet::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:179:5 + | +LL | let mut x = std::collections::BinaryHeap::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:182:5 + | +LL | let mut x = std::collections::HashMap::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:185:5 + | +LL | let mut x = std::collections::HashSet::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:188:5 + | +LL | let mut x = std::collections::LinkedList::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:191:5 + | +LL | let mut x = Some(true); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:194:5 + | +LL | let mut x = String::from("hello"); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: collection is never read + --> $DIR/collection_is_never_read.rs:197:5 + | +LL | let mut x = Vec::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^ error: collection is never read - --> $DIR/collection_is_never_read.rs:187:5 + --> $DIR/collection_is_never_read.rs:201:5 | -LL | let mut s = String::from("Hello, World!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let mut x = std::collections::VecDeque::new(); // WARNING + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/comparison_to_empty.fixed b/tests/ui/comparison_to_empty.fixed index 261024caca7..dd2615ab25c 100644 --- a/tests/ui/comparison_to_empty.fixed +++ b/tests/ui/comparison_to_empty.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::comparison_to_empty)] diff --git a/tests/ui/comparison_to_empty.rs b/tests/ui/comparison_to_empty.rs index 98ddd974951..5462784c6ac 100644 --- a/tests/ui/comparison_to_empty.rs +++ b/tests/ui/comparison_to_empty.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::comparison_to_empty)] diff --git a/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/tests/ui/crashes/auxiliary/proc_macro_crash.rs index 5ff2af7cd82..66419656a32 100644 --- a/tests/ui/crashes/auxiliary/proc_macro_crash.rs +++ b/tests/ui/crashes/auxiliary/proc_macro_crash.rs @@ -1,5 +1,5 @@ -// compile-flags: --emit=link -// no-prefer-dynamic +//@compile-flags: --emit=link +//@no-prefer-dynamic // ^ compiletest by default builds all aux files as dylibs, but we don't want that for proc-macro // crates. If we don't set this, compiletest will override the `crate_type` attribute below and // compile this as dylib. Removing this then causes the test to fail because a `dylib` crate can't diff --git a/tests/ui/crashes/ice-10148.rs b/tests/ui/crashes/ice-10148.rs index 1ab3570c907..c7f0224820e 100644 --- a/tests/ui/crashes/ice-10148.rs +++ b/tests/ui/crashes/ice-10148.rs @@ -1,4 +1,4 @@ -// aux-build:../../auxiliary/proc_macros.rs +//@aux-build:../../auxiliary/proc_macros.rs extern crate proc_macros; diff --git a/tests/ui/crashes/ice-3741.rs b/tests/ui/crashes/ice-3741.rs index 1253ddcfaeb..3106a2e7216 100644 --- a/tests/ui/crashes/ice-3741.rs +++ b/tests/ui/crashes/ice-3741.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_crash.rs +//@aux-build:proc_macro_crash.rs #![warn(clippy::suspicious_else_formatting)] diff --git a/tests/ui/crashes/ice-4968.rs b/tests/ui/crashes/ice-4968.rs index e0510d942c2..ac724ac93e3 100644 --- a/tests/ui/crashes/ice-4968.rs +++ b/tests/ui/crashes/ice-4968.rs @@ -1,4 +1,4 @@ -// check-pass +//@check-pass // Test for https://github.com/rust-lang/rust-clippy/issues/4968 diff --git a/tests/ui/crashes/ice-5207.stderr b/tests/ui/crashes/ice-5207.stderr index 367e9a08b75..59146c23e0d 100644 --- a/tests/ui/crashes/ice-5207.stderr +++ b/tests/ui/crashes/ice-5207.stderr @@ -1,4 +1,4 @@ -warning: future cannot be sent between threads safely +error: future cannot be sent between threads safely --> $DIR/ice-5207.rs:6:35 | LL | pub async fn bar<'a, T: 'a>(_: T) {} @@ -12,5 +12,5 @@ LL | pub async fn bar<'a, T: 'a>(_: T) {} = note: `T` doesn't implement `std::marker::Send` = note: `-D clippy::future-not-send` implied by `-D warnings` -warning: 1 warning emitted +error: aborting due to previous error diff --git a/tests/ui/crashes/ice-7272.rs b/tests/ui/crashes/ice-7272.rs index 57ab6ca14f8..e949038c8d0 100644 --- a/tests/ui/crashes/ice-7272.rs +++ b/tests/ui/crashes/ice-7272.rs @@ -1,4 +1,4 @@ -// aux-build:ice-7272-aux.rs +//@aux-build:ice-7272-aux.rs #![allow(clippy::no_effect)] diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs index 85fa4210321..ffe20ab1c31 100644 --- a/tests/ui/crashes/ice-7410.rs +++ b/tests/ui/crashes/ice-7410.rs @@ -1,6 +1,6 @@ -// compile-flags: -Clink-arg=-nostartfiles -// ignore-macos -// ignore-windows +//@compile-flags: -Clink-arg=-nostartfiles +//@ignore-macos +//@ignore-windows #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/crashes/ice-8681.rs b/tests/ui/crashes/ice-8681.rs index ee14f011f63..607b9caa324 100644 --- a/tests/ui/crashes/ice-8681.rs +++ b/tests/ui/crashes/ice-8681.rs @@ -1,4 +1,4 @@ -// aux-build: ice-8681-aux.rs +//@aux-build: ice-8681-aux.rs #![warn(clippy::undocumented_unsafe_blocks)] diff --git a/tests/ui/crate_in_macro_def.fixed b/tests/ui/crate_in_macro_def.fixed index 9fc594be311..12a7b9470b3 100644 --- a/tests/ui/crate_in_macro_def.fixed +++ b/tests/ui/crate_in_macro_def.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::crate_in_macro_def)] mod hygienic { diff --git a/tests/ui/crate_in_macro_def.rs b/tests/ui/crate_in_macro_def.rs index ac456108e4a..a1a9eabf639 100644 --- a/tests/ui/crate_in_macro_def.rs +++ b/tests/ui/crate_in_macro_def.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::crate_in_macro_def)] mod hygienic { diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index 1b3bcece6f1..d6cd594d7c9 100644 --- a/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,4 +1,4 @@ -// ignore-macos +//@ignore-macos #![feature(rustc_attrs)] diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs index e1c9fe30a9d..a382135bb69 100644 --- a/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -1,5 +1,5 @@ -// compile-flags: -Clink-arg=-nostartfiles -// ignore-macos +//@compile-flags: -Clink-arg=-nostartfiles +//@ignore-macos #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/create_dir.fixed b/tests/ui/create_dir.fixed index 8ed53a56ac0..5de3e9fea0b 100644 --- a/tests/ui/create_dir.fixed +++ b/tests/ui/create_dir.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_must_use)] #![warn(clippy::create_dir)] diff --git a/tests/ui/create_dir.rs b/tests/ui/create_dir.rs index 19c8fc24ba2..d375bfb4a68 100644 --- a/tests/ui/create_dir.rs +++ b/tests/ui/create_dir.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_must_use)] #![warn(clippy::create_dir)] diff --git a/tests/ui/dbg_macro.rs b/tests/ui/dbg_macro.rs index 25294e8c766..8701e3cd29f 100644 --- a/tests/ui/dbg_macro.rs +++ b/tests/ui/dbg_macro.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![warn(clippy::dbg_macro)] fn foo(n: u32) -> u32 { diff --git a/tests/ui/decimal_literal_representation.fixed b/tests/ui/decimal_literal_representation.fixed index de391465125..a6eb8c21457 100644 --- a/tests/ui/decimal_literal_representation.fixed +++ b/tests/ui/decimal_literal_representation.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index 55d07698e7e..7c666d6d7a6 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs index 1af77d1a25b..f7819068ac5 100644 --- a/tests/ui/def_id_nocore.rs +++ b/tests/ui/def_id_nocore.rs @@ -1,4 +1,4 @@ -// ignore-macos +//@ignore-macos #![feature(no_core, lang_items, start)] #![no_core] diff --git a/tests/ui/default_instead_of_iter_empty.fixed b/tests/ui/default_instead_of_iter_empty.fixed index f1abfdcd6ce..f44d34576f6 100644 --- a/tests/ui/default_instead_of_iter_empty.fixed +++ b/tests/ui/default_instead_of_iter_empty.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::default_instead_of_iter_empty)] #![allow(dead_code)] use std::collections::HashMap; diff --git a/tests/ui/default_instead_of_iter_empty.rs b/tests/ui/default_instead_of_iter_empty.rs index 2630519c46d..1c649df253c 100644 --- a/tests/ui/default_instead_of_iter_empty.rs +++ b/tests/ui/default_instead_of_iter_empty.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::default_instead_of_iter_empty)] #![allow(dead_code)] use std::collections::HashMap; diff --git a/tests/ui/default_numeric_fallback_f64.fixed b/tests/ui/default_numeric_fallback_f64.fixed index 42c15d6a70b..9520efe6329 100644 --- a/tests/ui/default_numeric_fallback_f64.fixed +++ b/tests/ui/default_numeric_fallback_f64.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::default_numeric_fallback)] #![allow( diff --git a/tests/ui/default_numeric_fallback_f64.rs b/tests/ui/default_numeric_fallback_f64.rs index 7da7ea254e9..cacbdb4a95b 100644 --- a/tests/ui/default_numeric_fallback_f64.rs +++ b/tests/ui/default_numeric_fallback_f64.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::default_numeric_fallback)] #![allow( diff --git a/tests/ui/default_numeric_fallback_i32.fixed b/tests/ui/default_numeric_fallback_i32.fixed index b7485b73dcd..fbabb8bcf8e 100644 --- a/tests/ui/default_numeric_fallback_i32.fixed +++ b/tests/ui/default_numeric_fallback_i32.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![feature(lint_reasons)] #![warn(clippy::default_numeric_fallback)] diff --git a/tests/ui/default_numeric_fallback_i32.rs b/tests/ui/default_numeric_fallback_i32.rs index 7307d31354e..7bfc390e4bf 100644 --- a/tests/ui/default_numeric_fallback_i32.rs +++ b/tests/ui/default_numeric_fallback_i32.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![feature(lint_reasons)] #![warn(clippy::default_numeric_fallback)] diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed index 7842ef3ec40..bf5dca97641 100644 --- a/tests/ui/default_trait_access.fixed +++ b/tests/ui/default_trait_access.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: proc_macros.rs +//@run-rustfix +//@aux-build: proc_macros.rs #![deny(clippy::default_trait_access)] #![allow(dead_code, unused_imports)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs index cbb3e59c970..5e8e9ce85b1 100644 --- a/tests/ui/default_trait_access.rs +++ b/tests/ui/default_trait_access.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: proc_macros.rs +//@run-rustfix +//@aux-build: proc_macros.rs #![deny(clippy::default_trait_access)] #![allow(dead_code, unused_imports)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed index ca5c03304c7..b27d3bc1002 100644 --- a/tests/ui/deref_addrof.fixed +++ b/tests/ui/deref_addrof.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![allow(clippy::return_self_not_must_use)] #![warn(clippy::deref_addrof)] diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs index 3db5fafe944..825090c7c12 100644 --- a/tests/ui/deref_addrof.rs +++ b/tests/ui/deref_addrof.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![allow(clippy::return_self_not_must_use)] #![warn(clippy::deref_addrof)] diff --git a/tests/ui/deref_addrof_macro.rs b/tests/ui/deref_addrof_macro.rs index 57c0be3f51e..c7e60f36506 100644 --- a/tests/ui/deref_addrof_macro.rs +++ b/tests/ui/deref_addrof_macro.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::deref_addrof)] diff --git a/tests/ui/deref_by_slicing.fixed b/tests/ui/deref_by_slicing.fixed index 257393e56ff..f91a425c65d 100644 --- a/tests/ui/deref_by_slicing.fixed +++ b/tests/ui/deref_by_slicing.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::deref_by_slicing)] #![allow(clippy::borrow_deref_ref)] diff --git a/tests/ui/deref_by_slicing.rs b/tests/ui/deref_by_slicing.rs index e288046f927..1bfdd0a981b 100644 --- a/tests/ui/deref_by_slicing.rs +++ b/tests/ui/deref_by_slicing.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::deref_by_slicing)] #![allow(clippy::borrow_deref_ref)] diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed index 89ec33a0d8f..aa0efb85c29 100644 --- a/tests/ui/derivable_impls.fixed +++ b/tests/ui/derivable_impls.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index def6e41162f..8dc999ad586 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] diff --git a/tests/ui/derive_partial_eq_without_eq.fixed b/tests/ui/derive_partial_eq_without_eq.fixed index bbbe467590f..a1f29430c30 100644 --- a/tests/ui/derive_partial_eq_without_eq.fixed +++ b/tests/ui/derive_partial_eq_without_eq.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::derive_partial_eq_without_eq)] diff --git a/tests/ui/derive_partial_eq_without_eq.rs b/tests/ui/derive_partial_eq_without_eq.rs index 88d6fbd1af7..ff4d888559b 100644 --- a/tests/ui/derive_partial_eq_without_eq.rs +++ b/tests/ui/derive_partial_eq_without_eq.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::derive_partial_eq_without_eq)] diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index ecb0bf3644e..d3aa2816cb6 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix //! This file tests for the `DOC_MARKDOWN` lint. #![allow(dead_code, incomplete_features)] diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 11c48dd103d..d1e7d8017d7 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix //! This file tests for the `DOC_MARKDOWN` lint. #![allow(dead_code, incomplete_features)] diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index 30674ce3708..0c8eac5ccff 100644 --- a/tests/ui/doc_unsafe.rs +++ b/tests/ui/doc_unsafe.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![allow(clippy::let_unit_value)] diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index bb6cdaa667d..c80ff671a5d 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix fn main() { let x = 1; diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 9a2a9068a28..bc78694aa68 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix fn main() { let x = 1; diff --git a/tests/ui/duration_subsec.fixed b/tests/ui/duration_subsec.fixed index d92b8998e88..bfd30f0042d 100644 --- a/tests/ui/duration_subsec.fixed +++ b/tests/ui/duration_subsec.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::needless_borrow)] #![warn(clippy::duration_subsec)] diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 08da804996d..860233f084f 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::needless_borrow)] #![warn(clippy::duration_subsec)] diff --git a/tests/ui/empty_drop.fixed b/tests/ui/empty_drop.fixed index 2e1b768461a..fd0a9a7081e 100644 --- a/tests/ui/empty_drop.fixed +++ b/tests/ui/empty_drop.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::empty_drop)] #![allow(unused)] diff --git a/tests/ui/empty_drop.rs b/tests/ui/empty_drop.rs index 75232b0334d..6c15cb93302 100644 --- a/tests/ui/empty_drop.rs +++ b/tests/ui/empty_drop.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::empty_drop)] #![allow(unused)] diff --git a/tests/ui/empty_line_after_outer_attribute.rs b/tests/ui/empty_line_after_outer_attribute.rs index 697412c0027..269e66ea0a8 100644 --- a/tests/ui/empty_line_after_outer_attribute.rs +++ b/tests/ui/empty_line_after_outer_attribute.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_attr.rs +//@aux-build:proc_macro_attr.rs #![warn(clippy::empty_line_after_outer_attr)] #![allow(clippy::assertions_on_constants)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/empty_loop.rs b/tests/ui/empty_loop.rs index 6a8e6b550c1..54e8fb4907c 100644 --- a/tests/ui/empty_loop.rs +++ b/tests/ui/empty_loop.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::empty_loop)] diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs index e742b396fcd..d564b2d24f5 100644 --- a/tests/ui/empty_loop_no_std.rs +++ b/tests/ui/empty_loop_no_std.rs @@ -1,5 +1,5 @@ -// compile-flags: -Clink-arg=-nostartfiles -// ignore-macos +//@compile-flags: -Clink-arg=-nostartfiles +//@ignore-macos #![warn(clippy::empty_loop)] #![feature(lang_items, start, libc)] diff --git a/tests/ui/empty_structs_with_brackets.fixed b/tests/ui/empty_structs_with_brackets.fixed index 80f07603b8d..6fab3020839 100644 --- a/tests/ui/empty_structs_with_brackets.fixed +++ b/tests/ui/empty_structs_with_brackets.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::empty_structs_with_brackets)] #![allow(dead_code)] diff --git a/tests/ui/empty_structs_with_brackets.rs b/tests/ui/empty_structs_with_brackets.rs index 1d1ed4c7690..0caa3c49cd6 100644 --- a/tests/ui/empty_structs_with_brackets.rs +++ b/tests/ui/empty_structs_with_brackets.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::empty_structs_with_brackets)] #![allow(dead_code)] diff --git a/tests/ui/entry.fixed b/tests/ui/entry.fixed index dbe09e0ff3c..7e82390605c 100644 --- a/tests/ui/entry.fixed +++ b/tests/ui/entry.fixed @@ -1,5 +1,5 @@ -// needs-asm-support -// run-rustfix +//@needs-asm-support +//@run-rustfix #![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] #![warn(clippy::map_entry)] diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 30fed34fc5d..742c9322535 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -1,5 +1,5 @@ -// needs-asm-support -// run-rustfix +//@needs-asm-support +//@run-rustfix #![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] #![warn(clippy::map_entry)] diff --git a/tests/ui/entry_btree.fixed b/tests/ui/entry_btree.fixed index 94979104556..3baaacffd20 100644 --- a/tests/ui/entry_btree.fixed +++ b/tests/ui/entry_btree.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_entry)] #![allow(dead_code)] diff --git a/tests/ui/entry_btree.rs b/tests/ui/entry_btree.rs index 080c1d959e8..770e8e91da2 100644 --- a/tests/ui/entry_btree.rs +++ b/tests/ui/entry_btree.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_entry)] #![allow(dead_code)] diff --git a/tests/ui/entry_with_else.fixed b/tests/ui/entry_with_else.fixed index 2332fa6313f..71fe04fd648 100644 --- a/tests/ui/entry_with_else.fixed +++ b/tests/ui/entry_with_else.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] #![warn(clippy::map_entry)] diff --git a/tests/ui/entry_with_else.rs b/tests/ui/entry_with_else.rs index 2ff0c038efe..80f74649a60 100644 --- a/tests/ui/entry_with_else.rs +++ b/tests/ui/entry_with_else.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] #![warn(clippy::map_entry)] diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs index 7d6842f5b54..f17556ea907 100644 --- a/tests/ui/enum_clike_unportable_variant.rs +++ b/tests/ui/enum_clike_unportable_variant.rs @@ -1,4 +1,4 @@ -// ignore-x86 +//@ignore-x86 #![warn(clippy::enum_clike_unportable_variant)] #![allow(unused, non_upper_case_globals)] diff --git a/tests/ui/enum_glob_use.fixed b/tests/ui/enum_glob_use.fixed index a98216758bb..419370ffb1d 100644 --- a/tests/ui/enum_glob_use.fixed +++ b/tests/ui/enum_glob_use.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::enum_glob_use)] #![allow(unused)] diff --git a/tests/ui/enum_glob_use.rs b/tests/ui/enum_glob_use.rs index 5d929c9731d..645ed98325c 100644 --- a/tests/ui/enum_glob_use.rs +++ b/tests/ui/enum_glob_use.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::enum_glob_use)] #![allow(unused)] diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index efed12ee2ef..531652a0e00 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -179,4 +179,14 @@ mod issue9018 { } } +mod allow_attributes_on_variants { + enum Enum { + #[allow(clippy::enum_variant_names)] + EnumStartsWith, + #[allow(clippy::enum_variant_names)] + EndsWithEnum, + Foo, + } +} + fn main() {} diff --git a/tests/ui/eq_op.rs b/tests/ui/eq_op.rs index e7379550265..cdd33ebe582 100644 --- a/tests/ui/eq_op.rs +++ b/tests/ui/eq_op.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![warn(clippy::eq_op)] #![allow(clippy::double_parens, clippy::identity_op, clippy::nonminimal_bool)] diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed index 007702ab550..53e62760bef 100644 --- a/tests/ui/equatable_if_let.fixed +++ b/tests/ui/equatable_if_let.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)] #![warn(clippy::equatable_if_let)] diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs index 3bda7977645..55918a5bb11 100644 --- a/tests/ui/equatable_if_let.rs +++ b/tests/ui/equatable_if_let.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)] #![warn(clippy::equatable_if_let)] diff --git a/tests/ui/err_expect.fixed b/tests/ui/err_expect.fixed index b63cbd8a8e6..6ade6f54689 100644 --- a/tests/ui/err_expect.fixed +++ b/tests/ui/err_expect.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] diff --git a/tests/ui/err_expect.rs b/tests/ui/err_expect.rs index c081a745fb4..a93fb59493f 100644 --- a/tests/ui/err_expect.rs +++ b/tests/ui/err_expect.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index dc129591eac..b1baf462c0f 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)] #![allow(unused)] #![allow( diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 025fd6a0b7a..e113c3d6cd6 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)] #![allow(unused)] #![allow( diff --git a/tests/ui/excessive_precision.fixed b/tests/ui/excessive_precision.fixed index b74bda182be..0a07957386c 100644 --- a/tests/ui/excessive_precision.fixed +++ b/tests/ui/excessive_precision.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::excessive_precision)] #![allow(dead_code, unused_variables, clippy::print_literal)] diff --git a/tests/ui/excessive_precision.rs b/tests/ui/excessive_precision.rs index 6e84a71f24c..62a832caa67 100644 --- a/tests/ui/excessive_precision.rs +++ b/tests/ui/excessive_precision.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::excessive_precision)] #![allow(dead_code, unused_variables, clippy::print_literal)] diff --git a/tests/ui/exhaustive_items.fixed b/tests/ui/exhaustive_items.fixed index c209f5b4b72..6c7b1cab6f2 100644 --- a/tests/ui/exhaustive_items.fixed +++ b/tests/ui/exhaustive_items.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)] #![allow(unused)] diff --git a/tests/ui/exhaustive_items.rs b/tests/ui/exhaustive_items.rs index 6f59dbf2da5..d205bac2d2a 100644 --- a/tests/ui/exhaustive_items.rs +++ b/tests/ui/exhaustive_items.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)] #![allow(unused)] diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed index 15172ae345c..8e97054fb6b 100644 --- a/tests/ui/expect_fun_call.fixed +++ b/tests/ui/expect_fun_call.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::expect_fun_call)] #![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)] diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index 0f448d00417..31e6bcc7ff6 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::expect_fun_call)] #![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)] diff --git a/tests/ui/explicit_auto_deref.fixed b/tests/ui/explicit_auto_deref.fixed index 5d40c850424..71a5ed96d5c 100644 --- a/tests/ui/explicit_auto_deref.fixed +++ b/tests/ui/explicit_auto_deref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(closure_lifetime_binder)] #![warn(clippy::explicit_auto_deref)] diff --git a/tests/ui/explicit_auto_deref.rs b/tests/ui/explicit_auto_deref.rs index 79e03f4d76c..9d0cafa150f 100644 --- a/tests/ui/explicit_auto_deref.rs +++ b/tests/ui/explicit_auto_deref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(closure_lifetime_binder)] #![warn(clippy::explicit_auto_deref)] diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 6d32bbece1e..77e9f5fc1fd 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::explicit_deref_methods)] #![allow(unused_variables)] #![allow( diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index 779909e4238..0c2cc7c2c3a 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::explicit_deref_methods)] #![allow(unused_variables)] #![allow( diff --git a/tests/ui/explicit_write.fixed b/tests/ui/explicit_write.fixed index 862c3fea9ee..213485bc221 100644 --- a/tests/ui/explicit_write.fixed +++ b/tests/ui/explicit_write.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::explicit_write)] #![allow(unused_imports)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/explicit_write.rs b/tests/ui/explicit_write.rs index 41d7c225573..64acd7108bf 100644 --- a/tests/ui/explicit_write.rs +++ b/tests/ui/explicit_write.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::explicit_write)] #![allow(unused_imports)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/extend_with_drain.fixed b/tests/ui/extend_with_drain.fixed index 71ebad24c16..594f2f6d413 100644 --- a/tests/ui/extend_with_drain.fixed +++ b/tests/ui/extend_with_drain.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::extend_with_drain)] #![allow(clippy::iter_with_drain)] use std::collections::BinaryHeap; diff --git a/tests/ui/extend_with_drain.rs b/tests/ui/extend_with_drain.rs index e9f011abb0e..3e2ad02052d 100644 --- a/tests/ui/extend_with_drain.rs +++ b/tests/ui/extend_with_drain.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::extend_with_drain)] #![allow(clippy::iter_with_drain)] use std::collections::BinaryHeap; diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index d6631e01290..cdfaf8d3afe 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs #![allow( unused, diff --git a/tests/ui/extra_unused_type_parameters.fixed b/tests/ui/extra_unused_type_parameters.fixed index 19e71862558..adcd1f6d407 100644 --- a/tests/ui/extra_unused_type_parameters.fixed +++ b/tests/ui/extra_unused_type_parameters.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] diff --git a/tests/ui/extra_unused_type_parameters.rs b/tests/ui/extra_unused_type_parameters.rs index e53bb587e89..c4c5227ac91 100644 --- a/tests/ui/extra_unused_type_parameters.rs +++ b/tests/ui/extra_unused_type_parameters.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::needless_lifetimes)] #![warn(clippy::extra_unused_type_parameters)] diff --git a/tests/ui/field_reassign_with_default.rs b/tests/ui/field_reassign_with_default.rs index 0e208b3ed0e..2045b1eebcd 100644 --- a/tests/ui/field_reassign_with_default.rs +++ b/tests/ui/field_reassign_with_default.rs @@ -1,5 +1,5 @@ -// aux-build:proc_macro_derive.rs -// aux-build:proc_macros.rs +//@aux-build:proc_macro_derive.rs +//@aux-build:proc_macros.rs #![warn(clippy::field_reassign_with_default)] diff --git a/tests/ui/filter_map_identity.fixed b/tests/ui/filter_map_identity.fixed index a5860aa49b3..44665b451ad 100644 --- a/tests/ui/filter_map_identity.fixed +++ b/tests/ui/filter_map_identity.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_imports, clippy::needless_return)] #![warn(clippy::filter_map_identity)] diff --git a/tests/ui/filter_map_identity.rs b/tests/ui/filter_map_identity.rs index 7e998b9cdf7..9832acb013f 100644 --- a/tests/ui/filter_map_identity.rs +++ b/tests/ui/filter_map_identity.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_imports, clippy::needless_return)] #![warn(clippy::filter_map_identity)] diff --git a/tests/ui/filter_map_next_fixable.fixed b/tests/ui/filter_map_next_fixable.fixed index 462d46169fc..efb37f8b1b7 100644 --- a/tests/ui/filter_map_next_fixable.fixed +++ b/tests/ui/filter_map_next_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all, clippy::pedantic)] #![allow(unused)] diff --git a/tests/ui/filter_map_next_fixable.rs b/tests/ui/filter_map_next_fixable.rs index 2ea00cf7307..b10e20d359e 100644 --- a/tests/ui/filter_map_next_fixable.rs +++ b/tests/ui/filter_map_next_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all, clippy::pedantic)] #![allow(unused)] diff --git a/tests/ui/flat_map_identity.fixed b/tests/ui/flat_map_identity.fixed index 1f4b880ef5b..97091d6f1a5 100644 --- a/tests/ui/flat_map_identity.fixed +++ b/tests/ui/flat_map_identity.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_imports, clippy::needless_return)] #![warn(clippy::flat_map_identity)] diff --git a/tests/ui/flat_map_identity.rs b/tests/ui/flat_map_identity.rs index de14a06d4e6..5607683a5d0 100644 --- a/tests/ui/flat_map_identity.rs +++ b/tests/ui/flat_map_identity.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_imports, clippy::needless_return)] #![warn(clippy::flat_map_identity)] diff --git a/tests/ui/flat_map_option.fixed b/tests/ui/flat_map_option.fixed index 6a34f008995..eeab864c42f 100644 --- a/tests/ui/flat_map_option.fixed +++ b/tests/ui/flat_map_option.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::flat_map_option)] #![allow(clippy::redundant_closure, clippy::unnecessary_filter_map)] diff --git a/tests/ui/flat_map_option.rs b/tests/ui/flat_map_option.rs index 2479abddbf0..ebc389f7f02 100644 --- a/tests/ui/flat_map_option.rs +++ b/tests/ui/flat_map_option.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::flat_map_option)] #![allow(clippy::redundant_closure, clippy::unnecessary_filter_map)] diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed index ca747fefc64..0cc572822e7 100644 --- a/tests/ui/floating_point_abs.fixed +++ b/tests/ui/floating_point_abs.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index e4b60657497..6c732d398f0 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/floating_point_exp.fixed b/tests/ui/floating_point_exp.fixed index b9e3d89c2b2..1a33b8153ec 100644 --- a/tests/ui/floating_point_exp.fixed +++ b/tests/ui/floating_point_exp.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::imprecise_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_exp.rs b/tests/ui/floating_point_exp.rs index ef008dd9be0..4f4a5ec81ac 100644 --- a/tests/ui/floating_point_exp.rs +++ b/tests/ui/floating_point_exp.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::imprecise_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_hypot.fixed b/tests/ui/floating_point_hypot.fixed index bbe411b3f48..431cb270978 100644 --- a/tests/ui/floating_point_hypot.fixed +++ b/tests/ui/floating_point_hypot.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::imprecise_flops)] fn main() { diff --git a/tests/ui/floating_point_hypot.rs b/tests/ui/floating_point_hypot.rs index 586fd170ea1..e5506ed391c 100644 --- a/tests/ui/floating_point_hypot.rs +++ b/tests/ui/floating_point_hypot.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::imprecise_flops)] fn main() { diff --git a/tests/ui/floating_point_log.fixed b/tests/ui/floating_point_log.fixed index ee540646160..6582c0a0f6c 100644 --- a/tests/ui/floating_point_log.fixed +++ b/tests/ui/floating_point_log.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::double_parens, clippy::unnecessary_cast)] #![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] diff --git a/tests/ui/floating_point_log.rs b/tests/ui/floating_point_log.rs index 0590670a50b..854d269fff5 100644 --- a/tests/ui/floating_point_log.rs +++ b/tests/ui/floating_point_log.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::double_parens, clippy::unnecessary_cast)] #![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] diff --git a/tests/ui/floating_point_logbase.fixed b/tests/ui/floating_point_logbase.fixed index 7347bf72cbe..0783ecee1ee 100644 --- a/tests/ui/floating_point_logbase.fixed +++ b/tests/ui/floating_point_logbase.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suboptimal_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_logbase.rs b/tests/ui/floating_point_logbase.rs index ba5b8d40692..80fcfab6825 100644 --- a/tests/ui/floating_point_logbase.rs +++ b/tests/ui/floating_point_logbase.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suboptimal_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed index d3e536ba350..8848981a11d 100644 --- a/tests/ui/floating_point_mul_add.fixed +++ b/tests/ui/floating_point_mul_add.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs index 5d4a9e35cfc..b0edf5cb210 100644 --- a/tests/ui/floating_point_mul_add.rs +++ b/tests/ui/floating_point_mul_add.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/floating_point_powf.fixed b/tests/ui/floating_point_powf.fixed index f7f93de2957..1e660b140c5 100644 --- a/tests/ui/floating_point_powf.fixed +++ b/tests/ui/floating_point_powf.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_powf.rs b/tests/ui/floating_point_powf.rs index 499fc0e15e4..71c2f529205 100644 --- a/tests/ui/floating_point_powf.rs +++ b/tests/ui/floating_point_powf.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suboptimal_flops, clippy::imprecise_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_powi.fixed b/tests/ui/floating_point_powi.fixed index 8ffd4cc5137..41d5288d6e0 100644 --- a/tests/ui/floating_point_powi.fixed +++ b/tests/ui/floating_point_powi.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suboptimal_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_powi.rs b/tests/ui/floating_point_powi.rs index 9ae3455a134..7951aab31be 100644 --- a/tests/ui/floating_point_powi.rs +++ b/tests/ui/floating_point_powi.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suboptimal_flops)] #![allow(clippy::unnecessary_cast)] diff --git a/tests/ui/floating_point_rad.fixed b/tests/ui/floating_point_rad.fixed index 27674b8a455..af236452712 100644 --- a/tests/ui/floating_point_rad.fixed +++ b/tests/ui/floating_point_rad.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/floating_point_rad.rs b/tests/ui/floating_point_rad.rs index f1ea73df398..d7612c56a3e 100644 --- a/tests/ui/floating_point_rad.rs +++ b/tests/ui/floating_point_rad.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(const_fn_floating_point_arithmetic)] #![warn(clippy::suboptimal_flops)] diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index a456c085c87..4f6af870889 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,4 +1,4 @@ -// ignore-32bit +//@ignore-32bit #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] diff --git a/tests/ui/fn_to_numeric_cast_32bit.rs b/tests/ui/fn_to_numeric_cast_32bit.rs index 04ee985c086..62ce97f098d 100644 --- a/tests/ui/fn_to_numeric_cast_32bit.rs +++ b/tests/ui/fn_to_numeric_cast_32bit.rs @@ -1,4 +1,4 @@ -// ignore-64bit +//@ignore-64bit #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] diff --git a/tests/ui/fn_to_numeric_cast_32bit.stderr b/tests/ui/fn_to_numeric_cast_32bit.stderr index 08dd611d675..671347d2bcd 100644 --- a/tests/ui/fn_to_numeric_cast_32bit.stderr +++ b/tests/ui/fn_to_numeric_cast_32bit.stderr @@ -12,19 +12,19 @@ error: casting function pointer `foo` to `i16`, which truncates the value LL | let _ = foo as i16; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `i32` +error: casting function pointer `foo` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast_32bit.rs:12:13 | LL | let _ = foo as i32; | ^^^^^^^^^^ help: try: `foo as usize` - | - = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` error: casting function pointer `foo` to `i64` --> $DIR/fn_to_numeric_cast_32bit.rs:13:13 | LL | let _ = foo as i64; | ^^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` error: casting function pointer `foo` to `i128` --> $DIR/fn_to_numeric_cast_32bit.rs:14:13 @@ -50,7 +50,7 @@ error: casting function pointer `foo` to `u16`, which truncates the value LL | let _ = foo as u16; | ^^^^^^^^^^ help: try: `foo as usize` -error: casting function pointer `foo` to `u32` +error: casting function pointer `foo` to `u32`, which truncates the value --> $DIR/fn_to_numeric_cast_32bit.rs:19:13 | LL | let _ = foo as u32; @@ -80,7 +80,7 @@ error: casting function pointer `abc` to `i16`, which truncates the value LL | let _ = abc as i16; | ^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `i32` +error: casting function pointer `abc` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast_32bit.rs:36:13 | LL | let _ = abc as i32; @@ -116,7 +116,7 @@ error: casting function pointer `abc` to `u16`, which truncates the value LL | let _ = abc as u16; | ^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `abc` to `u32` +error: casting function pointer `abc` to `u32`, which truncates the value --> $DIR/fn_to_numeric_cast_32bit.rs:43:13 | LL | let _ = abc as u32; @@ -134,7 +134,7 @@ error: casting function pointer `abc` to `u128` LL | let _ = abc as u128; | ^^^^^^^^^^^ help: try: `abc as usize` -error: casting function pointer `f` to `i32` +error: casting function pointer `f` to `i32`, which truncates the value --> $DIR/fn_to_numeric_cast_32bit.rs:52:5 | LL | f as i32 diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index e9dd38fe40e..f578c98da15 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 534fb4dd4ef..42bc6de0c7d 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index beedf2c1db2..9288956f513 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::useless_format)] #![allow( unused_tuple_struct_fields, diff --git a/tests/ui/format.rs b/tests/ui/format.rs index e805f181889..b2b817e0f4c 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::useless_format)] #![allow( unused_tuple_struct_fields, diff --git a/tests/ui/format_args.fixed b/tests/ui/format_args.fixed index 825e122be5a..ea383686135 100644 --- a/tests/ui/format_args.fixed +++ b/tests/ui/format_args.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::to_string_in_format_args)] #![allow(unused)] #![allow( diff --git a/tests/ui/format_args.rs b/tests/ui/format_args.rs index a41e53389e5..bfb32449246 100644 --- a/tests/ui/format_args.rs +++ b/tests/ui/format_args.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::to_string_in_format_args)] #![allow(unused)] #![allow( diff --git a/tests/ui/from_iter_instead_of_collect.fixed b/tests/ui/from_iter_instead_of_collect.fixed index 48f8093311c..915ff4fb079 100644 --- a/tests/ui/from_iter_instead_of_collect.fixed +++ b/tests/ui/from_iter_instead_of_collect.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::from_iter_instead_of_collect)] #![allow(unused_imports, unused_tuple_struct_fields)] diff --git a/tests/ui/from_iter_instead_of_collect.rs b/tests/ui/from_iter_instead_of_collect.rs index ebe0ad278be..e926f8c529d 100644 --- a/tests/ui/from_iter_instead_of_collect.rs +++ b/tests/ui/from_iter_instead_of_collect.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::from_iter_instead_of_collect)] #![allow(unused_imports, unused_tuple_struct_fields)] diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index 72d635c2ccd..fc6d937060d 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(type_alias_impl_trait)] #![warn(clippy::from_over_into)] diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index 965f4d5d785..fe1ebee35f1 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(type_alias_impl_trait)] #![warn(clippy::from_over_into)] diff --git a/tests/ui/get_first.fixed b/tests/ui/get_first.fixed index def58afa4fb..ef132b79611 100644 --- a/tests/ui/get_first.fixed +++ b/tests/ui/get_first.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::get_first)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/get_first.rs b/tests/ui/get_first.rs index 85a381854cd..4d872235614 100644 --- a/tests/ui/get_first.rs +++ b/tests/ui/get_first.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::get_first)] use std::collections::BTreeMap; use std::collections::HashMap; diff --git a/tests/ui/get_last_with_len.fixed b/tests/ui/get_last_with_len.fixed index 1e90b37687a..a58dfda7988 100644 --- a/tests/ui/get_last_with_len.fixed +++ b/tests/ui/get_last_with_len.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::get_last_with_len)] #![allow(unused)] diff --git a/tests/ui/get_last_with_len.rs b/tests/ui/get_last_with_len.rs index d63a731bd52..d626656c78f 100644 --- a/tests/ui/get_last_with_len.rs +++ b/tests/ui/get_last_with_len.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::get_last_with_len)] #![allow(unused)] diff --git a/tests/ui/get_unwrap.fixed b/tests/ui/get_unwrap.fixed index 5827fc7d76e..4950c47ddeb 100644 --- a/tests/ui/get_unwrap.fixed +++ b/tests/ui/get_unwrap.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)] #![warn(clippy::unwrap_used)] diff --git a/tests/ui/get_unwrap.rs b/tests/ui/get_unwrap.rs index a2a323c14fb..6b1e8edb7bd 100644 --- a/tests/ui/get_unwrap.rs +++ b/tests/ui/get_unwrap.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_mut, clippy::from_iter_instead_of_collect, clippy::get_first)] #![warn(clippy::unwrap_used)] diff --git a/tests/ui/identity_op.fixed b/tests/ui/identity_op.fixed index cac69ef42c4..beb16000eca 100644 --- a/tests/ui/identity_op.fixed +++ b/tests/ui/identity_op.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::identity_op)] #![allow(unused)] #![allow( diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index 33201aad4f6..072e00c00f0 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::identity_op)] #![allow(unused)] #![allow( diff --git a/tests/ui/implicit_clone.fixed b/tests/ui/implicit_clone.fixed index 8ccc3da7b47..e62db8b40be 100644 --- a/tests/ui/implicit_clone.fixed +++ b/tests/ui/implicit_clone.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::implicit_clone)] #![allow(clippy::clone_on_copy, clippy::redundant_clone)] use std::borrow::Borrow; diff --git a/tests/ui/implicit_clone.rs b/tests/ui/implicit_clone.rs index 59333312607..88352b06af3 100644 --- a/tests/ui/implicit_clone.rs +++ b/tests/ui/implicit_clone.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::implicit_clone)] #![allow(clippy::clone_on_copy, clippy::redundant_clone)] use std::borrow::Borrow; diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index 35d08a07bc3..ca7c1221372 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![deny(clippy::implicit_hasher)] #![allow(unused)] diff --git a/tests/ui/implicit_return.fixed b/tests/ui/implicit_return.fixed index 5e55b8b6739..64813eafda6 100644 --- a/tests/ui/implicit_return.fixed +++ b/tests/ui/implicit_return.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![warn(clippy::implicit_return)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index 76f0a980352..39d47b110db 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![warn(clippy::implicit_return)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] diff --git a/tests/ui/implicit_saturating_add.fixed b/tests/ui/implicit_saturating_add.fixed index 7d363d59a6f..7fc510d6b41 100644 --- a/tests/ui/implicit_saturating_add.fixed +++ b/tests/ui/implicit_saturating_add.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::implicit_saturating_add)] diff --git a/tests/ui/implicit_saturating_add.rs b/tests/ui/implicit_saturating_add.rs index 31a5916277f..3dcd91f42fe 100644 --- a/tests/ui/implicit_saturating_add.rs +++ b/tests/ui/implicit_saturating_add.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::implicit_saturating_add)] diff --git a/tests/ui/implicit_saturating_sub.fixed b/tests/ui/implicit_saturating_sub.fixed index 93df81b1a7f..1a11db0982f 100644 --- a/tests/ui/implicit_saturating_sub.fixed +++ b/tests/ui/implicit_saturating_sub.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_assignments, unused_mut, clippy::assign_op_pattern)] #![warn(clippy::implicit_saturating_sub)] diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs index 8340bc8264d..9369df67430 100644 --- a/tests/ui/implicit_saturating_sub.rs +++ b/tests/ui/implicit_saturating_sub.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_assignments, unused_mut, clippy::assign_op_pattern)] #![warn(clippy::implicit_saturating_sub)] diff --git a/tests/ui/inconsistent_digit_grouping.fixed b/tests/ui/inconsistent_digit_grouping.fixed index dd683e7f746..06919809ee9 100644 --- a/tests/ui/inconsistent_digit_grouping.fixed +++ b/tests/ui/inconsistent_digit_grouping.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[warn(clippy::inconsistent_digit_grouping)] #[deny(clippy::unreadable_literal)] #[allow(unused_variables, clippy::excessive_precision)] diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index d5d27c853c2..04d9125f2bf 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[warn(clippy::inconsistent_digit_grouping)] #[deny(clippy::unreadable_literal)] #[allow(unused_variables, clippy::excessive_precision)] diff --git a/tests/ui/inconsistent_struct_constructor.fixed b/tests/ui/inconsistent_struct_constructor.fixed index 5aaa00f8517..620d45e6828 100644 --- a/tests/ui/inconsistent_struct_constructor.fixed +++ b/tests/ui/inconsistent_struct_constructor.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] diff --git a/tests/ui/inconsistent_struct_constructor.rs b/tests/ui/inconsistent_struct_constructor.rs index 2b2dd7f59a4..10ffadcb2ba 100644 --- a/tests/ui/inconsistent_struct_constructor.rs +++ b/tests/ui/inconsistent_struct_constructor.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::inconsistent_struct_constructor)] #![allow(clippy::redundant_field_names)] diff --git a/tests/ui/inefficient_to_string.fixed b/tests/ui/inefficient_to_string.fixed index c972b9419ef..557f7fb7358 100644 --- a/tests/ui/inefficient_to_string.fixed +++ b/tests/ui/inefficient_to_string.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::inefficient_to_string)] use std::borrow::Cow; diff --git a/tests/ui/inefficient_to_string.rs b/tests/ui/inefficient_to_string.rs index acdc55aa0d6..6503001e345 100644 --- a/tests/ui/inefficient_to_string.rs +++ b/tests/ui/inefficient_to_string.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::inefficient_to_string)] use std::borrow::Cow; diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed index 61985e56b76..e396ae94aaa 100644 --- a/tests/ui/infallible_destructuring_match.fixed +++ b/tests/ui/infallible_destructuring_match.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(exhaustive_patterns, never_type)] #![allow(dead_code, unreachable_code, unused_variables)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index f2768245bbc..3fce7bbb6c7 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(exhaustive_patterns, never_type)] #![allow(dead_code, unreachable_code, unused_variables)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/inline_fn_without_body.fixed b/tests/ui/inline_fn_without_body.fixed index fe21a71a42c..9c5819558fe 100644 --- a/tests/ui/inline_fn_without_body.fixed +++ b/tests/ui/inline_fn_without_body.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::inline_fn_without_body)] #![allow(clippy::inline_always)] diff --git a/tests/ui/inline_fn_without_body.rs b/tests/ui/inline_fn_without_body.rs index 50746989466..43ffaf8122b 100644 --- a/tests/ui/inline_fn_without_body.rs +++ b/tests/ui/inline_fn_without_body.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::inline_fn_without_body)] #![allow(clippy::inline_always)] diff --git a/tests/ui/int_plus_one.fixed b/tests/ui/int_plus_one.fixed index 642830f24f5..5a36ec462d4 100644 --- a/tests/ui/int_plus_one.fixed +++ b/tests/ui/int_plus_one.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[allow(clippy::no_effect, clippy::unnecessary_operation)] #[warn(clippy::int_plus_one)] diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index 0755a0c79d2..bffa4afd6b0 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[allow(clippy::no_effect, clippy::unnecessary_operation)] #[warn(clippy::int_plus_one)] diff --git a/tests/ui/integer_arithmetic.rs b/tests/ui/integer_arithmetic.rs index 8dfdee662b9..ab9b6094c2c 100644 --- a/tests/ui/integer_arithmetic.rs +++ b/tests/ui/integer_arithmetic.rs @@ -1,6 +1,13 @@ +//@aux-build:proc_macro_derive.rs + #![warn(clippy::integer_arithmetic, clippy::float_arithmetic)] #![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::op_ref)] +extern crate proc_macro_derive; + +#[derive(proc_macro_derive::ShadowDerive)] +pub struct Nothing; + #[rustfmt::skip] fn main() { let mut i = 1i32; diff --git a/tests/ui/integer_arithmetic.stderr b/tests/ui/integer_arithmetic.stderr index 9a795b1f291..add3b6b90fa 100644 --- a/tests/ui/integer_arithmetic.stderr +++ b/tests/ui/integer_arithmetic.stderr @@ -1,5 +1,5 @@ error: this operation will panic at runtime - --> $DIR/integer_arithmetic.rs:30:5 + --> $DIR/integer_arithmetic.rs:37:5 | LL | i /= 0; | ^^^^^^ attempt to divide `_` by zero @@ -7,13 +7,13 @@ LL | i /= 0; = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime - --> $DIR/integer_arithmetic.rs:35:5 + --> $DIR/integer_arithmetic.rs:42:5 | LL | i %= 0; | ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:9:5 + --> $DIR/integer_arithmetic.rs:16:5 | LL | 1 + i; | ^^^^^ @@ -21,146 +21,146 @@ LL | 1 + i; = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:10:5 + --> $DIR/integer_arithmetic.rs:17:5 | LL | i * 2; | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:11:5 + --> $DIR/integer_arithmetic.rs:18:5 | LL | / 1 % LL | | i / 2; // no error, this is part of the expression in the preceding line | |_____^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:13:5 + --> $DIR/integer_arithmetic.rs:20:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:14:5 + --> $DIR/integer_arithmetic.rs:21:5 | LL | -i; | ^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:15:5 + --> $DIR/integer_arithmetic.rs:22:5 | LL | i >> 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:16:5 + --> $DIR/integer_arithmetic.rs:23:5 | LL | i << 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:26:5 + --> $DIR/integer_arithmetic.rs:33:5 | LL | i += 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:27:5 + --> $DIR/integer_arithmetic.rs:34:5 | LL | i -= 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:28:5 + --> $DIR/integer_arithmetic.rs:35:5 | LL | i *= 2; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:31:11 + --> $DIR/integer_arithmetic.rs:38:11 | LL | i /= -1; | ^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:32:5 + --> $DIR/integer_arithmetic.rs:39:5 | LL | i /= var1; | ^^^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:33:5 + --> $DIR/integer_arithmetic.rs:40:5 | LL | i /= var2; | ^^^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:36:11 + --> $DIR/integer_arithmetic.rs:43:11 | LL | i %= -1; | ^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:37:5 + --> $DIR/integer_arithmetic.rs:44:5 | LL | i %= var1; | ^^^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:38:5 + --> $DIR/integer_arithmetic.rs:45:5 | LL | i %= var2; | ^^^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:39:5 + --> $DIR/integer_arithmetic.rs:46:5 | LL | i <<= 3; | ^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:40:5 + --> $DIR/integer_arithmetic.rs:47:5 | LL | i >>= 2; | ^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:82:5 + --> $DIR/integer_arithmetic.rs:89:5 | LL | 3 + &1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:83:5 + --> $DIR/integer_arithmetic.rs:90:5 | LL | &3 + 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:84:5 + --> $DIR/integer_arithmetic.rs:91:5 | LL | &3 + &1; | ^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:89:5 + --> $DIR/integer_arithmetic.rs:96:5 | LL | a + x | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:93:5 + --> $DIR/integer_arithmetic.rs:100:5 | LL | x + y | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:97:5 + --> $DIR/integer_arithmetic.rs:104:5 | LL | x + y | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:101:5 + --> $DIR/integer_arithmetic.rs:108:5 | LL | (&x + &y) | ^^^^^^^^^ diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index b77f17944d8..9f550acb157 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::useless_vec, clippy::needless_borrow)] #![warn(clippy::into_iter_on_ref)] diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 3854bb05af8..3381ae04dce 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::useless_vec, clippy::needless_borrow)] #![warn(clippy::into_iter_on_ref)] diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed index 4f5322ebf20..9264fb7e9e7 100644 --- a/tests/ui/invalid_null_ptr_usage.fixed +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix fn main() { unsafe { diff --git a/tests/ui/invalid_null_ptr_usage.rs b/tests/ui/invalid_null_ptr_usage.rs index ae51c52d8af..80c942d7757 100644 --- a/tests/ui/invalid_null_ptr_usage.rs +++ b/tests/ui/invalid_null_ptr_usage.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix fn main() { unsafe { diff --git a/tests/ui/is_digit_ascii_radix.fixed b/tests/ui/is_digit_ascii_radix.fixed index c0ba647d707..bc43303a680 100644 --- a/tests/ui/is_digit_ascii_radix.fixed +++ b/tests/ui/is_digit_ascii_radix.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::is_digit_ascii_radix)] diff --git a/tests/ui/is_digit_ascii_radix.rs b/tests/ui/is_digit_ascii_radix.rs index 68e3f3243d9..93cba5c8e4e 100644 --- a/tests/ui/is_digit_ascii_radix.rs +++ b/tests/ui/is_digit_ascii_radix.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::is_digit_ascii_radix)] diff --git a/tests/ui/issue_2356.fixed b/tests/ui/issue_2356.fixed index a73ee0fb2e5..a69f5ebdc08 100644 --- a/tests/ui/issue_2356.fixed +++ b/tests/ui/issue_2356.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::while_let_on_iterator)] #![allow(unused_mut)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/issue_2356.rs b/tests/ui/issue_2356.rs index 9dd9069609b..50e1bce1f8c 100644 --- a/tests/ui/issue_2356.rs +++ b/tests/ui/issue_2356.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::while_let_on_iterator)] #![allow(unused_mut)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/items_after_test_module.rs b/tests/ui/items_after_test_module.rs new file mode 100644 index 00000000000..5136b2557ec --- /dev/null +++ b/tests/ui/items_after_test_module.rs @@ -0,0 +1,23 @@ +//@compile-flags: --test +#![allow(unused)] +#![warn(clippy::items_after_test_module)] + +fn main() {} + +fn should_not_lint() {} + +#[allow(dead_code)] +#[allow(unused)] // Some attributes to check that span replacement is good enough +#[allow(clippy::allow_attributes)] +#[cfg(test)] +mod tests { + #[test] + fn hi() {} +} + +fn should_lint() {} + +const SHOULD_ALSO_LINT: usize = 1; +macro_rules! should_not_lint { + () => {}; +} diff --git a/tests/ui/items_after_test_module.stderr b/tests/ui/items_after_test_module.stderr new file mode 100644 index 00000000000..8f1616dabc1 --- /dev/null +++ b/tests/ui/items_after_test_module.stderr @@ -0,0 +1,17 @@ +error: items were found after the testing module + --> $DIR/items_after_test_module.rs:13:1 + | +LL | / mod tests { +LL | | #[test] +LL | | fn hi() {} +LL | | } +... | +LL | | () => {}; +LL | | } + | |_^ + | + = help: move the items to before the testing module was defined + = note: `-D clippy::items-after-test-module` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed index 9b862133580..88f08bb991b 100644 --- a/tests/ui/iter_cloned_collect.fixed +++ b/tests/ui/iter_cloned_collect.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs index 639f50665f2..d3438b7f51a 100644 --- a/tests/ui/iter_cloned_collect.rs +++ b/tests/ui/iter_cloned_collect.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] diff --git a/tests/ui/iter_count.fixed b/tests/ui/iter_count.fixed index 90a6eef7526..4367a12f820 100644 --- a/tests/ui/iter_count.fixed +++ b/tests/ui/iter_count.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:option_helpers.rs +//@run-rustfix +//@aux-build:option_helpers.rs #![warn(clippy::iter_count)] #![allow( diff --git a/tests/ui/iter_count.rs b/tests/ui/iter_count.rs index 6681a480a28..8c7543cf03b 100644 --- a/tests/ui/iter_count.rs +++ b/tests/ui/iter_count.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:option_helpers.rs +//@run-rustfix +//@aux-build:option_helpers.rs #![warn(clippy::iter_count)] #![allow( diff --git a/tests/ui/iter_kv_map.fixed b/tests/ui/iter_kv_map.fixed index f2a4c284cb1..64201b553fd 100644 --- a/tests/ui/iter_kv_map.fixed +++ b/tests/ui/iter_kv_map.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_kv_map)] #![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)] diff --git a/tests/ui/iter_kv_map.rs b/tests/ui/iter_kv_map.rs index ad6564df408..ec0231ba572 100644 --- a/tests/ui/iter_kv_map.rs +++ b/tests/ui/iter_kv_map.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_kv_map)] #![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)] diff --git a/tests/ui/iter_next_slice.fixed b/tests/ui/iter_next_slice.fixed index f612d26aaab..d862abc34e0 100644 --- a/tests/ui/iter_next_slice.fixed +++ b/tests/ui/iter_next_slice.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_next_slice)] fn main() { diff --git a/tests/ui/iter_next_slice.rs b/tests/ui/iter_next_slice.rs index 5195f1c8667..da6fc46e428 100644 --- a/tests/ui/iter_next_slice.rs +++ b/tests/ui/iter_next_slice.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_next_slice)] fn main() { diff --git a/tests/ui/iter_nth.rs b/tests/ui/iter_nth.rs index 9c21dd82ee4..e7fb97d4fbc 100644 --- a/tests/ui/iter_nth.rs +++ b/tests/ui/iter_nth.rs @@ -1,4 +1,4 @@ -// aux-build:option_helpers.rs +//@aux-build:option_helpers.rs #![warn(clippy::iter_nth)] diff --git a/tests/ui/iter_nth_zero.fixed b/tests/ui/iter_nth_zero.fixed index f23671c26e4..587b0d1d366 100644 --- a/tests/ui/iter_nth_zero.fixed +++ b/tests/ui/iter_nth_zero.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_nth_zero)] use std::collections::HashSet; diff --git a/tests/ui/iter_nth_zero.rs b/tests/ui/iter_nth_zero.rs index 7c968d49845..93b576ec56f 100644 --- a/tests/ui/iter_nth_zero.rs +++ b/tests/ui/iter_nth_zero.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_nth_zero)] use std::collections::HashSet; diff --git a/tests/ui/iter_on_empty_collections.fixed b/tests/ui/iter_on_empty_collections.fixed index bd9b07aefbf..4616f0cdc45 100644 --- a/tests/ui/iter_on_empty_collections.fixed +++ b/tests/ui/iter_on_empty_collections.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_on_empty_collections)] #![allow(clippy::iter_next_slice, clippy::redundant_clone)] diff --git a/tests/ui/iter_on_empty_collections.rs b/tests/ui/iter_on_empty_collections.rs index e15ba94bd46..81cc7265e11 100644 --- a/tests/ui/iter_on_empty_collections.rs +++ b/tests/ui/iter_on_empty_collections.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_on_empty_collections)] #![allow(clippy::iter_next_slice, clippy::redundant_clone)] diff --git a/tests/ui/iter_on_single_items.fixed b/tests/ui/iter_on_single_items.fixed index 1fa4b03641b..80dbe454b47 100644 --- a/tests/ui/iter_on_single_items.fixed +++ b/tests/ui/iter_on_single_items.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_on_single_items)] #![allow(clippy::iter_next_slice, clippy::redundant_clone)] diff --git a/tests/ui/iter_on_single_items.rs b/tests/ui/iter_on_single_items.rs index ea96d8066c5..71c8c7a3f94 100644 --- a/tests/ui/iter_on_single_items.rs +++ b/tests/ui/iter_on_single_items.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_on_single_items)] #![allow(clippy::iter_next_slice, clippy::redundant_clone)] diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed index c100705d017..bf576e9cbfb 100644 --- a/tests/ui/iter_overeager_cloned.fixed +++ b/tests/ui/iter_overeager_cloned.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] #![allow(dead_code, clippy::let_unit_value)] diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs index 2caa8802066..df42d88eff0 100644 --- a/tests/ui/iter_overeager_cloned.rs +++ b/tests/ui/iter_overeager_cloned.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)] #![allow(dead_code, clippy::let_unit_value)] diff --git a/tests/ui/iter_skip_next.fixed b/tests/ui/iter_skip_next.fixed index d56d623b526..8f2cefc4304 100644 --- a/tests/ui/iter_skip_next.fixed +++ b/tests/ui/iter_skip_next.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:option_helpers.rs +//@run-rustfix +//@aux-build:option_helpers.rs #![warn(clippy::iter_skip_next)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 3ec5d1b8214..71d83384f3a 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:option_helpers.rs +//@run-rustfix +//@aux-build:option_helpers.rs #![warn(clippy::iter_skip_next)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/iter_with_drain.fixed b/tests/ui/iter_with_drain.fixed index 0330d554926..24a95c4d0fe 100644 --- a/tests/ui/iter_with_drain.fixed +++ b/tests/ui/iter_with_drain.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // will emits unused mut warnings after fixing #![allow(unused_mut)] // will emits needless collect warnings after fixing diff --git a/tests/ui/iter_with_drain.rs b/tests/ui/iter_with_drain.rs index 993936fb8de..a118c981ee3 100644 --- a/tests/ui/iter_with_drain.rs +++ b/tests/ui/iter_with_drain.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // will emits unused mut warnings after fixing #![allow(unused_mut)] // will emits needless collect warnings after fixing diff --git a/tests/ui/large_const_arrays.fixed b/tests/ui/large_const_arrays.fixed index c5af07c8a17..f7ce6fbe6bb 100644 --- a/tests/ui/large_const_arrays.fixed +++ b/tests/ui/large_const_arrays.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::large_const_arrays)] #![allow(dead_code)] diff --git a/tests/ui/large_const_arrays.rs b/tests/ui/large_const_arrays.rs index a160b9f8ad5..002ac77ddda 100644 --- a/tests/ui/large_const_arrays.rs +++ b/tests/ui/large_const_arrays.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::large_const_arrays)] #![allow(dead_code)] diff --git a/tests/ui/large_digit_groups.fixed b/tests/ui/large_digit_groups.fixed index ea18dac0683..f42fcd96d79 100644 --- a/tests/ui/large_digit_groups.fixed +++ b/tests/ui/large_digit_groups.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::large_digit_groups)] fn main() { diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index ac116d5dbda..3db9da6a3a5 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::large_digit_groups)] fn main() { diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index f09f8ae0ccc..ea8bc5b4aca 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![allow(dead_code)] #![allow(unused_variables)] diff --git a/tests/ui/large_types_passed_by_value.rs b/tests/ui/large_types_passed_by_value.rs index 7601b5c66fa..f9e3c7192ad 100644 --- a/tests/ui/large_types_passed_by_value.rs +++ b/tests/ui/large_types_passed_by_value.rs @@ -1,5 +1,5 @@ -// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)" -// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)" +//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)" +//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)" #![warn(clippy::large_types_passed_by_value)] diff --git a/tests/ui/len_zero.fixed b/tests/ui/len_zero.fixed index c1c0b5ae40f..2c22abd7e4b 100644 --- a/tests/ui/len_zero.fixed +++ b/tests/ui/len_zero.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::len_zero)] #![allow(dead_code, unused, clippy::len_without_is_empty)] @@ -176,6 +176,10 @@ fn main() { // No error; `HasWrongIsEmpty` does not have `.is_empty()`. println!("Or this!"); } + + // issue #10529 + (!has_is_empty.is_empty()).then(|| println!("This can happen.")); + (has_is_empty.is_empty()).then(|| println!("Or this!")); } fn test_slice(b: &[u8]) { diff --git a/tests/ui/len_zero.rs b/tests/ui/len_zero.rs index cc2eb05b6bf..a011ff97644 100644 --- a/tests/ui/len_zero.rs +++ b/tests/ui/len_zero.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::len_zero)] #![allow(dead_code, unused, clippy::len_without_is_empty)] @@ -176,6 +176,10 @@ fn main() { // No error; `HasWrongIsEmpty` does not have `.is_empty()`. println!("Or this!"); } + + // issue #10529 + (has_is_empty.len() > 0).then(|| println!("This can happen.")); + (has_is_empty.len() == 0).then(|| println!("Or this!")); } fn test_slice(b: &[u8]) { diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index b6f13780253..396cfb75fb6 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -123,10 +123,22 @@ LL | if with_is_empty.len() == 0 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()` error: length comparison to zero - --> $DIR/len_zero.rs:182:8 + --> $DIR/len_zero.rs:181:6 + | +LL | (has_is_empty.len() > 0).then(|| println!("This can happen.")); + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + +error: length comparison to zero + --> $DIR/len_zero.rs:182:6 + | +LL | (has_is_empty.len() == 0).then(|| println!("Or this!")); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()` + +error: length comparison to zero + --> $DIR/len_zero.rs:186:8 | LL | if b.len() != 0 {} | ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()` -error: aborting due to 21 previous errors +error: aborting due to 23 previous errors diff --git a/tests/ui/len_zero_ranges.fixed b/tests/ui/len_zero_ranges.fixed index 79781766242..4b1241ec86b 100644 --- a/tests/ui/len_zero_ranges.fixed +++ b/tests/ui/len_zero_ranges.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::len_zero)] #![allow(unused)] diff --git a/tests/ui/len_zero_ranges.rs b/tests/ui/len_zero_ranges.rs index a0eb51cc976..4b47132c766 100644 --- a/tests/ui/len_zero_ranges.rs +++ b/tests/ui/len_zero_ranges.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::len_zero)] #![allow(unused)] diff --git a/tests/ui/let_underscore_untyped.rs b/tests/ui/let_underscore_untyped.rs index bcb33c5c7e3..8486137d3a6 100644 --- a/tests/ui/let_underscore_untyped.rs +++ b/tests/ui/let_underscore_untyped.rs @@ -28,6 +28,10 @@ fn f() -> Box { Box::new(1) } +fn g() -> impl Fn() { + || {} +} + fn main() { let _ = a(); let _ = b(1); @@ -35,6 +39,7 @@ fn main() { let _ = d(&1); let _ = e(); let _ = f(); + let _ = g(); _ = a(); _ = b(1); diff --git a/tests/ui/let_underscore_untyped.stderr b/tests/ui/let_underscore_untyped.stderr index 36c3d1214d6..47e76ea1d04 100644 --- a/tests/ui/let_underscore_untyped.stderr +++ b/tests/ui/let_underscore_untyped.stderr @@ -1,5 +1,5 @@ error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:32:5 + --> $DIR/let_underscore_untyped.rs:36:5 | LL | let _ = a(); | ^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = a(); = note: `-D clippy::let-underscore-untyped` implied by `-D warnings` error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:33:5 + --> $DIR/let_underscore_untyped.rs:37:5 | LL | let _ = b(1); | ^^^^^^^^^^^^^ @@ -16,15 +16,7 @@ LL | let _ = b(1); = help: consider adding a type annotation or removing the `let` keyword error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:34:5 - | -LL | let _ = c(); - | ^^^^^^^^^^^^ - | - = help: consider adding a type annotation or removing the `let` keyword - -error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:35:5 + --> $DIR/let_underscore_untyped.rs:39:5 | LL | let _ = d(&1); | ^^^^^^^^^^^^^^ @@ -32,7 +24,7 @@ LL | let _ = d(&1); = help: consider adding a type annotation or removing the `let` keyword error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:36:5 + --> $DIR/let_underscore_untyped.rs:40:5 | LL | let _ = e(); | ^^^^^^^^^^^^ @@ -40,12 +32,12 @@ LL | let _ = e(); = help: consider adding a type annotation or removing the `let` keyword error: non-binding `let` without a type annotation - --> $DIR/let_underscore_untyped.rs:37:5 + --> $DIR/let_underscore_untyped.rs:41:5 | LL | let _ = f(); | ^^^^^^^^^^^^ | = help: consider adding a type annotation or removing the `let` keyword -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed index 76ff0645f41..8ba89ec78bb 100644 --- a/tests/ui/let_unit.fixed +++ b/tests/ui/let_unit.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![warn(clippy::let_unit_value)] diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 895ccfe366a..7e8764a482a 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![warn(clippy::let_unit_value)] diff --git a/tests/ui/lines_filter_map_ok.fixed b/tests/ui/lines_filter_map_ok.fixed index f4033cd8ed8..64114f6585d 100644 --- a/tests/ui/lines_filter_map_ok.fixed +++ b/tests/ui/lines_filter_map_ok.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::map_identity)] #![warn(clippy::lines_filter_map_ok)] diff --git a/tests/ui/lines_filter_map_ok.rs b/tests/ui/lines_filter_map_ok.rs index 7e11816b2ac..5aedc686336 100644 --- a/tests/ui/lines_filter_map_ok.rs +++ b/tests/ui/lines_filter_map_ok.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::map_identity)] #![warn(clippy::lines_filter_map_ok)] diff --git a/tests/ui/lossy_float_literal.fixed b/tests/ui/lossy_float_literal.fixed index 24e372354fc..a2088575610 100644 --- a/tests/ui/lossy_float_literal.fixed +++ b/tests/ui/lossy_float_literal.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::lossy_float_literal)] fn main() { diff --git a/tests/ui/lossy_float_literal.rs b/tests/ui/lossy_float_literal.rs index 3dcf98fa0bd..1a75f214c85 100644 --- a/tests/ui/lossy_float_literal.rs +++ b/tests/ui/lossy_float_literal.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::lossy_float_literal)] fn main() { diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index a395e4f5653..b4dabe3cae5 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -1,8 +1,8 @@ -// aux-build:macro_rules.rs -// aux-build:macro_use_helper.rs -// aux-build:proc_macro_derive.rs -// run-rustfix -// ignore-32bit +//@aux-build:macro_rules.rs +//@aux-build:macro_use_helper.rs +//@aux-build:proc_macro_derive.rs +//@run-rustfix +//@ignore-32bit #![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index b1a28733294..925a2c61f8d 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -1,8 +1,8 @@ -// aux-build:macro_rules.rs -// aux-build:macro_use_helper.rs -// aux-build:proc_macro_derive.rs -// run-rustfix -// ignore-32bit +//@aux-build:macro_rules.rs +//@aux-build:macro_use_helper.rs +//@aux-build:proc_macro_derive.rs +//@run-rustfix +//@ignore-32bit #![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs index 5aac5af26db..b9677851b92 100644 --- a/tests/ui/macro_use_imports_expect.rs +++ b/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 +//@aux-build:macro_rules.rs +//@aux-build:macro_use_helper.rs +//@aux-build:proc_macro_derive.rs +//@ignore-32bit #![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] diff --git a/tests/ui/manual_assert.edition2018.fixed b/tests/ui/manual_assert.edition2018.fixed index 8c7e919bf62..ab9b375dc03 100644 --- a/tests/ui/manual_assert.edition2018.fixed +++ b/tests/ui/manual_assert.edition2018.fixed @@ -1,7 +1,7 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] diff --git a/tests/ui/manual_assert.edition2021.fixed b/tests/ui/manual_assert.edition2021.fixed index 8c7e919bf62..ab9b375dc03 100644 --- a/tests/ui/manual_assert.edition2021.fixed +++ b/tests/ui/manual_assert.edition2021.fixed @@ -1,7 +1,7 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index f037c5b8405..eac52d1b5de 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -1,7 +1,7 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix #![warn(clippy::manual_assert)] #![allow(dead_code, unused_doc_comments)] diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index 5cc4a43af7e..e458f0d254f 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_async_fn)] #![allow(unused)] diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index ba504b8a823..dd5ca1c9b5b 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_async_fn)] #![allow(unused)] diff --git a/tests/ui/manual_bits.fixed b/tests/ui/manual_bits.fixed index e7f8cd878ca..037de0262e2 100644 --- a/tests/ui/manual_bits.fixed +++ b/tests/ui/manual_bits.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_bits)] #![allow( diff --git a/tests/ui/manual_bits.rs b/tests/ui/manual_bits.rs index 7b1d1549528..b15a531ec17 100644 --- a/tests/ui/manual_bits.rs +++ b/tests/ui/manual_bits.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_bits)] #![allow( diff --git a/tests/ui/manual_filter.fixed b/tests/ui/manual_filter.fixed index ef6780dc96d..755caa664d5 100644 --- a/tests/ui/manual_filter.fixed +++ b/tests/ui/manual_filter.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_filter)] #![allow(unused_variables, dead_code)] diff --git a/tests/ui/manual_filter.rs b/tests/ui/manual_filter.rs index ea0ce83172b..faccfe9db12 100644 --- a/tests/ui/manual_filter.rs +++ b/tests/ui/manual_filter.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_filter)] #![allow(unused_variables, dead_code)] diff --git a/tests/ui/manual_filter_map.fixed b/tests/ui/manual_filter_map.fixed index 4936dc9b2e0..831323089e7 100644 --- a/tests/ui/manual_filter_map.fixed +++ b/tests/ui/manual_filter_map.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::manual_filter_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure diff --git a/tests/ui/manual_filter_map.rs b/tests/ui/manual_filter_map.rs index 8c67e827b4c..2692303d313 100644 --- a/tests/ui/manual_filter_map.rs +++ b/tests/ui/manual_filter_map.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::manual_filter_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure diff --git a/tests/ui/manual_find_fixable.fixed b/tests/ui/manual_find_fixable.fixed index 2bce6e624c9..9c5eb20c81c 100644 --- a/tests/ui/manual_find_fixable.fixed +++ b/tests/ui/manual_find_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_find)] #![allow(unused)] #![allow(clippy::needless_return, clippy::uninlined_format_args)] diff --git a/tests/ui/manual_find_fixable.rs b/tests/ui/manual_find_fixable.rs index f5c6de37a25..7b670320ee3 100644 --- a/tests/ui/manual_find_fixable.rs +++ b/tests/ui/manual_find_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_find)] #![allow(unused)] #![allow(clippy::needless_return, clippy::uninlined_format_args)] diff --git a/tests/ui/manual_find_map.fixed b/tests/ui/manual_find_map.fixed index 54302beceff..554613a30a9 100644 --- a/tests/ui/manual_find_map.fixed +++ b/tests/ui/manual_find_map.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::manual_find_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure diff --git a/tests/ui/manual_find_map.rs b/tests/ui/manual_find_map.rs index afcc1825a9a..d6245758f9d 100644 --- a/tests/ui/manual_find_map.rs +++ b/tests/ui/manual_find_map.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::manual_find_map)] #![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure diff --git a/tests/ui/manual_instant_elapsed.fixed b/tests/ui/manual_instant_elapsed.fixed index 85a91543c89..55073c3b57c 100644 --- a/tests/ui/manual_instant_elapsed.fixed +++ b/tests/ui/manual_instant_elapsed.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_instant_elapsed)] #![allow(clippy::unnecessary_operation)] #![allow(clippy::unchecked_duration_subtraction)] diff --git a/tests/ui/manual_instant_elapsed.rs b/tests/ui/manual_instant_elapsed.rs index c98cb15b916..c9029a04940 100644 --- a/tests/ui/manual_instant_elapsed.rs +++ b/tests/ui/manual_instant_elapsed.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_instant_elapsed)] #![allow(clippy::unnecessary_operation)] #![allow(clippy::unchecked_duration_subtraction)] diff --git a/tests/ui/manual_is_ascii_check.fixed b/tests/ui/manual_is_ascii_check.fixed index 5b2b44c2fdb..87e86658668 100644 --- a/tests/ui/manual_is_ascii_check.fixed +++ b/tests/ui/manual_is_ascii_check.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, dead_code)] #![warn(clippy::manual_is_ascii_check)] diff --git a/tests/ui/manual_is_ascii_check.rs b/tests/ui/manual_is_ascii_check.rs index c9433f33a1b..931f0f20276 100644 --- a/tests/ui/manual_is_ascii_check.rs +++ b/tests/ui/manual_is_ascii_check.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, dead_code)] #![warn(clippy::manual_is_ascii_check)] diff --git a/tests/ui/manual_main_separator_str.fixed b/tests/ui/manual_main_separator_str.fixed index 50f46d6b355..7e7da8f20bb 100644 --- a/tests/ui/manual_main_separator_str.fixed +++ b/tests/ui/manual_main_separator_str.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::manual_main_separator_str)] diff --git a/tests/ui/manual_main_separator_str.rs b/tests/ui/manual_main_separator_str.rs index 2dbb9e66151..cf90e12efc3 100644 --- a/tests/ui/manual_main_separator_str.rs +++ b/tests/ui/manual_main_separator_str.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::manual_main_separator_str)] diff --git a/tests/ui/manual_map_option.fixed b/tests/ui/manual_map_option.fixed index e12ea7ec145..e8ff65cad6a 100644 --- a/tests/ui/manual_map_option.fixed +++ b/tests/ui/manual_map_option.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_map)] #![allow( diff --git a/tests/ui/manual_map_option.rs b/tests/ui/manual_map_option.rs index 325a6db06c4..b06a96451ce 100644 --- a/tests/ui/manual_map_option.rs +++ b/tests/ui/manual_map_option.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_map)] #![allow( diff --git a/tests/ui/manual_map_option_2.fixed b/tests/ui/manual_map_option_2.fixed index ebf3f8cabd4..dc722878248 100644 --- a/tests/ui/manual_map_option_2.fixed +++ b/tests/ui/manual_map_option_2.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_map)] #![allow(clippy::toplevel_ref_arg)] diff --git a/tests/ui/manual_map_option_2.rs b/tests/ui/manual_map_option_2.rs index 1382d9af0aa..c495ab0fa6e 100644 --- a/tests/ui/manual_map_option_2.rs +++ b/tests/ui/manual_map_option_2.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_map)] #![allow(clippy::toplevel_ref_arg)] diff --git a/tests/ui/manual_ok_or.fixed b/tests/ui/manual_ok_or.fixed index fc8511626b3..d8901dc3b03 100644 --- a/tests/ui/manual_ok_or.fixed +++ b/tests/ui/manual_ok_or.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_ok_or)] #![allow(clippy::or_fun_call)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/manual_ok_or.rs b/tests/ui/manual_ok_or.rs index b5303d33f5f..7188a521357 100644 --- a/tests/ui/manual_ok_or.rs +++ b/tests/ui/manual_ok_or.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_ok_or)] #![allow(clippy::or_fun_call)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index 1f6df1b0a86..f2e44e56f02 100644 --- a/tests/ui/manual_rem_euclid.fixed +++ b/tests/ui/manual_rem_euclid.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::manual_rem_euclid)] #![allow(clippy::let_with_type_underscore)] diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs index b275e8a38d2..b2329c33a47 100644 --- a/tests/ui/manual_rem_euclid.rs +++ b/tests/ui/manual_rem_euclid.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::manual_rem_euclid)] #![allow(clippy::let_with_type_underscore)] diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index 8f25fea678f..d3cac666763 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::BTreeMap; diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index e6b3995a689..34f0c4d5029 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_retain)] #![allow(unused, clippy::redundant_clone)] use std::collections::BTreeMap; diff --git a/tests/ui/manual_saturating_arithmetic.fixed b/tests/ui/manual_saturating_arithmetic.fixed index c4f53c446c9..7dd4521fa78 100644 --- a/tests/ui/manual_saturating_arithmetic.fixed +++ b/tests/ui/manual_saturating_arithmetic.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_imports)] diff --git a/tests/ui/manual_saturating_arithmetic.rs b/tests/ui/manual_saturating_arithmetic.rs index cd83cf6e65e..463ee069289 100644 --- a/tests/ui/manual_saturating_arithmetic.rs +++ b/tests/ui/manual_saturating_arithmetic.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_imports)] diff --git a/tests/ui/manual_slice_size_calculation.fixed b/tests/ui/manual_slice_size_calculation.fixed new file mode 100644 index 00000000000..ac85bd8d3ac --- /dev/null +++ b/tests/ui/manual_slice_size_calculation.fixed @@ -0,0 +1,46 @@ +//@run-rustfix +//@aux-build:proc_macros.rs +#![allow(unused)] +#![warn(clippy::manual_slice_size_calculation)] + +extern crate proc_macros; + +use core::mem::{align_of, size_of}; +use proc_macros::external; + +fn main() { + let v_i32 = Vec::::new(); + let s_i32 = v_i32.as_slice(); + + // True positives: + let _ = std::mem::size_of_val(s_i32); // WARNING + let _ = std::mem::size_of_val(s_i32); // WARNING + let _ = std::mem::size_of_val(s_i32) * 5; // WARNING + + let len = s_i32.len(); + let size = size_of::(); + let _ = std::mem::size_of_val(s_i32); // WARNING + let _ = std::mem::size_of_val(s_i32); // WARNING + let _ = std::mem::size_of_val(s_i32); // WARNING + + let _ = std::mem::size_of_val(external!(&[1u64][..])); + + // True negatives: + let _ = size_of::() + s_i32.len(); // Ok, not a multiplication + let _ = size_of::() * s_i32.partition_point(|_| true); // Ok, not len() + let _ = size_of::() * v_i32.len(); // Ok, not a slice + let _ = align_of::() * s_i32.len(); // Ok, not size_of() + let _ = size_of::() * s_i32.len(); // Ok, different types + + let _ = external!($s_i32.len() * size_of::()); + let _ = external!($s_i32.len()) * size_of::(); + + // False negatives: + let _ = 5 * size_of::() * s_i32.len(); // Ok (MISSED OPPORTUNITY) + let _ = size_of::() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY) +} + +const fn _const(s_i32: &[i32]) { + // True negative: + let _ = s_i32.len() * size_of::(); // Ok, can't use size_of_val in const +} diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs index 5082f931f3c..1f824b12bc2 100644 --- a/tests/ui/manual_slice_size_calculation.rs +++ b/tests/ui/manual_slice_size_calculation.rs @@ -1,7 +1,12 @@ +//@run-rustfix +//@aux-build:proc_macros.rs #![allow(unused)] #![warn(clippy::manual_slice_size_calculation)] +extern crate proc_macros; + use core::mem::{align_of, size_of}; +use proc_macros::external; fn main() { let v_i32 = Vec::::new(); @@ -18,6 +23,8 @@ fn main() { let _ = s_i32.len() * size; // WARNING let _ = len * size; // WARNING + let _ = external!(&[1u64][..]).len() * size_of::(); + // True negatives: let _ = size_of::() + s_i32.len(); // Ok, not a multiplication let _ = size_of::() * s_i32.partition_point(|_| true); // Ok, not len() @@ -25,6 +32,9 @@ fn main() { let _ = align_of::() * s_i32.len(); // Ok, not size_of() let _ = size_of::() * s_i32.len(); // Ok, different types + let _ = external!($s_i32.len() * size_of::()); + let _ = external!($s_i32.len()) * size_of::(); + // False negatives: let _ = 5 * size_of::() * s_i32.len(); // Ok (MISSED OPPORTUNITY) let _ = size_of::() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY) diff --git a/tests/ui/manual_slice_size_calculation.stderr b/tests/ui/manual_slice_size_calculation.stderr index 4a24fc60a0f..e09d8057a3b 100644 --- a/tests/ui/manual_slice_size_calculation.stderr +++ b/tests/ui/manual_slice_size_calculation.stderr @@ -1,51 +1,46 @@ error: manual slice size calculation - --> $DIR/manual_slice_size_calculation.rs:11:13 + --> $DIR/manual_slice_size_calculation.rs:16:13 | LL | let _ = s_i32.len() * size_of::(); // WARNING - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` | - = help: consider using std::mem::size_of_value instead = note: `-D clippy::manual-slice-size-calculation` implied by `-D warnings` error: manual slice size calculation - --> $DIR/manual_slice_size_calculation.rs:12:13 + --> $DIR/manual_slice_size_calculation.rs:17:13 | LL | let _ = size_of::() * s_i32.len(); // WARNING - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using std::mem::size_of_value instead + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> $DIR/manual_slice_size_calculation.rs:13:13 + --> $DIR/manual_slice_size_calculation.rs:18:13 | LL | let _ = size_of::() * s_i32.len() * 5; // WARNING - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using std::mem::size_of_value instead + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> $DIR/manual_slice_size_calculation.rs:17:13 + --> $DIR/manual_slice_size_calculation.rs:22:13 | LL | let _ = len * size_of::(); // WARNING - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider using std::mem::size_of_value instead + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> $DIR/manual_slice_size_calculation.rs:18:13 + --> $DIR/manual_slice_size_calculation.rs:23:13 | LL | let _ = s_i32.len() * size; // WARNING - | ^^^^^^^^^^^^^^^^^^ - | - = help: consider using std::mem::size_of_value instead + | ^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` error: manual slice size calculation - --> $DIR/manual_slice_size_calculation.rs:19:13 + --> $DIR/manual_slice_size_calculation.rs:24:13 | LL | let _ = len * size; // WARNING - | ^^^^^^^^^^ + | ^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)` + +error: manual slice size calculation + --> $DIR/manual_slice_size_calculation.rs:26:13 | - = help: consider using std::mem::size_of_value instead +LL | let _ = external!(&[1u64][..]).len() * size_of::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(external!(&[1u64][..]))` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/manual_split_once.fixed b/tests/ui/manual_split_once.fixed index 50b02019cc2..e317c597109 100644 --- a/tests/ui/manual_split_once.fixed +++ b/tests/ui/manual_split_once.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_split_once)] #![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)] diff --git a/tests/ui/manual_split_once.rs b/tests/ui/manual_split_once.rs index e1e8b71a9de..7e2dc22bc46 100644 --- a/tests/ui/manual_split_once.rs +++ b/tests/ui/manual_split_once.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_split_once)] #![allow(unused, clippy::iter_skip_next, clippy::iter_nth_zero)] diff --git a/tests/ui/manual_str_repeat.fixed b/tests/ui/manual_str_repeat.fixed index 3d56f2a0ded..9468c3df904 100644 --- a/tests/ui/manual_str_repeat.fixed +++ b/tests/ui/manual_str_repeat.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_str_repeat)] diff --git a/tests/ui/manual_str_repeat.rs b/tests/ui/manual_str_repeat.rs index e8240a949db..baa0a10260d 100644 --- a/tests/ui/manual_str_repeat.rs +++ b/tests/ui/manual_str_repeat.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_str_repeat)] diff --git a/tests/ui/manual_string_new.fixed b/tests/ui/manual_string_new.fixed index a376411bfbc..0d1bab23304 100644 --- a/tests/ui/manual_string_new.fixed +++ b/tests/ui/manual_string_new.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_string_new)] diff --git a/tests/ui/manual_string_new.rs b/tests/ui/manual_string_new.rs index 6bfc52fb1bc..2392ebfc322 100644 --- a/tests/ui/manual_string_new.rs +++ b/tests/ui/manual_string_new.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_string_new)] diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed index 7d68978216c..c17634bffe3 100644 --- a/tests/ui/manual_unwrap_or.fixed +++ b/tests/ui/manual_unwrap_or.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![allow(unused_variables, clippy::unnecessary_wraps)] diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index b937fe6f977..6d49a6949fa 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![allow(unused_variables, clippy::unnecessary_wraps)] diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index 0860dcf8e0d..d7474f35719 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_clone)] #![allow( clippy::clone_on_copy, diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index b6987336834..74978ae8006 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_clone)] #![allow( clippy::clone_on_copy, diff --git a/tests/ui/map_collect_result_unit.fixed b/tests/ui/map_collect_result_unit.fixed index e66c9cc2420..b00c2cf284e 100644 --- a/tests/ui/map_collect_result_unit.fixed +++ b/tests/ui/map_collect_result_unit.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_collect_result_unit)] fn main() { diff --git a/tests/ui/map_collect_result_unit.rs b/tests/ui/map_collect_result_unit.rs index 6f08f4c3c53..ad2198ec1fe 100644 --- a/tests/ui/map_collect_result_unit.rs +++ b/tests/ui/map_collect_result_unit.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_collect_result_unit)] fn main() { diff --git a/tests/ui/map_flatten_fixable.fixed b/tests/ui/map_flatten_fixable.fixed index 8e2f11389f8..14816de1a63 100644 --- a/tests/ui/map_flatten_fixable.fixed +++ b/tests/ui/map_flatten_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::let_underscore_untyped)] diff --git a/tests/ui/map_flatten_fixable.rs b/tests/ui/map_flatten_fixable.rs index a783a99c4ff..f38a00a59fa 100644 --- a/tests/ui/map_flatten_fixable.rs +++ b/tests/ui/map_flatten_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all, clippy::pedantic)] #![allow(clippy::let_underscore_untyped)] diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed index 2256e51f2d0..7fb7d8c1218 100644 --- a/tests/ui/map_identity.fixed +++ b/tests/ui/map_identity.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_identity)] #![allow(clippy::needless_return)] diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs index ccfdc9ea76d..7891c242628 100644 --- a/tests/ui/map_identity.rs +++ b/tests/ui/map_identity.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::map_identity)] #![allow(clippy::needless_return)] diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index 32631024ca5..cb25d8567aa 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -1,4 +1,4 @@ -// aux-build:option_helpers.rs +//@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] #![allow(clippy::uninlined_format_args, clippy::unnecessary_lazy_evaluations)] diff --git a/tests/ui/map_unwrap_or_fixable.fixed b/tests/ui/map_unwrap_or_fixable.fixed index bd5b4f7165a..ea5b6a6691e 100644 --- a/tests/ui/map_unwrap_or_fixable.fixed +++ b/tests/ui/map_unwrap_or_fixable.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:option_helpers.rs +//@run-rustfix +//@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs index 0b892caf20e..f8bb9d8ca6a 100644 --- a/tests/ui/map_unwrap_or_fixable.rs +++ b/tests/ui/map_unwrap_or_fixable.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:option_helpers.rs +//@run-rustfix +//@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] diff --git a/tests/ui/match_as_ref.fixed b/tests/ui/match_as_ref.fixed index ddfa1e741ad..8fa3f532587 100644 --- a/tests/ui/match_as_ref.fixed +++ b/tests/ui/match_as_ref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::match_as_ref)] diff --git a/tests/ui/match_as_ref.rs b/tests/ui/match_as_ref.rs index 025d475ae13..02a17791426 100644 --- a/tests/ui/match_as_ref.rs +++ b/tests/ui/match_as_ref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::match_as_ref)] diff --git a/tests/ui/match_expr_like_matches_macro.fixed b/tests/ui/match_expr_like_matches_macro.fixed index 55cd15bd5c3..7215660da67 100644 --- a/tests/ui/match_expr_like_matches_macro.fixed +++ b/tests/ui/match_expr_like_matches_macro.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_like_matches_macro)] #![allow( diff --git a/tests/ui/match_expr_like_matches_macro.rs b/tests/ui/match_expr_like_matches_macro.rs index 5d645e108e5..afdf1069f5e 100644 --- a/tests/ui/match_expr_like_matches_macro.rs +++ b/tests/ui/match_expr_like_matches_macro.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_like_matches_macro)] #![allow( diff --git a/tests/ui/match_ref_pats.fixed b/tests/ui/match_ref_pats.fixed index cf37fc6dc90..50c3dcc1e0a 100644 --- a/tests/ui/match_ref_pats.fixed +++ b/tests/ui/match_ref_pats.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_ref_pats)] #![allow(dead_code, unused_variables)] #![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)] diff --git a/tests/ui/match_ref_pats.rs b/tests/ui/match_ref_pats.rs index 3220b97d1b5..d29ddacc04a 100644 --- a/tests/ui/match_ref_pats.rs +++ b/tests/ui/match_ref_pats.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_ref_pats)] #![allow(dead_code, unused_variables)] #![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)] diff --git a/tests/ui/match_result_ok.fixed b/tests/ui/match_result_ok.fixed index 10ae1ee5245..fe67b225fa1 100644 --- a/tests/ui/match_result_ok.fixed +++ b/tests/ui/match_result_ok.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_result_ok)] #![allow(dead_code)] #![allow(clippy::boxed_local, clippy::uninlined_format_args)] diff --git a/tests/ui/match_result_ok.rs b/tests/ui/match_result_ok.rs index bc2c4b50e27..eac382e1f62 100644 --- a/tests/ui/match_result_ok.rs +++ b/tests/ui/match_result_ok.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_result_ok)] #![allow(dead_code)] #![allow(clippy::boxed_local, clippy::uninlined_format_args)] diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index 201301cc9b7..7c29bb08e64 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_single_binding)] #![allow( unused, diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index 8b047b19ce9..c068d5e17c3 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_single_binding)] #![allow( unused, diff --git a/tests/ui/match_single_binding2.fixed b/tests/ui/match_single_binding2.fixed index e3cf56a4293..adfb4ba91f7 100644 --- a/tests/ui/match_single_binding2.fixed +++ b/tests/ui/match_single_binding2.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_single_binding)] #![allow(unused_variables)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/match_single_binding2.rs b/tests/ui/match_single_binding2.rs index 5a4bb8441ff..b5cfe3654a5 100644 --- a/tests/ui/match_single_binding2.rs +++ b/tests/ui/match_single_binding2.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_single_binding)] #![allow(unused_variables)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/match_str_case_mismatch.fixed b/tests/ui/match_str_case_mismatch.fixed index e436bcf495f..cd53b1f06fa 100644 --- a/tests/ui/match_str_case_mismatch.fixed +++ b/tests/ui/match_str_case_mismatch.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_str_case_mismatch)] #![allow(dead_code)] diff --git a/tests/ui/match_str_case_mismatch.rs b/tests/ui/match_str_case_mismatch.rs index 92e2a000ade..6885305662a 100644 --- a/tests/ui/match_str_case_mismatch.rs +++ b/tests/ui/match_str_case_mismatch.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_str_case_mismatch)] #![allow(dead_code)] diff --git a/tests/ui/match_wildcard_for_single_variants.fixed b/tests/ui/match_wildcard_for_single_variants.fixed index 9fd3739b69c..d2e6fef0759 100644 --- a/tests/ui/match_wildcard_for_single_variants.fixed +++ b/tests/ui/match_wildcard_for_single_variants.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_wildcard_for_single_variants)] #![allow(dead_code)] diff --git a/tests/ui/match_wildcard_for_single_variants.rs b/tests/ui/match_wildcard_for_single_variants.rs index 9a5c849e6ec..cff0c896065 100644 --- a/tests/ui/match_wildcard_for_single_variants.rs +++ b/tests/ui/match_wildcard_for_single_variants.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::match_wildcard_for_single_variants)] #![allow(dead_code)] diff --git a/tests/ui/mem_replace.fixed b/tests/ui/mem_replace.fixed index 7fd340173af..d37e97b0a06 100644 --- a/tests/ui/mem_replace.fixed +++ b/tests/ui/mem_replace.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn( diff --git a/tests/ui/mem_replace.rs b/tests/ui/mem_replace.rs index fa2903addbc..34e37f3dbbb 100644 --- a/tests/ui/mem_replace.rs +++ b/tests/ui/mem_replace.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn( diff --git a/tests/ui/mem_replace_macro.rs b/tests/ui/mem_replace_macro.rs index 3932e7d00c1..132873858b7 100644 --- a/tests/ui/mem_replace_macro.rs +++ b/tests/ui/mem_replace_macro.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::mem_replace_with_default)] extern crate proc_macros; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 1519e4da934..e0e2cac30a2 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -1,4 +1,4 @@ -// aux-build:option_helpers.rs +//@aux-build:option_helpers.rs #![warn(clippy::all, clippy::pedantic)] #![allow( diff --git a/tests/ui/methods_fixable.fixed b/tests/ui/methods_fixable.fixed index ee7c1b0da6d..dcbed5a4d99 100644 --- a/tests/ui/methods_fixable.fixed +++ b/tests/ui/methods_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::filter_next)] diff --git a/tests/ui/methods_fixable.rs b/tests/ui/methods_fixable.rs index 6d0f1b7bd51..3a976d23527 100644 --- a/tests/ui/methods_fixable.rs +++ b/tests/ui/methods_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::filter_next)] diff --git a/tests/ui/mismatched_target_os_non_unix.fixed b/tests/ui/mismatched_target_os_non_unix.fixed index f219a570e7f..f58e9a429b6 100644 --- a/tests/ui/mismatched_target_os_non_unix.fixed +++ b/tests/ui/mismatched_target_os_non_unix.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::mismatched_target_os)] #![allow(unused)] diff --git a/tests/ui/mismatched_target_os_non_unix.rs b/tests/ui/mismatched_target_os_non_unix.rs index 8a8ae756a4f..e00224f5ceb 100644 --- a/tests/ui/mismatched_target_os_non_unix.rs +++ b/tests/ui/mismatched_target_os_non_unix.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::mismatched_target_os)] #![allow(unused)] diff --git a/tests/ui/mismatched_target_os_unix.fixed b/tests/ui/mismatched_target_os_unix.fixed index 7d9d406d99d..330587a3c4c 100644 --- a/tests/ui/mismatched_target_os_unix.fixed +++ b/tests/ui/mismatched_target_os_unix.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::mismatched_target_os)] #![allow(unused)] diff --git a/tests/ui/mismatched_target_os_unix.rs b/tests/ui/mismatched_target_os_unix.rs index c1177f1eedc..5a90019a2e4 100644 --- a/tests/ui/mismatched_target_os_unix.rs +++ b/tests/ui/mismatched_target_os_unix.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::mismatched_target_os)] #![allow(unused)] diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index e6f88c6e622..5db73a7b8ea 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -2,8 +2,8 @@ //! compilation error. //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. -// aux-build:helper.rs -// aux-build:../../auxiliary/proc_macros.rs +//@aux-build:helper.rs +//@aux-build:../../auxiliary/proc_macros.rs #![warn(clippy::missing_const_for_fn)] #![feature(start)] diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs index 5752048949c..bf587e774f7 100644 --- a/tests/ui/missing_doc.rs +++ b/tests/ui/missing_doc.rs @@ -1,5 +1,5 @@ -// needs-asm-support -// aux-build: proc_macros.rs +//@needs-asm-support +//@aux-build: proc_macros.rs #![warn(clippy::missing_docs_in_private_items)] // When denying at the crate level, be sure to not get random warnings from the diff --git a/tests/ui/missing_doc_impl.rs b/tests/ui/missing_doc_impl.rs index e2d49b0907d..520ddbe16b8 100644 --- a/tests/ui/missing_doc_impl.rs +++ b/tests/ui/missing_doc_impl.rs @@ -1,4 +1,4 @@ -// aux-build: proc_macros.rs +//@aux-build: proc_macros.rs #![warn(clippy::missing_docs_in_private_items)] #![allow(dead_code)] diff --git a/tests/ui/missing_spin_loop.fixed b/tests/ui/missing_spin_loop.fixed index aa89e04d26e..a15298dc37b 100644 --- a/tests/ui/missing_spin_loop.fixed +++ b/tests/ui/missing_spin_loop.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::missing_spin_loop)] #![allow(clippy::bool_comparison)] #![allow(unused_braces)] diff --git a/tests/ui/missing_spin_loop.rs b/tests/ui/missing_spin_loop.rs index 88745e47732..be74581ecd0 100644 --- a/tests/ui/missing_spin_loop.rs +++ b/tests/ui/missing_spin_loop.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::missing_spin_loop)] #![allow(clippy::bool_comparison)] #![allow(unused_braces)] diff --git a/tests/ui/missing_spin_loop_no_std.fixed b/tests/ui/missing_spin_loop_no_std.fixed index bb4b4795516..960e5c05fb6 100644 --- a/tests/ui/missing_spin_loop_no_std.fixed +++ b/tests/ui/missing_spin_loop_no_std.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::missing_spin_loop)] #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/missing_spin_loop_no_std.rs b/tests/ui/missing_spin_loop_no_std.rs index a19bc72baf8..e532ca62dc5 100644 --- a/tests/ui/missing_spin_loop_no_std.rs +++ b/tests/ui/missing_spin_loop_no_std.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::missing_spin_loop)] #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed index 9a47d7c56ed..62cfeafdc49 100644 --- a/tests/ui/mistyped_literal_suffix.fixed +++ b/tests/ui/mistyped_literal_suffix.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: proc_macros.rs +//@run-rustfix +//@aux-build: proc_macros.rs #![allow( dead_code, diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs index 04261cba55a..f83b7c3dbda 100644 --- a/tests/ui/mistyped_literal_suffix.rs +++ b/tests/ui/mistyped_literal_suffix.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: proc_macros.rs +//@run-rustfix +//@aux-build: proc_macros.rs #![allow( dead_code, diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs index ebaa77cc283..fb2c7612343 100644 --- a/tests/ui/module_name_repetitions.rs +++ b/tests/ui/module_name_repetitions.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![warn(clippy::module_name_repetitions)] #![allow(dead_code)] diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs index 9082f1675a8..73ef35c8c36 100644 --- a/tests/ui/multiple_unsafe_ops_per_block.rs +++ b/tests/ui/multiple_unsafe_ops_per_block.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![allow(unused)] #![allow(deref_nullptr)] #![allow(clippy::unnecessary_operation)] diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index bbbb3cf621e..0c275504d36 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(never_type)] #![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)] #![warn(clippy::must_use_candidate)] diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 94d3c83bdb9..d1c9267732f 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(never_type)] #![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)] #![warn(clippy::must_use_candidate)] diff --git a/tests/ui/must_use_unit.fixed b/tests/ui/must_use_unit.fixed index b7d375ff80e..4f7cf4e56d1 100644 --- a/tests/ui/must_use_unit.fixed +++ b/tests/ui/must_use_unit.fixed @@ -1,5 +1,5 @@ -//run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::must_use_unit)] #![allow(clippy::unused_unit)] diff --git a/tests/ui/must_use_unit.rs b/tests/ui/must_use_unit.rs index 74d6b4ca865..3a814ce1685 100644 --- a/tests/ui/must_use_unit.rs +++ b/tests/ui/must_use_unit.rs @@ -1,5 +1,5 @@ -//run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::must_use_unit)] #![allow(clippy::unused_unit)] diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs index 06bb085442a..d838098de11 100644 --- a/tests/ui/mut_mut.rs +++ b/tests/ui/mut_mut.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::mut_mut)] #![allow(unused)] #![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)] diff --git a/tests/ui/mut_mutex_lock.fixed b/tests/ui/mut_mutex_lock.fixed index ecad10a8290..433817a4e03 100644 --- a/tests/ui/mut_mutex_lock.fixed +++ b/tests/ui/mut_mutex_lock.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_mut)] #![warn(clippy::mut_mutex_lock)] diff --git a/tests/ui/mut_mutex_lock.rs b/tests/ui/mut_mutex_lock.rs index f2b1d6fbfbc..567a0b59e70 100644 --- a/tests/ui/mut_mutex_lock.rs +++ b/tests/ui/mut_mutex_lock.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_mut)] #![warn(clippy::mut_mutex_lock)] diff --git a/tests/ui/needless_arbitrary_self_type.fixed b/tests/ui/needless_arbitrary_self_type.fixed index 9da21eb6b29..d7eb1a047ed 100644 --- a/tests/ui/needless_arbitrary_self_type.fixed +++ b/tests/ui/needless_arbitrary_self_type.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_arbitrary_self_type)] #![allow(unused_mut, clippy::needless_lifetimes)] diff --git a/tests/ui/needless_arbitrary_self_type.rs b/tests/ui/needless_arbitrary_self_type.rs index 17aeaaf97ac..85a2a957f29 100644 --- a/tests/ui/needless_arbitrary_self_type.rs +++ b/tests/ui/needless_arbitrary_self_type.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_arbitrary_self_type)] #![allow(unused_mut, clippy::needless_lifetimes)] diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.rs b/tests/ui/needless_arbitrary_self_type_unfixable.rs index 02b43cce2bd..00871f9f450 100644 --- a/tests/ui/needless_arbitrary_self_type_unfixable.rs +++ b/tests/ui/needless_arbitrary_self_type_unfixable.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_attr.rs +//@aux-build:proc_macro_attr.rs #![warn(clippy::needless_arbitrary_self_type)] diff --git a/tests/ui/needless_arbitrary_self_type_unfixable.stderr b/tests/ui/needless_arbitrary_self_type_unfixable.stderr index b2edbfe4323..c7df5936d70 100644 --- a/tests/ui/needless_arbitrary_self_type_unfixable.stderr +++ b/tests/ui/needless_arbitrary_self_type_unfixable.stderr @@ -2,7 +2,7 @@ error: the type of the `self` parameter does not need to be arbitrary --> $DIR/needless_arbitrary_self_type_unfixable.rs:42:31 | LL | fn call_with_mut_self(self: &mut Self) {} - | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'_ mut self` + | ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&mut self` | = note: `-D clippy::needless-arbitrary-self-type` implied by `-D warnings` diff --git a/tests/ui/needless_bitwise_bool.fixed b/tests/ui/needless_bitwise_bool.fixed index 5e1ea663a10..7543ab72ca2 100644 --- a/tests/ui/needless_bitwise_bool.fixed +++ b/tests/ui/needless_bitwise_bool.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_bitwise_bool)] diff --git a/tests/ui/needless_bitwise_bool.rs b/tests/ui/needless_bitwise_bool.rs index f3075fba0a2..2cea701dce6 100644 --- a/tests/ui/needless_bitwise_bool.rs +++ b/tests/ui/needless_bitwise_bool.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_bitwise_bool)] diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed index 89dc13fd5b1..f860852e7b7 100644 --- a/tests/ui/needless_bool/fixable.fixed +++ b/tests/ui/needless_bool/fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_bool)] #![allow( diff --git a/tests/ui/needless_bool/fixable.rs b/tests/ui/needless_bool/fixable.rs index c11d9472e8d..6680dab5b6d 100644 --- a/tests/ui/needless_bool/fixable.rs +++ b/tests/ui/needless_bool/fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_bool)] #![allow( diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 4cb7f6b687f..425e6eb6200 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![allow( unused, diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 9a01190ed8d..3f7fa4a9d7d 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![allow( unused, diff --git a/tests/ui/needless_borrowed_ref.fixed b/tests/ui/needless_borrowed_ref.fixed index 0c47ceb7b67..6663520da8a 100644 --- a/tests/ui/needless_borrowed_ref.fixed +++ b/tests/ui/needless_borrowed_ref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_borrowed_reference)] #![allow( diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index f883bb0c889..6c8efd2ce18 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_borrowed_reference)] #![allow( diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index 2659ad38488..024c22de225 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::suspicious_map, clippy::iter_count)] diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 535ec82982b..7ed7babec30 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::suspicious_map, clippy::iter_count)] diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed index 09e671b88e1..a04f9ec651e 100644 --- a/tests/ui/needless_for_each_fixable.fixed +++ b/tests/ui/needless_for_each_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_for_each)] #![allow(unused)] #![allow( diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs index abb4045b919..4975c705081 100644 --- a/tests/ui/needless_for_each_fixable.rs +++ b/tests/ui/needless_for_each_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_for_each)] #![allow(unused)] #![allow( diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed index 86d899bb46c..92f7b3f777a 100644 --- a/tests/ui/needless_late_init.fixed +++ b/tests/ui/needless_late_init.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![feature(let_chains)] #![allow(unused)] #![allow( diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs index 969afb38edf..be378c42f95 100644 --- a/tests/ui/needless_late_init.rs +++ b/tests/ui/needless_late_init.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![feature(let_chains)] #![allow(unused)] #![allow( diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index e6ead69d148..7b99042f744 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::needless_lifetimes)] #![allow( diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index 06eb430506f..6fcf1efc2ee 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::needless_lifetimes)] #![allow( diff --git a/tests/ui/needless_match.fixed b/tests/ui/needless_match.fixed index 7e47406798c..d8a0400a4f0 100644 --- a/tests/ui/needless_match.fixed +++ b/tests/ui/needless_match.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_match)] #![allow(clippy::manual_map)] #![allow(dead_code)] diff --git a/tests/ui/needless_match.rs b/tests/ui/needless_match.rs index 809c694bf40..3de9bd6d7a1 100644 --- a/tests/ui/needless_match.rs +++ b/tests/ui/needless_match.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_match)] #![allow(clippy::manual_map)] #![allow(dead_code)] diff --git a/tests/ui/needless_option_as_deref.fixed b/tests/ui/needless_option_as_deref.fixed index acd22c6bb43..70015fccf9e 100644 --- a/tests/ui/needless_option_as_deref.fixed +++ b/tests/ui/needless_option_as_deref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::needless_option_as_deref)] diff --git a/tests/ui/needless_option_as_deref.rs b/tests/ui/needless_option_as_deref.rs index 61eda5052a2..e2e35360cb3 100644 --- a/tests/ui/needless_option_as_deref.rs +++ b/tests/ui/needless_option_as_deref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::needless_option_as_deref)] diff --git a/tests/ui/needless_option_take.fixed b/tests/ui/needless_option_take.fixed index 29691e81666..bfc6d20d5a3 100644 --- a/tests/ui/needless_option_take.fixed +++ b/tests/ui/needless_option_take.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix fn main() { println!("Testing non erroneous option_take_on_temporary"); diff --git a/tests/ui/needless_option_take.rs b/tests/ui/needless_option_take.rs index 9f4109eb463..697eeab4207 100644 --- a/tests/ui/needless_option_take.rs +++ b/tests/ui/needless_option_take.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix fn main() { println!("Testing non erroneous option_take_on_temporary"); diff --git a/tests/ui/needless_parens_on_range_literals.fixed b/tests/ui/needless_parens_on_range_literals.fixed index f11330a8916..9b98f6ea7f7 100644 --- a/tests/ui/needless_parens_on_range_literals.fixed +++ b/tests/ui/needless_parens_on_range_literals.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// edition:2018 +//@run-rustfix +//@edition:2018 #![warn(clippy::needless_parens_on_range_literals)] #![allow(clippy::almost_complete_range)] diff --git a/tests/ui/needless_parens_on_range_literals.rs b/tests/ui/needless_parens_on_range_literals.rs index 671c0009e23..088e7b2b98f 100644 --- a/tests/ui/needless_parens_on_range_literals.rs +++ b/tests/ui/needless_parens_on_range_literals.rs @@ -1,5 +1,5 @@ -// run-rustfix -// edition:2018 +//@run-rustfix +//@edition:2018 #![warn(clippy::needless_parens_on_range_literals)] #![allow(clippy::almost_complete_range)] diff --git a/tests/ui/needless_question_mark.fixed b/tests/ui/needless_question_mark.fixed index 7eaca571992..679b73d404a 100644 --- a/tests/ui/needless_question_mark.fixed +++ b/tests/ui/needless_question_mark.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_question_mark)] #![allow( diff --git a/tests/ui/needless_question_mark.rs b/tests/ui/needless_question_mark.rs index 960bc7b7898..a993d3ec35d 100644 --- a/tests/ui/needless_question_mark.rs +++ b/tests/ui/needless_question_mark.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::needless_question_mark)] #![allow( diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index 57c08996ce2..ee4e5007dc5 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![feature(yeet_expr)] diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 7c1feefbe32..cd999db4f40 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lint_reasons)] #![feature(yeet_expr)] diff --git a/tests/ui/needless_splitn.fixed b/tests/ui/needless_splitn.fixed index 5496031fefa..30a038312c8 100644 --- a/tests/ui/needless_splitn.fixed +++ b/tests/ui/needless_splitn.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// edition:2018 +//@run-rustfix +//@edition:2018 #![warn(clippy::needless_splitn)] #![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)] diff --git a/tests/ui/needless_splitn.rs b/tests/ui/needless_splitn.rs index 35c2465bae1..1b0b9a5981a 100644 --- a/tests/ui/needless_splitn.rs +++ b/tests/ui/needless_splitn.rs @@ -1,5 +1,5 @@ -// run-rustfix -// edition:2018 +//@run-rustfix +//@edition:2018 #![warn(clippy::needless_splitn)] #![allow(clippy::iter_skip_next, clippy::iter_nth_zero, clippy::manual_split_once)] diff --git a/tests/ui/neg_multiply.fixed b/tests/ui/neg_multiply.fixed index 58ab9e85678..e07e7c88d68 100644 --- a/tests/ui/neg_multiply.fixed +++ b/tests/ui/neg_multiply.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::neg_multiply)] #![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::precedence)] #![allow(unused)] diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index 581290dc72e..2887af7b421 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::neg_multiply)] #![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::precedence)] #![allow(unused)] diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed index a9b2dcfb085..89d12752834 100644 --- a/tests/ui/non_octal_unix_permissions.fixed +++ b/tests/ui/non_octal_unix_permissions.fixed @@ -1,5 +1,5 @@ -// ignore-windows -// run-rustfix +//@ignore-windows +//@run-rustfix #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt}; diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs index 7d2922f494e..1b3a322d726 100644 --- a/tests/ui/non_octal_unix_permissions.rs +++ b/tests/ui/non_octal_unix_permissions.rs @@ -1,5 +1,5 @@ -// ignore-windows -// run-rustfix +//@ignore-windows +//@run-rustfix #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt, PermissionsExt}; diff --git a/tests/ui/nonminimal_bool_methods.fixed b/tests/ui/nonminimal_bool_methods.fixed index aad44089de4..05802a2c865 100644 --- a/tests/ui/nonminimal_bool_methods.fixed +++ b/tests/ui/nonminimal_bool_methods.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/nonminimal_bool_methods.rs b/tests/ui/nonminimal_bool_methods.rs index b9074da8427..cd5b576fa07 100644 --- a/tests/ui/nonminimal_bool_methods.rs +++ b/tests/ui/nonminimal_bool_methods.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::nonminimal_bool)] diff --git a/tests/ui/numbered_fields.fixed b/tests/ui/numbered_fields.fixed index 68c987eb4c6..a52845e53a4 100644 --- a/tests/ui/numbered_fields.fixed +++ b/tests/ui/numbered_fields.fixed @@ -1,4 +1,4 @@ -//run-rustfix +//@run-rustfix #![warn(clippy::init_numbered_fields)] #![allow(unused_tuple_struct_fields)] diff --git a/tests/ui/numbered_fields.rs b/tests/ui/numbered_fields.rs index 2ef4fb4de53..ca93f7dce59 100644 --- a/tests/ui/numbered_fields.rs +++ b/tests/ui/numbered_fields.rs @@ -1,4 +1,4 @@ -//run-rustfix +//@run-rustfix #![warn(clippy::init_numbered_fields)] #![allow(unused_tuple_struct_fields)] diff --git a/tests/ui/obfuscated_if_else.fixed b/tests/ui/obfuscated_if_else.fixed index 62d932c2c6b..9e4f97253f8 100644 --- a/tests/ui/obfuscated_if_else.fixed +++ b/tests/ui/obfuscated_if_else.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::obfuscated_if_else)] diff --git a/tests/ui/obfuscated_if_else.rs b/tests/ui/obfuscated_if_else.rs index 273be9092a7..c2351d64c1c 100644 --- a/tests/ui/obfuscated_if_else.rs +++ b/tests/ui/obfuscated_if_else.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::obfuscated_if_else)] diff --git a/tests/ui/octal_escapes.rs b/tests/ui/octal_escapes.rs index 53145ef0fd2..61ea9660457 100644 --- a/tests/ui/octal_escapes.rs +++ b/tests/ui/octal_escapes.rs @@ -17,4 +17,5 @@ fn main() { let _good3 = "\0\0"; let _good4 = "X\0\0X"; let _good5 = "锈\0锈"; + let _good6 = "\0\\01"; } diff --git a/tests/ui/octal_escapes.stderr b/tests/ui/octal_escapes.stderr index 295dc1798e3..aa362e96321 100644 --- a/tests/ui/octal_escapes.stderr +++ b/tests/ui/octal_escapes.stderr @@ -63,6 +63,22 @@ help: if the null character is intended, disambiguate using LL | let _bad4 = "/x001234567"; | ~~~~~~~~~~~~~ +error: octal-looking escape in string literal + --> $DIR/octal_escapes.rs:9:17 + | +LL | let _bad5 = "/0/03"; + | ^^^^^^^ + | + = help: octal escapes are not supported, `/0` is always a null character +help: if an octal escape was intended, use the hexadecimal representation instead + | +LL | let _bad5 = "/0/x03"; + | ~~~~~~~~ +help: if the null character is intended, disambiguate using + | +LL | let _bad5 = "/0/x003"; + | ~~~~~~~~~ + error: octal-looking escape in string literal --> $DIR/octal_escapes.rs:10:17 | @@ -127,5 +143,5 @@ help: if the null character is intended, disambiguate using LL | let _bad9 = "锈/x0011锈"; | ~~~~~~~~~~~~ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index d124d133faa..e1c0fa3f7fd 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::redundant_clone)] #![warn(clippy::option_as_ref_deref)] diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index 86e354c6716..6f4917fd149 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::redundant_clone)] #![warn(clippy::option_as_ref_deref)] diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs index 9a56cf40d8a..ee1fe3f1fc0 100644 --- a/tests/ui/option_env_unwrap.rs +++ b/tests/ui/option_env_unwrap.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::option_env_unwrap)] #![allow(clippy::map_flatten)] diff --git a/tests/ui/option_filter_map.fixed b/tests/ui/option_filter_map.fixed index b20f73f3110..93c250cfa73 100644 --- a/tests/ui/option_filter_map.fixed +++ b/tests/ui/option_filter_map.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::option_filter_map)] #![allow(clippy::map_flatten)] diff --git a/tests/ui/option_filter_map.rs b/tests/ui/option_filter_map.rs index 7abaaa0fb83..2c5f03250b9 100644 --- a/tests/ui/option_filter_map.rs +++ b/tests/ui/option_filter_map.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::option_filter_map)] #![allow(clippy::map_flatten)] diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 35ce89c7986..9aebcf47100 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::option_if_let_else)] #![allow( unused_tuple_struct_fields, diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index c8683e5aae2..b40b324902a 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::option_if_let_else)] #![allow( unused_tuple_struct_fields, diff --git a/tests/ui/option_map_or_none.fixed b/tests/ui/option_map_or_none.fixed index 04bfac7735f..501757647bf 100644 --- a/tests/ui/option_map_or_none.fixed +++ b/tests/ui/option_map_or_none.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/option_map_or_none.rs b/tests/ui/option_map_or_none.rs index bb84f8a48f4..4d8704e737d 100644 --- a/tests/ui/option_map_or_none.rs +++ b/tests/ui/option_map_or_none.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/option_map_unit_fn_fixable.fixed b/tests/ui/option_map_unit_fn_fixable.fixed index 00264dcceaa..8f64451edf3 100644 --- a/tests/ui/option_map_unit_fn_fixable.fixed +++ b/tests/ui/option_map_unit_fn_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::option_map_unit_fn)] #![allow(unused)] #![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)] diff --git a/tests/ui/option_map_unit_fn_fixable.rs b/tests/ui/option_map_unit_fn_fixable.rs index f3363ebce54..2bf7a8e0f7d 100644 --- a/tests/ui/option_map_unit_fn_fixable.rs +++ b/tests/ui/option_map_unit_fn_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::option_map_unit_fn)] #![allow(unused)] #![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)] diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index be9a65506e1..f723a55f77f 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::or_fun_call)] #![allow(dead_code)] #![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)] diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 628c9704638..61ef6e27f32 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::or_fun_call)] #![allow(dead_code)] #![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)] diff --git a/tests/ui/or_then_unwrap.fixed b/tests/ui/or_then_unwrap.fixed index 844cc4b7a09..40badac4424 100644 --- a/tests/ui/or_then_unwrap.fixed +++ b/tests/ui/or_then_unwrap.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::or_then_unwrap)] #![allow(clippy::map_identity, clippy::let_unit_value)] diff --git a/tests/ui/or_then_unwrap.rs b/tests/ui/or_then_unwrap.rs index 1528ef9be96..76c9942fe6c 100644 --- a/tests/ui/or_then_unwrap.rs +++ b/tests/ui/or_then_unwrap.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::or_then_unwrap)] #![allow(clippy::map_identity, clippy::let_unit_value)] diff --git a/tests/ui/partialeq_to_none.fixed b/tests/ui/partialeq_to_none.fixed index 4644ea8f51d..81a716bd276 100644 --- a/tests/ui/partialeq_to_none.fixed +++ b/tests/ui/partialeq_to_none.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::partialeq_to_none)] struct Foobar; diff --git a/tests/ui/partialeq_to_none.rs b/tests/ui/partialeq_to_none.rs index 61011b3a8c5..f454715fa30 100644 --- a/tests/ui/partialeq_to_none.rs +++ b/tests/ui/partialeq_to_none.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::partialeq_to_none)] struct Foobar; diff --git a/tests/ui/path_buf_push_overwrite.fixed b/tests/ui/path_buf_push_overwrite.fixed index ef8856830fc..393fc6e1c69 100644 --- a/tests/ui/path_buf_push_overwrite.fixed +++ b/tests/ui/path_buf_push_overwrite.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix use std::path::PathBuf; #[warn(clippy::all, clippy::path_buf_push_overwrite)] diff --git a/tests/ui/path_buf_push_overwrite.rs b/tests/ui/path_buf_push_overwrite.rs index 6e2d483f454..18de6e06412 100644 --- a/tests/ui/path_buf_push_overwrite.rs +++ b/tests/ui/path_buf_push_overwrite.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix use std::path::PathBuf; #[warn(clippy::all, clippy::path_buf_push_overwrite)] diff --git a/tests/ui/patterns.fixed b/tests/ui/patterns.fixed index cd69014326e..a1da47d84fd 100644 --- a/tests/ui/patterns.fixed +++ b/tests/ui/patterns.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/patterns.rs b/tests/ui/patterns.rs index 9128da420c0..399066b813e 100644 --- a/tests/ui/patterns.rs +++ b/tests/ui/patterns.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/precedence.fixed b/tests/ui/precedence.fixed index 163bd044c17..af4d5636b61 100644 --- a/tests/ui/precedence.fixed +++ b/tests/ui/precedence.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::precedence)] #![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] #![allow(clippy::identity_op)] diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 8c849e3209b..e23ae912786 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::precedence)] #![allow(unused_must_use, clippy::no_effect, clippy::unnecessary_operation)] #![allow(clippy::identity_op)] diff --git a/tests/ui/print_stdout_build_script.rs b/tests/ui/print_stdout_build_script.rs index 997ebef8a69..91448cb0faf 100644 --- a/tests/ui/print_stdout_build_script.rs +++ b/tests/ui/print_stdout_build_script.rs @@ -1,4 +1,4 @@ -// compile-flags: --crate-name=build_script_build +//@compile-flags: --crate-name=build_script_build #![warn(clippy::print_stdout)] diff --git a/tests/ui/print_with_newline.rs b/tests/ui/print_with_newline.rs index b8c29d207ad..ff79ca75ffa 100644 --- a/tests/ui/print_with_newline.rs +++ b/tests/ui/print_with_newline.rs @@ -1,5 +1,5 @@ // FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934 -// // run-rustfix +// #![allow(clippy::print_literal)] #![warn(clippy::print_with_newline)] diff --git a/tests/ui/println_empty_string.fixed b/tests/ui/println_empty_string.fixed index 9760680927a..abf951ae22d 100644 --- a/tests/ui/println_empty_string.fixed +++ b/tests/ui/println_empty_string.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::match_single_binding)] fn main() { diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 80fdb3e6e21..fd86e2543cc 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::match_single_binding)] fn main() { diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed index ee7b998a0b2..2c2567d67cd 100644 --- a/tests/ui/ptr_as_ptr.fixed +++ b/tests/ui/ptr_as_ptr.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::ptr_as_ptr)] diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs index c88329ce4ec..6000e5c08ac 100644 --- a/tests/ui/ptr_as_ptr.rs +++ b/tests/ui/ptr_as_ptr.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::ptr_as_ptr)] diff --git a/tests/ui/ptr_eq.fixed b/tests/ui/ptr_eq.fixed index 209081e6e80..d5fa273d41f 100644 --- a/tests/ui/ptr_eq.fixed +++ b/tests/ui/ptr_eq.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::ptr_eq)] macro_rules! mac { diff --git a/tests/ui/ptr_eq.rs b/tests/ui/ptr_eq.rs index 69162870807..e033366a4aa 100644 --- a/tests/ui/ptr_eq.rs +++ b/tests/ui/ptr_eq.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::ptr_eq)] macro_rules! mac { diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed index c57e2990fb9..f69bc131898 100644 --- a/tests/ui/ptr_offset_with_cast.fixed +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::unnecessary_cast)] fn main() { diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 3de7997acdd..eae36c27729 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::unnecessary_cast)] fn main() { diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 5c49d46da72..7f1660f31fa 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index d057df6a9b3..a90eae50ed4 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] diff --git a/tests/ui/range_contains.fixed b/tests/ui/range_contains.fixed index 4923731fe45..0a92ee7c8dd 100644 --- a/tests/ui/range_contains.fixed +++ b/tests/ui/range_contains.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_range_contains)] #![allow(unused)] diff --git a/tests/ui/range_contains.rs b/tests/ui/range_contains.rs index d623ccb5da6..7a83be60957 100644 --- a/tests/ui/range_contains.rs +++ b/tests/ui/range_contains.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::manual_range_contains)] #![allow(unused)] diff --git a/tests/ui/range_plus_minus_one.fixed b/tests/ui/range_plus_minus_one.fixed index a16a3e54d45..79c133cb5e3 100644 --- a/tests/ui/range_plus_minus_one.fixed +++ b/tests/ui/range_plus_minus_one.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_parens)] #![allow(clippy::iter_with_drain)] diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index bd6cb4d21be..689a6b7a17c 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_parens)] #![allow(clippy::iter_with_drain)] diff --git a/tests/ui/rc_buffer.fixed b/tests/ui/rc_buffer.fixed index 8910c01b1fc..4cba292c1b7 100644 --- a/tests/ui/rc_buffer.fixed +++ b/tests/ui/rc_buffer.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::rc_buffer)] #![allow(dead_code, unused_imports)] diff --git a/tests/ui/rc_buffer.rs b/tests/ui/rc_buffer.rs index 1e63a43262e..d8a9aa2786d 100644 --- a/tests/ui/rc_buffer.rs +++ b/tests/ui/rc_buffer.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::rc_buffer)] #![allow(dead_code, unused_imports)] diff --git a/tests/ui/rc_buffer_arc.fixed b/tests/ui/rc_buffer_arc.fixed index 13dd6f5fcd1..ac51ac9e467 100644 --- a/tests/ui/rc_buffer_arc.fixed +++ b/tests/ui/rc_buffer_arc.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::rc_buffer)] #![allow(dead_code, unused_imports)] diff --git a/tests/ui/rc_buffer_arc.rs b/tests/ui/rc_buffer_arc.rs index 1a521bfeb7c..21dc27bc5fa 100644 --- a/tests/ui/rc_buffer_arc.rs +++ b/tests/ui/rc_buffer_arc.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::rc_buffer)] #![allow(dead_code, unused_imports)] diff --git a/tests/ui/redundant_allocation_fixable.fixed b/tests/ui/redundant_allocation_fixable.fixed index 6db02718c70..edb7715f42c 100644 --- a/tests/ui/redundant_allocation_fixable.fixed +++ b/tests/ui/redundant_allocation_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![allow(clippy::boxed_local, clippy::needless_pass_by_value)] #![allow(clippy::disallowed_names, unused_variables, dead_code)] diff --git a/tests/ui/redundant_allocation_fixable.rs b/tests/ui/redundant_allocation_fixable.rs index c15806f30c0..c59422dd966 100644 --- a/tests/ui/redundant_allocation_fixable.rs +++ b/tests/ui/redundant_allocation_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![allow(clippy::boxed_local, clippy::needless_pass_by_value)] #![allow(clippy::disallowed_names, unused_variables, dead_code)] diff --git a/tests/ui/redundant_async_block.fixed b/tests/ui/redundant_async_block.fixed index ad96993c4a7..328958491ee 100644 --- a/tests/ui/redundant_async_block.fixed +++ b/tests/ui/redundant_async_block.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] diff --git a/tests/ui/redundant_async_block.rs b/tests/ui/redundant_async_block.rs index 7ae23558369..cd189b31555 100644 --- a/tests/ui/redundant_async_block.rs +++ b/tests/ui/redundant_async_block.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::manual_async_fn)] #![warn(clippy::redundant_async_block)] diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 00b42745093..8bebb5183bc 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // rustfix-only-machine-applicable #![feature(lint_reasons)] #![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index f899127db8d..b4bd5d16b1a 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // rustfix-only-machine-applicable #![feature(lint_reasons)] #![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)] diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index b987fd2ce6f..61aed2733fe 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(async_closure)] #![warn(clippy::redundant_closure_call)] diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index 633a2979d5d..56b28663539 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(async_closure)] #![warn(clippy::redundant_closure_call)] diff --git a/tests/ui/redundant_field_names.fixed b/tests/ui/redundant_field_names.fixed index 276266a2dd8..d2a65399da6 100644 --- a/tests/ui/redundant_field_names.fixed +++ b/tests/ui/redundant_field_names.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::redundant_field_names)] #![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)] diff --git a/tests/ui/redundant_field_names.rs b/tests/ui/redundant_field_names.rs index f674141c138..605ffd21e2f 100644 --- a/tests/ui/redundant_field_names.rs +++ b/tests/ui/redundant_field_names.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::redundant_field_names)] #![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)] diff --git a/tests/ui/redundant_pattern_matching_drop_order.fixed b/tests/ui/redundant_pattern_matching_drop_order.fixed index ce3229f1759..bebdf89716f 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.fixed +++ b/tests/ui/redundant_pattern_matching_drop_order.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // Issue #5746 #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching_drop_order.rs b/tests/ui/redundant_pattern_matching_drop_order.rs index 29b8543cf47..8fb6ed5f7ec 100644 --- a/tests/ui/redundant_pattern_matching_drop_order.rs +++ b/tests/ui/redundant_pattern_matching_drop_order.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // Issue #5746 #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching_ipaddr.fixed b/tests/ui/redundant_pattern_matching_ipaddr.fixed index 21bae909555..a9faf12cd5a 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.fixed +++ b/tests/ui/redundant_pattern_matching_ipaddr.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all, clippy::redundant_pattern_matching)] #![allow(unused_must_use)] #![allow( diff --git a/tests/ui/redundant_pattern_matching_ipaddr.rs b/tests/ui/redundant_pattern_matching_ipaddr.rs index 4dd9171677e..574671d03d1 100644 --- a/tests/ui/redundant_pattern_matching_ipaddr.rs +++ b/tests/ui/redundant_pattern_matching_ipaddr.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all, clippy::redundant_pattern_matching)] #![allow(unused_must_use)] #![allow( diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index a89845c1dd3..87100b97288 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index d6f44403487..0b69e13f655 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching_poll.fixed b/tests/ui/redundant_pattern_matching_poll.fixed index 3645f2c4bfd..bf3e692202c 100644 --- a/tests/ui/redundant_pattern_matching_poll.fixed +++ b/tests/ui/redundant_pattern_matching_poll.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching_poll.rs b/tests/ui/redundant_pattern_matching_poll.rs index 866c71b7cfa..892a21d9d29 100644 --- a/tests/ui/redundant_pattern_matching_poll.rs +++ b/tests/ui/redundant_pattern_matching_poll.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] diff --git a/tests/ui/redundant_pattern_matching_result.fixed b/tests/ui/redundant_pattern_matching_result.fixed index 42348df4480..c48d1522935 100644 --- a/tests/ui/redundant_pattern_matching_result.fixed +++ b/tests/ui/redundant_pattern_matching_result.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] #![allow(deprecated, unused_must_use)] diff --git a/tests/ui/redundant_pattern_matching_result.rs b/tests/ui/redundant_pattern_matching_result.rs index 5949cb2271c..26f37d169fa 100644 --- a/tests/ui/redundant_pattern_matching_result.rs +++ b/tests/ui/redundant_pattern_matching_result.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] #![allow(deprecated, unused_must_use)] diff --git a/tests/ui/redundant_pub_crate.fixed b/tests/ui/redundant_pub_crate.fixed index 106947de68c..f65c0fdd35d 100644 --- a/tests/ui/redundant_pub_crate.fixed +++ b/tests/ui/redundant_pub_crate.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::redundant_pub_crate)] diff --git a/tests/ui/redundant_pub_crate.rs b/tests/ui/redundant_pub_crate.rs index f96cfd31843..fb07fed98be 100644 --- a/tests/ui/redundant_pub_crate.rs +++ b/tests/ui/redundant_pub_crate.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] #![warn(clippy::redundant_pub_crate)] diff --git a/tests/ui/redundant_slicing.fixed b/tests/ui/redundant_slicing.fixed index 8dd8d309237..56ddca71903 100644 --- a/tests/ui/redundant_slicing.fixed +++ b/tests/ui/redundant_slicing.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::deref_by_slicing)] #![warn(clippy::redundant_slicing)] diff --git a/tests/ui/redundant_slicing.rs b/tests/ui/redundant_slicing.rs index 51c16dd8d65..d67b6665e26 100644 --- a/tests/ui/redundant_slicing.rs +++ b/tests/ui/redundant_slicing.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused, clippy::deref_by_slicing)] #![warn(clippy::redundant_slicing)] diff --git a/tests/ui/redundant_static_lifetimes.fixed b/tests/ui/redundant_static_lifetimes.fixed index bca777a890c..2651735d103 100644 --- a/tests/ui/redundant_static_lifetimes.fixed +++ b/tests/ui/redundant_static_lifetimes.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] diff --git a/tests/ui/redundant_static_lifetimes.rs b/tests/ui/redundant_static_lifetimes.rs index afe7644816d..7286652899d 100644 --- a/tests/ui/redundant_static_lifetimes.rs +++ b/tests/ui/redundant_static_lifetimes.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index 5076f61334d..e8a00a9e7f7 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -2,7 +2,7 @@ // Use that command to update this file and do not edit by hand. // Manual edits will be overwritten. -// run-rustfix +//@run-rustfix #![allow(clippy::almost_complete_range)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index 64bc1ca7116..c8ea70c2bcb 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -2,7 +2,7 @@ // Use that command to update this file and do not edit by hand. // Manual edits will be overwritten. -// run-rustfix +//@run-rustfix #![allow(clippy::almost_complete_range)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/renamed_builtin_attr.fixed b/tests/ui/renamed_builtin_attr.fixed index cb91b841d2c..0334c1e1a29 100644 --- a/tests/ui/renamed_builtin_attr.fixed +++ b/tests/ui/renamed_builtin_attr.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[clippy::cognitive_complexity = "1"] fn main() {} diff --git a/tests/ui/renamed_builtin_attr.rs b/tests/ui/renamed_builtin_attr.rs index b3ce2758067..d350370c244 100644 --- a/tests/ui/renamed_builtin_attr.rs +++ b/tests/ui/renamed_builtin_attr.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[clippy::cyclomatic_complexity = "1"] fn main() {} diff --git a/tests/ui/repeat_once.fixed b/tests/ui/repeat_once.fixed index dc197e50300..c517bfcc6aa 100644 --- a/tests/ui/repeat_once.fixed +++ b/tests/ui/repeat_once.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::repeat_once)] #[allow(unused, clippy::redundant_clone)] fn main() { diff --git a/tests/ui/repeat_once.rs b/tests/ui/repeat_once.rs index 0ec5127117c..9a30b47418f 100644 --- a/tests/ui/repeat_once.rs +++ b/tests/ui/repeat_once.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::repeat_once)] #[allow(unused, clippy::redundant_clone)] fn main() { diff --git a/tests/ui/result_map_or_into_option.fixed b/tests/ui/result_map_or_into_option.fixed index 331531b5165..119ff25918a 100644 --- a/tests/ui/result_map_or_into_option.fixed +++ b/tests/ui/result_map_or_into_option.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::result_map_or_into_option)] diff --git a/tests/ui/result_map_or_into_option.rs b/tests/ui/result_map_or_into_option.rs index 3058480e2ad..eeeef830af0 100644 --- a/tests/ui/result_map_or_into_option.rs +++ b/tests/ui/result_map_or_into_option.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::result_map_or_into_option)] diff --git a/tests/ui/result_map_unit_fn_fixable.fixed b/tests/ui/result_map_unit_fn_fixable.fixed index d8b56237e98..0583d29277b 100644 --- a/tests/ui/result_map_unit_fn_fixable.fixed +++ b/tests/ui/result_map_unit_fn_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::result_map_unit_fn)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/result_map_unit_fn_fixable.rs b/tests/ui/result_map_unit_fn_fixable.rs index 44f50d21109..7ad3bdd04bd 100644 --- a/tests/ui/result_map_unit_fn_fixable.rs +++ b/tests/ui/result_map_unit_fn_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::result_map_unit_fn)] #![allow(unused)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/reversed_empty_ranges_fixable.fixed b/tests/ui/reversed_empty_ranges_fixable.fixed index c67edb36c67..30dfc977681 100644 --- a/tests/ui/reversed_empty_ranges_fixable.fixed +++ b/tests/ui/reversed_empty_ranges_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::reversed_empty_ranges)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/reversed_empty_ranges_fixable.rs b/tests/ui/reversed_empty_ranges_fixable.rs index 0a4fef5bfe8..1837249eae1 100644 --- a/tests/ui/reversed_empty_ranges_fixable.rs +++ b/tests/ui/reversed_empty_ranges_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::reversed_empty_ranges)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.fixed b/tests/ui/reversed_empty_ranges_loops_fixable.fixed index 78401e463d5..a74569599c7 100644 --- a/tests/ui/reversed_empty_ranges_loops_fixable.fixed +++ b/tests/ui/reversed_empty_ranges_loops_fixable.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::reversed_empty_ranges)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/reversed_empty_ranges_loops_fixable.rs b/tests/ui/reversed_empty_ranges_loops_fixable.rs index f9e0f7fcd6d..42f9957dfbd 100644 --- a/tests/ui/reversed_empty_ranges_loops_fixable.rs +++ b/tests/ui/reversed_empty_ranges_loops_fixable.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::reversed_empty_ranges)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/same_functions_in_if_condition.rs b/tests/ui/same_functions_in_if_condition.rs index e6198a1bc9a..aea1507cc5b 100644 --- a/tests/ui/same_functions_in_if_condition.rs +++ b/tests/ui/same_functions_in_if_condition.rs @@ -1,5 +1,5 @@ #![feature(adt_const_params)] -#![warn(clippy::same_functions_in_if_condition)] +#![deny(clippy::same_functions_in_if_condition)] // ifs_same_cond warning is different from `ifs_same_cond`. // clippy::if_same_then_else, clippy::comparison_chain -- all empty blocks #![allow(incomplete_features)] diff --git a/tests/ui/same_functions_in_if_condition.stderr b/tests/ui/same_functions_in_if_condition.stderr index f352ade150e..aade3b1fa45 100644 --- a/tests/ui/same_functions_in_if_condition.stderr +++ b/tests/ui/same_functions_in_if_condition.stderr @@ -9,7 +9,11 @@ note: same as this | LL | if function() { | ^^^^^^^^^^ - = note: `-D clippy::same-functions-in-if-condition` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/same_functions_in_if_condition.rs:2:9 + | +LL | #![deny(clippy::same_functions_in_if_condition)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` --> $DIR/same_functions_in_if_condition.rs:42:15 diff --git a/tests/ui/search_is_some.rs b/tests/ui/search_is_some.rs index 72f335153c1..670599b0dcf 100644 --- a/tests/ui/search_is_some.rs +++ b/tests/ui/search_is_some.rs @@ -1,4 +1,4 @@ -// aux-build:option_helpers.rs +//@aux-build:option_helpers.rs #![warn(clippy::search_is_some)] #![allow(dead_code)] extern crate option_helpers; diff --git a/tests/ui/search_is_some_fixable_none.fixed b/tests/ui/search_is_some_fixable_none.fixed index 5190c5304c7..9386618c123 100644 --- a/tests/ui/search_is_some_fixable_none.fixed +++ b/tests/ui/search_is_some_fixable_none.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] diff --git a/tests/ui/search_is_some_fixable_none.rs b/tests/ui/search_is_some_fixable_none.rs index 310d87333a9..6b2537a96c2 100644 --- a/tests/ui/search_is_some_fixable_none.rs +++ b/tests/ui/search_is_some_fixable_none.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] diff --git a/tests/ui/search_is_some_fixable_some.fixed b/tests/ui/search_is_some_fixable_some.fixed index 385a9986aba..e9116fc59f1 100644 --- a/tests/ui/search_is_some_fixable_some.fixed +++ b/tests/ui/search_is_some_fixable_some.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs index 67e190ee378..b1528399457 100644 --- a/tests/ui/search_is_some_fixable_some.rs +++ b/tests/ui/search_is_some_fixable_some.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, clippy::explicit_auto_deref)] #![warn(clippy::search_is_some)] diff --git a/tests/ui/seek_from_current.fixed b/tests/ui/seek_from_current.fixed index 1309c91b81c..34c33baf686 100644 --- a/tests/ui/seek_from_current.fixed +++ b/tests/ui/seek_from_current.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::seek_from_current)] use std::fs::File; diff --git a/tests/ui/seek_from_current.rs b/tests/ui/seek_from_current.rs index 5d9b1424cf6..22bcff1bc40 100644 --- a/tests/ui/seek_from_current.rs +++ b/tests/ui/seek_from_current.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::seek_from_current)] use std::fs::File; diff --git a/tests/ui/seek_to_start_instead_of_rewind.fixed b/tests/ui/seek_to_start_instead_of_rewind.fixed index dc24d447c60..d8a6e6985d4 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.fixed +++ b/tests/ui/seek_to_start_instead_of_rewind.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::seek_to_start_instead_of_rewind)] diff --git a/tests/ui/seek_to_start_instead_of_rewind.rs b/tests/ui/seek_to_start_instead_of_rewind.rs index 4adde2c4018..fc6a6433c2b 100644 --- a/tests/ui/seek_to_start_instead_of_rewind.rs +++ b/tests/ui/seek_to_start_instead_of_rewind.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::seek_to_start_instead_of_rewind)] diff --git a/tests/ui/semicolon_inside_block.fixed b/tests/ui/semicolon_inside_block.fixed index 42e97e1ca35..ee359f60cbd 100644 --- a/tests/ui/semicolon_inside_block.fixed +++ b/tests/ui/semicolon_inside_block.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui/semicolon_inside_block.rs b/tests/ui/semicolon_inside_block.rs index f40848f702e..e8516f79b20 100644 --- a/tests/ui/semicolon_inside_block.rs +++ b/tests/ui/semicolon_inside_block.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui/semicolon_outside_block.fixed b/tests/ui/semicolon_outside_block.fixed index 091eaa7518e..034c7f8c7c1 100644 --- a/tests/ui/semicolon_outside_block.fixed +++ b/tests/ui/semicolon_outside_block.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui/semicolon_outside_block.rs b/tests/ui/semicolon_outside_block.rs index 7ce46431fac..4dc956d8a4b 100644 --- a/tests/ui/semicolon_outside_block.rs +++ b/tests/ui/semicolon_outside_block.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui/shadow.rs b/tests/ui/shadow.rs index 1fa9fc749a9..03337ec3564 100644 --- a/tests/ui/shadow.rs +++ b/tests/ui/shadow.rs @@ -1,6 +1,13 @@ +//@aux-build:proc_macro_derive.rs + #![warn(clippy::shadow_same, clippy::shadow_reuse, clippy::shadow_unrelated)] #![allow(clippy::let_unit_value)] +extern crate proc_macro_derive; + +#[derive(proc_macro_derive::ShadowDerive)] +pub struct Nothing; + fn shadow_same() { let x = 1; let x = x; diff --git a/tests/ui/shadow.stderr b/tests/ui/shadow.stderr index c3d7bc2a536..92bb937d086 100644 --- a/tests/ui/shadow.stderr +++ b/tests/ui/shadow.stderr @@ -1,278 +1,278 @@ error: `x` is shadowed by itself in `x` - --> $DIR/shadow.rs:6:9 + --> $DIR/shadow.rs:13:9 | LL | let x = x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:5:9 + --> $DIR/shadow.rs:12:9 | LL | let x = 1; | ^ = note: `-D clippy::shadow-same` implied by `-D warnings` error: `mut x` is shadowed by itself in `&x` - --> $DIR/shadow.rs:7:13 + --> $DIR/shadow.rs:14:13 | LL | let mut x = &x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:6:9 + --> $DIR/shadow.rs:13:9 | LL | let x = x; | ^ error: `x` is shadowed by itself in `&mut x` - --> $DIR/shadow.rs:8:9 + --> $DIR/shadow.rs:15:9 | LL | let x = &mut x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:7:9 + --> $DIR/shadow.rs:14:9 | LL | let mut x = &x; | ^^^^^ error: `x` is shadowed by itself in `*x` - --> $DIR/shadow.rs:9:9 + --> $DIR/shadow.rs:16:9 | LL | let x = *x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:8:9 + --> $DIR/shadow.rs:15:9 | LL | let x = &mut x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:21:9 | LL | let x = x.0; | ^ | note: previous binding is here - --> $DIR/shadow.rs:13:9 + --> $DIR/shadow.rs:20:9 | LL | let x = ([[0]], ()); | ^ = note: `-D clippy::shadow-reuse` implied by `-D warnings` error: `x` is shadowed - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:22:9 | LL | let x = x[0]; | ^ | note: previous binding is here - --> $DIR/shadow.rs:14:9 + --> $DIR/shadow.rs:21:9 | LL | let x = x.0; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:16:10 + --> $DIR/shadow.rs:23:10 | LL | let [x] = x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:15:9 + --> $DIR/shadow.rs:22:9 | LL | let x = x[0]; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:24:9 | LL | let x = Some(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:16:10 + --> $DIR/shadow.rs:23:10 | LL | let [x] = x; | ^ error: `x` is shadowed - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:25:9 | LL | let x = foo(x); | ^ | note: previous binding is here - --> $DIR/shadow.rs:17:9 + --> $DIR/shadow.rs:24:9 | LL | let x = Some(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:26:9 | LL | let x = || x; | ^ | note: previous binding is here - --> $DIR/shadow.rs:18:9 + --> $DIR/shadow.rs:25:9 | LL | let x = foo(x); | ^ error: `x` is shadowed - --> $DIR/shadow.rs:20:9 + --> $DIR/shadow.rs:27:9 | LL | let x = Some(1).map(|_| x)?; | ^ | note: previous binding is here - --> $DIR/shadow.rs:19:9 + --> $DIR/shadow.rs:26:9 | LL | let x = || x; | ^ error: `y` is shadowed - --> $DIR/shadow.rs:22:9 + --> $DIR/shadow.rs:29:9 | LL | let y = match y { | ^ | note: previous binding is here - --> $DIR/shadow.rs:21:9 + --> $DIR/shadow.rs:28:9 | LL | let y = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:31:9 + --> $DIR/shadow.rs:38:9 | LL | let x = 2; | ^ | note: previous binding is here - --> $DIR/shadow.rs:30:9 + --> $DIR/shadow.rs:37:9 | LL | let x = 1; | ^ = note: `-D clippy::shadow-unrelated` implied by `-D warnings` error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:36:13 + --> $DIR/shadow.rs:43:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:35:10 + --> $DIR/shadow.rs:42:10 | LL | fn f(x: u32) { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:41:14 + --> $DIR/shadow.rs:48:14 | LL | Some(x) => { | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:45:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:42:17 + --> $DIR/shadow.rs:49:17 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:41:14 + --> $DIR/shadow.rs:48:14 | LL | Some(x) => { | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:46:17 + --> $DIR/shadow.rs:53:17 | LL | if let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:45:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:47:20 + --> $DIR/shadow.rs:54:20 | LL | while let Some(x) = Some(1) {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:45:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:48:15 + --> $DIR/shadow.rs:55:15 | LL | let _ = |[x]: [u32; 1]| { | ^ | note: previous binding is here - --> $DIR/shadow.rs:38:9 + --> $DIR/shadow.rs:45:9 | LL | let x = 1; | ^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:49:13 + --> $DIR/shadow.rs:56:13 | LL | let x = 1; | ^ | note: previous binding is here - --> $DIR/shadow.rs:48:15 + --> $DIR/shadow.rs:55:15 | LL | let _ = |[x]: [u32; 1]| { | ^ error: `y` is shadowed - --> $DIR/shadow.rs:52:17 + --> $DIR/shadow.rs:59:17 | LL | if let Some(y) = y {} | ^ | note: previous binding is here - --> $DIR/shadow.rs:51:9 + --> $DIR/shadow.rs:58:9 | LL | let y = Some(1); | ^ error: `_b` shadows a previous, unrelated binding - --> $DIR/shadow.rs:88:9 + --> $DIR/shadow.rs:95:9 | LL | let _b = _a; | ^^ | note: previous binding is here - --> $DIR/shadow.rs:87:28 + --> $DIR/shadow.rs:94:28 | LL | pub async fn foo2(_a: i32, _b: i64) { | ^^ error: `x` shadows a previous, unrelated binding - --> $DIR/shadow.rs:94:21 + --> $DIR/shadow.rs:101:21 | LL | if let Some(x) = Some(1) { x } else { 1 } | ^ | note: previous binding is here - --> $DIR/shadow.rs:93:13 + --> $DIR/shadow.rs:100:13 | LL | let x = 1; | ^ diff --git a/tests/ui/short_circuit_statement.fixed b/tests/ui/short_circuit_statement.fixed index dd22ecab0b5..1737d501441 100644 --- a/tests/ui/short_circuit_statement.fixed +++ b/tests/ui/short_circuit_statement.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::short_circuit_statement)] #![allow(clippy::nonminimal_bool)] diff --git a/tests/ui/short_circuit_statement.rs b/tests/ui/short_circuit_statement.rs index 73a55bf1f5e..ab93aa1ca5c 100644 --- a/tests/ui/short_circuit_statement.rs +++ b/tests/ui/short_circuit_statement.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::short_circuit_statement)] #![allow(clippy::nonminimal_bool)] diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index c65df9ece38..8c48b21f188 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -1,5 +1,5 @@ // FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934 -// // run-rustfix +// #![warn(clippy::significant_drop_in_scrutinee)] #![allow(dead_code, unused_assignments)] #![allow(clippy::match_single_binding, clippy::single_match, clippy::uninlined_format_args)] diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index da998c610bd..ee7f2b0631a 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::significant_drop_tightening)] diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index 83823f95f68..9c139deb95f 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::significant_drop_tightening)] diff --git a/tests/ui/single_char_add_str.fixed b/tests/ui/single_char_add_str.fixed index 63a6d37a9cc..cbcf1ab21c9 100644 --- a/tests/ui/single_char_add_str.fixed +++ b/tests/ui/single_char_add_str.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::single_char_add_str)] macro_rules! get_string { diff --git a/tests/ui/single_char_add_str.rs b/tests/ui/single_char_add_str.rs index a799ea7d885..a1f005cc833 100644 --- a/tests/ui/single_char_add_str.rs +++ b/tests/ui/single_char_add_str.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::single_char_add_str)] macro_rules! get_string { diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index 68e26726724..dba89872070 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_must_use)] diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 186202d78ec..6a145a14bfd 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_must_use)] diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed index 8c96c4715d3..d4d2cbbe57a 100644 --- a/tests/ui/single_component_path_imports.fixed +++ b/tests/ui/single_component_path_imports.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs index 8434bf7eaf1..80d72115f43 100644 --- a/tests/ui/single_component_path_imports.rs +++ b/tests/ui/single_component_path_imports.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::single_component_path_imports)] #![allow(unused_imports)] diff --git a/tests/ui/single_element_loop.fixed b/tests/ui/single_element_loop.fixed index a0dcc0172e8..1697a0cf29b 100644 --- a/tests/ui/single_element_loop.fixed +++ b/tests/ui/single_element_loop.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // Tests from for_loop.rs that don't have suggestions #[warn(clippy::single_element_loop)] diff --git a/tests/ui/single_element_loop.rs b/tests/ui/single_element_loop.rs index bc014035c98..860424f42dd 100644 --- a/tests/ui/single_element_loop.rs +++ b/tests/ui/single_element_loop.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // Tests from for_loop.rs that don't have suggestions #[warn(clippy::single_element_loop)] diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 3c86f41f3a6..c8ac768b60f 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -1,4 +1,4 @@ -// aux-build: proc_macros.rs +//@aux-build: proc_macros.rs #![warn(clippy::single_match_else)] #![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] diff --git a/tests/ui/skip_while_next.rs b/tests/ui/skip_while_next.rs index a551c19d98b..62574e2c8ce 100644 --- a/tests/ui/skip_while_next.rs +++ b/tests/ui/skip_while_next.rs @@ -1,4 +1,4 @@ -// aux-build:option_helpers.rs +//@aux-build:option_helpers.rs #![warn(clippy::skip_while_next)] #![allow(clippy::disallowed_names)] diff --git a/tests/ui/stable_sort_primitive.fixed b/tests/ui/stable_sort_primitive.fixed index f5f18169df2..1370dd2df4d 100644 --- a/tests/ui/stable_sort_primitive.fixed +++ b/tests/ui/stable_sort_primitive.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::stable_sort_primitive)] fn main() { diff --git a/tests/ui/stable_sort_primitive.rs b/tests/ui/stable_sort_primitive.rs index 8149c5638e0..cd344dd1238 100644 --- a/tests/ui/stable_sort_primitive.rs +++ b/tests/ui/stable_sort_primitive.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::stable_sort_primitive)] fn main() { diff --git a/tests/ui/starts_ends_with.fixed b/tests/ui/starts_ends_with.fixed index 983fac7afe6..29d56f852ed 100644 --- a/tests/ui/starts_ends_with.fixed +++ b/tests/ui/starts_ends_with.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/starts_ends_with.rs b/tests/ui/starts_ends_with.rs index e3335dd2e2e..56bbe2574d4 100644 --- a/tests/ui/starts_ends_with.rs +++ b/tests/ui/starts_ends_with.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_must_use)] fn main() {} diff --git a/tests/ui/string_add.rs b/tests/ui/string_add.rs index 20edbe31fa9..de78dfe4d69 100644 --- a/tests/ui/string_add.rs +++ b/tests/ui/string_add.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs extern crate proc_macros; use proc_macros::external; diff --git a/tests/ui/string_add_assign.fixed b/tests/ui/string_add_assign.fixed index b687f43b254..616c6daaf66 100644 --- a/tests/ui/string_add_assign.fixed +++ b/tests/ui/string_add_assign.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[allow(clippy::string_add, unused)] #[warn(clippy::string_add_assign)] diff --git a/tests/ui/string_add_assign.rs b/tests/ui/string_add_assign.rs index e5dbde108fb..e1f8859757c 100644 --- a/tests/ui/string_add_assign.rs +++ b/tests/ui/string_add_assign.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[allow(clippy::string_add, unused)] #[warn(clippy::string_add_assign)] diff --git a/tests/ui/string_extend.fixed b/tests/ui/string_extend.fixed index d200d7310fc..65c9abff3d4 100644 --- a/tests/ui/string_extend.fixed +++ b/tests/ui/string_extend.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[derive(Copy, Clone)] struct HasChars; diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index 0dd96a3b210..5f72ffe2fda 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #[derive(Copy, Clone)] struct HasChars; diff --git a/tests/ui/string_from_utf8_as_bytes.fixed b/tests/ui/string_from_utf8_as_bytes.fixed index 6e665cdd563..9b315ae2b55 100644 --- a/tests/ui/string_from_utf8_as_bytes.fixed +++ b/tests/ui/string_from_utf8_as_bytes.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::string_from_utf8_as_bytes)] fn main() { diff --git a/tests/ui/string_from_utf8_as_bytes.rs b/tests/ui/string_from_utf8_as_bytes.rs index 670d206d367..043dd235082 100644 --- a/tests/ui/string_from_utf8_as_bytes.rs +++ b/tests/ui/string_from_utf8_as_bytes.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::string_from_utf8_as_bytes)] fn main() { diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 506187fc125..058f2aa54da 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 2c339f1ddb8..b550bea001f 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] diff --git a/tests/ui/strlen_on_c_strings.fixed b/tests/ui/strlen_on_c_strings.fixed index 947a59bcc02..ef207e28cca 100644 --- a/tests/ui/strlen_on_c_strings.fixed +++ b/tests/ui/strlen_on_c_strings.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::strlen_on_c_strings)] #![allow(dead_code)] diff --git a/tests/ui/strlen_on_c_strings.rs b/tests/ui/strlen_on_c_strings.rs index 1237f1ab03a..03ec5f79d09 100644 --- a/tests/ui/strlen_on_c_strings.rs +++ b/tests/ui/strlen_on_c_strings.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::strlen_on_c_strings)] #![allow(dead_code)] diff --git a/tests/ui/suspicious_doc_comments.fixed b/tests/ui/suspicious_doc_comments.fixed index b404df94d3c..bffda1cc412 100644 --- a/tests/ui/suspicious_doc_comments.fixed +++ b/tests/ui/suspicious_doc_comments.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::suspicious_doc_comments)] diff --git a/tests/ui/suspicious_doc_comments.rs b/tests/ui/suspicious_doc_comments.rs index 46eff51e220..cdd972ee30f 100644 --- a/tests/ui/suspicious_doc_comments.rs +++ b/tests/ui/suspicious_doc_comments.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::suspicious_doc_comments)] diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index 21753e5dc6a..e0153cdd8cd 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_suspicious_else_formatting.rs +//@aux-build:proc_macro_suspicious_else_formatting.rs #![warn(clippy::suspicious_else_formatting)] #![allow(clippy::if_same_then_else, clippy::let_unit_value)] diff --git a/tests/ui/suspicious_operation_groupings.fixed b/tests/ui/suspicious_operation_groupings.fixed index ede8a39fed7..0e37701ec48 100644 --- a/tests/ui/suspicious_operation_groupings.fixed +++ b/tests/ui/suspicious_operation_groupings.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suspicious_operation_groupings)] #![allow(dead_code, unused_parens, clippy::eq_op)] diff --git a/tests/ui/suspicious_operation_groupings.rs b/tests/ui/suspicious_operation_groupings.rs index 26ce97bb37f..dd4f3b71c37 100644 --- a/tests/ui/suspicious_operation_groupings.rs +++ b/tests/ui/suspicious_operation_groupings.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::suspicious_operation_groupings)] #![allow(dead_code, unused_parens, clippy::eq_op)] diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed index 9703674d1a4..fd3569cf362 100644 --- a/tests/ui/swap.fixed +++ b/tests/ui/swap.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: macro_rules.rs +//@run-rustfix +//@aux-build: macro_rules.rs #![warn(clippy::all)] #![allow( diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index a0228065e46..34fbce0524b 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: macro_rules.rs +//@run-rustfix +//@aux-build: macro_rules.rs #![warn(clippy::all)] #![allow( diff --git a/tests/ui/swap_ptr_to_ref.fixed b/tests/ui/swap_ptr_to_ref.fixed index 596b6ee919b..3bede3017a1 100644 --- a/tests/ui/swap_ptr_to_ref.fixed +++ b/tests/ui/swap_ptr_to_ref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::swap_ptr_to_ref)] diff --git a/tests/ui/swap_ptr_to_ref.rs b/tests/ui/swap_ptr_to_ref.rs index 282f571211d..726b09d3764 100644 --- a/tests/ui/swap_ptr_to_ref.rs +++ b/tests/ui/swap_ptr_to_ref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::swap_ptr_to_ref)] diff --git a/tests/ui/tabs_in_doc_comments.fixed b/tests/ui/tabs_in_doc_comments.fixed index 4bc4bc86c76..21020182c24 100644 --- a/tests/ui/tabs_in_doc_comments.fixed +++ b/tests/ui/tabs_in_doc_comments.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::tabs_in_doc_comments)] #[allow(dead_code)] diff --git a/tests/ui/tabs_in_doc_comments.rs b/tests/ui/tabs_in_doc_comments.rs index 9db3416e659..df704267dd2 100644 --- a/tests/ui/tabs_in_doc_comments.rs +++ b/tests/ui/tabs_in_doc_comments.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::tabs_in_doc_comments)] #[allow(dead_code)] diff --git a/tests/ui/tests_outside_test_module.rs b/tests/ui/tests_outside_test_module.rs index 1982b1d0107..21fdfdf9005 100644 --- a/tests/ui/tests_outside_test_module.rs +++ b/tests/ui/tests_outside_test_module.rs @@ -1,4 +1,4 @@ -// compile-flags: --test +//@compile-flags: --test #![allow(unused)] #![warn(clippy::tests_outside_test_module)] diff --git a/tests/ui/to_digit_is_some.fixed b/tests/ui/to_digit_is_some.fixed index 3c5e9642714..dc9be66d48a 100644 --- a/tests/ui/to_digit_is_some.fixed +++ b/tests/ui/to_digit_is_some.fixed @@ -1,4 +1,4 @@ -//run-rustfix +//@run-rustfix #![warn(clippy::to_digit_is_some)] diff --git a/tests/ui/to_digit_is_some.rs b/tests/ui/to_digit_is_some.rs index 4f247c06cee..d2a09ac30de 100644 --- a/tests/ui/to_digit_is_some.rs +++ b/tests/ui/to_digit_is_some.rs @@ -1,4 +1,4 @@ -//run-rustfix +//@run-rustfix #![warn(clippy::to_digit_is_some)] diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed index 174c858a47d..ea30c1fda6f 100644 --- a/tests/ui/toplevel_ref_arg.fixed +++ b/tests/ui/toplevel_ref_arg.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::toplevel_ref_arg)] #![allow(clippy::uninlined_format_args, unused)] diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs index 4b81a06112f..7a3d33e5be5 100644 --- a/tests/ui/toplevel_ref_arg.rs +++ b/tests/ui/toplevel_ref_arg.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![warn(clippy::toplevel_ref_arg)] #![allow(clippy::uninlined_format_args, unused)] diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.rs b/tests/ui/toplevel_ref_arg_non_rustfix.rs index 2047593e7e4..8aaf47b1bd0 100644 --- a/tests/ui/toplevel_ref_arg_non_rustfix.rs +++ b/tests/ui/toplevel_ref_arg_non_rustfix.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![warn(clippy::toplevel_ref_arg)] #![allow(unused)] diff --git a/tests/ui/track-diagnostics.rs b/tests/ui/track-diagnostics.rs index fa9221ed02d..6ab0bce770e 100644 --- a/tests/ui/track-diagnostics.rs +++ b/tests/ui/track-diagnostics.rs @@ -1,9 +1,8 @@ -// compile-flags: -Z track-diagnostics -// error-pattern: created at +//@compile-flags: -Z track-diagnostics // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. -// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" +//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC" struct A; struct B; diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed index 4ce5d421782..eef8024b131 100644 --- a/tests/ui/trait_duplication_in_bounds.fixed +++ b/tests/ui/trait_duplication_in_bounds.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::trait_duplication_in_bounds)] #![allow(unused)] diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index 7f2e96a22e6..a7a1caf2880 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::trait_duplication_in_bounds)] #![allow(unused)] diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index ffe22b12f55..8e1316ca39d 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -1,4 +1,4 @@ -// ignore-64bit +//@ignore-64bit #[warn(clippy::wrong_transmute)] fn main() { diff --git a/tests/ui/transmute_32bit.stderr b/tests/ui/transmute_32bit.stderr index 040519564b9..75ddca60d2a 100644 --- a/tests/ui/transmute_32bit.stderr +++ b/tests/ui/transmute_32bit.stderr @@ -1,28 +1,39 @@ -error: transmute from a `f32` to a pointer +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute_32bit.rs:6:31 | LL | let _: *const usize = std::mem::transmute(6.0f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | - = note: `-D clippy::wrong-transmute` implied by `-D warnings` + = note: source type: `f32` (32 bits) + = note: target type: `*const usize` (64 bits) -error: transmute from a `f32` to a pointer +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute_32bit.rs:8:29 | LL | let _: *mut usize = std::mem::transmute(6.0f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `f32` (32 bits) + = note: target type: `*mut usize` (64 bits) -error: transmute from a `char` to a pointer +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute_32bit.rs:10:31 | LL | let _: *const usize = std::mem::transmute('x'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `char` (32 bits) + = note: target type: `*const usize` (64 bits) -error: transmute from a `char` to a pointer +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute_32bit.rs:12:29 | LL | let _: *mut usize = std::mem::transmute('x'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `char` (32 bits) + = note: target type: `*mut usize` (64 bits) error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 00dc0b2c360..ceecf9b279f 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,4 +1,4 @@ -// ignore-32bit +//@ignore-32bit #[warn(clippy::wrong_transmute)] fn main() { diff --git a/tests/ui/transmute_ptr_to_ref.fixed b/tests/ui/transmute_ptr_to_ref.fixed index 074dae5fb28..575dadde906 100644 --- a/tests/ui/transmute_ptr_to_ref.fixed +++ b/tests/ui/transmute_ptr_to_ref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] diff --git a/tests/ui/transmute_ptr_to_ref.rs b/tests/ui/transmute_ptr_to_ref.rs index 2edc122cf47..4238ff80478 100644 --- a/tests/ui/transmute_ptr_to_ref.rs +++ b/tests/ui/transmute_ptr_to_ref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::transmute_ptr_to_ref)] #![allow(clippy::match_single_binding)] diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/tests/ui/transmutes_expressible_as_ptr_casts.fixed index cc84ba25bd0..05aa86c479a 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::transmutes_expressible_as_ptr_casts)] // These two warnings currently cover the cases transmutes_expressible_as_ptr_casts // would otherwise be responsible for diff --git a/tests/ui/transmutes_expressible_as_ptr_casts.rs b/tests/ui/transmutes_expressible_as_ptr_casts.rs index aa65ab4dd24..29fa6914cfd 100644 --- a/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::transmutes_expressible_as_ptr_casts)] // These two warnings currently cover the cases transmutes_expressible_as_ptr_casts // would otherwise be responsible for diff --git a/tests/ui/trim_split_whitespace.fixed b/tests/ui/trim_split_whitespace.fixed index e4d352f7367..7909b319ddd 100644 --- a/tests/ui/trim_split_whitespace.fixed +++ b/tests/ui/trim_split_whitespace.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::trim_split_whitespace)] #![allow(clippy::let_unit_value)] diff --git a/tests/ui/trim_split_whitespace.rs b/tests/ui/trim_split_whitespace.rs index f98451a9837..0cf58979fb2 100644 --- a/tests/ui/trim_split_whitespace.rs +++ b/tests/ui/trim_split_whitespace.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::trim_split_whitespace)] #![allow(clippy::let_unit_value)] diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index c0af011d33d..48615583156 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -1,5 +1,5 @@ -// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)" -// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)" +//@normalize-stderr-test: "\(\d+ byte\)" -> "(N byte)" +//@normalize-stderr-test: "\(limit: \d+ byte\)" -> "(limit: N byte)" #![deny(clippy::trivially_copy_pass_by_ref)] #![allow( clippy::disallowed_names, diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index dc497b1690f..dc773ad4bad 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![deny(clippy::try_err)] #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)] diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 86aeb75cd96..7a7433a7ec2 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macros.rs +//@run-rustfix +//@aux-build:proc_macros.rs #![deny(clippy::try_err)] #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)] diff --git a/tests/ui/types.fixed b/tests/ui/types.fixed index 417da42edf1..4a2616a7a22 100644 --- a/tests/ui/types.fixed +++ b/tests/ui/types.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_variables)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/types.rs b/tests/ui/types.rs index b16e9e538b1..5e0917907db 100644 --- a/tests/ui/types.rs +++ b/tests/ui/types.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code, unused_variables)] #![warn(clippy::cast_lossless)] diff --git a/tests/ui/unchecked_duration_subtraction.fixed b/tests/ui/unchecked_duration_subtraction.fixed index a0e49a8beb1..757d1592184 100644 --- a/tests/ui/unchecked_duration_subtraction.fixed +++ b/tests/ui/unchecked_duration_subtraction.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unchecked_duration_subtraction)] use std::time::{Duration, Instant}; diff --git a/tests/ui/unchecked_duration_subtraction.rs b/tests/ui/unchecked_duration_subtraction.rs index a14a7ea57cc..da7faab6753 100644 --- a/tests/ui/unchecked_duration_subtraction.rs +++ b/tests/ui/unchecked_duration_subtraction.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unchecked_duration_subtraction)] use std::time::{Duration, Instant}; diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index c05eb447b2e..229d150851a 100644 --- a/tests/ui/undocumented_unsafe_blocks.rs +++ b/tests/ui/undocumented_unsafe_blocks.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_unsafe.rs +//@aux-build:proc_macro_unsafe.rs #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] #![allow(clippy::let_unit_value, clippy::missing_safety_doc)] diff --git a/tests/ui/unicode.fixed b/tests/ui/unicode.fixed index 94b4723452f..910968afa7f 100644 --- a/tests/ui/unicode.fixed +++ b/tests/ui/unicode.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// compile-flags: --test +//@run-rustfix +//@compile-flags: --test #![allow(dead_code)] #[warn(clippy::invisible_characters)] diff --git a/tests/ui/unicode.rs b/tests/ui/unicode.rs index 6ad0b255b94..bc4b84d3435 100644 --- a/tests/ui/unicode.rs +++ b/tests/ui/unicode.rs @@ -1,5 +1,5 @@ -// run-rustfix -// compile-flags: --test +//@run-rustfix +//@compile-flags: --test #![allow(dead_code)] #[warn(clippy::invisible_characters)] diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 3122081a44f..e25d123dd51 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -1,5 +1,5 @@ -// aux-build:proc_macros.rs -// run-rustfix +//@aux-build:proc_macros.rs +//@run-rustfix #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused)] #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index b153ef256e0..6793ec24441 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -1,5 +1,5 @@ -// aux-build:proc_macros.rs -// run-rustfix +//@aux-build:proc_macros.rs +//@run-rustfix #![warn(clippy::uninlined_format_args)] #![allow(named_arguments_used_positionally, unused)] #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)] diff --git a/tests/ui/uninlined_format_args_panic.edition2018.fixed b/tests/ui/uninlined_format_args_panic.edition2018.fixed index 52b5343c351..559050b3df6 100644 --- a/tests/ui/uninlined_format_args_panic.edition2018.fixed +++ b/tests/ui/uninlined_format_args_panic.edition2018.fixed @@ -1,7 +1,7 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix #![warn(clippy::uninlined_format_args)] diff --git a/tests/ui/uninlined_format_args_panic.edition2021.fixed b/tests/ui/uninlined_format_args_panic.edition2021.fixed index ee72065e28a..3a753b49caf 100644 --- a/tests/ui/uninlined_format_args_panic.edition2021.fixed +++ b/tests/ui/uninlined_format_args_panic.edition2021.fixed @@ -1,7 +1,7 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix #![warn(clippy::uninlined_format_args)] diff --git a/tests/ui/uninlined_format_args_panic.rs b/tests/ui/uninlined_format_args_panic.rs index b4a0a0f496e..83fbb9afd2a 100644 --- a/tests/ui/uninlined_format_args_panic.rs +++ b/tests/ui/uninlined_format_args_panic.rs @@ -1,7 +1,7 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix #![warn(clippy::uninlined_format_args)] diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 674ae4f1df9..d082063c8e8 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,4 +1,4 @@ -// aux-build: proc_macros.rs +//@aux-build: proc_macros.rs #![warn(clippy::unit_arg)] #![allow(unused_must_use, unused_variables)] #![allow( diff --git a/tests/ui/unit_arg_empty_blocks.fixed b/tests/ui/unit_arg_empty_blocks.fixed index 5787471a32c..8c065115a74 100644 --- a/tests/ui/unit_arg_empty_blocks.fixed +++ b/tests/ui/unit_arg_empty_blocks.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unit_arg)] #![allow(unused_must_use, unused_variables)] #![allow(clippy::no_effect, clippy::uninlined_format_args)] diff --git a/tests/ui/unit_arg_empty_blocks.rs b/tests/ui/unit_arg_empty_blocks.rs index 6a42c2ccf42..af166b56ff4 100644 --- a/tests/ui/unit_arg_empty_blocks.rs +++ b/tests/ui/unit_arg_empty_blocks.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unit_arg)] #![allow(unused_must_use, unused_variables)] #![allow(clippy::no_effect, clippy::uninlined_format_args)] diff --git a/tests/ui/unknown_clippy_lints.fixed b/tests/ui/unknown_clippy_lints.fixed index 4249ff8a958..0c269d650c8 100644 --- a/tests/ui/unknown_clippy_lints.fixed +++ b/tests/ui/unknown_clippy_lints.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::pedantic)] // Should suggest lowercase diff --git a/tests/ui/unknown_clippy_lints.rs b/tests/ui/unknown_clippy_lints.rs index 5db345f5444..b60042923ea 100644 --- a/tests/ui/unknown_clippy_lints.rs +++ b/tests/ui/unknown_clippy_lints.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::pedantic)] // Should suggest lowercase diff --git a/tests/ui/unnecessary_box_returns.rs b/tests/ui/unnecessary_box_returns.rs index fe60d929759..ce7cc2e97cb 100644 --- a/tests/ui/unnecessary_box_returns.rs +++ b/tests/ui/unnecessary_box_returns.rs @@ -54,6 +54,16 @@ fn string() -> String { String::from("Hello, world") } +struct Huge([u8; 500]); +struct HasHuge(Box); + +impl HasHuge { + // don't lint: The size of `Huge` is very large + fn into_huge(self) -> Box { + self.0 + } +} + fn main() { // don't lint: this is a closure let a = || -> Box { Box::new(5) }; diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 2f7e2997e73..bcc231ea7bc 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_cast)] #![allow( unused_must_use, diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index 54dd46ba59f..282b2f1283e 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_cast)] #![allow( unused_must_use, diff --git a/tests/ui/unnecessary_fold.fixed b/tests/ui/unnecessary_fold.fixed index 52300a3b640..2bed14973ca 100644 --- a/tests/ui/unnecessary_fold.fixed +++ b/tests/ui/unnecessary_fold.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] diff --git a/tests/ui/unnecessary_fold.rs b/tests/ui/unnecessary_fold.rs index 4028d80c0a3..a3cec8ea3d5 100644 --- a/tests/ui/unnecessary_fold.rs +++ b/tests/ui/unnecessary_fold.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] diff --git a/tests/ui/unnecessary_iter_cloned.fixed b/tests/ui/unnecessary_iter_cloned.fixed index e01e9f07baf..a0f8dd1a200 100644 --- a/tests/ui/unnecessary_iter_cloned.fixed +++ b/tests/ui/unnecessary_iter_cloned.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_assignments)] #![warn(clippy::unnecessary_to_owned)] diff --git a/tests/ui/unnecessary_iter_cloned.rs b/tests/ui/unnecessary_iter_cloned.rs index 6ef2966c8b7..98f2dfe7549 100644 --- a/tests/ui/unnecessary_iter_cloned.rs +++ b/tests/ui/unnecessary_iter_cloned.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_assignments)] #![warn(clippy::unnecessary_to_owned)] diff --git a/tests/ui/unnecessary_join.fixed b/tests/ui/unnecessary_join.fixed index 34795396025..e102df62599 100644 --- a/tests/ui/unnecessary_join.fixed +++ b/tests/ui/unnecessary_join.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_join)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/unnecessary_join.rs b/tests/ui/unnecessary_join.rs index 344918cd2a2..b87c15bc126 100644 --- a/tests/ui/unnecessary_join.rs +++ b/tests/ui/unnecessary_join.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_join)] #![allow(clippy::uninlined_format_args)] diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed index 3b93800f8b7..c3728886ec9 100644 --- a/tests/ui/unnecessary_lazy_eval.fixed +++ b/tests/ui/unnecessary_lazy_eval.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: proc_macros.rs +//@run-rustfix +//@aux-build: proc_macros.rs #![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs index 2851c0c5190..76e50fa5b03 100644 --- a/tests/ui/unnecessary_lazy_eval.rs +++ b/tests/ui/unnecessary_lazy_eval.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build: proc_macros.rs +//@run-rustfix +//@aux-build: proc_macros.rs #![warn(clippy::unnecessary_lazy_evaluations)] #![allow(clippy::redundant_closure)] #![allow(clippy::bind_instead_of_map)] diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed index b046694f8c6..fbd2d34591f 100644 --- a/tests/ui/unnecessary_operation.fixed +++ b/tests/ui/unnecessary_operation.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( clippy::deref_addrof, diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index 9ed9679e938..b45298a6dc4 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( clippy::deref_addrof, diff --git a/tests/ui/unnecessary_owned_empty_strings.fixed b/tests/ui/unnecessary_owned_empty_strings.fixed index 40052c41039..af12fd1d63d 100644 --- a/tests/ui/unnecessary_owned_empty_strings.fixed +++ b/tests/ui/unnecessary_owned_empty_strings.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_owned_empty_strings)] diff --git a/tests/ui/unnecessary_owned_empty_strings.rs b/tests/ui/unnecessary_owned_empty_strings.rs index 2304dff5192..a460b21af8c 100644 --- a/tests/ui/unnecessary_owned_empty_strings.rs +++ b/tests/ui/unnecessary_owned_empty_strings.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_owned_empty_strings)] diff --git a/tests/ui/unnecessary_self_imports.fixed b/tests/ui/unnecessary_self_imports.fixed index 1185eaa1d55..7fc978d3ef7 100644 --- a/tests/ui/unnecessary_self_imports.fixed +++ b/tests/ui/unnecessary_self_imports.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_self_imports)] #![allow(unused_imports, dead_code)] diff --git a/tests/ui/unnecessary_self_imports.rs b/tests/ui/unnecessary_self_imports.rs index 56bfbc09402..02424bc12b0 100644 --- a/tests/ui/unnecessary_self_imports.rs +++ b/tests/ui/unnecessary_self_imports.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unnecessary_self_imports)] #![allow(unused_imports, dead_code)] diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 21e2da474a8..165cabd8298 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::stable_sort_primitive)] diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 3365bf6e119..8a2158d5a84 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::stable_sort_primitive)] diff --git a/tests/ui/unnecessary_struct_initialization.fixed b/tests/ui/unnecessary_struct_initialization.fixed index b47129e4a36..bdf746cf2c4 100644 --- a/tests/ui/unnecessary_struct_initialization.fixed +++ b/tests/ui/unnecessary_struct_initialization.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::unnecessary_struct_initialization)] diff --git a/tests/ui/unnecessary_struct_initialization.rs b/tests/ui/unnecessary_struct_initialization.rs index 63b11c626e5..7271e2f957a 100644 --- a/tests/ui/unnecessary_struct_initialization.rs +++ b/tests/ui/unnecessary_struct_initialization.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::unnecessary_struct_initialization)] diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index 345f6d604c4..c879fdc3b6a 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::needless_borrow, clippy::ptr_arg)] #![warn(clippy::unnecessary_to_owned)] diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 7eb53df39e5..10588beb263 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(clippy::needless_borrow, clippy::ptr_arg)] #![warn(clippy::unnecessary_to_owned)] diff --git a/tests/ui/unnecessary_unsafety_doc.rs b/tests/ui/unnecessary_unsafety_doc.rs index 431093ab369..373b18470f6 100644 --- a/tests/ui/unnecessary_unsafety_doc.rs +++ b/tests/ui/unnecessary_unsafety_doc.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macros.rs +//@aux-build:proc_macros.rs #![allow(clippy::let_unit_value)] #![warn(clippy::unnecessary_safety_doc)] diff --git a/tests/ui/unneeded_wildcard_pattern.fixed b/tests/ui/unneeded_wildcard_pattern.fixed index 12c3461c955..16c2de760e5 100644 --- a/tests/ui/unneeded_wildcard_pattern.fixed +++ b/tests/ui/unneeded_wildcard_pattern.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] diff --git a/tests/ui/unneeded_wildcard_pattern.rs b/tests/ui/unneeded_wildcard_pattern.rs index 4ac01d5d23b..9d9eae1d903 100644 --- a/tests/ui/unneeded_wildcard_pattern.rs +++ b/tests/ui/unneeded_wildcard_pattern.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(stmt_expr_attributes)] #![deny(clippy::unneeded_wildcard_pattern)] diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 0a8e7b34dfa..8ec35ba4eea 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index 2c454adfe89..efdb91b2402 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] diff --git a/tests/ui/unnested_or_patterns2.fixed b/tests/ui/unnested_or_patterns2.fixed index d3539d79815..de40e936747 100644 --- a/tests/ui/unnested_or_patterns2.fixed +++ b/tests/ui/unnested_or_patterns2.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] diff --git a/tests/ui/unnested_or_patterns2.rs b/tests/ui/unnested_or_patterns2.rs index 9cea5cdea69..87f66d26c46 100644 --- a/tests/ui/unnested_or_patterns2.rs +++ b/tests/ui/unnested_or_patterns2.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(box_patterns)] #![warn(clippy::unnested_or_patterns)] diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed index 13e5feb1926..f5e87648a23 100644 --- a/tests/ui/unreadable_literal.fixed +++ b/tests/ui/unreadable_literal.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unreadable_literal)] #![allow(unused_tuple_struct_fields)] diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 82f04e7ced5..426bdf7d732 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unreadable_literal)] #![allow(unused_tuple_struct_fields)] diff --git a/tests/ui/unseparated_prefix_literals.fixed b/tests/ui/unseparated_prefix_literals.fixed index f0c2ba7ccdf..b6241612d9d 100644 --- a/tests/ui/unseparated_prefix_literals.fixed +++ b/tests/ui/unseparated_prefix_literals.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macro_derive.rs +//@run-rustfix +//@aux-build:proc_macro_derive.rs #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] diff --git a/tests/ui/unseparated_prefix_literals.rs b/tests/ui/unseparated_prefix_literals.rs index f44880b4147..ae583f4bde3 100644 --- a/tests/ui/unseparated_prefix_literals.rs +++ b/tests/ui/unseparated_prefix_literals.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macro_derive.rs +//@run-rustfix +//@aux-build:proc_macro_derive.rs #![warn(clippy::unseparated_literal_suffix)] #![allow(dead_code)] diff --git a/tests/ui/unused_rounding.fixed b/tests/ui/unused_rounding.fixed index f6f734c05ed..f02b55502a0 100644 --- a/tests/ui/unused_rounding.fixed +++ b/tests/ui/unused_rounding.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unused_rounding)] fn main() { diff --git a/tests/ui/unused_rounding.rs b/tests/ui/unused_rounding.rs index a0267d8144a..c7bd4906d0b 100644 --- a/tests/ui/unused_rounding.rs +++ b/tests/ui/unused_rounding.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unused_rounding)] fn main() { diff --git a/tests/ui/unused_unit.fixed b/tests/ui/unused_unit.fixed index 3dd640b86f0..7b8f7847dbf 100644 --- a/tests/ui/unused_unit.fixed +++ b/tests/ui/unused_unit.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // The output for humans should just highlight the whole span without showing // the suggested replacement, but we also want to test that suggested diff --git a/tests/ui/unused_unit.rs b/tests/ui/unused_unit.rs index bddecf06fb7..fdde1ecadf0 100644 --- a/tests/ui/unused_unit.rs +++ b/tests/ui/unused_unit.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix // The output for humans should just highlight the whole span without showing // the suggested replacement, but we also want to test that suggested diff --git a/tests/ui/unwrap_or_else_default.fixed b/tests/ui/unwrap_or_else_default.fixed index 84f779569ff..59a0ca3f192 100644 --- a/tests/ui/unwrap_or_else_default.fixed +++ b/tests/ui/unwrap_or_else_default.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unwrap_or_else_default)] #![allow(dead_code)] diff --git a/tests/ui/unwrap_or_else_default.rs b/tests/ui/unwrap_or_else_default.rs index 1735bd5808e..97cafa336ed 100644 --- a/tests/ui/unwrap_or_else_default.rs +++ b/tests/ui/unwrap_or_else_default.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::unwrap_or_else_default)] #![allow(dead_code)] diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 3ac6217312a..89ea14759b7 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macro_derive.rs +//@run-rustfix +//@aux-build:proc_macro_derive.rs #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 9dc5d1e3f9b..49e5bcb7ed9 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macro_derive.rs +//@run-rustfix +//@aux-build:proc_macro_derive.rs #![warn(clippy::use_self)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/use_self_trait.fixed b/tests/ui/use_self_trait.fixed index 4e779308d02..4623aeeb0eb 100644 --- a/tests/ui/use_self_trait.fixed +++ b/tests/ui/use_self_trait.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::use_self)] #![allow(dead_code)] diff --git a/tests/ui/use_self_trait.rs b/tests/ui/use_self_trait.rs index 325dc73b21e..d7d76dd9623 100644 --- a/tests/ui/use_self_trait.rs +++ b/tests/ui/use_self_trait.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::use_self)] #![allow(dead_code)] diff --git a/tests/ui/used_underscore_binding.rs b/tests/ui/used_underscore_binding.rs index 8c29e15b145..c672eff1c27 100644 --- a/tests/ui/used_underscore_binding.rs +++ b/tests/ui/used_underscore_binding.rs @@ -1,4 +1,4 @@ -// aux-build:proc_macro_derive.rs +//@aux-build:proc_macro_derive.rs #![feature(rustc_private)] #![warn(clippy::all)] #![warn(clippy::used_underscore_binding)] diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index 38e4b9201e6..490d36ae6d6 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::useless_asref)] #![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)] diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index f1e83f9d396..f2681af924d 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::useless_asref)] #![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)] diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index 871e4fb5c3a..de6660c95e6 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macro_derive.rs +//@run-rustfix +//@aux-build:proc_macro_derive.rs #![allow(unused)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index cb50736ba39..8de4331e8a6 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:proc_macro_derive.rs +//@run-rustfix +//@aux-build:proc_macro_derive.rs #![allow(unused)] #![warn(clippy::useless_attribute)] diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index 94b206d8e58..01eb6c5b080 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::useless_conversion)] #![allow(clippy::unnecessary_wraps)] diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index c7ae927941b..34b43a6299b 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![deny(clippy::useless_conversion)] #![allow(clippy::unnecessary_wraps)] diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index 2518d804915..d77a4dd8e0b 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::useless_vec)] #![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index e1492e2f3ae..dfed3a29a03 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::useless_vec)] #![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)] diff --git a/tests/ui/vec_box_sized.fixed b/tests/ui/vec_box_sized.fixed index a40d91fdb18..0d0f710b558 100644 --- a/tests/ui/vec_box_sized.fixed +++ b/tests/ui/vec_box_sized.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs index 843bbb64e71..fd3a7543ee1 100644 --- a/tests/ui/vec_box_sized.rs +++ b/tests/ui/vec_box_sized.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(dead_code)] diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index 5afa0a89f82..c2f216a8911 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::while_let_on_iterator)] #![allow(dead_code, unreachable_code, unused_mut)] #![allow( diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 3de586c9d8f..971bd5f0c4a 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![warn(clippy::while_let_on_iterator)] #![allow(dead_code, unreachable_code, unused_mut)] #![allow( diff --git a/tests/ui/wildcard_enum_match_arm.fixed b/tests/ui/wildcard_enum_match_arm.fixed index 293bf75a717..ccb40acfbe1 100644 --- a/tests/ui/wildcard_enum_match_arm.fixed +++ b/tests/ui/wildcard_enum_match_arm.fixed @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:non-exhaustive-enum.rs +//@run-rustfix +//@aux-build:non-exhaustive-enum.rs #![deny(clippy::wildcard_enum_match_arm)] #![allow(dead_code, unreachable_code, unused_variables)] #![allow( diff --git a/tests/ui/wildcard_enum_match_arm.rs b/tests/ui/wildcard_enum_match_arm.rs index decd86165f3..3ce00b021a5 100644 --- a/tests/ui/wildcard_enum_match_arm.rs +++ b/tests/ui/wildcard_enum_match_arm.rs @@ -1,5 +1,5 @@ -// run-rustfix -// aux-build:non-exhaustive-enum.rs +//@run-rustfix +//@aux-build:non-exhaustive-enum.rs #![deny(clippy::wildcard_enum_match_arm)] #![allow(dead_code, unreachable_code, unused_variables)] #![allow( diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 0baec6f0b64..bd845361fa8 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -1,6 +1,6 @@ -// edition:2015 -// run-rustfix -// aux-build:wildcard_imports_helper.rs +//@edition:2015 +//@run-rustfix +//@aux-build:wildcard_imports_helper.rs // the 2015 edition here is needed because edition 2018 changed the module system // (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index db591d56ab4..fb51f7bdfcc 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -1,6 +1,6 @@ -// edition:2015 -// run-rustfix -// aux-build:wildcard_imports_helper.rs +//@edition:2015 +//@run-rustfix +//@aux-build:wildcard_imports_helper.rs // the 2015 edition here is needed because edition 2018 changed the module system // (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint diff --git a/tests/ui/wildcard_imports_2021.edition2018.fixed b/tests/ui/wildcard_imports_2021.edition2018.fixed index 6d534a10edc..3aea013fb3a 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -1,8 +1,8 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix -// aux-build:wildcard_imports_helper.rs +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix +//@aux-build:wildcard_imports_helper.rs #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/tests/ui/wildcard_imports_2021.edition2021.fixed b/tests/ui/wildcard_imports_2021.edition2021.fixed index 6d534a10edc..3aea013fb3a 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -1,8 +1,8 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix -// aux-build:wildcard_imports_helper.rs +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix +//@aux-build:wildcard_imports_helper.rs #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/tests/ui/wildcard_imports_2021.rs b/tests/ui/wildcard_imports_2021.rs index b5ed58e6813..40c2d07527d 100644 --- a/tests/ui/wildcard_imports_2021.rs +++ b/tests/ui/wildcard_imports_2021.rs @@ -1,8 +1,8 @@ -// revisions: edition2018 edition2021 -//[edition2018] edition:2018 -//[edition2021] edition:2021 -// run-rustfix -// aux-build:wildcard_imports_helper.rs +//@revisions: edition2018 edition2021 +//@[edition2018] edition:2018 +//@[edition2021] edition:2021 +//@run-rustfix +//@aux-build:wildcard_imports_helper.rs #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/tests/ui/wildcard_imports_2021.stderr b/tests/ui/wildcard_imports_2021.stderr deleted file mode 100644 index 92f6d31530f..00000000000 --- a/tests/ui/wildcard_imports_2021.stderr +++ /dev/null @@ -1,132 +0,0 @@ -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:9:5 - | -LL | use crate::fn_mod::*; - | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` - | - = note: `-D clippy::wildcard-imports` implied by `-D warnings` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:10:5 - | -LL | use crate::mod_mod::*; - | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:11:5 - | -LL | use crate::multi_fn_mod::*; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:12:5 - | -LL | use crate::struct_mod::*; - | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:15:5 - | -LL | use wildcard_imports_helper::inner::inner_for_self_import::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:17:5 - | -LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:87:13 - | -LL | use crate::fn_mod::*; - | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:93:75 - | -LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; - | ^ help: try: `inner_extern_foo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:94:13 - | -LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:105:20 - | -LL | use self::{inner::*, inner2::*}; - | ^^^^^^^^ help: try: `inner::inner_foo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:105:30 - | -LL | use self::{inner::*, inner2::*}; - | ^^^^^^^^^ help: try: `inner2::inner_bar` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:112:13 - | -LL | use wildcard_imports_helper::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:141:9 - | -LL | use crate::in_fn_test::*; - | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:150:9 - | -LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:151:9 - | -LL | use crate:: fn_mod:: - | _________^ -LL | | *; - | |_________^ help: try: `crate:: fn_mod::foo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:162:13 - | -LL | use super::*; - | ^^^^^^^^ help: try: `super::foofoo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:197:17 - | -LL | use super::*; - | ^^^^^^^^ help: try: `super::insidefoo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:205:13 - | -LL | use crate::super_imports::*; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:214:17 - | -LL | use super::super::*; - | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:223:13 - | -LL | use super::super::super_imports::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` - -error: usage of wildcard import - --> $DIR/wildcard_imports_2021.rs:231:13 - | -LL | use super::*; - | ^^^^^^^^ help: try: `super::foofoo` - -error: aborting due to 21 previous errors - diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index b79364c8758..35bd9e7f3a0 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -1,5 +1,5 @@ // FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934 -// // run-rustfix +// #![allow(clippy::write_literal)] #![warn(clippy::write_with_newline)] @@ -54,7 +54,7 @@ fn main() { // Don't warn on CRLF (#4208) write!(v, "\r\n"); write!(v, "foo\r\n"); - write!(v, "\\r\n"); //~ ERROR + write!(v, "\\r\n"); write!(v, "foo\rbar\n"); // Ignore expanded format strings diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 2baaea166d8..9035275b29d 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -106,13 +106,13 @@ LL ~ v error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:57:5 | -LL | write!(v, "/r/n"); //~ ERROR +LL | write!(v, "/r/n"); | ^^^^^^^^^^^^^^^^^^ | help: use `writeln!` instead | -LL - write!(v, "/r/n"); //~ ERROR -LL + writeln!(v, "/r"); //~ ERROR +LL - write!(v, "/r/n"); +LL + writeln!(v, "/r"); | error: aborting due to 9 previous errors diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed index e7d94acd130..45dedd9ead6 100644 --- a/tests/ui/writeln_empty_string.fixed +++ b/tests/ui/writeln_empty_string.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_must_use)] #![warn(clippy::writeln_empty_string)] diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 662c62f0211..3b9f51a15d2 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused_must_use)] #![warn(clippy::writeln_empty_string)] diff --git a/tests/ui/zero_ptr.fixed b/tests/ui/zero_ptr.fixed index 489aa4121a3..bed38ecafc7 100644 --- a/tests/ui/zero_ptr.fixed +++ b/tests/ui/zero_ptr.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix pub fn foo(_const: *const f32, _mut: *mut i64) {} fn main() { diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index c3b55ef9ebd..b7b778915a8 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix pub fn foo(_const: *const f32, _mut: *mut i64) {} fn main() { diff --git a/tests/ui/zero_ptr_no_std.fixed b/tests/ui/zero_ptr_no_std.fixed index 8906c776977..7afd80ccaca 100644 --- a/tests/ui/zero_ptr_no_std.fixed +++ b/tests/ui/zero_ptr_no_std.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/zero_ptr_no_std.rs b/tests/ui/zero_ptr_no_std.rs index 379c1b18d29..05a0587d22b 100644 --- a/tests/ui/zero_ptr_no_std.rs +++ b/tests/ui/zero_ptr_no_std.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![feature(lang_items, start, libc)] #![no_std] -- cgit 1.4.1-3-g733a5 From 69da902f417547831009a4957037cd21b5aab678 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 26 Feb 2023 15:44:04 +0100 Subject: Detect if expressions with boolean assignments to the same target --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/needless_bool.rs | 71 ++++++++++++++++++++++++++++++++++-- tests/ui/needless_bool_assign.fixed | 33 +++++++++++++++++ tests/ui/needless_bool_assign.rs | 45 +++++++++++++++++++++++ tests/ui/needless_bool_assign.stderr | 53 +++++++++++++++++++++++++++ 6 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 tests/ui/needless_bool_assign.fixed create mode 100644 tests/ui/needless_bool_assign.rs create mode 100644 tests/ui/needless_bool_assign.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 10dd28a8f6a..f3f43830f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4863,6 +4863,7 @@ Released 2018-09-13 [`needless_arbitrary_self_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_arbitrary_self_type [`needless_bitwise_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bitwise_bool [`needless_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool +[`needless_bool_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_bool_assign [`needless_borrow`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow [`needless_borrowed_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrowed_reference [`needless_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_collect diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index f24dab62780..9633f0d55f7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -445,6 +445,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE_INFO, crate::needless_bool::BOOL_COMPARISON_INFO, crate::needless_bool::NEEDLESS_BOOL_INFO, + crate::needless_bool::NEEDLESS_BOOL_ASSIGN_INFO, crate::needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE_INFO, crate::needless_continue::NEEDLESS_CONTINUE_INFO, crate::needless_for_each::NEEDLESS_FOR_EACH_INFO, diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index c87059bf61d..bd2e39e6ed6 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,10 +3,12 @@ //! This lint is **warn** by default use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::higher; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; -use clippy_utils::{get_parent_node, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt}; +use clippy_utils::{ + get_parent_node, is_else_clause, is_expn_of, peel_blocks, peel_blocks_with_stmt, span_extract_comment, +}; +use clippy_utils::{higher, SpanlessEq}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Node, UnOp}; @@ -77,7 +79,39 @@ declare_clippy_lint! { "comparing a variable to a boolean, e.g., `if x == true` or `if x != true`" } -declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL]); +declare_clippy_lint! { + /// ### What it does + /// Checks for expressions of the form `if c { x = true } else { x = false }` + /// (or vice versa) and suggest assigning the variable directly from the + /// condition. + /// + /// ### Why is this bad? + /// Redundant code. + /// + /// ### Example + /// ```rust,ignore + /// # fn must_keep(x: i32, y: i32) -> bool { x == y } + /// # let x = 32; let y = 10; + /// # let mut skip: bool; + /// if must_keep(x, y) { + /// skip = false; + /// } else { + /// skip = true; + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// # fn must_keep(x: i32, y: i32) -> bool { x == y } + /// # let x = 32; let y = 10; + /// # let mut skip: bool; + /// skip = !must_keep(x, y); + /// ``` + #[clippy::version = "1.69.0"] + pub NEEDLESS_BOOL_ASSIGN, + complexity, + "setting the same boolean variable in both branches of an if-statement" +} +declare_lint_pass!(NeedlessBool => [NEEDLESS_BOOL, NEEDLESS_BOOL_ASSIGN]); fn condition_needs_parentheses(e: &Expr<'_>) -> bool { let mut inner = e; @@ -173,6 +207,29 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool { _ => (), } } + if let Some((lhs_a, a)) = fetch_assign(then) && + let Some((lhs_b, b)) = fetch_assign(r#else) && + SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b) && + span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty() + { + let mut applicability = Applicability::MachineApplicable; + let cond = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability); + let lhs = snippet_with_applicability(cx, lhs_a.span, "..", &mut applicability); + let sugg = if a == b { + format!("{cond}; {lhs} = {a:?};") + } else { + format!("{lhs} = {};", if a { cond } else { !cond }) + }; + span_lint_and_sugg( + cx, + NEEDLESS_BOOL_ASSIGN, + e.span, + "this if-then-else expression assigns a bool literal", + "you can reduce it to", + sugg, + applicability + ); + } } } } @@ -376,3 +433,11 @@ fn fetch_bool_expr(expr: &Expr<'_>) -> Option { } None } + +fn fetch_assign<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, bool)> { + if let ExprKind::Assign(lhs, rhs, _) = peel_blocks_with_stmt(expr).kind { + fetch_bool_expr(rhs).map(|b| (lhs, b)) + } else { + None + } +} diff --git a/tests/ui/needless_bool_assign.fixed b/tests/ui/needless_bool_assign.fixed new file mode 100644 index 00000000000..3ed31d4d711 --- /dev/null +++ b/tests/ui/needless_bool_assign.fixed @@ -0,0 +1,33 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::needless_bool_assign)] + +fn random() -> bool { + true +} + +fn main() { + struct Data { + field: bool, + }; + let mut a = Data { field: false }; + a.field = random() && random(); + a.field = !(random() && random()); + // Do not lint… + if random() { + a.field = false; + } else { + // …to avoid losing this comment + a.field = true + } + // This one also triggers lint `clippy::if_same_then_else` + // which does not suggest a rewrite. + random(); a.field = true; + let mut b = false; + if random() { + a.field = false; + } else { + b = true; + } +} diff --git a/tests/ui/needless_bool_assign.rs b/tests/ui/needless_bool_assign.rs new file mode 100644 index 00000000000..efaeb67fa45 --- /dev/null +++ b/tests/ui/needless_bool_assign.rs @@ -0,0 +1,45 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::needless_bool_assign)] + +fn random() -> bool { + true +} + +fn main() { + struct Data { + field: bool, + }; + let mut a = Data { field: false }; + if random() && random() { + a.field = true; + } else { + a.field = false + } + if random() && random() { + a.field = false; + } else { + a.field = true + } + // Do not lint… + if random() { + a.field = false; + } else { + // …to avoid losing this comment + a.field = true + } + // This one also triggers lint `clippy::if_same_then_else` + // which does not suggest a rewrite. + if random() { + a.field = true; + } else { + a.field = true; + } + let mut b = false; + if random() { + a.field = false; + } else { + b = true; + } +} diff --git a/tests/ui/needless_bool_assign.stderr b/tests/ui/needless_bool_assign.stderr new file mode 100644 index 00000000000..601bbed5493 --- /dev/null +++ b/tests/ui/needless_bool_assign.stderr @@ -0,0 +1,53 @@ +error: this if-then-else expression assigns a bool literal + --> $DIR/needless_bool_assign.rs:15:5 + | +LL | / if random() && random() { +LL | | a.field = true; +LL | | } else { +LL | | a.field = false +LL | | } + | |_____^ help: you can reduce it to: `a.field = random() && random();` + | + = note: `-D clippy::needless-bool-assign` implied by `-D warnings` + +error: this if-then-else expression assigns a bool literal + --> $DIR/needless_bool_assign.rs:20:5 + | +LL | / if random() && random() { +LL | | a.field = false; +LL | | } else { +LL | | a.field = true +LL | | } + | |_____^ help: you can reduce it to: `a.field = !(random() && random());` + +error: this if-then-else expression assigns a bool literal + --> $DIR/needless_bool_assign.rs:34:5 + | +LL | / if random() { +LL | | a.field = true; +LL | | } else { +LL | | a.field = true; +LL | | } + | |_____^ help: you can reduce it to: `random(); a.field = true;` + +error: this `if` has identical blocks + --> $DIR/needless_bool_assign.rs:34:17 + | +LL | if random() { + | _________________^ +LL | | a.field = true; +LL | | } else { + | |_____^ + | +note: same as this + --> $DIR/needless_bool_assign.rs:36:12 + | +LL | } else { + | ____________^ +LL | | a.field = true; +LL | | } + | |_____^ + = note: `#[deny(clippy::if_same_then_else)]` on by default + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From 572eecd267cd89086820ea72f403aba09b6268a2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sun, 23 Apr 2023 15:11:31 +0200 Subject: split test into 2 --- tests/ui/crashes/ice-10645.rs | 7 +++++++ tests/ui/crashes/ice-10645.stderr | 16 ++++++++++++++++ tests/ui/crashes/ice-5207.rs | 4 ---- tests/ui/crashes/ice-5207.stderr | 16 ---------------- 4 files changed, 23 insertions(+), 20 deletions(-) create mode 100644 tests/ui/crashes/ice-10645.rs create mode 100644 tests/ui/crashes/ice-10645.stderr delete mode 100644 tests/ui/crashes/ice-5207.stderr diff --git a/tests/ui/crashes/ice-10645.rs b/tests/ui/crashes/ice-10645.rs new file mode 100644 index 00000000000..4d8698d383b --- /dev/null +++ b/tests/ui/crashes/ice-10645.rs @@ -0,0 +1,7 @@ +// compile-flags: --cap-lints=warn +// https://github.com/rust-lang/rust-clippy/issues/10645 + +#![warn(clippy::future_not_send)] +pub async fn bar<'a, T: 'a>(_: T) {} + +fn main() {} diff --git a/tests/ui/crashes/ice-10645.stderr b/tests/ui/crashes/ice-10645.stderr new file mode 100644 index 00000000000..fc084e30d7f --- /dev/null +++ b/tests/ui/crashes/ice-10645.stderr @@ -0,0 +1,16 @@ +error: future cannot be sent between threads safely + --> $DIR/ice-10645.rs:5:35 + | +LL | pub async fn bar<'a, T: 'a>(_: T) {} + | ^ future returned by `bar` is not `Send` + | +note: captured value is not `Send` + --> $DIR/ice-10645.rs:5:29 + | +LL | pub async fn bar<'a, T: 'a>(_: T) {} + | ^ has type `T` which is not `Send` + = note: `T` doesn't implement `std::marker::Send` + = note: `-D clippy::future-not-send` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/crashes/ice-5207.rs b/tests/ui/crashes/ice-5207.rs index 893c15f5d73..0df8b88fea2 100644 --- a/tests/ui/crashes/ice-5207.rs +++ b/tests/ui/crashes/ice-5207.rs @@ -1,8 +1,4 @@ -// compile-flags: --cap-lints=warn -// ^ for https://github.com/rust-lang/rust-clippy/issues/10645 - // Regression test for https://github.com/rust-lang/rust-clippy/issues/5207 -#![warn(clippy::future_not_send)] pub async fn bar<'a, T: 'a>(_: T) {} fn main() {} diff --git a/tests/ui/crashes/ice-5207.stderr b/tests/ui/crashes/ice-5207.stderr deleted file mode 100644 index 59146c23e0d..00000000000 --- a/tests/ui/crashes/ice-5207.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: future cannot be sent between threads safely - --> $DIR/ice-5207.rs:6:35 - | -LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^ future returned by `bar` is not `Send` - | -note: captured value is not `Send` - --> $DIR/ice-5207.rs:6:29 - | -LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^ has type `T` which is not `Send` - = note: `T` doesn't implement `std::marker::Send` - = note: `-D clippy::future-not-send` implied by `-D warnings` - -error: aborting due to previous error - -- cgit 1.4.1-3-g733a5 From 022baa5ce360d4d90b5ab7141ba1607112fa00a6 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 23 Apr 2023 14:25:19 +0000 Subject: Remove check for `lib.register_*` and `src/docs*` in `cargo dev update_lints` This reverts commit 22d435b26627c1085c5b761846ca08870288794f. --- clippy_dev/src/update_lints.rs | 54 ------------------------------------------ 1 file changed, 54 deletions(-) diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index dd90a38f757..7213c9dfede 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -36,60 +36,6 @@ pub enum UpdateMode { pub fn update(update_mode: UpdateMode) { let (lints, deprecated_lints, renamed_lints) = gather_all(); generate_lint_files(update_mode, &lints, &deprecated_lints, &renamed_lints); - remove_old_files(update_mode); -} - -/// Remove files no longer needed after -/// that may be reintroduced unintentionally -/// -/// FIXME: This is a temporary measure that should be removed when there are no more PRs that -/// include the stray files -fn remove_old_files(update_mode: UpdateMode) { - let mut failed = false; - let mut remove_file = |path: &Path| match update_mode { - UpdateMode::Check => { - if path.exists() { - failed = true; - println!("unexpected file: {}", path.display()); - } - }, - UpdateMode::Change => { - if fs::remove_file(path).is_ok() { - println!("removed file: {}", path.display()); - } - }, - }; - - let files = [ - "clippy_lints/src/lib.register_all.rs", - "clippy_lints/src/lib.register_cargo.rs", - "clippy_lints/src/lib.register_complexity.rs", - "clippy_lints/src/lib.register_correctness.rs", - "clippy_lints/src/lib.register_internal.rs", - "clippy_lints/src/lib.register_lints.rs", - "clippy_lints/src/lib.register_nursery.rs", - "clippy_lints/src/lib.register_pedantic.rs", - "clippy_lints/src/lib.register_perf.rs", - "clippy_lints/src/lib.register_restriction.rs", - "clippy_lints/src/lib.register_style.rs", - "clippy_lints/src/lib.register_suspicious.rs", - "src/docs.rs", - ]; - - for file in files { - remove_file(Path::new(file)); - } - - if let Ok(docs_dir) = fs::read_dir("src/docs") { - for doc_file in docs_dir { - let path = doc_file.unwrap().path(); - remove_file(&path); - } - } - - if failed { - exit_with_failure(); - } } fn generate_lint_files( -- cgit 1.4.1-3-g733a5 From d2061faf9e7774bf8bc3ac6842cd2a095e1f2597 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:59:01 -0400 Subject: Spelling * applying * binding * complex * constituent * demonstrate * desugaring * exact * expression * for * functionalities * github * implementation * infers * multiple conflicting traits * mutable * necessarily * nightly * nonexistent * optional * parameter * reassignments * resources * substitution * suggestion * that * that array is * using the Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../src/development/proposals/syntax-tree-patterns.md | 2 +- clippy_lints/src/casts/mod.rs | 2 +- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/from_over_into.rs | 2 +- clippy_lints/src/functions/misnamed_getters.rs | 2 +- clippy_lints/src/functions/mod.rs | 2 +- clippy_lints/src/large_futures.rs | 2 +- clippy_lints/src/loops/manual_memcpy.rs | 2 +- clippy_lints/src/manual_assert.rs | 2 +- clippy_lints/src/manual_let_else.rs | 2 +- clippy_lints/src/manual_retain.rs | 2 +- clippy_lints/src/missing_trait_methods.rs | 2 +- clippy_lints/src/slow_vector_initialization.rs | 2 +- clippy_lints/src/trailing_empty_array.rs | 2 +- clippy_lints/src/types/mod.rs | 4 ++-- clippy_lints/src/unnecessary_box_returns.rs | 2 +- clippy_utils/src/ty.rs | 4 ++-- lintcheck/src/main.rs | 2 +- tests/ui/auxiliary/proc_macro_attr.rs | 2 +- tests/ui/cast_slice_different_sizes.rs | 2 +- tests/ui/crashes/ice_exact_size.rs | 19 +++++++++++++++++++ tests/ui/crashes/ice_exacte_size.rs | 19 ------------------- tests/ui/from_over_into.stderr | 10 +++++----- tests/ui/from_over_into_unfixable.stderr | 6 +++--- tests/ui/let_with_type_underscore.rs | 2 +- tests/ui/manual_retain.fixed | 4 ++-- tests/ui/manual_retain.rs | 4 ++-- tests/ui/needless_for_each_fixable.fixed | 2 +- tests/ui/needless_for_each_fixable.rs | 2 +- tests/ui/no_mangle_with_rust_abi.rs | 2 +- tests/ui/option_if_let_else.fixed | 2 +- tests/ui/option_if_let_else.rs | 2 +- tests/ui/same_name_method.rs | 2 +- tests/ui/trailing_empty_array.rs | 2 +- tests/ui/uninit.rs | 4 ++-- util/gh-pages/index.html | 2 +- 37 files changed, 65 insertions(+), 65 deletions(-) create mode 100644 tests/ui/crashes/ice_exact_size.rs delete mode 100644 tests/ui/crashes/ice_exacte_size.rs diff --git a/book/src/development/proposals/syntax-tree-patterns.md b/book/src/development/proposals/syntax-tree-patterns.md index 36d722609f4..285488cec55 100644 --- a/book/src/development/proposals/syntax-tree-patterns.md +++ b/book/src/development/proposals/syntax-tree-patterns.md @@ -139,7 +139,7 @@ whether the pattern matched. ## Pattern syntax -The following examples demonstate the pattern syntax: +The following examples demonstrate the pattern syntax: #### Any (`_`) diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index d74bd57fe45..cfeb75eed3b 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -638,7 +638,7 @@ declare_clippy_lint! { #[clippy::version = "1.66.0"] pub AS_PTR_CAST_MUT, nursery, - "casting the result of the `&self`-taking `as_ptr` to a mutabe pointer" + "casting the result of the `&self`-taking `as_ptr` to a mutable pointer" } declare_clippy_lint! { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 970f5004993..1c321f46e2d 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -591,7 +591,7 @@ fn lint_same_cond(cx: &LateContext<'_>, conds: &[&Expr<'_>], ignored_ty_ids: &De conds, |e| hash_expr(cx, e), |lhs, rhs| { - // Ignore eq_expr side effects iff one of the expressin kind is a method call + // Ignore eq_expr side effects iff one of the expression kind is a method call // and the caller is not a mutable, including inner mutable type. if let ExprKind::MethodCall(_, caller, _, _) = lhs.kind { if method_caller_is_mutable(cx, caller, ignored_ty_ids) { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 4762b354392..62b419a5226 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -10,7 +10,7 @@ use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does - /// Checks for usage of the non-existent `=*`, `=!` and `=-` + /// Checks for usage of the nonexistent `=*`, `=!` and `=-` /// operators. /// /// ### Why is this bad? diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index bd66ace4500..10ce2a0f0c7 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { ); } - let message = format!("replace the `Into` implentation with `From<{}>`", middle_trait_ref.self_ty()); + let message = format!("replace the `Into` implementation with `From<{}>`", middle_trait_ref.self_ty()); if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) { diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable); } else { diff --git a/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs index e5945939e60..b244b913314 100644 --- a/clippy_lints/src/functions/misnamed_getters.rs +++ b/clippy_lints/src/functions/misnamed_getters.rs @@ -40,7 +40,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: }; // Body must be &(mut) .name - // self_data is not neccessarilly self, to also lint sub-getters, etc… + // self_data is not necessarily self, to also lint sub-getters, etc… let block_expr = if_chain! { if let ExprKind::Block(block,_) = body.value.kind; diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 7c5e44bb7dc..c485bf8a473 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -330,7 +330,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Lints when `impl Trait` is being used in a function's paremeters. + /// Lints when `impl Trait` is being used in a function's parameters. /// ### Why is this bad? /// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor. /// diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs index 1b054481371..0ca31033b16 100644 --- a/clippy_lints/src/large_futures.rs +++ b/clippy_lints/src/large_futures.rs @@ -11,7 +11,7 @@ declare_clippy_lint! { /// It checks for the size of a `Future` created by `async fn` or `async {}`. /// /// ### Why is this bad? - /// Due to the current [unideal implemention](https://github.com/rust-lang/rust/issues/69826) of `Generator`, + /// Due to the current [unideal implementation](https://github.com/rust-lang/rust/issues/69826) of `Generator`, /// large size of a `Future` may cause stack overflows. /// /// ### Example diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index c87fc4f90e2..d4c3f76b864 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -15,7 +15,7 @@ use rustc_span::symbol::sym; use std::fmt::Display; use std::iter::Iterator; -/// Checks for for loops that sequentially copy items from one slice-like +/// Checks for `for` loops that sequentially copy items from one slice-like /// object to another. pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, diff --git a/clippy_lints/src/manual_assert.rs b/clippy_lints/src/manual_assert.rs index ce5d657bcf0..45ea5aab4c2 100644 --- a/clippy_lints/src/manual_assert.rs +++ b/clippy_lints/src/manual_assert.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert { }; let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par(); let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});"); - // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block + // we show to the user the suggestion without the comments, but when applying the fix, include the comments in the block span_lint_and_then( cx, MANUAL_ASSERT, diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 98e698c6c2a..1247370b74a 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse { if source != MatchSource::Normal { return; } - // Any other number than two arms doesn't (neccessarily) + // Any other number than two arms doesn't (necessarily) // have a trivial mapping to let else. if arms.len() != 2 { return; diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index 72cdb9c1736..5259066eb71 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -46,7 +46,7 @@ declare_clippy_lint! { #[clippy::version = "1.64.0"] pub MANUAL_RETAIN, perf, - "`retain()` is simpler and the same functionalitys" + "`retain()` is simpler and the same functionalities" } pub struct ManualRetain { diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs index e99081ad062..1adecd2caac 100644 --- a/clippy_lints/src/missing_trait_methods.rs +++ b/clippy_lints/src/missing_trait_methods.rs @@ -12,7 +12,7 @@ declare_clippy_lint! { /// Checks if a provided method is used implicitly by a trait /// implementation. A usage example would be a wrapper where every method /// should perform some operation before delegating to the inner type's - /// implemenation. + /// implementation. /// /// This lint should typically be enabled on a specific trait `impl` item /// rather than globally. diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index a2109038a05..858135c8d46 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -74,7 +74,7 @@ enum InitializationType<'tcx> { impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // Matches initialization on reassignements. For example: `vec = Vec::with_capacity(100)` + // Matches initialization on reassignments. For example: `vec = Vec::with_capacity(100)` if_chain! { if let ExprKind::Assign(left, right, _) = expr.kind; diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs index 1382c1a40da..f40229e03a2 100644 --- a/clippy_lints/src/trailing_empty_array.rs +++ b/clippy_lints/src/trailing_empty_array.rs @@ -60,7 +60,7 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_ if let Some(last_field) = data.fields().last(); if let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind; - // Then check if that that array zero-sized + // Then check if that array is zero-sized let length = Const::from_anon_const(cx.tcx, length.def_id); let length = length.try_eval_target_usize(cx.tcx, cx.param_env); if let Some(length) = length; diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index c6834a8fdaa..3c873a5901d 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -90,8 +90,8 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// `Option<_>` represents an optional value. `Option>` - /// represents an optional optional value which is logically the same thing as an optional - /// value but has an unneeded extra level of wrapping. + /// represents an optional value which itself wraps an optional. This is logically the + /// same thing as an optional value but has an unneeded extra level of wrapping. /// /// If you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases, /// consider a custom `enum` instead, with clear names for each case. diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs index 912bcda630b..407a38779aa 100644 --- a/clippy_lints/src/unnecessary_box_returns.rs +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -102,7 +102,7 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns { fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) { // Ignore implementations of traits, because the lint should be on the - // trait, not on the implmentation of it. + // trait, not on the implementation of it. let Node::Item(parent) = cx.tcx.hir().get_parent(item.hir_id()) else { return }; let ItemKind::Impl(parent) = parent.kind else { return }; if parent.of_trait.is_some() { diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 9449f0b5567..3fcab34047e 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -93,7 +93,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through - // and check substituions to find `U`. + // and check substitutions to find `U`. ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { if trait_predicate .trait_ref @@ -1101,7 +1101,7 @@ pub fn make_projection<'tcx>( /// /// This function is for associated types which are "known" to be valid with the given /// substitutions, and as such, will only return `None` when debug assertions are disabled in order -/// to prevent ICE's. With debug assertions enabled this will check that that type normalization +/// to prevent ICE's. With debug assertions enabled this will check that type normalization /// succeeds as well as everything checked by `make_projection`. pub fn make_normalized_projection<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index 23c85298027..03d1877d6c6 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -421,7 +421,7 @@ impl Crate { { let subcrate = &stderr[63..]; println!( - "ERROR: failed to apply some suggetion to {} / to (sub)crate {subcrate}", + "ERROR: failed to apply some suggestion to {} / to (sub)crate {subcrate}", self.name ); } diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index b498fece513..9b4b3aef64a 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -82,7 +82,7 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea elided += 1; // HACK: Syn uses `Span` from the proc_macro2 crate, and does not seem to reexport it. - // In order to avoid adding the dependency, get a default span from a non-existent token. + // In order to avoid adding the dependency, get a default span from a nonexistent token. // A default span is needed to mark the code as coming from expansion. let span = Star::default().span(); diff --git a/tests/ui/cast_slice_different_sizes.rs b/tests/ui/cast_slice_different_sizes.rs index 24d7eb28a19..b77f01883bf 100644 --- a/tests/ui/cast_slice_different_sizes.rs +++ b/tests/ui/cast_slice_different_sizes.rs @@ -23,7 +23,7 @@ fn main() { r_x as *const [i32] } as *const [u8]; - // Check that resores of the same size are detected through blocks + // Check that resources of the same size are detected through blocks let restore_block_1 = { r_x as *const [i32] } as *const [u8] as *const [u32]; let restore_block_2 = { ({ r_x as *const [i32] }) as *const [u8] } as *const [u32]; let restore_block_3 = { diff --git a/tests/ui/crashes/ice_exact_size.rs b/tests/ui/crashes/ice_exact_size.rs new file mode 100644 index 00000000000..30e4b11ec0b --- /dev/null +++ b/tests/ui/crashes/ice_exact_size.rs @@ -0,0 +1,19 @@ +#![deny(clippy::all)] + +/// Test for https://github.com/rust-lang/rust-clippy/issues/1336 + +#[allow(dead_code)] +struct Foo; + +impl Iterator for Foo { + type Item = (); + + fn next(&mut self) -> Option<()> { + let _ = self.len() == 0; + unimplemented!() + } +} + +impl ExactSizeIterator for Foo {} + +fn main() {} diff --git a/tests/ui/crashes/ice_exacte_size.rs b/tests/ui/crashes/ice_exacte_size.rs deleted file mode 100644 index 30e4b11ec0b..00000000000 --- a/tests/ui/crashes/ice_exacte_size.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![deny(clippy::all)] - -/// Test for https://github.com/rust-lang/rust-clippy/issues/1336 - -#[allow(dead_code)] -struct Foo; - -impl Iterator for Foo { - type Item = (); - - fn next(&mut self) -> Option<()> { - let _ = self.len() == 0; - unimplemented!() - } -} - -impl ExactSizeIterator for Foo {} - -fn main() {} diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 3c4d011d6fb..990b905c1b1 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -5,7 +5,7 @@ LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::from-over-into` implied by `-D warnings` -help: replace the `Into` implentation with `From` +help: replace the `Into` implementation with `From` | LL ~ impl From for StringWrapper { LL ~ fn from(val: String) -> Self { @@ -18,7 +18,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: replace the `Into` implentation with `From` +help: replace the `Into` implementation with `From` | LL ~ impl From for SelfType { LL ~ fn from(val: String) -> Self { @@ -31,7 +31,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: replace the `Into` implentation with `From` +help: replace the `Into` implementation with `From` | LL ~ impl From for SelfKeywords { LL ~ fn from(val: X) -> Self { @@ -48,7 +48,7 @@ LL | impl core::convert::Into for crate::ExplicitPaths { | = help: `impl From for Foreign` is allowed by the orphan rules, for more information see https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence -help: replace the `Into` implentation with `From` +help: replace the `Into` implementation with `From` | LL ~ impl core::convert::From for bool { LL ~ fn from(mut val: crate::ExplicitPaths) -> Self { @@ -64,7 +64,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into> for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: replace the `Into` implentation with `From>` +help: replace the `Into` implementation with `From>` | LL ~ impl From> for FromOverInto { LL ~ fn from(val: Vec) -> Self { diff --git a/tests/ui/from_over_into_unfixable.stderr b/tests/ui/from_over_into_unfixable.stderr index 6f6ce351921..251f1d84e74 100644 --- a/tests/ui/from_over_into_unfixable.stderr +++ b/tests/ui/from_over_into_unfixable.stderr @@ -4,7 +4,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: replace the `Into` implentation with `From` + = help: replace the `Into` implementation with `From` = note: `-D clippy::from-over-into` implied by `-D warnings` error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true @@ -13,7 +13,7 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for LL | impl Into for &'static [u8] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: replace the `Into` implentation with `From<&'static [u8]>` + = help: replace the `Into` implementation with `From<&'static [u8]>` error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true --> $DIR/from_over_into_unfixable.rs:28:1 @@ -23,7 +23,7 @@ LL | impl Into for ContainsVal { | = help: `impl From for Foreign` is allowed by the orphan rules, for more information see https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence - = help: replace the `Into` implentation with `From` + = help: replace the `Into` implementation with `From` error: aborting due to 3 previous errors diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index 175718b94c8..7c1835e8cd1 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -12,7 +12,7 @@ fn main() { let _: _ = 2; let x: _ = func(); - let x = 1; // Will not lint, Rust inferres this to an integer before Clippy + let x = 1; // Will not lint, Rust infers this to an integer before Clippy let x = func(); let x: Vec<_> = Vec::::new(); let x: [_; 1] = [1]; diff --git a/tests/ui/manual_retain.fixed b/tests/ui/manual_retain.fixed index 8f25fea678f..fa3773dc908 100644 --- a/tests/ui/manual_retain.fixed +++ b/tests/ui/manual_retain.fixed @@ -23,8 +23,8 @@ fn main() { } fn binary_heap_retain() { - // NOTE: Do not lint now, because binary_heap_retain is nighyly API. - // And we need to add a test case for msrv if we update this implmention. + // NOTE: Do not lint now, because binary_heap_retain is nightly API. + // And we need to add a test case for msrv if we update this implementation. // https://github.com/rust-lang/rust/issues/71503 let mut heap = BinaryHeap::from([1, 2, 3]); heap = heap.into_iter().filter(|x| x % 2 == 0).collect(); diff --git a/tests/ui/manual_retain.rs b/tests/ui/manual_retain.rs index e6b3995a689..f982a105597 100644 --- a/tests/ui/manual_retain.rs +++ b/tests/ui/manual_retain.rs @@ -23,8 +23,8 @@ fn main() { } fn binary_heap_retain() { - // NOTE: Do not lint now, because binary_heap_retain is nighyly API. - // And we need to add a test case for msrv if we update this implmention. + // NOTE: Do not lint now, because binary_heap_retain is nightly API. + // And we need to add a test case for msrv if we update this implementation. // https://github.com/rust-lang/rust/issues/71503 let mut heap = BinaryHeap::from([1, 2, 3]); heap = heap.into_iter().filter(|x| x % 2 == 0).collect(); diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed index 09e671b88e1..5ee7f1fb2b6 100644 --- a/tests/ui/needless_for_each_fixable.fixed +++ b/tests/ui/needless_for_each_fixable.fixed @@ -110,7 +110,7 @@ fn should_not_lint() { }), } - // `for_each` is in a let bingind. + // `for_each` is in a let binding. let _ = v.iter().for_each(|elem| { acc += elem; }); diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs index abb4045b919..ec4da9eb997 100644 --- a/tests/ui/needless_for_each_fixable.rs +++ b/tests/ui/needless_for_each_fixable.rs @@ -110,7 +110,7 @@ fn should_not_lint() { }), } - // `for_each` is in a let bingind. + // `for_each` is in a let binding. let _ = v.iter().for_each(|elem| { acc += elem; }); diff --git a/tests/ui/no_mangle_with_rust_abi.rs b/tests/ui/no_mangle_with_rust_abi.rs index b32e721110e..818119f7be5 100644 --- a/tests/ui/no_mangle_with_rust_abi.rs +++ b/tests/ui/no_mangle_with_rust_abi.rs @@ -25,7 +25,7 @@ fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lin 0 } -// Must not run on functions that explicitly opt in to Rust ABI with `extern "Rust"` +// Must not run on functions that explicitly opt in to using the Rust ABI with `extern "Rust"` #[no_mangle] #[rustfmt::skip] extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {} diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index 0456005dce4..d4343c98d27 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -97,7 +97,7 @@ enum DummyEnum { Two, } -// should not warn since there is a compled complex subpat +// should not warn since there is a complex subpat // see #7991 fn complex_subpat() -> DummyEnum { let x = Some(DummyEnum::One(1)); diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 23b148752cb..c78e31fed96 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -120,7 +120,7 @@ enum DummyEnum { Two, } -// should not warn since there is a compled complex subpat +// should not warn since there is a complex subpat // see #7991 fn complex_subpat() -> DummyEnum { let x = Some(DummyEnum::One(1)); diff --git a/tests/ui/same_name_method.rs b/tests/ui/same_name_method.rs index daef95a425c..f31a7e33c4b 100644 --- a/tests/ui/same_name_method.rs +++ b/tests/ui/same_name_method.rs @@ -62,7 +62,7 @@ mod should_lint { impl T1 for S {} } - mod multiply_conflicit_trait { + mod multiple_conflicting_traits { use crate::{T1, T2}; struct S; diff --git a/tests/ui/trailing_empty_array.rs b/tests/ui/trailing_empty_array.rs index 8e3749eef35..928475b5f35 100644 --- a/tests/ui/trailing_empty_array.rs +++ b/tests/ui/trailing_empty_array.rs @@ -144,7 +144,7 @@ struct ReprCAlign { // NOTE: because of https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-representation-of-enums-with-fields and I'm not sure when in the compilation pipeline that would happen #[repr(C)] -enum DontLintAnonymousStructsFromDesuraging { +enum DontLintAnonymousStructsFromDesugaring { A(u32), B(f32, [u64; 0]), C { x: u32, y: [u64; 0] }, diff --git a/tests/ui/uninit.rs b/tests/ui/uninit.rs index c996de89422..2d567630e15 100644 --- a/tests/ui/uninit.rs +++ b/tests/ui/uninit.rs @@ -17,10 +17,10 @@ fn main() { // This is OK, because `MaybeUninit` allows uninitialized data. let _: MaybeUninit = unsafe { MaybeUninit::uninit().assume_init() }; - // This is OK, because all constitutent types are uninit-compatible. + // This is OK, because all constituent types are uninit-compatible. let _: (MaybeUninit, MaybeUninit) = unsafe { MaybeUninit::uninit().assume_init() }; - // This is OK, because all constitutent types are uninit-compatible. + // This is OK, because all constituent types are uninit-compatible. let _: (MaybeUninit, [MaybeUninit; 2]) = unsafe { MaybeUninit::uninit().assume_init() }; // This is OK, because our own MaybeUninit is just as fine as the one from core. diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html index e46ad2c6e0e..8791debad72 100644 --- a/util/gh-pages/index.html +++ b/util/gh-pages/index.html @@ -564,7 +564,7 @@ Otherwise, have a great day =^.^= - Fork me on Github + Fork me on GitHub -- cgit 1.4.1-3-g733a5 From 6f7801f810644c22dfe8c089b5ccc32c9de833d7 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:22:43 -0400 Subject: Rewrite search_same description --- clippy_utils/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index f1d2ae220f8..35378143a79 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2233,8 +2233,12 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)> where Hash: Fn(&T) -> u64, -- cgit 1.4.1-3-g733a5 From e8726b20b2a64b4553c87d02a330fd2bc62064bd Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 23 Apr 2023 21:34:42 +0200 Subject: also check for rest pat in `redundant_pattern_matching` --- clippy_lints/src/indexing_slicing.rs | 2 +- .../src/matches/redundant_pattern_match.rs | 7 +++++-- tests/ui/redundant_pattern_matching_option.fixed | 2 ++ tests/ui/redundant_pattern_matching_option.rs | 2 ++ tests/ui/redundant_pattern_matching_option.stderr | 24 ++++++++++++++-------- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index c384172fbde..924a361c0f6 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -170,7 +170,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { return; } // Index is a constant uint. - if let Some(..) = constant(cx, cx.typeck_results(), index) { + if constant(cx, cx.typeck_results(), index).is_some() { // Let rustc's `const_err` lint handle constant `usize` indexing on arrays. return; } diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index fb9f9c1122f..af121f317cd 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -63,8 +63,11 @@ fn find_sugg_for_if_let<'tcx>( // Determine which function should be used, and the type contained by the corresponding // variant. let (good_method, inner_ty) = match check_pat.kind { - PatKind::TupleStruct(ref qpath, [sub_pat], _) => { - if let PatKind::Wild = sub_pat.kind { + PatKind::TupleStruct(ref qpath, args, rest) => { + let is_wildcard = matches!(args.first().map(|p| &p.kind), Some(PatKind::Wild)); + let is_rest = matches!((args, rest.as_opt_usize()), ([], Some(_))); + + if is_wildcard || is_rest { let res = cx.typeck_results().qpath_res(qpath, check_pat.hir_id); let Some(id) = res.opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id)) else { return }; let lang_items = cx.tcx.lang_items(); diff --git a/tests/ui/redundant_pattern_matching_option.fixed b/tests/ui/redundant_pattern_matching_option.fixed index 87100b97288..d62f7d26a35 100644 --- a/tests/ui/redundant_pattern_matching_option.fixed +++ b/tests/ui/redundant_pattern_matching_option.fixed @@ -54,6 +54,8 @@ fn main() { } else { 3 }; + + if gen_opt().is_some() {} } fn gen_opt() -> Option<()> { diff --git a/tests/ui/redundant_pattern_matching_option.rs b/tests/ui/redundant_pattern_matching_option.rs index 0b69e13f655..d6429426573 100644 --- a/tests/ui/redundant_pattern_matching_option.rs +++ b/tests/ui/redundant_pattern_matching_option.rs @@ -63,6 +63,8 @@ fn main() { } else { 3 }; + + if let Some(..) = gen_opt() {} } fn gen_opt() -> Option<()> { diff --git a/tests/ui/redundant_pattern_matching_option.stderr b/tests/ui/redundant_pattern_matching_option.stderr index 27ff812ba45..7c5a047e455 100644 --- a/tests/ui/redundant_pattern_matching_option.stderr +++ b/tests/ui/redundant_pattern_matching_option.stderr @@ -89,31 +89,37 @@ LL | } else if let None = gen_opt() { | -------^^^^------------ help: try this: `if gen_opt().is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:80:12 + --> $DIR/redundant_pattern_matching_option.rs:67:12 + | +LL | if let Some(..) = gen_opt() {} + | -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()` + +error: redundant pattern matching, consider using `is_some()` + --> $DIR/redundant_pattern_matching_option.rs:82:12 | LL | if let Some(_) = Some(42) {} | -------^^^^^^^----------- help: try this: `if Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:82:12 + --> $DIR/redundant_pattern_matching_option.rs:84:12 | LL | if let None = None::<()> {} | -------^^^^------------- help: try this: `if None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:84:15 + --> $DIR/redundant_pattern_matching_option.rs:86:15 | LL | while let Some(_) = Some(42) {} | ----------^^^^^^^----------- help: try this: `while Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:86:15 + --> $DIR/redundant_pattern_matching_option.rs:88:15 | LL | while let None = None::<()> {} | ----------^^^^------------- help: try this: `while None::<()>.is_none()` error: redundant pattern matching, consider using `is_some()` - --> $DIR/redundant_pattern_matching_option.rs:88:5 + --> $DIR/redundant_pattern_matching_option.rs:90:5 | LL | / match Some(42) { LL | | Some(_) => true, @@ -122,7 +128,7 @@ LL | | }; | |_____^ help: try this: `Some(42).is_some()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:93:5 + --> $DIR/redundant_pattern_matching_option.rs:95:5 | LL | / match None::<()> { LL | | Some(_) => false, @@ -131,16 +137,16 @@ LL | | }; | |_____^ help: try this: `None::<()>.is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:101:12 + --> $DIR/redundant_pattern_matching_option.rs:103:12 | LL | if let None = *(&None::<()>) {} | -------^^^^----------------- help: try this: `if (&None::<()>).is_none()` error: redundant pattern matching, consider using `is_none()` - --> $DIR/redundant_pattern_matching_option.rs:102:12 + --> $DIR/redundant_pattern_matching_option.rs:104:12 | LL | if let None = *&None::<()> {} | -------^^^^--------------- help: try this: `if (&None::<()>).is_none()` -error: aborting due to 21 previous errors +error: aborting due to 22 previous errors -- cgit 1.4.1-3-g733a5 From 6c859b6d2e8c14cb83dde578884f31596a869182 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Mon, 24 Apr 2023 09:47:54 +0200 Subject: Clippy book: hotfix for broken link --- book/src/development/lint_passes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/development/lint_passes.md b/book/src/development/lint_passes.md index c41b6ea0de8..131f6455fde 100644 --- a/book/src/development/lint_passes.md +++ b/book/src/development/lint_passes.md @@ -50,7 +50,7 @@ questions already, but the parser is okay with it. This is what we mean when we say `EarlyLintPass` deals with only syntax on the AST level. Alternatively, think of the `foo_functions` lint we mentioned in -[define new lints](define_lints.md#name-the-lint) chapter. +define new lints chapter. We want the `foo_functions` lint to detect functions with `foo` as their name. Writing a lint that only checks for the name of a function means that we only -- cgit 1.4.1-3-g733a5 From 3045998bcc2f6cea7611bb02455faa8a9cf081bf Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Mon, 24 Apr 2023 12:01:29 -0500 Subject: Update allow_attributes_false_positive.rs --- tests/ui/allow_attributes_false_positive.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/allow_attributes_false_positive.rs b/tests/ui/allow_attributes_false_positive.rs index a34a5d91ef5..5c3407628be 100644 --- a/tests/ui/allow_attributes_false_positive.rs +++ b/tests/ui/allow_attributes_false_positive.rs @@ -1,4 +1,3 @@ -#![allow(unused)] #![warn(clippy::allow_attributes)] #![feature(lint_reasons)] #![crate_type = "proc-macro"] -- cgit 1.4.1-3-g733a5 From 4a76b6f04f9731ab1c106f33a1023658e7d06107 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Tue, 25 Apr 2023 00:14:26 +0200 Subject: Add the warning to all documentation. --- README.md | 3 ++- book/src/usage.md | 3 ++- lintcheck/README.md | 4 +++- src/main.rs | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 85798e0e80c..6745e15c006 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,8 @@ cargo clippy #### Automatically applying Clippy suggestions -Clippy can automatically apply some lint suggestions, just like the compiler. +Clippy can automatically apply some lint suggestions, just like the compiler. Note that `--fix` implies +`--all-targets`, so it can fix as much code as it can. ```terminal cargo clippy --fix diff --git a/book/src/usage.md b/book/src/usage.md index 32084a9199b..36448e4cccf 100644 --- a/book/src/usage.md +++ b/book/src/usage.md @@ -111,7 +111,8 @@ fn main() { ### Automatically applying Clippy suggestions -Clippy can automatically apply some lint suggestions, just like the compiler. +Clippy can automatically apply some lint suggestions, just like the compiler. Note that `--fix` implies +`--all-targets`, so it can fix as much code as it can. ```terminal cargo clippy --fix diff --git a/lintcheck/README.md b/lintcheck/README.md index faf3ce9093a..37cc0453809 100644 --- a/lintcheck/README.md +++ b/lintcheck/README.md @@ -79,9 +79,11 @@ is explicitly specified in the options. ### Fix mode You can run `cargo lintcheck --fix` which will run Clippy with `--fix` and -print a warning if Clippy's suggestions fail to apply (if the resulting code does not build). +print a warning if Clippy's suggestions fail to apply (if the resulting code does not build). This lets us spot bad suggestions or false positives automatically in some cases. +> Note: Fix mode implies `--all-targets`, so it can fix as much code as it can. + Please note that the target dir should be cleaned afterwards since clippy will modify the downloaded sources which can lead to unexpected results when running lintcheck again afterwards. diff --git a/src/main.rs b/src/main.rs index c5e9b96cf3f..188ff87abfc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ Usage: Common options: --no-deps Run Clippy only on the given crate, without linting the dependencies - --fix Automatically apply lint suggestions. This flag implies `--no-deps` + --fix Automatically apply lint suggestions. This flag implies `--no-deps` and `--all-targets` -h, --help Print this message -V, --version Print version info and exit --explain LINT Print the documentation for a given lint -- cgit 1.4.1-3-g733a5 From acfb2c45ba337b3265ab35dee5c94d3641c3ccf7 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 18 Apr 2023 02:14:00 -0500 Subject: don't check if from macro invocation --- clippy_lints/src/strings.rs | 4 ++++ tests/ui/string_lit_as_bytes.fixed | 8 ++++++++ tests/ui/string_lit_as_bytes.rs | 8 ++++++++ tests/ui/string_lit_as_bytes.stderr | 12 ++++++------ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index b2f4b310915..c8ea151ffce 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -253,6 +253,10 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use rustc_ast::LitKind; + if e.span.from_expansion() { + return; + } + if_chain! { // Find std::str::converts::from_utf8 if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8); diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 058f2aa54da..14cb799d916 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -3,6 +3,12 @@ #![allow(dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] +macro_rules! b { + ($b:literal) => { + const C: &[u8] = $b.as_bytes(); + } +} + fn str_lit_as_bytes() { let bs = b"hello there"; @@ -11,6 +17,8 @@ fn str_lit_as_bytes() { let bs = b"lit to string".to_vec(); let bs = b"lit to owned".to_vec(); + b!("aaa"); + // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); let ubs = "hello there! this is a very long string".as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index b550bea001f..44b468e6bf0 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -3,6 +3,12 @@ #![allow(dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] +macro_rules! b { + ($b:literal) => { + const C: &[u8] = $b.as_bytes(); + } +} + fn str_lit_as_bytes() { let bs = "hello there".as_bytes(); @@ -11,6 +17,8 @@ fn str_lit_as_bytes() { let bs = "lit to string".to_string().into_bytes(); let bs = "lit to owned".to_owned().into_bytes(); + b!("aaa"); + // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); let ubs = "hello there! this is a very long string".as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index f47d6161c6c..5be3eb9f2ff 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -1,5 +1,5 @@ error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:7:14 + --> $DIR/string_lit_as_bytes.rs:13:14 | LL | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` @@ -7,31 +7,31 @@ LL | let bs = "hello there".as_bytes(); = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:9:14 + --> $DIR/string_lit_as_bytes.rs:15:14 | LL | let bs = r###"raw string with 3# plus " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###` error: calling `into_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:11:14 + --> $DIR/string_lit_as_bytes.rs:17:14 | LL | let bs = "lit to string".to_string().into_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to string".to_vec()` error: calling `into_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:12:14 + --> $DIR/string_lit_as_bytes.rs:18:14 | LL | let bs = "lit to owned".to_owned().into_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to owned".to_vec()` error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/string_lit_as_bytes.rs:25:22 + --> $DIR/string_lit_as_bytes.rs:33:22 | LL | let includestr = include_str!("string_lit_as_bytes.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("string_lit_as_bytes.rs")` error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:27:13 + --> $DIR/string_lit_as_bytes.rs:35:13 | LL | let _ = "string with newline/t/n".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"` -- cgit 1.4.1-3-g733a5 From 8efe9ff9fb5bd6c661f7d57d4069b127544ebe8d Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 18 Apr 2023 10:12:34 -0500 Subject: run cargo dev fmt --- tests/ui/string_lit_as_bytes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 44b468e6bf0..7ca383567a3 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -6,7 +6,7 @@ macro_rules! b { ($b:literal) => { const C: &[u8] = $b.as_bytes(); - } + }; } fn str_lit_as_bytes() { -- cgit 1.4.1-3-g733a5 From 1ac30d3c860a5ed67c3d31b9d93c251a19af9c6f Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 18 Apr 2023 10:16:10 -0500 Subject: make cargo test pass --- tests/ui/string_lit_as_bytes.fixed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 14cb799d916..91cdf179b82 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -6,7 +6,7 @@ macro_rules! b { ($b:literal) => { const C: &[u8] = $b.as_bytes(); - } + }; } fn str_lit_as_bytes() { -- cgit 1.4.1-3-g733a5 From 14a6fa4a34d24ec81fe562b71966471efcbb32b2 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Wed, 19 Apr 2023 21:09:27 -0500 Subject: use in_external_macro --- clippy_lints/src/strings.rs | 5 +---- tests/ui/auxiliary/macro_rules.rs | 7 +++++++ tests/ui/string_lit_as_bytes.fixed | 10 ++++++++-- tests/ui/string_lit_as_bytes.rs | 10 ++++++++-- tests/ui/string_lit_as_bytes.stderr | 25 ++++++++++++++++++------- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index c8ea151ffce..5b588e914fd 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -253,10 +253,6 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use rustc_ast::LitKind; - if e.span.from_expansion() { - return; - } - if_chain! { // Find std::str::converts::from_utf8 if let Some(args) = match_function_call(cx, e, &paths::STR_FROM_UTF8); @@ -296,6 +292,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { } if_chain! { + if !in_external_macro(cx.sess(), e.span); if let ExprKind::MethodCall(path, receiver, ..) = &e.kind; if path.ident.name == sym!(as_bytes); if let ExprKind::Lit(lit) = &receiver.kind; diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs index a9bb61451dc..e5bb906663c 100644 --- a/tests/ui/auxiliary/macro_rules.rs +++ b/tests/ui/auxiliary/macro_rules.rs @@ -21,6 +21,13 @@ macro_rules! string_add { }; } +#[macro_export] +macro_rules! string_lit_as_bytes { + ($s:literal) => { + const C: &[u8] = $s.as_bytes(); + }; +} + #[macro_export] macro_rules! mut_mut { () => { diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index 91cdf179b82..3fc11b8b088 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -1,11 +1,15 @@ //@run-rustfix +//@aux-build:macro_rules.rs #![allow(dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] +#[macro_use] +extern crate macro_rules; + macro_rules! b { ($b:literal) => { - const C: &[u8] = $b.as_bytes(); + const B: &[u8] = b"warning"; }; } @@ -17,7 +21,9 @@ fn str_lit_as_bytes() { let bs = b"lit to string".to_vec(); let bs = b"lit to owned".to_vec(); - b!("aaa"); + b!("warning"); + + string_lit_as_bytes!("no warning"); // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index 7ca383567a3..7d54acf630e 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -1,11 +1,15 @@ //@run-rustfix +//@aux-build:macro_rules.rs #![allow(dead_code, unused_variables)] #![warn(clippy::string_lit_as_bytes)] +#[macro_use] +extern crate macro_rules; + macro_rules! b { ($b:literal) => { - const C: &[u8] = $b.as_bytes(); + const B: &[u8] = $b.as_bytes(); }; } @@ -17,7 +21,9 @@ fn str_lit_as_bytes() { let bs = "lit to string".to_string().into_bytes(); let bs = "lit to owned".to_owned().into_bytes(); - b!("aaa"); + b!("warning"); + + string_lit_as_bytes!("no warning"); // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index 5be3eb9f2ff..61b4e210e0f 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -1,5 +1,5 @@ error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:13:14 + --> $DIR/string_lit_as_bytes.rs:17:14 | LL | let bs = "hello there".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` @@ -7,34 +7,45 @@ LL | let bs = "hello there".as_bytes(); = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:15:14 + --> $DIR/string_lit_as_bytes.rs:19:14 | LL | let bs = r###"raw string with 3# plus " ""###.as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###` error: calling `into_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:17:14 + --> $DIR/string_lit_as_bytes.rs:21:14 | LL | let bs = "lit to string".to_string().into_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to string".to_vec()` error: calling `into_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:18:14 + --> $DIR/string_lit_as_bytes.rs:22:14 | LL | let bs = "lit to owned".to_owned().into_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"lit to owned".to_vec()` +error: calling `as_bytes()` on a string literal + --> $DIR/string_lit_as_bytes.rs:12:26 + | +LL | const B: &[u8] = $b.as_bytes(); + | ^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"warning"` +... +LL | b!("warning"); + | ------------- in this macro invocation + | + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/string_lit_as_bytes.rs:33:22 + --> $DIR/string_lit_as_bytes.rs:39:22 | LL | let includestr = include_str!("string_lit_as_bytes.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("string_lit_as_bytes.rs")` error: calling `as_bytes()` on a string literal - --> $DIR/string_lit_as_bytes.rs:35:13 + --> $DIR/string_lit_as_bytes.rs:41:13 | LL | let _ = "string with newline/t/n".as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From 637d10b292bad1417c6661c22ddb7c9b7ca8afac Mon Sep 17 00:00:00 2001 From: xFrednet Date: Tue, 25 Apr 2023 17:32:50 +0200 Subject: Catching, stray, commas, (I'll, never, learn, to, use, them, correctly) :sweat_smile: --- CHANGELOG.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3a340d0cc8..23f4f97ee07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,7 @@ Current stable, released 2023-04-20 ### Enhancements -* [`arithmetic_side_effects`]: No longer lints, if safe constant values are used. +* [`arithmetic_side_effects`]: No longer lints if safe constant values are used. [#10310](https://github.com/rust-lang/rust-clippy/pull/10310) * [`needless_lifetimes`]: Now works in local macros [#10257](https://github.com/rust-lang/rust-clippy/pull/10257) @@ -60,39 +60,39 @@ Current stable, released 2023-04-20 ### False Positive Fixes -* [`explicit_auto_deref`]: Now considers projections, when determining if auto deref is applicable +* [`explicit_auto_deref`]: Now considers projections when determining if auto deref is applicable [#10386](https://github.com/rust-lang/rust-clippy/pull/10386) -* [`manual_let_else`]: Now considers side effects of branches, before linting +* [`manual_let_else`]: Now considers side effects of branches before linting [#10336](https://github.com/rust-lang/rust-clippy/pull/10336) * [`uninlined_format_args`]: No longer lints for arguments with generic parameters [#10343](https://github.com/rust-lang/rust-clippy/pull/10343) -* [`needless_lifetimes`]: No longer lints signatures in macros, if the lifetime is a metavariable +* [`needless_lifetimes`]: No longer lints signatures in macros if the lifetime is a metavariable [#10380](https://github.com/rust-lang/rust-clippy/pull/10380) -* [`len_without_is_empty`]: No longer lints, if `len` as a non-default signature +* [`len_without_is_empty`]: No longer lints if `len` as a non-default signature [#10255](https://github.com/rust-lang/rust-clippy/pull/10255) -* [`unusual_byte_groupings`]: Relaxed the required restrictions for specific sizes, to reduce false +* [`unusual_byte_groupings`]: Relaxed the required restrictions for specific sizes to reduce false positives [#10353](https://github.com/rust-lang/rust-clippy/pull/10353) * [`manual_let_else`]: No longer lints `if-else` blocks if they can divergent [#10332](https://github.com/rust-lang/rust-clippy/pull/10332) * [`expect_used`], [`unwrap_used`], [`dbg_macro`], [`print_stdout`], [`print_stderr`]: No longer lint - in test functions, if `allow-expect-in-tests` is set + in test functions if `allow-expect-in-tests` is set [#10391](https://github.com/rust-lang/rust-clippy/pull/10391) * [`unnecessary_safety_comment`]: No longer lints code inside macros [#10106](https://github.com/rust-lang/rust-clippy/pull/10106) -* [`never_loop`]: No longer lints, for statements following break statements for outer blocks. +* [`never_loop`]: No longer lints statements following break statements for outer blocks. [#10311](https://github.com/rust-lang/rust-clippy/pull/10311) ### Suggestion Fixes/Improvements -* [`box_default`]: The suggestion now includes the type for trait objects, when needed +* [`box_default`]: The suggestion now includes the type for trait objects when needed [#10382](https://github.com/rust-lang/rust-clippy/pull/10382) * [`cast_possible_truncation`]: Now suggests using `try_from` or allowing the lint [#10038](https://github.com/rust-lang/rust-clippy/pull/10038) * [`invalid_regex`]: Regex errors for non-literals or regular strings containing escape sequences will now show the complete error [#10231](https://github.com/rust-lang/rust-clippy/pull/10231) -* [`transmutes_expressible_as_ptr_casts`]: The suggestion now works, if the base type is borrowed +* [`transmutes_expressible_as_ptr_casts`]: The suggestion now works if the base type is borrowed [#10193](https://github.com/rust-lang/rust-clippy/pull/10193) * [`needless_return`]: Now removes all semicolons on the same line [#10187](https://github.com/rust-lang/rust-clippy/pull/10187) @@ -113,7 +113,7 @@ Current stable, released 2023-04-20 ### ICE Fixes -* [`needless_pass_by_value`]: Fixed an ICE, caused by how late bounds were handled +* [`needless_pass_by_value`]: Fixed an ICE caused by how late bounds were handled [#10328](https://github.com/rust-lang/rust-clippy/pull/10328) * [`needless_borrow`]: No longer panics on ambiguous projections [#10403](https://github.com/rust-lang/rust-clippy/pull/10403) -- cgit 1.4.1-3-g733a5 From aa6c27a74e00e8e98cd3ce3e0db6149bb5bc7bcf Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:14:52 -0500 Subject: change names to not be implicitly negative --- clippy_lints/src/lib.rs | 8 +- clippy_lints/src/semicolon_block.rs | 132 ++++++++++----------- clippy_lints/src/utils/conf.rs | 4 +- tests/ui-toml/semicolon_block/clippy.toml | 4 +- .../toml_unknown_key/conf_unknown_key.stderr | 4 +- 5 files changed, 73 insertions(+), 79 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index cb223ce9d16..d8bfb84537d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -932,12 +932,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr)); store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv()))); - let semicolon_inside_block_if_multiline = conf.semicolon_inside_block_if_multiline; - let semicolon_outside_block_if_singleline = conf.semicolon_outside_block_if_singleline; + let semicolon_inside_block_ignore_singleline = conf.semicolon_inside_block_ignore_singleline; + let semicolon_outside_block_ignore_multiline = conf.semicolon_outside_block_ignore_multiline; store.register_late_pass(move |_| { Box::new(semicolon_block::SemicolonBlock::new( - semicolon_inside_block_if_multiline, - semicolon_outside_block_if_singleline, + semicolon_inside_block_ignore_singleline, + semicolon_outside_block_ignore_multiline, )) }); store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck)); diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index c1c0325b786..419d7991f0e 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -68,17 +68,73 @@ impl_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLO #[derive(Copy, Clone)] pub struct SemicolonBlock { - semicolon_inside_block_if_multiline: bool, - semicolon_outside_block_if_singleline: bool, + semicolon_inside_block_ignore_singleline: bool, + semicolon_outside_block_ignore_multiline: bool, } impl SemicolonBlock { - pub fn new(semicolon_inside_block_if_multiline: bool, semicolon_outside_block_if_singleline: bool) -> Self { + pub fn new(semicolon_inside_block_ignore_singleline: bool, semicolon_outside_block_ignore_multiline: bool) -> Self { Self { - semicolon_inside_block_if_multiline, - semicolon_outside_block_if_singleline, + semicolon_inside_block_ignore_singleline, + semicolon_outside_block_ignore_multiline, } } + + fn semicolon_inside_block(self, cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) { + let insert_span = tail.span.source_callsite().shrink_to_hi(); + let remove_span = semi_span.with_lo(block.span.hi()); + + if self.semicolon_inside_block_ignore_singleline && get_line(cx, remove_span) == get_line(cx, insert_span) { + return; + } + + span_lint_and_then( + cx, + SEMICOLON_INSIDE_BLOCK, + semi_span, + "consider moving the `;` inside the block for consistent formatting", + |diag| { + multispan_sugg_with_applicability( + diag, + "put the `;` here", + Applicability::MachineApplicable, + [(remove_span, String::new()), (insert_span, ";".to_owned())], + ); + }, + ); + } + + fn semicolon_outside_block( + self, + cx: &LateContext<'_>, + block: &Block<'_>, + tail_stmt_expr: &Expr<'_>, + semi_span: Span, + ) { + let insert_span = block.span.with_lo(block.span.hi()); + // account for macro calls + let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); + let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); + + if self.semicolon_outside_block_ignore_multiline && get_line(cx, remove_span) != get_line(cx, insert_span) { + return; + } + + span_lint_and_then( + cx, + SEMICOLON_OUTSIDE_BLOCK, + block.span, + "consider moving the `;` outside the block for consistent formatting", + |diag| { + multispan_sugg_with_applicability( + diag, + "put the `;` here", + Applicability::MachineApplicable, + [(remove_span, String::new()), (insert_span, ";".to_owned())], + ); + }, + ); + } } impl LateLintPass<'_> for SemicolonBlock { @@ -98,81 +154,19 @@ impl LateLintPass<'_> for SemicolonBlock { span, .. } = stmt else { return }; - semicolon_outside_block(self, cx, block, expr, span); + self.semicolon_outside_block(cx, block, expr, span); }, StmtKind::Semi(Expr { kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _), .. }) if !block.span.from_expansion() => { - semicolon_inside_block(self, cx, block, tail, stmt.span); + self.semicolon_inside_block(cx, block, tail, stmt.span); }, _ => (), } } } -fn semicolon_inside_block( - conf: &mut SemicolonBlock, - cx: &LateContext<'_>, - block: &Block<'_>, - tail: &Expr<'_>, - semi_span: Span, -) { - let insert_span = tail.span.source_callsite().shrink_to_hi(); - let remove_span = semi_span.with_lo(block.span.hi()); - - if conf.semicolon_inside_block_if_multiline && get_line(cx, remove_span) == get_line(cx, insert_span) { - return; - } - - span_lint_and_then( - cx, - SEMICOLON_INSIDE_BLOCK, - semi_span, - "consider moving the `;` inside the block for consistent formatting", - |diag| { - multispan_sugg_with_applicability( - diag, - "put the `;` here", - Applicability::MachineApplicable, - [(remove_span, String::new()), (insert_span, ";".to_owned())], - ); - }, - ); -} - -fn semicolon_outside_block( - conf: &mut SemicolonBlock, - cx: &LateContext<'_>, - block: &Block<'_>, - tail_stmt_expr: &Expr<'_>, - semi_span: Span, -) { - let insert_span = block.span.with_lo(block.span.hi()); - // account for macro calls - let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span); - let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi()); - - if conf.semicolon_outside_block_if_singleline && get_line(cx, remove_span) != get_line(cx, insert_span) { - return; - } - - span_lint_and_then( - cx, - SEMICOLON_OUTSIDE_BLOCK, - block.span, - "consider moving the `;` outside the block for consistent formatting", - |diag| { - multispan_sugg_with_applicability( - diag, - "put the `;` here", - Applicability::MachineApplicable, - [(remove_span, String::new()), (insert_span, ";".to_owned())], - ); - }, - ); -} - fn get_line(cx: &LateContext<'_>, span: Span) -> Option { if let Ok(line) = cx.sess().source_map().lookup_line(span.lo()) { return Some(line.line); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 939f6cd5f1f..18a6e2a4a3a 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -280,11 +280,11 @@ define_Conf! { /// Lint: SEMICOLON_INSIDE_BLOCK. /// /// Whether to lint only if it's multiline. - (semicolon_inside_block_if_multiline: bool = false), + (semicolon_inside_block_ignore_singleline: bool = false), /// Lint: SEMICOLON_OUTSIDE_BLOCK. /// /// Whether to lint only if it's singleline. - (semicolon_outside_block_if_singleline: bool = false), + (semicolon_outside_block_ignore_multiline: bool = false), /// Lint: DOC_MARKDOWN. /// /// The list of words this lint should not consider as identifiers needing ticks. The value diff --git a/tests/ui-toml/semicolon_block/clippy.toml b/tests/ui-toml/semicolon_block/clippy.toml index cc3bc8cae14..4d03e88deba 100644 --- a/tests/ui-toml/semicolon_block/clippy.toml +++ b/tests/ui-toml/semicolon_block/clippy.toml @@ -1,2 +1,2 @@ -semicolon-inside-block-if-multiline = true -semicolon-outside-block-if-singleline = true +semicolon-inside-block-ignore-singleline = true +semicolon-outside-block-ignore-multiline = true diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index c49c9087946..1e0d7499c7e 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -37,8 +37,8 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie missing-docs-in-crate-items msrv pass-by-value-size-limit - semicolon-inside-block-if-multiline - semicolon-outside-block-if-singleline + semicolon-inside-block-ignore-singleline + semicolon-outside-block-ignore-multiline single-char-binding-names-threshold standard-macro-braces suppress-restriction-lint-in-const -- cgit 1.4.1-3-g733a5 From e3ee10d42851fa2fd88216773b6835b5125e1ddc Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 25 Apr 2023 11:23:02 -0500 Subject: use `//@` for commands in tests --- tests/ui-toml/semicolon_block/both.fixed | 2 +- tests/ui-toml/semicolon_block/both.rs | 2 +- tests/ui-toml/semicolon_block/semicolon_inside_block.fixed | 2 +- tests/ui-toml/semicolon_block/semicolon_inside_block.rs | 2 +- tests/ui-toml/semicolon_block/semicolon_outside_block.fixed | 2 +- tests/ui-toml/semicolon_block/semicolon_outside_block.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ui-toml/semicolon_block/both.fixed b/tests/ui-toml/semicolon_block/both.fixed index 981b661bc78..fc8038a0907 100644 --- a/tests/ui-toml/semicolon_block/both.fixed +++ b/tests/ui-toml/semicolon_block/both.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui-toml/semicolon_block/both.rs b/tests/ui-toml/semicolon_block/both.rs index d4dcd6e7240..52ce1f0387e 100644 --- a/tests/ui-toml/semicolon_block/both.rs +++ b/tests/ui-toml/semicolon_block/both.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed b/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed index 6a08bc905b1..23df9830177 100644 --- a/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui-toml/semicolon_block/semicolon_inside_block.rs b/tests/ui-toml/semicolon_block/semicolon_inside_block.rs index f40848f702e..e8516f79b20 100644 --- a/tests/ui-toml/semicolon_block/semicolon_inside_block.rs +++ b/tests/ui-toml/semicolon_block/semicolon_inside_block.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed b/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed index e2d653dc3c3..7e9055e7110 100644 --- a/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, diff --git a/tests/ui-toml/semicolon_block/semicolon_outside_block.rs b/tests/ui-toml/semicolon_block/semicolon_outside_block.rs index 7ce46431fac..4dc956d8a4b 100644 --- a/tests/ui-toml/semicolon_block/semicolon_outside_block.rs +++ b/tests/ui-toml/semicolon_block/semicolon_outside_block.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow( unused, clippy::unused_unit, -- cgit 1.4.1-3-g733a5 From 9cf96429a7ae13f89def17def0b70aa61d2672eb Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 25 Apr 2023 16:31:51 +0000 Subject: Use `ty::TraitRef::new` in clippy --- clippy_lints/src/derive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index f425dd5fb70..8f5d319cd4f 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -517,7 +517,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate { - trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]), + trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, })))) -- cgit 1.4.1-3-g733a5 From 8c8cf407074b2a1d56a285a575035e1c454c3195 Mon Sep 17 00:00:00 2001 From: Centri3 <114838443+Centri3@users.noreply.github.com> Date: Tue, 25 Apr 2023 14:44:56 -0500 Subject: Update lint_configuration.md --- book/src/lint_configuration.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 78e1a55cff3..16d19965868 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -13,6 +13,8 @@ Please use that command to update the file and do not edit it by hand. | [msrv](#msrv) | `None` | | [cognitive-complexity-threshold](#cognitive-complexity-threshold) | `25` | | [disallowed-names](#disallowed-names) | `["foo", "baz", "quux"]` | +| [semicolon-inside-block-ignore-singleline](#semicolon-inside-block-ignore-singleline) | `false` | +| [semicolon-outside-block-ignore-multiline](#semicolon-outside-block-ignore-multiline) | `false` | | [doc-valid-idents](#doc-valid-idents) | `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` | | [too-many-arguments-threshold](#too-many-arguments-threshold) | `7` | | [type-complexity-threshold](#type-complexity-threshold) | `250` | @@ -202,6 +204,22 @@ default configuration of Clippy. By default, any configuration will replace the * [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) +### semicolon-inside-block-ignore-singleline +Whether to lint only if it's multiline. + +**Default Value:** `false` (`bool`) + +* [semicolon_inside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) + + +### semicolon-outside-block-ignore-multiline +Whether to lint only if it's singleline. + +**Default Value:** `false` (`bool`) + +* [semicolon_outside_block](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) + + ### doc-valid-idents The list of words this lint should not consider as identifiers needing ticks. The value `".."` can be used as part of the list to indicate, that the configured values should be appended to the -- cgit 1.4.1-3-g733a5 From 95648951ea98f4c59f923f7c10b8742df841d66d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 26 Apr 2023 13:48:56 +0000 Subject: Fix uses of `TraitRef::identity` in clippy and rustdoc --- clippy_lints/src/escape.rs | 3 +-- clippy_lints/src/methods/mod.rs | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index d6ab4c25e83..6615f9c9953 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -94,8 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { if trait_item.kind == (AssocItemKind::Fn { has_self: true }) { trait_self_ty = Some( TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id()) - .self_ty() - .skip_binder(), + .self_ty(), ); } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9cafbc2e5f5..09e09728573 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3500,8 +3500,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { let first_arg_span = first_arg_ty.span; let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()) - .self_ty() - .skip_binder(); + .self_ty(); wrong_self_convention::check( cx, item.ident.name.as_str(), @@ -3519,8 +3518,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let TraitItemKind::Fn(_, _) = item.kind; let ret_ty = return_ty(cx, item.owner_id); let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id()) - .self_ty() - .skip_binder(); + .self_ty(); if !ret_ty.contains(self_ty); then { -- cgit 1.4.1-3-g733a5 From 9428138562bad89fc2d7d011fe276cd198e6155a Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Tue, 25 Apr 2023 20:44:09 +0200 Subject: adds lint to detect construction of unit struct using `default` Using `default` to construct a unit struct increases code complexity and adds a function call. This can be avoided by simply removing the call to `default` and simply construct by name. --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + .../src/default_constructed_unit_struct.rs | 66 ++++++++++++++++++++ clippy_lints/src/lib.rs | 2 + tests/ui/default_constructed_unit_struct.rs | 72 ++++++++++++++++++++++ tests/ui/default_constructed_unit_struct.stderr | 28 +++++++++ 6 files changed, 170 insertions(+) create mode 100644 clippy_lints/src/default_constructed_unit_struct.rs create mode 100644 tests/ui/default_constructed_unit_struct.rs create mode 100644 tests/ui/default_constructed_unit_struct.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 23f4f97ee07..735ac59758a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4582,6 +4582,7 @@ Released 2018-09-13 [`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call [`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation [`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const +[`default_constructed_unit_struct`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_constructed_unit_struct [`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_instead_of_iter_empty [`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 4aebd0b7d01..bf30f5b52f7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -105,6 +105,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::dbg_macro::DBG_MACRO_INFO, crate::default::DEFAULT_TRAIT_ACCESS_INFO, crate::default::FIELD_REASSIGN_WITH_DEFAULT_INFO, + crate::default_constructed_unit_struct::DEFAULT_CONSTRUCTED_UNIT_STRUCT_INFO, crate::default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY_INFO, crate::default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK_INFO, crate::default_union_representation::DEFAULT_UNION_REPRESENTATION_INFO, diff --git a/clippy_lints/src/default_constructed_unit_struct.rs b/clippy_lints/src/default_constructed_unit_struct.rs new file mode 100644 index 00000000000..a04f7b9d9a9 --- /dev/null +++ b/clippy_lints/src/default_constructed_unit_struct.rs @@ -0,0 +1,66 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, match_def_path, paths}; +use hir::{def::Res, ExprKind}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Check for construction on unit struct using `default`. + /// + /// ### Why is this bad? + /// This adds code complexity and an unnecessary function call. + /// + /// ### Example + /// ```rust + /// #[derive(Default)] + /// struct S { + /// _marker: PhantomData + /// } + /// + /// let _: S = S { + /// _marker: PhantomData::default() + /// }; + /// ``` + /// Use instead: + /// ```rust + /// let _: S = Something { + /// _marker: PhantomData + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub DEFAULT_CONSTRUCTED_UNIT_STRUCT, + complexity, + "unit structs can be contructed without calling `default`" +} +declare_lint_pass!(DefaultConstructedUnitStruct => [DEFAULT_CONSTRUCTED_UNIT_STRUCT]); + +impl LateLintPass<'_> for DefaultConstructedUnitStruct { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if_chain!( + // make sure we have a call to `Default::default` + if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind; + if let ExprKind::Path(ref qpath) = fn_expr.kind; + if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); + if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); + // make sure we have a struct with no fields (unit struct) + if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); + if def.is_struct() && def.is_payloadfree() + && !def.non_enum_variant().is_field_list_non_exhaustive() + && !is_from_proc_macro(cx, expr); + then { + span_lint_and_sugg( + cx, + DEFAULT_CONSTRUCTED_UNIT_STRUCT, + qpath.last_segment_span(), + "Use of `default` to create a unit struct.", + "remove this call to `default`", + String::new(), + Applicability::MachineApplicable, + ) + } + ); + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 48dbecc9f6a..9af0b17e27b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -94,6 +94,7 @@ mod crate_in_macro_def; mod create_dir; mod dbg_macro; mod default; +mod default_constructed_unit_struct; mod default_instead_of_iter_empty; mod default_numeric_fallback; mod default_union_representation; @@ -970,6 +971,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments)); store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); + store.register_late_pass(|_| Box::new(default_constructed_unit_struct::DefaultConstructedUnitStruct)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/default_constructed_unit_struct.rs b/tests/ui/default_constructed_unit_struct.rs new file mode 100644 index 00000000000..b64da9b863a --- /dev/null +++ b/tests/ui/default_constructed_unit_struct.rs @@ -0,0 +1,72 @@ +#![allow(unused)] +#![warn(clippy::default_constructed_unit_struct)] +use std::marker::PhantomData; + +#[derive(Default)] +struct UnitStruct; + +#[derive(Default)] +struct TupleStruct(usize); + +// no lint for derived impl +#[derive(Default)] +struct NormalStruct { + inner: PhantomData, +} + +struct NonDefaultStruct; + +impl NonDefaultStruct { + fn default() -> Self { + Self + } +} + +#[derive(Default)] +enum SomeEnum { + #[default] + Unit, + Tuple(UnitStruct), + Struct { + inner: usize, + }, +} + +impl NormalStruct { + fn new() -> Self { + // should lint + Self { + inner: PhantomData::default(), + } + } +} + +#[derive(Default)] +struct GenericStruct { + t: T, +} + +impl GenericStruct { + fn new() -> Self { + // should not lint + Self { t: T::default() } + } +} + +#[derive(Default)] +#[non_exhaustive] +struct NonExhaustiveStruct; + +fn main() { + // should lint + let _ = PhantomData::::default(); + let _: PhantomData = PhantomData::default(); + let _ = UnitStruct::default(); + + // should not lint + let _ = TupleStruct::default(); + let _ = NormalStruct::default(); + let _ = NonExhaustiveStruct::default(); + let _ = SomeEnum::default(); + let _ = NonDefaultStruct::default(); +} diff --git a/tests/ui/default_constructed_unit_struct.stderr b/tests/ui/default_constructed_unit_struct.stderr new file mode 100644 index 00000000000..13439414f4a --- /dev/null +++ b/tests/ui/default_constructed_unit_struct.stderr @@ -0,0 +1,28 @@ +error: Use of `default` to create a unit struct. + --> $DIR/default_constructed_unit_struct.rs:39:33 + | +LL | inner: PhantomData::default(), + | ^^^^^^^ help: remove this call to `default` + | + = note: `-D clippy::default-constructed-unit-struct` implied by `-D warnings` + +error: Use of `default` to create a unit struct. + --> $DIR/default_constructed_unit_struct.rs:62:35 + | +LL | let _ = PhantomData::::default(); + | ^^^^^^^ help: remove this call to `default` + +error: Use of `default` to create a unit struct. + --> $DIR/default_constructed_unit_struct.rs:63:44 + | +LL | let _: PhantomData = PhantomData::default(); + | ^^^^^^^ help: remove this call to `default` + +error: Use of `default` to create a unit struct. + --> $DIR/default_constructed_unit_struct.rs:64:25 + | +LL | let _ = UnitStruct::default(); + | ^^^^^^^ help: remove this call to `default` + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From 0339d4e982e21dd29c473f945bf23a0a119648f5 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 27 Apr 2023 08:34:11 +0100 Subject: rename `needs_infer` to `has_infer` --- clippy_utils/src/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index cb700126c2b..a6572011644 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -226,7 +226,7 @@ pub fn implements_trait_with_env<'tcx>( ty_params: impl IntoIterator>>, ) -> bool { // Clippy shouldn't have infer types - assert!(!ty.needs_infer()); + assert!(!ty.has_infer()); let ty = tcx.erase_regions(ty); if ty.has_escaping_bound_vars() { -- cgit 1.4.1-3-g733a5 From 273c898aefeaec89b547f07bce98ad34aee8d38a Mon Sep 17 00:00:00 2001 From: blyxyas Date: Thu, 27 Apr 2023 16:43:51 +0200 Subject: Fix #10713 and move the tests to a subdir --- clippy_lints/src/items_after_test_module.rs | 15 +++++++------- tests/ui/items_after_test_module.rs | 23 ---------------------- tests/ui/items_after_test_module.stderr | 17 ---------------- tests/ui/items_after_test_module/block_module.rs | 23 ++++++++++++++++++++++ .../ui/items_after_test_module/block_module.stderr | 17 ++++++++++++++++ .../ui/items_after_test_module/imported_module.rs | 17 ++++++++++++++++ .../items_after_test_module/imported_module.stderr | 0 tests/ui/items_after_test_module/tests/mod.rs | 1 + 8 files changed, 66 insertions(+), 47 deletions(-) delete mode 100644 tests/ui/items_after_test_module.rs delete mode 100644 tests/ui/items_after_test_module.stderr create mode 100644 tests/ui/items_after_test_module/block_module.rs create mode 100644 tests/ui/items_after_test_module/block_module.stderr create mode 100644 tests/ui/items_after_test_module/imported_module.rs create mode 100644 tests/ui/items_after_test_module/imported_module.stderr create mode 100644 tests/ui/items_after_test_module/tests/mod.rs diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index 52d716feea0..96097575c9c 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -64,20 +64,21 @@ impl LateLintPass<'_> for ItemsAfterTestModule { span_lint_and_help(cx, ITEMS_AFTER_TEST_MODULE, test_mod_span.unwrap().with_hi(item.span.hi()), "items were found after the testing module", None, "move the items to before the testing module was defined"); }}; - if matches!(item.kind, ItemKind::Mod(_)) { - for attr in cx.tcx.get_attrs(item.owner_id.to_def_id(), sym::cfg) { - if_chain! { - if attr.has_name(sym::cfg); + if let ItemKind::Mod(module) = item.kind && item.span.hi() == module.spans.inner_span.hi() { + // Check that it works the same way, the only I way I've found for #10713 + for attr in cx.tcx.get_attrs(item.owner_id.to_def_id(), sym::cfg) { + if_chain! { + if attr.has_name(sym::cfg); if let Some(mitems) = attr.meta_item_list(); if let [mitem] = &*mitems; if mitem.has_name(sym::test); then { - was_test_mod_visited = true; - test_mod_span = Some(item.span); + was_test_mod_visited = true; + test_mod_span = Some(module.spans.inner_span.with_lo(item.span.lo())); } } } - } + } } } } diff --git a/tests/ui/items_after_test_module.rs b/tests/ui/items_after_test_module.rs deleted file mode 100644 index 5136b2557ec..00000000000 --- a/tests/ui/items_after_test_module.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@compile-flags: --test -#![allow(unused)] -#![warn(clippy::items_after_test_module)] - -fn main() {} - -fn should_not_lint() {} - -#[allow(dead_code)] -#[allow(unused)] // Some attributes to check that span replacement is good enough -#[allow(clippy::allow_attributes)] -#[cfg(test)] -mod tests { - #[test] - fn hi() {} -} - -fn should_lint() {} - -const SHOULD_ALSO_LINT: usize = 1; -macro_rules! should_not_lint { - () => {}; -} diff --git a/tests/ui/items_after_test_module.stderr b/tests/ui/items_after_test_module.stderr deleted file mode 100644 index 8f1616dabc1..00000000000 --- a/tests/ui/items_after_test_module.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: items were found after the testing module - --> $DIR/items_after_test_module.rs:13:1 - | -LL | / mod tests { -LL | | #[test] -LL | | fn hi() {} -LL | | } -... | -LL | | () => {}; -LL | | } - | |_^ - | - = help: move the items to before the testing module was defined - = note: `-D clippy::items-after-test-module` implied by `-D warnings` - -error: aborting due to previous error - diff --git a/tests/ui/items_after_test_module/block_module.rs b/tests/ui/items_after_test_module/block_module.rs new file mode 100644 index 00000000000..5136b2557ec --- /dev/null +++ b/tests/ui/items_after_test_module/block_module.rs @@ -0,0 +1,23 @@ +//@compile-flags: --test +#![allow(unused)] +#![warn(clippy::items_after_test_module)] + +fn main() {} + +fn should_not_lint() {} + +#[allow(dead_code)] +#[allow(unused)] // Some attributes to check that span replacement is good enough +#[allow(clippy::allow_attributes)] +#[cfg(test)] +mod tests { + #[test] + fn hi() {} +} + +fn should_lint() {} + +const SHOULD_ALSO_LINT: usize = 1; +macro_rules! should_not_lint { + () => {}; +} diff --git a/tests/ui/items_after_test_module/block_module.stderr b/tests/ui/items_after_test_module/block_module.stderr new file mode 100644 index 00000000000..597f1b9510c --- /dev/null +++ b/tests/ui/items_after_test_module/block_module.stderr @@ -0,0 +1,17 @@ +error: items were found after the testing module + --> $DIR/block_module.rs:13:1 + | +LL | / mod tests { +LL | | #[test] +LL | | fn hi() {} +LL | | } +... | +LL | | () => {}; +LL | | } + | |_^ + | + = help: move the items to before the testing module was defined + = note: `-D clippy::items-after-test-module` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/items_after_test_module/imported_module.rs b/tests/ui/items_after_test_module/imported_module.rs new file mode 100644 index 00000000000..819b6c8a9e0 --- /dev/null +++ b/tests/ui/items_after_test_module/imported_module.rs @@ -0,0 +1,17 @@ +//@compile-flags: --test +#![allow(unused)] +#![warn(clippy::items_after_test_module)] + +fn main() {} + +fn should_not_lint() {} + +#[cfg(test)] +mod tests; // Should not lint + +fn should_lint() {} + +const SHOULD_ALSO_LINT: usize = 1; +macro_rules! should_not_lint { + () => {}; +} diff --git a/tests/ui/items_after_test_module/imported_module.stderr b/tests/ui/items_after_test_module/imported_module.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/ui/items_after_test_module/tests/mod.rs b/tests/ui/items_after_test_module/tests/mod.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/ui/items_after_test_module/tests/mod.rs @@ -0,0 +1 @@ +fn main() {} -- cgit 1.4.1-3-g733a5 From 83504fa7638d70aa726b02ec0fd1ad5d170ae1d1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Apr 2023 19:52:17 +0000 Subject: Make clippy happy --- clippy_lints/src/suspicious_operation_groupings.rs | 2 +- clippy_utils/src/ast_utils.rs | 2 +- tests/ui/future_not_send.stderr | 24 +++++++++++----------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs index fab8e9c2ec1..e2cdc48b583 100644 --- a/clippy_lints/src/suspicious_operation_groupings.rs +++ b/clippy_lints/src/suspicious_operation_groupings.rs @@ -577,7 +577,7 @@ fn ident_difference_expr_with_base_location( | (AssignOp(_, _, _), AssignOp(_, _, _)) | (Assign(_, _, _), Assign(_, _, _)) | (TryBlock(_), TryBlock(_)) - | (Await(_), Await(_)) + | (Await(_, _), Await(_, _)) | (Async(_, _), Async(_, _)) | (Block(_, _), Block(_, _)) | (Closure(_), Closure(_)) diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 1f15598db36..8cc01f1ef97 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -143,7 +143,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Paren(l), _) => eq_expr(l, r), (_, Paren(r)) => eq_expr(l, r), (Err, Err) => true, - (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r), + (Try(l), Try(r)) | (Await(l, _), Await(r, _)) => eq_expr(l, r), (Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)), (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)), (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value), diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index 5b6858e4568..5c6348962a5 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -5,22 +5,22 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:8:19 + --> $DIR/future_not_send.rs:8:20 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | -- has type `std::rc::Rc<[u8]>` which is not `Send` LL | async { true }.await - | ^^^^^^ await occurs here, with `rc` maybe used later + | ^^^^^ await occurs here, with `rc` maybe used later LL | } | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:8:19 + --> $DIR/future_not_send.rs:8:20 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | ---- has type `&std::cell::Cell` which is not `Send` LL | async { true }.await - | ^^^^^^ await occurs here, with `cell` maybe used later + | ^^^^^ await occurs here, with `cell` maybe used later LL | } | - `cell` is later dropped here = note: `std::cell::Cell` doesn't implement `std::marker::Sync` @@ -33,12 +33,12 @@ LL | pub async fn public_future(rc: Rc<[u8]>) { | ^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:12:19 + --> $DIR/future_not_send.rs:12:20 | LL | pub async fn public_future(rc: Rc<[u8]>) { | -- has type `std::rc::Rc<[u8]>` which is not `Send` LL | async { true }.await; - | ^^^^^^ await occurs here, with `rc` maybe used later + | ^^^^^ await occurs here, with `rc` maybe used later LL | } | - `rc` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` @@ -82,12 +82,12 @@ LL | async fn private_future(&self) -> usize { | ^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:35:23 + --> $DIR/future_not_send.rs:35:24 | LL | async fn private_future(&self) -> usize { | ----- has type `&Dummy` which is not `Send` LL | async { true }.await; - | ^^^^^^ await occurs here, with `&self` maybe used later + | ^^^^^ await occurs here, with `&self` maybe used later LL | self.rc.len() LL | } | - `&self` is later dropped here @@ -100,12 +100,12 @@ LL | pub async fn public_future(&self) { | ^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:40:30 + --> $DIR/future_not_send.rs:40:31 | LL | pub async fn public_future(&self) { | ----- has type `&Dummy` which is not `Send` LL | self.private_future().await; - | ^^^^^^ await occurs here, with `&self` maybe used later + | ^^^^^ await occurs here, with `&self` maybe used later LL | } | - `&self` is later dropped here = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` @@ -117,12 +117,12 @@ LL | async fn generic_future(t: T) -> T | ^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:54:19 + --> $DIR/future_not_send.rs:54:20 | LL | let rt = &t; | -- has type `&T` which is not `Send` LL | async { true }.await; - | ^^^^^^ await occurs here, with `rt` maybe used later + | ^^^^^ await occurs here, with `rt` maybe used later LL | t LL | } | - `rt` is later dropped here -- cgit 1.4.1-3-g733a5 From d1f55e6b5313ec389f323a149b7cb4628e97a03a Mon Sep 17 00:00:00 2001 From: Sergen Karaoglan <38327805+SergenKaraoglan@users.noreply.github.com> Date: Thu, 27 Apr 2023 18:43:51 +0100 Subject: run linkcheck in Remark CI fix new lints link install nightly rust-docs run linkcheck without nightly toolchain remove nightly toolchain, add rust-docs component Test Remark Update basics.md Update basics.md Update basics.md update workflow add rust docs toolchain Update remark.yml workflow test manual test update book path add linkcheck book to CI Update lint_passes.md --- .github/workflows/remark.yml | 6 ++++++ book/src/development/lint_passes.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/remark.yml b/.github/workflows/remark.yml index 116058b7c75..0bc2f49f5e9 100644 --- a/.github/workflows/remark.yml +++ b/.github/workflows/remark.yml @@ -36,6 +36,12 @@ jobs: - name: Check *.md files run: git ls-files -z '*.md' | xargs -0 -n 1 -I {} ./node_modules/.bin/remark {} -u lint -f > /dev/null + - name: Linkcheck book + run: | + rustup toolchain install nightly --component rust-docs + curl https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh -o linkcheck.sh + sh linkcheck.sh clippy --path ./book + - name: Build mdbook run: mdbook build book diff --git a/book/src/development/lint_passes.md b/book/src/development/lint_passes.md index c41b6ea0de8..621fc20972e 100644 --- a/book/src/development/lint_passes.md +++ b/book/src/development/lint_passes.md @@ -50,7 +50,7 @@ questions already, but the parser is okay with it. This is what we mean when we say `EarlyLintPass` deals with only syntax on the AST level. Alternatively, think of the `foo_functions` lint we mentioned in -[define new lints](define_lints.md#name-the-lint) chapter. +define new lints chapter. We want the `foo_functions` lint to detect functions with `foo` as their name. Writing a lint that only checks for the name of a function means that we only -- cgit 1.4.1-3-g733a5 From 81a614145f689fca24bed3020eb7837aee1d874d Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 28 Apr 2023 17:17:46 +0000 Subject: uplift `clippy::clone_double_ref` as `suspicious_double_ref_op` --- clippy_lints/src/declared_lints.rs | 1 - clippy_lints/src/methods/clone_on_copy.rs | 40 +------------- clippy_lints/src/methods/mod.rs | 24 -------- clippy_lints/src/renamed_lints.rs | 1 + tests/ui/explicit_deref_methods.fixed | 2 +- tests/ui/explicit_deref_methods.rs | 2 +- tests/ui/rename.fixed | 2 + tests/ui/rename.rs | 2 + tests/ui/rename.stderr | 92 ++++++++++++++++--------------- tests/ui/unnecessary_clone.rs | 13 ----- tests/ui/unnecessary_clone.stderr | 52 +---------------- 11 files changed, 61 insertions(+), 170 deletions(-) diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 0c66d36a1d6..fa726a64937 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -313,7 +313,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::CHARS_NEXT_CMP_INFO, crate::methods::CLEAR_WITH_DRAIN_INFO, crate::methods::CLONED_INSTEAD_OF_COPIED_INFO, - crate::methods::CLONE_DOUBLE_REF_INFO, crate::methods::CLONE_ON_COPY_INFO, crate::methods::CLONE_ON_REF_PTR_INFO, crate::methods::COLLAPSIBLE_STR_REPLACE_INFO, diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index 3795c0ec250..65fd50dff58 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -1,7 +1,6 @@ -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_node; use clippy_utils::source::snippet_with_context; -use clippy_utils::sugg; use clippy_utils::ty::is_copy; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; @@ -9,7 +8,6 @@ use rustc_lint::LateContext; use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths}; use rustc_span::symbol::{sym, Symbol}; -use super::CLONE_DOUBLE_REF; use super::CLONE_ON_COPY; /// Checks for the `CLONE_ON_COPY` lint. @@ -42,41 +40,7 @@ pub(super) fn check( let ty = cx.typeck_results().expr_ty(expr); if let ty::Ref(_, inner, _) = arg_ty.kind() { - if let ty::Ref(_, innermost, _) = inner.kind() { - span_lint_and_then( - cx, - CLONE_DOUBLE_REF, - expr.span, - &with_forced_trimmed_paths!(format!( - "using `clone` on a double-reference; \ - this will copy the reference of type `{ty}` instead of cloning the inner type" - )), - |diag| { - if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - let mut ty = innermost; - let mut n = 0; - while let ty::Ref(_, inner, _) = ty.kind() { - ty = inner; - n += 1; - } - let refs = "&".repeat(n + 1); - let derefs = "*".repeat(n); - let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})")); - diag.span_suggestion( - expr.span, - "try dereferencing it", - with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())), - Applicability::MaybeIncorrect, - ); - diag.span_suggestion( - expr.span, - "or try being explicit if you are sure, that you want to clone a reference", - explicit, - Applicability::MaybeIncorrect, - ); - } - }, - ); + if let ty::Ref(..) = inner.kind() { return; // don't report clone_on_copy } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 9cafbc2e5f5..e4a659d3ce7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -984,29 +984,6 @@ declare_clippy_lint! { "using 'clone' on a ref-counted pointer" } -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of `.clone()` on an `&&T`. - /// - /// ### Why is this bad? - /// Cloning an `&&T` copies the inner `&T`, instead of - /// cloning the underlying `T`. - /// - /// ### Example - /// ```rust - /// fn main() { - /// let x = vec![1]; - /// let y = &&x; - /// let z = y.clone(); - /// println!("{:p} {:p}", *y, z); // prints out the same pointer - /// } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub CLONE_DOUBLE_REF, - correctness, - "using `clone` on `&&T`" -} - declare_clippy_lint! { /// ### What it does /// Checks for usage of `.to_string()` on an `&&T` where @@ -3258,7 +3235,6 @@ impl_lint_pass!(Methods => [ CHARS_LAST_CMP, CLONE_ON_COPY, CLONE_ON_REF_PTR, - CLONE_DOUBLE_REF, COLLAPSIBLE_STR_REPLACE, ITER_OVEREAGER_CLONED, CLONED_INSTEAD_OF_COPIED, diff --git a/clippy_lints/src/renamed_lints.rs b/clippy_lints/src/renamed_lints.rs index 9f487dedb8c..5e81a01a461 100644 --- a/clippy_lints/src/renamed_lints.rs +++ b/clippy_lints/src/renamed_lints.rs @@ -30,6 +30,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::stutter", "clippy::module_name_repetitions"), ("clippy::to_string_in_display", "clippy::recursive_format_impl"), ("clippy::zero_width_space", "clippy::invisible_characters"), + ("clippy::clone_double_ref", "suspicious_double_ref_op"), ("clippy::drop_bounds", "drop_bounds"), ("clippy::for_loop_over_option", "for_loops_over_fallibles"), ("clippy::for_loop_over_result", "for_loops_over_fallibles"), diff --git a/tests/ui/explicit_deref_methods.fixed b/tests/ui/explicit_deref_methods.fixed index 77e9f5fc1fd..60482c66da7 100644 --- a/tests/ui/explicit_deref_methods.fixed +++ b/tests/ui/explicit_deref_methods.fixed @@ -3,7 +3,7 @@ #![allow(unused_variables)] #![allow( clippy::borrow_deref_ref, - clippy::clone_double_ref, + suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::uninlined_format_args diff --git a/tests/ui/explicit_deref_methods.rs b/tests/ui/explicit_deref_methods.rs index 0c2cc7c2c3a..e3613e216bb 100644 --- a/tests/ui/explicit_deref_methods.rs +++ b/tests/ui/explicit_deref_methods.rs @@ -3,7 +3,7 @@ #![allow(unused_variables)] #![allow( clippy::borrow_deref_ref, - clippy::clone_double_ref, + suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::uninlined_format_args diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index e8a00a9e7f7..ff19a042825 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -36,6 +36,7 @@ #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] +#![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] #![allow(unknown_lints)] #![allow(unused_labels)] @@ -67,6 +68,7 @@ #![warn(clippy::module_name_repetitions)] #![warn(clippy::recursive_format_impl)] #![warn(clippy::invisible_characters)] +#![warn(suspicious_double_ref_op)] #![warn(drop_bounds)] #![warn(for_loops_over_fallibles)] #![warn(for_loops_over_fallibles)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index c8ea70c2bcb..38b1647c0cc 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -36,6 +36,7 @@ #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] +#![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] #![allow(unknown_lints)] #![allow(unused_labels)] @@ -67,6 +68,7 @@ #![warn(clippy::stutter)] #![warn(clippy::to_string_in_display)] #![warn(clippy::zero_width_space)] +#![warn(clippy::clone_double_ref)] #![warn(clippy::drop_bounds)] #![warn(clippy::for_loop_over_option)] #![warn(clippy::for_loop_over_result)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 27a0263292e..70d15408b9f 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> $DIR/rename.rs:42:9 + --> $DIR/rename.rs:43:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,250 +7,256 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:43:9 + --> $DIR/rename.rs:44:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:44:9 + --> $DIR/rename.rs:45:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:45:9 + --> $DIR/rename.rs:46:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:46:9 + --> $DIR/rename.rs:47:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:47:9 + --> $DIR/rename.rs:48:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:48:9 + --> $DIR/rename.rs:49:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> $DIR/rename.rs:49:9 + --> $DIR/rename.rs:50:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:50:9 + --> $DIR/rename.rs:51:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:51:9 + --> $DIR/rename.rs:52:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:52:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` +error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` + --> $DIR/rename.rs:71:9 + | +LL | #![warn(clippy::clone_double_ref)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` + error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:75:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:76:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:77:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:78:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 42 previous errors +error: aborting due to 43 previous errors diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 8b1629b19a7..7ceed3c75fd 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -42,14 +42,6 @@ fn clone_on_copy_generic(t: T) { Some(t).clone(); } -fn clone_on_double_ref() { - let x = vec![1]; - let y = &&x; - let z: &Vec<_> = y.clone(); - - println!("{:p} {:p}", *y, z); -} - mod many_derefs { struct A; struct B; @@ -84,11 +76,6 @@ mod many_derefs { let _: E = a.clone(); let _: E = *****a; } - - fn check(mut encoded: &[u8]) { - let _ = &mut encoded.clone(); - let _ = &encoded.clone(); - } } mod issue2076 { diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 6022d9fa4c5..5686ab6b453 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -44,63 +44,17 @@ error: using `clone` on type `Option` which implements the `Copy` trait LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` -error: using `clone` on a double-reference; this will copy the reference of type `&Vec` instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:48:22 - | -LL | let z: &Vec<_> = y.clone(); - | ^^^^^^^^^ - | - = note: `#[deny(clippy::clone_double_ref)]` on by default -help: try dereferencing it - | -LL | let z: &Vec<_> = &(*y).clone(); - | ~~~~~~~~~~~~~ -help: or try being explicit if you are sure, that you want to clone a reference - | -LL | let z: &Vec<_> = <&Vec>::clone(y); - | ~~~~~~~~~~~~~~~~~~~~~ - error: using `clone` on type `E` which implements the `Copy` trait - --> $DIR/unnecessary_clone.rs:84:20 + --> $DIR/unnecessary_clone.rs:76:20 | LL | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` -error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:89:22 - | -LL | let _ = &mut encoded.clone(); - | ^^^^^^^^^^^^^^^ - | -help: try dereferencing it - | -LL | let _ = &mut &(*encoded).clone(); - | ~~~~~~~~~~~~~~~~~~~ -help: or try being explicit if you are sure, that you want to clone a reference - | -LL | let _ = &mut <&[u8]>::clone(encoded); - | ~~~~~~~~~~~~~~~~~~~~~~~ - -error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:90:18 - | -LL | let _ = &encoded.clone(); - | ^^^^^^^^^^^^^^^ - | -help: try dereferencing it - | -LL | let _ = &&(*encoded).clone(); - | ~~~~~~~~~~~~~~~~~~~ -help: or try being explicit if you are sure, that you want to clone a reference - | -LL | let _ = &<&[u8]>::clone(encoded); - | ~~~~~~~~~~~~~~~~~~~~~~~ - error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:108:14 + --> $DIR/unnecessary_clone.rs:95:14 | LL | Some(try_opt!(Some(rc)).clone()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::::clone(&try_opt!(Some(rc)))` -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors -- cgit 1.4.1-3-g733a5 From f37054b396cc67f2633d929c35cd88ecdb383ba8 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Fri, 28 Apr 2023 20:19:36 +0200 Subject: Remove useless span magic --- clippy_lints/src/items_after_test_module.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index 96097575c9c..b992d689aa9 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -74,7 +74,7 @@ impl LateLintPass<'_> for ItemsAfterTestModule { if mitem.has_name(sym::test); then { was_test_mod_visited = true; - test_mod_span = Some(module.spans.inner_span.with_lo(item.span.lo())); + test_mod_span = Some(item.span); } } } -- cgit 1.4.1-3-g733a5 From 2b5820d58b62845ac23bda57533b44178c93cb7c Mon Sep 17 00:00:00 2001 From: blyxyas Date: Fri, 28 Apr 2023 20:23:05 +0200 Subject: Change module import system --- tests/ui/items_after_test_module/auxiliary/tests.rs | 1 + tests/ui/items_after_test_module/imported_module.rs | 1 + tests/ui/items_after_test_module/tests/mod.rs | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 tests/ui/items_after_test_module/auxiliary/tests.rs delete mode 100644 tests/ui/items_after_test_module/tests/mod.rs diff --git a/tests/ui/items_after_test_module/auxiliary/tests.rs b/tests/ui/items_after_test_module/auxiliary/tests.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/ui/items_after_test_module/auxiliary/tests.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/ui/items_after_test_module/imported_module.rs b/tests/ui/items_after_test_module/imported_module.rs index 819b6c8a9e0..22b1d3e2a9b 100644 --- a/tests/ui/items_after_test_module/imported_module.rs +++ b/tests/ui/items_after_test_module/imported_module.rs @@ -6,6 +6,7 @@ fn main() {} fn should_not_lint() {} +#[path = "auxiliary/tests.rs"] #[cfg(test)] mod tests; // Should not lint diff --git a/tests/ui/items_after_test_module/tests/mod.rs b/tests/ui/items_after_test_module/tests/mod.rs deleted file mode 100644 index f328e4d9d04..00000000000 --- a/tests/ui/items_after_test_module/tests/mod.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} -- cgit 1.4.1-3-g733a5 From 395b1f5bf333e2ff168a3cf34592a816cab6016c Mon Sep 17 00:00:00 2001 From: blyxyas Date: Fri, 28 Apr 2023 20:40:47 +0200 Subject: Rename items + Delete `imported_module.stderr` --- tests/ui/items_after_test_module/imported_module.rs | 6 ++++-- tests/ui/items_after_test_module/imported_module.stderr | 0 2 files changed, 4 insertions(+), 2 deletions(-) delete mode 100644 tests/ui/items_after_test_module/imported_module.stderr diff --git a/tests/ui/items_after_test_module/imported_module.rs b/tests/ui/items_after_test_module/imported_module.rs index 22b1d3e2a9b..6a757aef48e 100644 --- a/tests/ui/items_after_test_module/imported_module.rs +++ b/tests/ui/items_after_test_module/imported_module.rs @@ -2,6 +2,8 @@ #![allow(unused)] #![warn(clippy::items_after_test_module)] +// Nothing here should lint, as `tests` is an imported module (that has no body). + fn main() {} fn should_not_lint() {} @@ -10,9 +12,9 @@ fn should_not_lint() {} #[cfg(test)] mod tests; // Should not lint -fn should_lint() {} +fn should_not_lint2() {} -const SHOULD_ALSO_LINT: usize = 1; +const SHOULD_ALSO_NOT_LINT: usize = 1; macro_rules! should_not_lint { () => {}; } diff --git a/tests/ui/items_after_test_module/imported_module.stderr b/tests/ui/items_after_test_module/imported_module.stderr deleted file mode 100644 index e69de29bb2d..00000000000 -- cgit 1.4.1-3-g733a5 From 2ed254e29f237c90bafdc1c064f98c61cf42f685 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Sat, 29 Apr 2023 14:18:31 +0200 Subject: Clarify docs for RESULT_LARGE_ERR --- clippy_lints/src/functions/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 1528a7be09c..ee10334c67f 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -252,6 +252,11 @@ declare_clippy_lint! { /// A `Result` is at least as large as the `Err`-variant. While we /// expect that variant to be seldomly used, the compiler needs to reserve /// and move that much memory every single time. + /// Furthermore, errors are often simply passed up the call-stack, making + /// use of the `?`-operator and its type-conversion mechanics. If the + /// `Err`-variant further up the call-stack stores the `Err`-variant in + /// question (as library code often does), it itself needs to be at least + /// as large, propagating the problem. /// /// ### Known problems /// The size determined by Clippy is platform-dependent. -- cgit 1.4.1-3-g733a5 From bb58083ce59b44c54866a4d8305f59c7e7742593 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 4 Apr 2023 08:16:37 +0200 Subject: new lint: `while_pop_unwrap` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 1 + clippy_lints/src/loops/mod.rs | 3 + clippy_lints/src/while_pop_unwrap.rs | 126 +++++++++++++++++++++++++++++++++++ clippy_utils/src/paths.rs | 4 ++ tests/ui/while_pop_unwrap.rs | 47 +++++++++++++ tests/ui/while_pop_unwrap.stderr | 43 ++++++++++++ 8 files changed, 226 insertions(+) create mode 100644 clippy_lints/src/while_pop_unwrap.rs create mode 100644 tests/ui/while_pop_unwrap.rs create mode 100644 tests/ui/while_pop_unwrap.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 23f4f97ee07..da03f5c012b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5160,6 +5160,7 @@ Released 2018-09-13 [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator +[`while_pop_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_pop_unwrap [`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies [`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm [`wildcard_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 4aebd0b7d01..ddc4b139670 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -645,6 +645,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::useless_conversion::USELESS_CONVERSION_INFO, crate::vec::USELESS_VEC_INFO, crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO, + crate::while_pop_unwrap::WHILE_POP_UNWRAP_INFO, crate::wildcard_imports::ENUM_GLOB_USE_INFO, crate::wildcard_imports::WILDCARD_IMPORTS_INFO, crate::write::PRINTLN_EMPTY_STRING_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 48dbecc9f6a..0d594612b79 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -324,6 +324,7 @@ mod use_self; mod useless_conversion; mod vec; mod vec_init_then_push; +mod while_pop_unwrap; mod wildcard_imports; mod write; mod zero_div_zero; diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 610a0233eee..90012694062 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -25,6 +25,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; +use crate::while_pop_unwrap; + declare_clippy_lint! { /// ### What it does /// Checks for for-loops that manually copy items between @@ -643,6 +645,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { if let Some(higher::While { condition, body }) = higher::While::hir(expr) { while_immutable_condition::check(cx, condition, body); missing_spin_loop::check(cx, condition, body); + while_pop_unwrap::check(cx, condition, body); } } } diff --git a/clippy_lints/src/while_pop_unwrap.rs b/clippy_lints/src/while_pop_unwrap.rs new file mode 100644 index 00000000000..fc77febad6b --- /dev/null +++ b/clippy_lints/src/while_pop_unwrap.rs @@ -0,0 +1,126 @@ +use clippy_utils::{diagnostics::span_lint_and_then, match_def_path, paths, source::snippet}; +use rustc_errors::Applicability; +use rustc_hir::*; +use rustc_lint::LateContext; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::{symbol::Ident, Span}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for loops that check for emptiness of a `Vec` in the condition and pop an element + /// in the body as a separate operation. + /// + /// ### Why is this bad? + /// Such loops can be written in a more idiomatic way by using a while..let loop and directly + /// pattern matching on the return value of `Vec::pop()`. + /// + /// ### Example + /// ```rust + /// let mut numbers = vec![1, 2, 3, 4, 5]; + /// while !numbers.is_empty() { + /// let number = numbers.pop().unwrap(); + /// // use `number` + /// } + /// ``` + /// Use instead: + /// ```rust + /// let mut numbers = vec![1, 2, 3, 4, 5]; + /// while let Some(number) = numbers.pop() { + /// // use `number` + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub WHILE_POP_UNWRAP, + style, + "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" +} +declare_lint_pass!(WhilePopUnwrap => [WHILE_POP_UNWRAP]); + +fn report_lint<'tcx>( + cx: &LateContext<'tcx>, + pop_span: Span, + ident: Option, + loop_span: Span, + receiver_span: Span, +) { + span_lint_and_then( + cx, + WHILE_POP_UNWRAP, + pop_span, + "you seem to be trying to pop elements from a `Vec` in a loop", + |diag| { + diag.span_suggestion( + loop_span, + "try", + format!( + "while let Some({}) = {}.pop()", + ident.as_ref().map(Ident::as_str).unwrap_or("element"), + snippet(cx, receiver_span, "..") + ), + Applicability::MaybeIncorrect, + ) + .note("this while loop can be written in a more idiomatic way"); + }, + ); +} + +fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool { + if let ExprKind::MethodCall(..) = expr.kind + && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + && match_def_path(cx, id, method) + { + true + } else { + false + } +} + +fn is_vec_pop<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { + match_method_call(cx, expr, &paths::VEC_POP) +} + +fn is_vec_pop_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { + if let ExprKind::MethodCall(_, inner, ..) = expr.kind + && (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT)) + && is_vec_pop(cx, inner) + { + true + } else { + false + } +} + +fn check_local<'tcx>(cx: &LateContext<'tcx>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { + if let StmtKind::Local(local) = stmt.kind + && let PatKind::Binding(.., ident, _) = local.pat.kind + && let Some(init) = local.init + && let ExprKind::MethodCall(_, inner, ..) = init.kind + && is_vec_pop_unwrap(cx, init) + { + report_lint(cx, init.span.to(inner.span), Some(ident), loop_span, recv_span); + } +} + +fn check_call_arguments<'tcx>(cx: &LateContext<'tcx>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { + if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { + if let ExprKind::MethodCall(_, _, args, _) | ExprKind::Call(_, args) = expr.kind { + let offending_arg = args.iter().find_map(|arg| is_vec_pop_unwrap(cx, arg).then(|| arg.span)); + + if let Some(offending_arg) = offending_arg { + report_lint(cx, offending_arg, None, loop_span, recv_span); + } + } + } +} + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { + if let ExprKind::Unary(UnOp::Not, cond) = cond.kind + && let ExprKind::MethodCall(_, Expr { span: recv_span, .. }, _, _) = cond.kind + && match_method_call(cx, cond, &paths::VEC_IS_EMPTY) + && let ExprKind::Block(body, _) = body.kind + && let Some(stmt) = body.stmts.first() + { + check_local(cx, stmt, cond.span, *recv_span); + check_call_arguments(cx, stmt, cond.span, *recv_span); + } +} diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 9be2d0eae80..0f0792fdaa9 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -159,3 +159,7 @@ pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"]; pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"]; pub const INSTANT: [&str; 3] = ["std", "time", "Instant"]; +pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"]; +pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"]; +pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"]; +pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"]; diff --git a/tests/ui/while_pop_unwrap.rs b/tests/ui/while_pop_unwrap.rs new file mode 100644 index 00000000000..1b6de8f1f89 --- /dev/null +++ b/tests/ui/while_pop_unwrap.rs @@ -0,0 +1,47 @@ +#![allow(unused)] +#![warn(clippy::while_pop_unwrap)] + +struct VecInStruct { + numbers: Vec, + unrelated: String, +} + +fn accept_i32(_: i32) {} + +fn main() { + let mut numbers = vec![1, 2, 3, 4, 5]; + while !numbers.is_empty() { + let number = numbers.pop().unwrap(); + } + + let mut val = VecInStruct { + numbers: vec![1, 2, 3, 4, 5], + unrelated: String::new(), + }; + while !val.numbers.is_empty() { + let number = val.numbers.pop().unwrap(); + } + + while !numbers.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + + while !numbers.is_empty() { + accept_i32(numbers.pop().expect("")); + } + + // This should not warn. It "conditionally" pops elements. + while !numbers.is_empty() { + if true { + accept_i32(numbers.pop().unwrap()); + } + } + + // This should also not warn. It conditionally pops elements. + while !numbers.is_empty() { + if false { + continue; + } + accept_i32(numbers.pop().unwrap()); + } +} diff --git a/tests/ui/while_pop_unwrap.stderr b/tests/ui/while_pop_unwrap.stderr new file mode 100644 index 00000000000..8dc77db8b5a --- /dev/null +++ b/tests/ui/while_pop_unwrap.stderr @@ -0,0 +1,43 @@ +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:14:22 + | +LL | while !numbers.is_empty() { + | ------------------ help: try: `while let Some(number) = numbers.pop()` +LL | let number = numbers.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this while loop can be written in a more idiomatic way + = note: `-D clippy::while-pop-unwrap` implied by `-D warnings` + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:22:22 + | +LL | while !val.numbers.is_empty() { + | ---------------------- help: try: `while let Some(number) = val.numbers.pop()` +LL | let number = val.numbers.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this while loop can be written in a more idiomatic way + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:26:20 + | +LL | while !numbers.is_empty() { + | ------------------ help: try: `while let Some(element) = numbers.pop()` +LL | accept_i32(numbers.pop().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this while loop can be written in a more idiomatic way + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:30:20 + | +LL | while !numbers.is_empty() { + | ------------------ help: try: `while let Some(element) = numbers.pop()` +LL | accept_i32(numbers.pop().expect("")); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this while loop can be written in a more idiomatic way + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From bcdcc34ba95cd27cab6da68fcac820ca6968d3e2 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 15 Apr 2023 23:01:53 +0200 Subject: elide lifetimes, get rid of glob import --- clippy_lints/src/while_pop_unwrap.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/while_pop_unwrap.rs b/clippy_lints/src/while_pop_unwrap.rs index fc77febad6b..0a3f08888a3 100644 --- a/clippy_lints/src/while_pop_unwrap.rs +++ b/clippy_lints/src/while_pop_unwrap.rs @@ -1,6 +1,6 @@ use clippy_utils::{diagnostics::span_lint_and_then, match_def_path, paths, source::snippet}; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{Expr, ExprKind, PatKind, Stmt, StmtKind, UnOp}; use rustc_lint::LateContext; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{symbol::Ident, Span}; @@ -36,13 +36,7 @@ declare_clippy_lint! { } declare_lint_pass!(WhilePopUnwrap => [WHILE_POP_UNWRAP]); -fn report_lint<'tcx>( - cx: &LateContext<'tcx>, - pop_span: Span, - ident: Option, - loop_span: Span, - receiver_span: Span, -) { +fn report_lint(cx: &LateContext<'_>, pop_span: Span, ident: Option, loop_span: Span, receiver_span: Span) { span_lint_and_then( cx, WHILE_POP_UNWRAP, @@ -54,7 +48,7 @@ fn report_lint<'tcx>( "try", format!( "while let Some({}) = {}.pop()", - ident.as_ref().map(Ident::as_str).unwrap_or("element"), + ident.as_ref().map_or("element", Ident::as_str), snippet(cx, receiver_span, "..") ), Applicability::MaybeIncorrect, @@ -75,11 +69,11 @@ fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> } } -fn is_vec_pop<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { +fn is_vec_pop(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match_method_call(cx, expr, &paths::VEC_POP) } -fn is_vec_pop_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { +fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let ExprKind::MethodCall(_, inner, ..) = expr.kind && (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT)) && is_vec_pop(cx, inner) @@ -90,7 +84,7 @@ fn is_vec_pop_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool { } } -fn check_local<'tcx>(cx: &LateContext<'tcx>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { +fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { if let StmtKind::Local(local) = stmt.kind && let PatKind::Binding(.., ident, _) = local.pat.kind && let Some(init) = local.init @@ -101,10 +95,12 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, stmt: &Stmt<'_>, loop_span: Span, r } } -fn check_call_arguments<'tcx>(cx: &LateContext<'tcx>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { +fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { if let ExprKind::MethodCall(_, _, args, _) | ExprKind::Call(_, args) = expr.kind { - let offending_arg = args.iter().find_map(|arg| is_vec_pop_unwrap(cx, arg).then(|| arg.span)); + let offending_arg = args + .iter() + .find_map(|arg| is_vec_pop_unwrap(cx, arg).then_some(arg.span)); if let Some(offending_arg) = offending_arg { report_lint(cx, offending_arg, None, loop_span, recv_span); -- cgit 1.4.1-3-g733a5 From 1d08325293f0dcccd29700d6b14755f8fbd5f076 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 18 Apr 2023 00:14:56 +0200 Subject: move lint to loops, emit proper suggestion, more tests --- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 1 - clippy_lints/src/loops/mod.rs | 38 ++++++++- clippy_lints/src/loops/while_pop_unwrap.rs | 109 ++++++++++++++++++++++++++ clippy_lints/src/utils/author.rs | 2 +- clippy_lints/src/while_pop_unwrap.rs | 122 ----------------------------- clippy_utils/src/higher.rs | 6 +- tests/ui/while_pop_unwrap.fixed | 93 ++++++++++++++++++++++ tests/ui/while_pop_unwrap.rs | 46 +++++++++++ tests/ui/while_pop_unwrap.stderr | 82 ++++++++++++++----- 10 files changed, 351 insertions(+), 150 deletions(-) create mode 100644 clippy_lints/src/loops/while_pop_unwrap.rs delete mode 100644 clippy_lints/src/while_pop_unwrap.rs create mode 100644 tests/ui/while_pop_unwrap.fixed diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index ddc4b139670..ff418092e4b 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -258,6 +258,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::loops::WHILE_IMMUTABLE_CONDITION_INFO, crate::loops::WHILE_LET_LOOP_INFO, crate::loops::WHILE_LET_ON_ITERATOR_INFO, + crate::loops::WHILE_POP_UNWRAP_INFO, crate::macro_use::MACRO_USE_IMPORTS_INFO, crate::main_recursion::MAIN_RECURSION_INFO, crate::manual_assert::MANUAL_ASSERT_INFO, @@ -645,7 +646,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::useless_conversion::USELESS_CONVERSION_INFO, crate::vec::USELESS_VEC_INFO, crate::vec_init_then_push::VEC_INIT_THEN_PUSH_INFO, - crate::while_pop_unwrap::WHILE_POP_UNWRAP_INFO, crate::wildcard_imports::ENUM_GLOB_USE_INFO, crate::wildcard_imports::WILDCARD_IMPORTS_INFO, crate::write::PRINTLN_EMPTY_STRING_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0d594612b79..48dbecc9f6a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -324,7 +324,6 @@ mod use_self; mod useless_conversion; mod vec; mod vec_init_then_push; -mod while_pop_unwrap; mod wildcard_imports; mod write; mod zero_div_zero; diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 90012694062..02197e9c187 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -17,6 +17,7 @@ mod utils; mod while_immutable_condition; mod while_let_loop; mod while_let_on_iterator; +mod while_pop_unwrap; use clippy_utils::higher; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; @@ -25,8 +26,6 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use utils::{make_iterator_snippet, IncrementVisitor, InitializeVisitor}; -use crate::while_pop_unwrap; - declare_clippy_lint! { /// ### What it does /// Checks for for-loops that manually copy items between @@ -577,6 +576,36 @@ declare_clippy_lint! { "manual implementation of `Iterator::find`" } +declare_clippy_lint! { + /// ### What it does + /// Looks for loops that check for emptiness of a `Vec` in the condition and pop an element + /// in the body as a separate operation. + /// + /// ### Why is this bad? + /// Such loops can be written in a more idiomatic way by using a while..let loop and directly + /// pattern matching on the return value of `Vec::pop()`. + /// + /// ### Example + /// ```rust + /// let mut numbers = vec![1, 2, 3, 4, 5]; + /// while !numbers.is_empty() { + /// let number = numbers.pop().unwrap(); + /// // use `number` + /// } + /// ``` + /// Use instead: + /// ```rust + /// let mut numbers = vec![1, 2, 3, 4, 5]; + /// while let Some(number) = numbers.pop() { + /// // use `number` + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub WHILE_POP_UNWRAP, + style, + "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" +} + declare_lint_pass!(Loops => [ MANUAL_MEMCPY, MANUAL_FLATTEN, @@ -596,6 +625,7 @@ declare_lint_pass!(Loops => [ SINGLE_ELEMENT_LOOP, MISSING_SPIN_LOOP, MANUAL_FIND, + WHILE_POP_UNWRAP ]); impl<'tcx> LateLintPass<'tcx> for Loops { @@ -642,10 +672,10 @@ impl<'tcx> LateLintPass<'tcx> for Loops { while_let_on_iterator::check(cx, expr); - if let Some(higher::While { condition, body }) = higher::While::hir(expr) { + if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) { while_immutable_condition::check(cx, condition, body); missing_spin_loop::check(cx, condition, body); - while_pop_unwrap::check(cx, condition, body); + while_pop_unwrap::check(cx, condition, body, span); } } } diff --git a/clippy_lints/src/loops/while_pop_unwrap.rs b/clippy_lints/src/loops/while_pop_unwrap.rs new file mode 100644 index 00000000000..1e31184b34d --- /dev/null +++ b/clippy_lints/src/loops/while_pop_unwrap.rs @@ -0,0 +1,109 @@ +use clippy_utils::{ + diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, + match_def_path, paths, + source::snippet, + SpanlessEq, +}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp}; +use rustc_lint::LateContext; +use rustc_span::Span; +use std::borrow::Cow; + +use super::WHILE_POP_UNWRAP; + +/// The kind of statement that the `pop()` call appeared in. +/// +/// Depending on whether the value was assigned to a variable or not changes what pattern +/// we use for the suggestion. +enum PopStmt<'hir> { + /// `x.pop().unwrap()` was and assigned to a variable. + /// The pattern of this local variable will be used and the local statement + /// is deleted in the suggestion. + Local(&'hir Pat<'hir>), + /// `x.pop().unwrap()` appeared in an arbitrary expression and was not assigned to a variable. + /// The suggestion will use some placeholder identifier and the `x.pop().unwrap()` expression + /// is replaced with that identifier. + Anonymous, +} + +fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>, loop_span: Span, receiver_span: Span) { + span_lint_and_then( + cx, + WHILE_POP_UNWRAP, + pop_span, + "you seem to be trying to pop elements from a `Vec` in a loop", + |diag| { + let (pat, pop_replacement) = match &pop_stmt_kind { + PopStmt::Local(pat) => (snippet(cx, pat.span, ".."), String::new()), + PopStmt::Anonymous => (Cow::Borrowed("element"), "element".into()), + }; + + let loop_replacement = format!("while let Some({}) = {}.pop()", pat, snippet(cx, receiver_span, "..")); + multispan_sugg_with_applicability( + diag, + "consider using a `while..let` loop", + Applicability::MachineApplicable, + [(loop_span, loop_replacement), (pop_span, pop_replacement)], + ); + }, + ); +} + +fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool { + if let ExprKind::MethodCall(..) = expr.kind + && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + { + match_def_path(cx, id, method) + } else { + false + } +} + +fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool { + if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT)) + && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind + && match_method_call(cx, unwrap_recv, &paths::VEC_POP) + && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind + { + // make sure they're the same `Vec` + SpanlessEq::new(cx).eq_expr(pop_recv, is_empty_recv) + } else { + false + } +} + +fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { + if let StmtKind::Local(local) = stmt.kind + && let Some(init) = local.init + && is_vec_pop_unwrap(cx, init, is_empty_recv) + { + report_lint(cx, stmt.span, PopStmt::Local(&local.pat), loop_span, is_empty_recv.span); + } +} + +fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { + if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { + if let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind { + let offending_arg = args + .iter() + .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span)); + + if let Some(offending_arg) = offending_arg { + report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span); + } + } + } +} + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) { + if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind + && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind + && match_method_call(cx, cond, &paths::VEC_IS_EMPTY) + && let ExprKind::Block(body, _) = body.kind + && let Some(stmt) = body.stmts.first() + { + check_local(cx, stmt, is_empty_recv, loop_span); + check_call_arguments(cx, stmt, is_empty_recv, loop_span); + } +} diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 1f632916c57..108077b9d15 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -333,7 +333,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { #[allow(clippy::too_many_lines)] fn expr(&self, expr: &Binding<&hir::Expr<'_>>) { - if let Some(higher::While { condition, body }) = higher::While::hir(expr.value) { + if let Some(higher::While { condition, body, .. }) = higher::While::hir(expr.value) { bind!(self, condition, body); chain!( self, diff --git a/clippy_lints/src/while_pop_unwrap.rs b/clippy_lints/src/while_pop_unwrap.rs deleted file mode 100644 index 0a3f08888a3..00000000000 --- a/clippy_lints/src/while_pop_unwrap.rs +++ /dev/null @@ -1,122 +0,0 @@ -use clippy_utils::{diagnostics::span_lint_and_then, match_def_path, paths, source::snippet}; -use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, PatKind, Stmt, StmtKind, UnOp}; -use rustc_lint::LateContext; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{symbol::Ident, Span}; - -declare_clippy_lint! { - /// ### What it does - /// Looks for loops that check for emptiness of a `Vec` in the condition and pop an element - /// in the body as a separate operation. - /// - /// ### Why is this bad? - /// Such loops can be written in a more idiomatic way by using a while..let loop and directly - /// pattern matching on the return value of `Vec::pop()`. - /// - /// ### Example - /// ```rust - /// let mut numbers = vec![1, 2, 3, 4, 5]; - /// while !numbers.is_empty() { - /// let number = numbers.pop().unwrap(); - /// // use `number` - /// } - /// ``` - /// Use instead: - /// ```rust - /// let mut numbers = vec![1, 2, 3, 4, 5]; - /// while let Some(number) = numbers.pop() { - /// // use `number` - /// } - /// ``` - #[clippy::version = "1.70.0"] - pub WHILE_POP_UNWRAP, - style, - "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" -} -declare_lint_pass!(WhilePopUnwrap => [WHILE_POP_UNWRAP]); - -fn report_lint(cx: &LateContext<'_>, pop_span: Span, ident: Option, loop_span: Span, receiver_span: Span) { - span_lint_and_then( - cx, - WHILE_POP_UNWRAP, - pop_span, - "you seem to be trying to pop elements from a `Vec` in a loop", - |diag| { - diag.span_suggestion( - loop_span, - "try", - format!( - "while let Some({}) = {}.pop()", - ident.as_ref().map_or("element", Ident::as_str), - snippet(cx, receiver_span, "..") - ), - Applicability::MaybeIncorrect, - ) - .note("this while loop can be written in a more idiomatic way"); - }, - ); -} - -fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool { - if let ExprKind::MethodCall(..) = expr.kind - && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && match_def_path(cx, id, method) - { - true - } else { - false - } -} - -fn is_vec_pop(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - match_method_call(cx, expr, &paths::VEC_POP) -} - -fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - if let ExprKind::MethodCall(_, inner, ..) = expr.kind - && (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT)) - && is_vec_pop(cx, inner) - { - true - } else { - false - } -} - -fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { - if let StmtKind::Local(local) = stmt.kind - && let PatKind::Binding(.., ident, _) = local.pat.kind - && let Some(init) = local.init - && let ExprKind::MethodCall(_, inner, ..) = init.kind - && is_vec_pop_unwrap(cx, init) - { - report_lint(cx, init.span.to(inner.span), Some(ident), loop_span, recv_span); - } -} - -fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, loop_span: Span, recv_span: Span) { - if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { - if let ExprKind::MethodCall(_, _, args, _) | ExprKind::Call(_, args) = expr.kind { - let offending_arg = args - .iter() - .find_map(|arg| is_vec_pop_unwrap(cx, arg).then_some(arg.span)); - - if let Some(offending_arg) = offending_arg { - report_lint(cx, offending_arg, None, loop_span, recv_span); - } - } - } -} - -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { - if let ExprKind::Unary(UnOp::Not, cond) = cond.kind - && let ExprKind::MethodCall(_, Expr { span: recv_span, .. }, _, _) = cond.kind - && match_method_call(cx, cond, &paths::VEC_IS_EMPTY) - && let ExprKind::Block(body, _) = body.kind - && let Some(stmt) = body.stmts.first() - { - check_local(cx, stmt, cond.span, *recv_span); - check_call_arguments(cx, stmt, cond.span, *recv_span); - } -} diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 50bef370930..a61e4c38088 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -311,6 +311,8 @@ pub struct While<'hir> { pub condition: &'hir Expr<'hir>, /// `while` loop body pub body: &'hir Expr<'hir>, + /// Span of the loop header + pub span: Span, } impl<'hir> While<'hir> { @@ -336,10 +338,10 @@ impl<'hir> While<'hir> { }, _, LoopSource::While, - _, + span, ) = expr.kind { - return Some(Self { condition, body }); + return Some(Self { condition, body, span }); } None } diff --git a/tests/ui/while_pop_unwrap.fixed b/tests/ui/while_pop_unwrap.fixed new file mode 100644 index 00000000000..a635e054e6e --- /dev/null +++ b/tests/ui/while_pop_unwrap.fixed @@ -0,0 +1,93 @@ +// run-rustfix + +#![allow(unused)] +#![warn(clippy::while_pop_unwrap)] + +struct VecInStruct { + numbers: Vec, + unrelated: String, +} + +struct Foo { + a: i32, + b: i32, +} + +fn accept_i32(_: i32) {} +fn accept_optional_i32(_: Option) {} +fn accept_i32_tuple(_: (i32, i32)) {} + +fn main() { + let mut numbers = vec![1, 2, 3, 4, 5]; + while let Some(number) = numbers.pop() { + + } + + let mut val = VecInStruct { + numbers: vec![1, 2, 3, 4, 5], + unrelated: String::new(), + }; + while let Some(number) = val.numbers.pop() { + + } + + while let Some(element) = numbers.pop() { + accept_i32(element); + } + + while let Some(element) = numbers.pop() { + accept_i32(element); + } + + // This should not warn. It "conditionally" pops elements. + while !numbers.is_empty() { + if true { + accept_i32(numbers.pop().unwrap()); + } + } + + // This should also not warn. It conditionally pops elements. + while !numbers.is_empty() { + if false { + continue; + } + accept_i32(numbers.pop().unwrap()); + } + + // This should not warn. It pops elements, but does not unwrap it. + // Might handle the Option in some other arbitrary way. + while !numbers.is_empty() { + accept_optional_i32(numbers.pop()); + } + + let unrelated_vec: Vec = Vec::new(); + // This should not warn. It pops elements from a different vector. + while !unrelated_vec.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + + macro_rules! generate_loop { + () => { + while !numbers.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + }; + } + // Do not warn if the loop is in a macro. + generate_loop!(); + + // Try other kinds of patterns + let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; + while let Some((a, b)) = numbers.pop() { + + } + + while let Some(element) = numbers.pop() { + accept_i32_tuple(element); + } + + let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; + while let Some(Foo { a, b }) = results.pop() { + + } +} diff --git a/tests/ui/while_pop_unwrap.rs b/tests/ui/while_pop_unwrap.rs index 1b6de8f1f89..820ff211086 100644 --- a/tests/ui/while_pop_unwrap.rs +++ b/tests/ui/while_pop_unwrap.rs @@ -1,3 +1,5 @@ +// run-rustfix + #![allow(unused)] #![warn(clippy::while_pop_unwrap)] @@ -6,7 +8,14 @@ struct VecInStruct { unrelated: String, } +struct Foo { + a: i32, + b: i32, +} + fn accept_i32(_: i32) {} +fn accept_optional_i32(_: Option) {} +fn accept_i32_tuple(_: (i32, i32)) {} fn main() { let mut numbers = vec![1, 2, 3, 4, 5]; @@ -44,4 +53,41 @@ fn main() { } accept_i32(numbers.pop().unwrap()); } + + // This should not warn. It pops elements, but does not unwrap it. + // Might handle the Option in some other arbitrary way. + while !numbers.is_empty() { + accept_optional_i32(numbers.pop()); + } + + let unrelated_vec: Vec = Vec::new(); + // This should not warn. It pops elements from a different vector. + while !unrelated_vec.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + + macro_rules! generate_loop { + () => { + while !numbers.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + }; + } + // Do not warn if the loop is in a macro. + generate_loop!(); + + // Try other kinds of patterns + let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; + while !numbers.is_empty() { + let (a, b) = numbers.pop().unwrap(); + } + + while !numbers.is_empty() { + accept_i32_tuple(numbers.pop().unwrap()); + } + + let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; + while !results.is_empty() { + let Foo { a, b } = results.pop().unwrap(); + } } diff --git a/tests/ui/while_pop_unwrap.stderr b/tests/ui/while_pop_unwrap.stderr index 8dc77db8b5a..f8a6cfcda0e 100644 --- a/tests/ui/while_pop_unwrap.stderr +++ b/tests/ui/while_pop_unwrap.stderr @@ -1,43 +1,87 @@ error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:14:22 + --> $DIR/while_pop_unwrap.rs:23:9 | -LL | while !numbers.is_empty() { - | ------------------ help: try: `while let Some(number) = numbers.pop()` LL | let number = numbers.pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this while loop can be written in a more idiomatic way = note: `-D clippy::while-pop-unwrap` implied by `-D warnings` +help: consider using a `while..let` loop + | +LL ~ while let Some(number) = numbers.pop() { +LL ~ + | error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:22:22 + --> $DIR/while_pop_unwrap.rs:31:9 | -LL | while !val.numbers.is_empty() { - | ---------------------- help: try: `while let Some(number) = val.numbers.pop()` LL | let number = val.numbers.pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(number) = val.numbers.pop() { +LL ~ | - = note: this while loop can be written in a more idiomatic way error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:26:20 + --> $DIR/while_pop_unwrap.rs:35:20 | -LL | while !numbers.is_empty() { - | ------------------ help: try: `while let Some(element) = numbers.pop()` LL | accept_i32(numbers.pop().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: this while loop can be written in a more idiomatic way +help: consider using a `while..let` loop + | +LL ~ while let Some(element) = numbers.pop() { +LL ~ accept_i32(element); + | error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:30:20 + --> $DIR/while_pop_unwrap.rs:39:20 | -LL | while !numbers.is_empty() { - | ------------------ help: try: `while let Some(element) = numbers.pop()` LL | accept_i32(numbers.pop().expect("")); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this while loop can be written in a more idiomatic way +help: consider using a `while..let` loop + | +LL ~ while let Some(element) = numbers.pop() { +LL ~ accept_i32(element); + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:82:9 + | +LL | let (a, b) = numbers.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some((a, b)) = numbers.pop() { +LL ~ + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:86:26 + | +LL | accept_i32_tuple(numbers.pop().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(element) = numbers.pop() { +LL ~ accept_i32_tuple(element); + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/while_pop_unwrap.rs:91:9 + | +LL | let Foo { a, b } = results.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(Foo { a, b }) = results.pop() { +LL ~ + | -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors -- cgit 1.4.1-3-g733a5 From ab9b7a5ad23bd2cb2097719ad9439277b8f5d987 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 18 Apr 2023 00:25:39 +0200 Subject: remove unnecessary reference --- clippy_lints/src/loops/while_pop_unwrap.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops/while_pop_unwrap.rs b/clippy_lints/src/loops/while_pop_unwrap.rs index 1e31184b34d..fc6797d72c0 100644 --- a/clippy_lints/src/loops/while_pop_unwrap.rs +++ b/clippy_lints/src/loops/while_pop_unwrap.rs @@ -34,7 +34,7 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>, pop_span, "you seem to be trying to pop elements from a `Vec` in a loop", |diag| { - let (pat, pop_replacement) = match &pop_stmt_kind { + let (pat, pop_replacement) = match pop_stmt_kind { PopStmt::Local(pat) => (snippet(cx, pat.span, ".."), String::new()), PopStmt::Anonymous => (Cow::Borrowed("element"), "element".into()), }; @@ -78,7 +78,7 @@ fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, && let Some(init) = local.init && is_vec_pop_unwrap(cx, init, is_empty_recv) { - report_lint(cx, stmt.span, PopStmt::Local(&local.pat), loop_span, is_empty_recv.span); + report_lint(cx, stmt.span, PopStmt::Local(local.pat), loop_span, is_empty_recv.span); } } -- cgit 1.4.1-3-g733a5 From f10e39fd2be243b7f0d4f82f56420ba1cbd4a7bb Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Tue, 18 Apr 2023 00:40:03 +0200 Subject: make PopStmt copy+clone --- clippy_lints/src/loops/while_pop_unwrap.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/loops/while_pop_unwrap.rs b/clippy_lints/src/loops/while_pop_unwrap.rs index fc6797d72c0..3a583396230 100644 --- a/clippy_lints/src/loops/while_pop_unwrap.rs +++ b/clippy_lints/src/loops/while_pop_unwrap.rs @@ -16,6 +16,7 @@ use super::WHILE_POP_UNWRAP; /// /// Depending on whether the value was assigned to a variable or not changes what pattern /// we use for the suggestion. +#[derive(Copy, Clone)] enum PopStmt<'hir> { /// `x.pop().unwrap()` was and assigned to a variable. /// The pattern of this local variable will be used and the local statement -- cgit 1.4.1-3-g733a5 From 8d8178f93184d09cf1e3f813257d6aeb19d08c57 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 19 Apr 2023 22:26:50 +0200 Subject: rename lint to `manual_while_let_some` --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/loops/manual_while_let_some.rs | 110 ++++++++++++++++++++++++ clippy_lints/src/loops/mod.rs | 10 +-- clippy_lints/src/loops/while_pop_unwrap.rs | 110 ------------------------ tests/ui/manual_while_let_some.fixed | 93 ++++++++++++++++++++ tests/ui/manual_while_let_some.rs | 93 ++++++++++++++++++++ tests/ui/manual_while_let_some.stderr | 87 +++++++++++++++++++ tests/ui/while_pop_unwrap.fixed | 93 -------------------- tests/ui/while_pop_unwrap.rs | 93 -------------------- tests/ui/while_pop_unwrap.stderr | 87 ------------------- 11 files changed, 390 insertions(+), 390 deletions(-) create mode 100644 clippy_lints/src/loops/manual_while_let_some.rs delete mode 100644 clippy_lints/src/loops/while_pop_unwrap.rs create mode 100644 tests/ui/manual_while_let_some.fixed create mode 100644 tests/ui/manual_while_let_some.rs create mode 100644 tests/ui/manual_while_let_some.stderr delete mode 100644 tests/ui/while_pop_unwrap.fixed delete mode 100644 tests/ui/while_pop_unwrap.rs delete mode 100644 tests/ui/while_pop_unwrap.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index da03f5c012b..d1e98a93940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4797,6 +4797,7 @@ Released 2018-09-13 [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or +[`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone [`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit @@ -5160,7 +5161,6 @@ Released 2018-09-13 [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator -[`while_pop_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_pop_unwrap [`wildcard_dependencies`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_dependencies [`wildcard_enum_match_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_enum_match_arm [`wildcard_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index ff418092e4b..44e725be710 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -249,6 +249,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::loops::MANUAL_FIND_INFO, crate::loops::MANUAL_FLATTEN_INFO, crate::loops::MANUAL_MEMCPY_INFO, + crate::loops::MANUAL_WHILE_LET_SOME_INFO, crate::loops::MISSING_SPIN_LOOP_INFO, crate::loops::MUT_RANGE_BOUND_INFO, crate::loops::NEEDLESS_RANGE_LOOP_INFO, @@ -258,7 +259,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::loops::WHILE_IMMUTABLE_CONDITION_INFO, crate::loops::WHILE_LET_LOOP_INFO, crate::loops::WHILE_LET_ON_ITERATOR_INFO, - crate::loops::WHILE_POP_UNWRAP_INFO, crate::macro_use::MACRO_USE_IMPORTS_INFO, crate::main_recursion::MAIN_RECURSION_INFO, crate::manual_assert::MANUAL_ASSERT_INFO, diff --git a/clippy_lints/src/loops/manual_while_let_some.rs b/clippy_lints/src/loops/manual_while_let_some.rs new file mode 100644 index 00000000000..cb9c84be4c7 --- /dev/null +++ b/clippy_lints/src/loops/manual_while_let_some.rs @@ -0,0 +1,110 @@ +use clippy_utils::{ + diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, + match_def_path, paths, + source::snippet, + SpanlessEq, +}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp}; +use rustc_lint::LateContext; +use rustc_span::Span; +use std::borrow::Cow; + +use super::MANUAL_WHILE_LET_SOME; + +/// The kind of statement that the `pop()` call appeared in. +/// +/// Depending on whether the value was assigned to a variable or not changes what pattern +/// we use for the suggestion. +#[derive(Copy, Clone)] +enum PopStmt<'hir> { + /// `x.pop().unwrap()` was and assigned to a variable. + /// The pattern of this local variable will be used and the local statement + /// is deleted in the suggestion. + Local(&'hir Pat<'hir>), + /// `x.pop().unwrap()` appeared in an arbitrary expression and was not assigned to a variable. + /// The suggestion will use some placeholder identifier and the `x.pop().unwrap()` expression + /// is replaced with that identifier. + Anonymous, +} + +fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>, loop_span: Span, receiver_span: Span) { + span_lint_and_then( + cx, + MANUAL_WHILE_LET_SOME, + pop_span, + "you seem to be trying to pop elements from a `Vec` in a loop", + |diag| { + let (pat, pop_replacement) = match pop_stmt_kind { + PopStmt::Local(pat) => (snippet(cx, pat.span, ".."), String::new()), + PopStmt::Anonymous => (Cow::Borrowed("element"), "element".into()), + }; + + let loop_replacement = format!("while let Some({}) = {}.pop()", pat, snippet(cx, receiver_span, "..")); + multispan_sugg_with_applicability( + diag, + "consider using a `while..let` loop", + Applicability::MachineApplicable, + [(loop_span, loop_replacement), (pop_span, pop_replacement)], + ); + }, + ); +} + +fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool { + if let ExprKind::MethodCall(..) = expr.kind + && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) + { + match_def_path(cx, id, method) + } else { + false + } +} + +fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool { + if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT)) + && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind + && match_method_call(cx, unwrap_recv, &paths::VEC_POP) + && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind + { + // make sure they're the same `Vec` + SpanlessEq::new(cx).eq_expr(pop_recv, is_empty_recv) + } else { + false + } +} + +fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { + if let StmtKind::Local(local) = stmt.kind + && let Some(init) = local.init + && is_vec_pop_unwrap(cx, init, is_empty_recv) + { + report_lint(cx, stmt.span, PopStmt::Local(local.pat), loop_span, is_empty_recv.span); + } +} + +fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { + if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { + if let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind { + let offending_arg = args + .iter() + .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span)); + + if let Some(offending_arg) = offending_arg { + report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span); + } + } + } +} + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) { + if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind + && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind + && match_method_call(cx, cond, &paths::VEC_IS_EMPTY) + && let ExprKind::Block(body, _) = body.kind + && let Some(stmt) = body.stmts.first() + { + check_local(cx, stmt, is_empty_recv, loop_span); + check_call_arguments(cx, stmt, is_empty_recv, loop_span); + } +} diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 02197e9c187..f83ad388a74 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -7,6 +7,7 @@ mod iter_next_loop; mod manual_find; mod manual_flatten; mod manual_memcpy; +mod manual_while_let_some; mod missing_spin_loop; mod mut_range_bound; mod needless_range_loop; @@ -17,7 +18,6 @@ mod utils; mod while_immutable_condition; mod while_let_loop; mod while_let_on_iterator; -mod while_pop_unwrap; use clippy_utils::higher; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; @@ -582,7 +582,7 @@ declare_clippy_lint! { /// in the body as a separate operation. /// /// ### Why is this bad? - /// Such loops can be written in a more idiomatic way by using a while..let loop and directly + /// Such loops can be written in a more idiomatic way by using a while-let loop and directly /// pattern matching on the return value of `Vec::pop()`. /// /// ### Example @@ -601,7 +601,7 @@ declare_clippy_lint! { /// } /// ``` #[clippy::version = "1.70.0"] - pub WHILE_POP_UNWRAP, + pub MANUAL_WHILE_LET_SOME, style, "checking for emptiness of a `Vec` in the loop condition and popping an element in the body" } @@ -625,7 +625,7 @@ declare_lint_pass!(Loops => [ SINGLE_ELEMENT_LOOP, MISSING_SPIN_LOOP, MANUAL_FIND, - WHILE_POP_UNWRAP + MANUAL_WHILE_LET_SOME ]); impl<'tcx> LateLintPass<'tcx> for Loops { @@ -675,7 +675,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) { while_immutable_condition::check(cx, condition, body); missing_spin_loop::check(cx, condition, body); - while_pop_unwrap::check(cx, condition, body, span); + manual_while_let_some::check(cx, condition, body, span); } } } diff --git a/clippy_lints/src/loops/while_pop_unwrap.rs b/clippy_lints/src/loops/while_pop_unwrap.rs deleted file mode 100644 index 3a583396230..00000000000 --- a/clippy_lints/src/loops/while_pop_unwrap.rs +++ /dev/null @@ -1,110 +0,0 @@ -use clippy_utils::{ - diagnostics::{multispan_sugg_with_applicability, span_lint_and_then}, - match_def_path, paths, - source::snippet, - SpanlessEq, -}; -use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp}; -use rustc_lint::LateContext; -use rustc_span::Span; -use std::borrow::Cow; - -use super::WHILE_POP_UNWRAP; - -/// The kind of statement that the `pop()` call appeared in. -/// -/// Depending on whether the value was assigned to a variable or not changes what pattern -/// we use for the suggestion. -#[derive(Copy, Clone)] -enum PopStmt<'hir> { - /// `x.pop().unwrap()` was and assigned to a variable. - /// The pattern of this local variable will be used and the local statement - /// is deleted in the suggestion. - Local(&'hir Pat<'hir>), - /// `x.pop().unwrap()` appeared in an arbitrary expression and was not assigned to a variable. - /// The suggestion will use some placeholder identifier and the `x.pop().unwrap()` expression - /// is replaced with that identifier. - Anonymous, -} - -fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>, loop_span: Span, receiver_span: Span) { - span_lint_and_then( - cx, - WHILE_POP_UNWRAP, - pop_span, - "you seem to be trying to pop elements from a `Vec` in a loop", - |diag| { - let (pat, pop_replacement) = match pop_stmt_kind { - PopStmt::Local(pat) => (snippet(cx, pat.span, ".."), String::new()), - PopStmt::Anonymous => (Cow::Borrowed("element"), "element".into()), - }; - - let loop_replacement = format!("while let Some({}) = {}.pop()", pat, snippet(cx, receiver_span, "..")); - multispan_sugg_with_applicability( - diag, - "consider using a `while..let` loop", - Applicability::MachineApplicable, - [(loop_span, loop_replacement), (pop_span, pop_replacement)], - ); - }, - ); -} - -fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool { - if let ExprKind::MethodCall(..) = expr.kind - && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - { - match_def_path(cx, id, method) - } else { - false - } -} - -fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool { - if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT)) - && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind - && match_method_call(cx, unwrap_recv, &paths::VEC_POP) - && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind - { - // make sure they're the same `Vec` - SpanlessEq::new(cx).eq_expr(pop_recv, is_empty_recv) - } else { - false - } -} - -fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { - if let StmtKind::Local(local) = stmt.kind - && let Some(init) = local.init - && is_vec_pop_unwrap(cx, init, is_empty_recv) - { - report_lint(cx, stmt.span, PopStmt::Local(local.pat), loop_span, is_empty_recv.span); - } -} - -fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { - if let StmtKind::Semi(expr) | StmtKind::Expr(expr) = stmt.kind { - if let ExprKind::MethodCall(.., args, _) | ExprKind::Call(_, args) = expr.kind { - let offending_arg = args - .iter() - .find_map(|arg| is_vec_pop_unwrap(cx, arg, is_empty_recv).then_some(arg.span)); - - if let Some(offending_arg) = offending_arg { - report_lint(cx, offending_arg, PopStmt::Anonymous, loop_span, is_empty_recv.span); - } - } - } -} - -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) { - if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind - && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind - && match_method_call(cx, cond, &paths::VEC_IS_EMPTY) - && let ExprKind::Block(body, _) = body.kind - && let Some(stmt) = body.stmts.first() - { - check_local(cx, stmt, is_empty_recv, loop_span); - check_call_arguments(cx, stmt, is_empty_recv, loop_span); - } -} diff --git a/tests/ui/manual_while_let_some.fixed b/tests/ui/manual_while_let_some.fixed new file mode 100644 index 00000000000..75738209bad --- /dev/null +++ b/tests/ui/manual_while_let_some.fixed @@ -0,0 +1,93 @@ +// run-rustfix + +#![allow(unused)] +#![warn(clippy::manual_while_let_some)] + +struct VecInStruct { + numbers: Vec, + unrelated: String, +} + +struct Foo { + a: i32, + b: i32, +} + +fn accept_i32(_: i32) {} +fn accept_optional_i32(_: Option) {} +fn accept_i32_tuple(_: (i32, i32)) {} + +fn main() { + let mut numbers = vec![1, 2, 3, 4, 5]; + while let Some(number) = numbers.pop() { + + } + + let mut val = VecInStruct { + numbers: vec![1, 2, 3, 4, 5], + unrelated: String::new(), + }; + while let Some(number) = val.numbers.pop() { + + } + + while let Some(element) = numbers.pop() { + accept_i32(element); + } + + while let Some(element) = numbers.pop() { + accept_i32(element); + } + + // This should not warn. It "conditionally" pops elements. + while !numbers.is_empty() { + if true { + accept_i32(numbers.pop().unwrap()); + } + } + + // This should also not warn. It conditionally pops elements. + while !numbers.is_empty() { + if false { + continue; + } + accept_i32(numbers.pop().unwrap()); + } + + // This should not warn. It pops elements, but does not unwrap it. + // Might handle the Option in some other arbitrary way. + while !numbers.is_empty() { + accept_optional_i32(numbers.pop()); + } + + let unrelated_vec: Vec = Vec::new(); + // This should not warn. It pops elements from a different vector. + while !unrelated_vec.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + + macro_rules! generate_loop { + () => { + while !numbers.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + }; + } + // Do not warn if the loop comes from a macro. + generate_loop!(); + + // Try other kinds of patterns + let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; + while let Some((a, b)) = numbers.pop() { + + } + + while let Some(element) = numbers.pop() { + accept_i32_tuple(element); + } + + let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; + while let Some(Foo { a, b }) = results.pop() { + + } +} diff --git a/tests/ui/manual_while_let_some.rs b/tests/ui/manual_while_let_some.rs new file mode 100644 index 00000000000..142c1471598 --- /dev/null +++ b/tests/ui/manual_while_let_some.rs @@ -0,0 +1,93 @@ +// run-rustfix + +#![allow(unused)] +#![warn(clippy::manual_while_let_some)] + +struct VecInStruct { + numbers: Vec, + unrelated: String, +} + +struct Foo { + a: i32, + b: i32, +} + +fn accept_i32(_: i32) {} +fn accept_optional_i32(_: Option) {} +fn accept_i32_tuple(_: (i32, i32)) {} + +fn main() { + let mut numbers = vec![1, 2, 3, 4, 5]; + while !numbers.is_empty() { + let number = numbers.pop().unwrap(); + } + + let mut val = VecInStruct { + numbers: vec![1, 2, 3, 4, 5], + unrelated: String::new(), + }; + while !val.numbers.is_empty() { + let number = val.numbers.pop().unwrap(); + } + + while !numbers.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + + while !numbers.is_empty() { + accept_i32(numbers.pop().expect("")); + } + + // This should not warn. It "conditionally" pops elements. + while !numbers.is_empty() { + if true { + accept_i32(numbers.pop().unwrap()); + } + } + + // This should also not warn. It conditionally pops elements. + while !numbers.is_empty() { + if false { + continue; + } + accept_i32(numbers.pop().unwrap()); + } + + // This should not warn. It pops elements, but does not unwrap it. + // Might handle the Option in some other arbitrary way. + while !numbers.is_empty() { + accept_optional_i32(numbers.pop()); + } + + let unrelated_vec: Vec = Vec::new(); + // This should not warn. It pops elements from a different vector. + while !unrelated_vec.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + + macro_rules! generate_loop { + () => { + while !numbers.is_empty() { + accept_i32(numbers.pop().unwrap()); + } + }; + } + // Do not warn if the loop comes from a macro. + generate_loop!(); + + // Try other kinds of patterns + let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; + while !numbers.is_empty() { + let (a, b) = numbers.pop().unwrap(); + } + + while !numbers.is_empty() { + accept_i32_tuple(numbers.pop().unwrap()); + } + + let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; + while !results.is_empty() { + let Foo { a, b } = results.pop().unwrap(); + } +} diff --git a/tests/ui/manual_while_let_some.stderr b/tests/ui/manual_while_let_some.stderr new file mode 100644 index 00000000000..633fe05c49b --- /dev/null +++ b/tests/ui/manual_while_let_some.stderr @@ -0,0 +1,87 @@ +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:23:9 + | +LL | let number = numbers.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::manual-while-let-some` implied by `-D warnings` +help: consider using a `while..let` loop + | +LL ~ while let Some(number) = numbers.pop() { +LL ~ + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:31:9 + | +LL | let number = val.numbers.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(number) = val.numbers.pop() { +LL ~ + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:35:20 + | +LL | accept_i32(numbers.pop().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(element) = numbers.pop() { +LL ~ accept_i32(element); + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:39:20 + | +LL | accept_i32(numbers.pop().expect("")); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(element) = numbers.pop() { +LL ~ accept_i32(element); + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:82:9 + | +LL | let (a, b) = numbers.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some((a, b)) = numbers.pop() { +LL ~ + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:86:26 + | +LL | accept_i32_tuple(numbers.pop().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(element) = numbers.pop() { +LL ~ accept_i32_tuple(element); + | + +error: you seem to be trying to pop elements from a `Vec` in a loop + --> $DIR/manual_while_let_some.rs:91:9 + | +LL | let Foo { a, b } = results.pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a `while..let` loop + | +LL ~ while let Some(Foo { a, b }) = results.pop() { +LL ~ + | + +error: aborting due to 7 previous errors + diff --git a/tests/ui/while_pop_unwrap.fixed b/tests/ui/while_pop_unwrap.fixed deleted file mode 100644 index a635e054e6e..00000000000 --- a/tests/ui/while_pop_unwrap.fixed +++ /dev/null @@ -1,93 +0,0 @@ -// run-rustfix - -#![allow(unused)] -#![warn(clippy::while_pop_unwrap)] - -struct VecInStruct { - numbers: Vec, - unrelated: String, -} - -struct Foo { - a: i32, - b: i32, -} - -fn accept_i32(_: i32) {} -fn accept_optional_i32(_: Option) {} -fn accept_i32_tuple(_: (i32, i32)) {} - -fn main() { - let mut numbers = vec![1, 2, 3, 4, 5]; - while let Some(number) = numbers.pop() { - - } - - let mut val = VecInStruct { - numbers: vec![1, 2, 3, 4, 5], - unrelated: String::new(), - }; - while let Some(number) = val.numbers.pop() { - - } - - while let Some(element) = numbers.pop() { - accept_i32(element); - } - - while let Some(element) = numbers.pop() { - accept_i32(element); - } - - // This should not warn. It "conditionally" pops elements. - while !numbers.is_empty() { - if true { - accept_i32(numbers.pop().unwrap()); - } - } - - // This should also not warn. It conditionally pops elements. - while !numbers.is_empty() { - if false { - continue; - } - accept_i32(numbers.pop().unwrap()); - } - - // This should not warn. It pops elements, but does not unwrap it. - // Might handle the Option in some other arbitrary way. - while !numbers.is_empty() { - accept_optional_i32(numbers.pop()); - } - - let unrelated_vec: Vec = Vec::new(); - // This should not warn. It pops elements from a different vector. - while !unrelated_vec.is_empty() { - accept_i32(numbers.pop().unwrap()); - } - - macro_rules! generate_loop { - () => { - while !numbers.is_empty() { - accept_i32(numbers.pop().unwrap()); - } - }; - } - // Do not warn if the loop is in a macro. - generate_loop!(); - - // Try other kinds of patterns - let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; - while let Some((a, b)) = numbers.pop() { - - } - - while let Some(element) = numbers.pop() { - accept_i32_tuple(element); - } - - let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; - while let Some(Foo { a, b }) = results.pop() { - - } -} diff --git a/tests/ui/while_pop_unwrap.rs b/tests/ui/while_pop_unwrap.rs deleted file mode 100644 index 820ff211086..00000000000 --- a/tests/ui/while_pop_unwrap.rs +++ /dev/null @@ -1,93 +0,0 @@ -// run-rustfix - -#![allow(unused)] -#![warn(clippy::while_pop_unwrap)] - -struct VecInStruct { - numbers: Vec, - unrelated: String, -} - -struct Foo { - a: i32, - b: i32, -} - -fn accept_i32(_: i32) {} -fn accept_optional_i32(_: Option) {} -fn accept_i32_tuple(_: (i32, i32)) {} - -fn main() { - let mut numbers = vec![1, 2, 3, 4, 5]; - while !numbers.is_empty() { - let number = numbers.pop().unwrap(); - } - - let mut val = VecInStruct { - numbers: vec![1, 2, 3, 4, 5], - unrelated: String::new(), - }; - while !val.numbers.is_empty() { - let number = val.numbers.pop().unwrap(); - } - - while !numbers.is_empty() { - accept_i32(numbers.pop().unwrap()); - } - - while !numbers.is_empty() { - accept_i32(numbers.pop().expect("")); - } - - // This should not warn. It "conditionally" pops elements. - while !numbers.is_empty() { - if true { - accept_i32(numbers.pop().unwrap()); - } - } - - // This should also not warn. It conditionally pops elements. - while !numbers.is_empty() { - if false { - continue; - } - accept_i32(numbers.pop().unwrap()); - } - - // This should not warn. It pops elements, but does not unwrap it. - // Might handle the Option in some other arbitrary way. - while !numbers.is_empty() { - accept_optional_i32(numbers.pop()); - } - - let unrelated_vec: Vec = Vec::new(); - // This should not warn. It pops elements from a different vector. - while !unrelated_vec.is_empty() { - accept_i32(numbers.pop().unwrap()); - } - - macro_rules! generate_loop { - () => { - while !numbers.is_empty() { - accept_i32(numbers.pop().unwrap()); - } - }; - } - // Do not warn if the loop is in a macro. - generate_loop!(); - - // Try other kinds of patterns - let mut numbers = vec![(0, 0), (1, 1), (2, 2)]; - while !numbers.is_empty() { - let (a, b) = numbers.pop().unwrap(); - } - - while !numbers.is_empty() { - accept_i32_tuple(numbers.pop().unwrap()); - } - - let mut results = vec![Foo { a: 1, b: 2 }, Foo { a: 3, b: 4 }]; - while !results.is_empty() { - let Foo { a, b } = results.pop().unwrap(); - } -} diff --git a/tests/ui/while_pop_unwrap.stderr b/tests/ui/while_pop_unwrap.stderr deleted file mode 100644 index f8a6cfcda0e..00000000000 --- a/tests/ui/while_pop_unwrap.stderr +++ /dev/null @@ -1,87 +0,0 @@ -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:23:9 - | -LL | let number = numbers.pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::while-pop-unwrap` implied by `-D warnings` -help: consider using a `while..let` loop - | -LL ~ while let Some(number) = numbers.pop() { -LL ~ - | - -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:31:9 - | -LL | let number = val.numbers.pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using a `while..let` loop - | -LL ~ while let Some(number) = val.numbers.pop() { -LL ~ - | - -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:35:20 - | -LL | accept_i32(numbers.pop().unwrap()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using a `while..let` loop - | -LL ~ while let Some(element) = numbers.pop() { -LL ~ accept_i32(element); - | - -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:39:20 - | -LL | accept_i32(numbers.pop().expect("")); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using a `while..let` loop - | -LL ~ while let Some(element) = numbers.pop() { -LL ~ accept_i32(element); - | - -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:82:9 - | -LL | let (a, b) = numbers.pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using a `while..let` loop - | -LL ~ while let Some((a, b)) = numbers.pop() { -LL ~ - | - -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:86:26 - | -LL | accept_i32_tuple(numbers.pop().unwrap()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using a `while..let` loop - | -LL ~ while let Some(element) = numbers.pop() { -LL ~ accept_i32_tuple(element); - | - -error: you seem to be trying to pop elements from a `Vec` in a loop - --> $DIR/while_pop_unwrap.rs:91:9 - | -LL | let Foo { a, b } = results.pop().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider using a `while..let` loop - | -LL ~ while let Some(Foo { a, b }) = results.pop() { -LL ~ - | - -error: aborting due to 7 previous errors - -- cgit 1.4.1-3-g733a5 From 9613ea85c65c8c4f75b443e061739c82f75e317d Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 29 Apr 2023 19:10:52 +0200 Subject: fix run-rustfix directive --- tests/ui/manual_while_let_some.fixed | 2 +- tests/ui/manual_while_let_some.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/manual_while_let_some.fixed b/tests/ui/manual_while_let_some.fixed index 75738209bad..8b610919536 100644 --- a/tests/ui/manual_while_let_some.fixed +++ b/tests/ui/manual_while_let_some.fixed @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::manual_while_let_some)] diff --git a/tests/ui/manual_while_let_some.rs b/tests/ui/manual_while_let_some.rs index 142c1471598..85a0a084a42 100644 --- a/tests/ui/manual_while_let_some.rs +++ b/tests/ui/manual_while_let_some.rs @@ -1,4 +1,4 @@ -// run-rustfix +//@run-rustfix #![allow(unused)] #![warn(clippy::manual_while_let_some)] -- cgit 1.4.1-3-g733a5 From 032bc11fd482cc99fd3f85f053855b3e3e6ad18a Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Sat, 29 Apr 2023 21:11:34 +0200 Subject: fix diagnostic message style Co-authored-by: Ruby Lazuli --- clippy_lints/src/default_constructed_unit_struct.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/default_constructed_unit_struct.rs b/clippy_lints/src/default_constructed_unit_struct.rs index a04f7b9d9a9..d518c8e7c56 100644 --- a/clippy_lints/src/default_constructed_unit_struct.rs +++ b/clippy_lints/src/default_constructed_unit_struct.rs @@ -55,7 +55,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStruct { cx, DEFAULT_CONSTRUCTED_UNIT_STRUCT, qpath.last_segment_span(), - "Use of `default` to create a unit struct.", + "use of `default` to create a unit struct", "remove this call to `default`", String::new(), Applicability::MachineApplicable, -- cgit 1.4.1-3-g733a5 From d4baabe9027b17714038cf392e2bfdd9d4effdb3 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 15 Mar 2023 00:23:34 +0800 Subject: clean up Colon from clippy --- clippy_utils/src/sugg.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index e81eadceec0..03cd8e48b9a 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -163,7 +163,8 @@ impl<'a> Sugg<'a> { get_snippet(rhs.span), ), hir::ExprKind::Cast(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)), - hir::ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::Colon, get_snippet(lhs.span), get_snippet(ty.span)), + //FIXME(chenyukang), remove this after type ascription is removed from AST + hir::ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)), } } @@ -258,8 +259,9 @@ impl<'a> Sugg<'a> { snippet_with_context(cx, lhs.span, ctxt, default, app).0, snippet_with_context(cx, ty.span, ctxt, default, app).0, ), + //FIXME(chenyukang), remove this after type ascription is removed from AST ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp( - AssocOp::Colon, + AssocOp::As, snippet_with_context(cx, lhs.span, ctxt, default, app).0, snippet_with_context(cx, ty.span, ctxt, default, app).0, ), @@ -392,7 +394,6 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { AssocOp::As => format!("{lhs} as {rhs}"), AssocOp::DotDot => format!("{lhs}..{rhs}"), AssocOp::DotDotEq => format!("{lhs}..={rhs}"), - AssocOp::Colon => format!("{lhs}: {rhs}"), } } @@ -602,13 +603,13 @@ enum Associativity { #[must_use] fn associativity(op: AssocOp) -> Associativity { use rustc_ast::util::parser::AssocOp::{ - Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Colon, Divide, DotDot, DotDotEq, Equal, Greater, + Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd, LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract, }; match op { Assign | AssignOp(_) => Associativity::Right, - Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As | Colon => Associativity::Both, + Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both, Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight | Subtract => Associativity::Left, DotDot | DotDotEq => Associativity::None, -- cgit 1.4.1-3-g733a5 From 57490542419e50a22eca2b4aa79e2a64ad39c4cd Mon Sep 17 00:00:00 2001 From: blyxyas Date: Mon, 1 May 2023 12:39:20 +0200 Subject: globally ignore `#[no_std]` crates --- clippy_lints/src/floating_point_arithmetic.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index da3d0da994c..e221905580c 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -453,9 +453,6 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&' // TODO: Fix rust-lang/rust-clippy#4735 fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { - if is_no_std_crate(cx) { - return; // The suggested methods are not available in core - } if let ExprKind::Binary( Spanned { node: op @ (BinOpKind::Add | BinOpKind::Sub), @@ -570,9 +567,6 @@ fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a } fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { - if is_no_std_crate(cx) { - return; // The suggested methods are not available in core - } if_chain! { if let Some(higher::If { cond, then, r#else: Some(r#else) }) = higher::If::hir(expr); let if_body_expr = peel_blocks(then); @@ -737,8 +731,8 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // All of these operations are currently not const. - if in_constant(cx, expr.hir_id) { + // All of these operations are currently not const and are in std. + if in_constant(cx, expr.hir_id) || is_no_std_crate(cx) { return; } -- cgit 1.4.1-3-g733a5 From 220a9db64215df07f730cd01322a0c8b658629cd Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Mon, 1 May 2023 20:12:34 +0200 Subject: fixed span and corrected test output --- .../src/default_constructed_unit_struct.rs | 2 +- tests/ui/default_constructed_unit_struct.stderr | 24 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/default_constructed_unit_struct.rs b/clippy_lints/src/default_constructed_unit_struct.rs index d518c8e7c56..d261cdd44a5 100644 --- a/clippy_lints/src/default_constructed_unit_struct.rs +++ b/clippy_lints/src/default_constructed_unit_struct.rs @@ -54,7 +54,7 @@ impl LateLintPass<'_> for DefaultConstructedUnitStruct { span_lint_and_sugg( cx, DEFAULT_CONSTRUCTED_UNIT_STRUCT, - qpath.last_segment_span(), + expr.span.with_lo(qpath.qself_span().hi()), "use of `default` to create a unit struct", "remove this call to `default`", String::new(), diff --git a/tests/ui/default_constructed_unit_struct.stderr b/tests/ui/default_constructed_unit_struct.stderr index 13439414f4a..952d4019644 100644 --- a/tests/ui/default_constructed_unit_struct.stderr +++ b/tests/ui/default_constructed_unit_struct.stderr @@ -1,28 +1,28 @@ -error: Use of `default` to create a unit struct. - --> $DIR/default_constructed_unit_struct.rs:39:33 +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_struct.rs:39:31 | LL | inner: PhantomData::default(), - | ^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^ help: remove this call to `default` | = note: `-D clippy::default-constructed-unit-struct` implied by `-D warnings` -error: Use of `default` to create a unit struct. - --> $DIR/default_constructed_unit_struct.rs:62:35 +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_struct.rs:62:33 | LL | let _ = PhantomData::::default(); - | ^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^ help: remove this call to `default` -error: Use of `default` to create a unit struct. - --> $DIR/default_constructed_unit_struct.rs:63:44 +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_struct.rs:63:42 | LL | let _: PhantomData = PhantomData::default(); - | ^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^ help: remove this call to `default` -error: Use of `default` to create a unit struct. - --> $DIR/default_constructed_unit_struct.rs:64:25 +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_struct.rs:64:23 | LL | let _ = UnitStruct::default(); - | ^^^^^^^ help: remove this call to `default` + | ^^^^^^^^^^^ help: remove this call to `default` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 0dd2501e0d06684de5836a00d5e039f25793fd74 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Tue, 2 May 2023 20:47:18 +0200 Subject: Don't ignore `check_radians` --- clippy_lints/src/floating_point_arithmetic.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index e221905580c..a1a2c398a8a 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -732,14 +732,14 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // All of these operations are currently not const and are in std. - if in_constant(cx, expr.hir_id) || is_no_std_crate(cx) { + if in_constant(cx, expr.hir_id) { return; } if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind { let recv_ty = cx.typeck_results().expr_ty(receiver); - if recv_ty.is_floating_point() { + if recv_ty.is_floating_point() && !is_no_std_crate(cx) { match path.ident.name.as_str() { "ln" => check_ln1p(cx, expr, receiver), "log" => check_log_base(cx, expr, receiver, args), @@ -750,10 +750,12 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { } } } else { - check_expm1(cx, expr); - check_mul_add(cx, expr); - check_custom_abs(cx, expr); - check_log_division(cx, expr); + if !is_no_std_crate(cx) { + check_expm1(cx, expr); + check_mul_add(cx, expr); + check_custom_abs(cx, expr); + check_log_division(cx, expr); + } check_radians(cx, expr); } } -- cgit 1.4.1-3-g733a5 From 431cce15401f9dc99ac9ac08551d803130896b83 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Apr 2023 13:26:58 +1000 Subject: Restrict `From` for `{D,Subd}iagnosticMessage`. Currently a `{D,Subd}iagnosticMessage` can be created from any type that impls `Into`. That includes `&str`, `String`, and `Cow<'static, str>`, which are reasonable. It also includes `&String`, which is pretty weird, and results in many places making unnecessary allocations for patterns like this: ``` self.fatal(&format!(...)) ``` This creates a string with `format!`, takes a reference, passes the reference to `fatal`, which does an `into()`, which clones the reference, doing a second allocation. Two allocations for a single string, bleh. This commit changes the `From` impls so that you can only create a `{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static, str>`. This requires changing all the places that currently create one from a `&String`. Most of these are of the `&format!(...)` form described above; each one removes an unnecessary static `&`, plus an allocation when executed. There are also a few places where the existing use of `&String` was more reasonable; these now just use `clone()` at the call site. As well as making the code nicer and more efficient, this is a step towards possibly using `Cow<'static, str>` in `{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing the `From<&'a str>` impls to `From<&'static str>`, which is doable, but I'm not yet sure if it's worthwhile. --- clippy_lints/src/future_not_send.rs | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 4 ++-- clippy_lints/src/non_send_fields_in_send_ty.rs | 6 +++--- clippy_utils/src/attrs.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index ff838c2d56e..d1314795f58 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if let PredicateKind::Clause(Clause::Trait(trait_pred)) = obligation.predicate.kind().skip_binder() { - db.note(&format!( + db.note(format!( "`{}` doesn't implement `{}`", trait_pred.self_ty(), trait_pred.trait_ref.print_only_trait_path(), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 573ffe349ec..9e65f9ecd16 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -353,7 +353,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se pub fn read_conf(sess: &Session, path: &io::Result<(Option, Vec)>) -> Conf { if let Ok((_, warnings)) = path { for warning in warnings { - sess.warn(warning); + sess.warn(warning.clone()); } } let file_name = match path { diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index d00708e828e..91f7ce1dbe5 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -175,13 +175,13 @@ fn check_manual_split_once_indirect( let remove_msg = format!("remove the `{iter_ident}` usages"); diag.span_suggestion( first.span, - &remove_msg, + remove_msg.clone(), "", app, ); diag.span_suggestion( second.span, - &remove_msg, + remove_msg, "", app, ); diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs index 839c3a3815c..7eaa7db78a4 100644 --- a/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -131,13 +131,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { for field in non_send_fields { diag.span_note( field.def.span, - &format!("it is not safe to send field `{}` to another thread", field.def.ident.name), + format!("it is not safe to send field `{}` to another thread", field.def.ident.name), ); match field.generic_params.len() { 0 => diag.help("use a thread-safe type that implements `Send`"), - 1 if is_ty_param(field.ty) => diag.help(&format!("add `{}: Send` bound in `Send` impl", field.ty)), - _ => diag.help(&format!( + 1 if is_ty_param(field.ty) => diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty)), + _ => diag.help(format!( "add bounds on type parameter{} `{}` that satisfy `{}: Send`", if field.generic_params.len() > 1 { "s" } else { "" }, field.generic_params_string(), diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index b4ad42a5027..49cb9718ef6 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -133,7 +133,7 @@ pub fn get_unique_attr<'a>( let mut unique_attr: Option<&ast::Attribute> = None; for attr in get_attr(sess, attrs, name) { if let Some(duplicate) = unique_attr { - sess.struct_span_err(attr.span, &format!("`{name}` is defined multiple times")) + sess.struct_span_err(attr.span, format!("`{name}` is defined multiple times")) .span_note(duplicate.span, "first definition found here") .emit(); } else { -- cgit 1.4.1-3-g733a5 From 7e24ff33e4a940df392e5329e18e6bc05f882088 Mon Sep 17 00:00:00 2001 From: Samuel Moelius <35515885+smoelius@users.noreply.github.com> Date: Tue, 2 May 2023 19:02:06 -0400 Subject: Update macros.rs --- clippy_utils/src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 62d388a5ece..e4a4936ff42 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -362,7 +362,7 @@ thread_local! { /// able to access the many features of a [`LateContext`]. /// /// A thread local is used because [`FormatArgs`] is `!Send` and `!Sync`, we are making an - /// assumption that the early pass the populates the map and the later late passes will all be + /// assumption that the early pass that populates the map and the later late passes will all be /// running on the same thread. static AST_FORMAT_ARGS: RefCell> = { static CALLED: AtomicBool = AtomicBool::new(false); -- cgit 1.4.1-3-g733a5 From 4e049036313759df55c4c68ad87e1cd7ad5cf214 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Wed, 3 May 2023 19:25:25 +0200 Subject: rename to plural form --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- .../src/default_constructed_unit_struct.rs | 66 -------------------- .../src/default_constructed_unit_structs.rs | 66 ++++++++++++++++++++ clippy_lints/src/lib.rs | 4 +- tests/ui/default_constructed_unit_struct.rs | 72 ---------------------- tests/ui/default_constructed_unit_struct.stderr | 28 --------- tests/ui/default_constructed_unit_structs.rs | 72 ++++++++++++++++++++++ tests/ui/default_constructed_unit_structs.stderr | 28 +++++++++ 9 files changed, 170 insertions(+), 170 deletions(-) delete mode 100644 clippy_lints/src/default_constructed_unit_struct.rs create mode 100644 clippy_lints/src/default_constructed_unit_structs.rs delete mode 100644 tests/ui/default_constructed_unit_struct.rs delete mode 100644 tests/ui/default_constructed_unit_struct.stderr create mode 100644 tests/ui/default_constructed_unit_structs.rs create mode 100644 tests/ui/default_constructed_unit_structs.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 735ac59758a..31ad00536c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4582,7 +4582,7 @@ Released 2018-09-13 [`debug_assert_with_mut_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#debug_assert_with_mut_call [`decimal_literal_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation [`declare_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const -[`default_constructed_unit_struct`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_constructed_unit_struct +[`default_constructed_unit_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_constructed_unit_structs [`default_instead_of_iter_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_instead_of_iter_empty [`default_numeric_fallback`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_numeric_fallback [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index bf30f5b52f7..d3f5cb6e5f4 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -105,7 +105,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::dbg_macro::DBG_MACRO_INFO, crate::default::DEFAULT_TRAIT_ACCESS_INFO, crate::default::FIELD_REASSIGN_WITH_DEFAULT_INFO, - crate::default_constructed_unit_struct::DEFAULT_CONSTRUCTED_UNIT_STRUCT_INFO, + crate::default_constructed_unit_structs::DEFAULT_CONSTRUCTED_UNIT_STRUCTS_INFO, crate::default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY_INFO, crate::default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK_INFO, crate::default_union_representation::DEFAULT_UNION_REPRESENTATION_INFO, diff --git a/clippy_lints/src/default_constructed_unit_struct.rs b/clippy_lints/src/default_constructed_unit_struct.rs deleted file mode 100644 index d261cdd44a5..00000000000 --- a/clippy_lints/src/default_constructed_unit_struct.rs +++ /dev/null @@ -1,66 +0,0 @@ -use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, match_def_path, paths}; -use hir::{def::Res, ExprKind}; -use rustc_errors::Applicability; -use rustc_hir as hir; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Check for construction on unit struct using `default`. - /// - /// ### Why is this bad? - /// This adds code complexity and an unnecessary function call. - /// - /// ### Example - /// ```rust - /// #[derive(Default)] - /// struct S { - /// _marker: PhantomData - /// } - /// - /// let _: S = S { - /// _marker: PhantomData::default() - /// }; - /// ``` - /// Use instead: - /// ```rust - /// let _: S = Something { - /// _marker: PhantomData - /// } - /// ``` - #[clippy::version = "1.71.0"] - pub DEFAULT_CONSTRUCTED_UNIT_STRUCT, - complexity, - "unit structs can be contructed without calling `default`" -} -declare_lint_pass!(DefaultConstructedUnitStruct => [DEFAULT_CONSTRUCTED_UNIT_STRUCT]); - -impl LateLintPass<'_> for DefaultConstructedUnitStruct { - fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if_chain!( - // make sure we have a call to `Default::default` - if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind; - if let ExprKind::Path(ref qpath) = fn_expr.kind; - if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); - if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); - // make sure we have a struct with no fields (unit struct) - if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); - if def.is_struct() && def.is_payloadfree() - && !def.non_enum_variant().is_field_list_non_exhaustive() - && !is_from_proc_macro(cx, expr); - then { - span_lint_and_sugg( - cx, - DEFAULT_CONSTRUCTED_UNIT_STRUCT, - expr.span.with_lo(qpath.qself_span().hi()), - "use of `default` to create a unit struct", - "remove this call to `default`", - String::new(), - Applicability::MachineApplicable, - ) - } - ); - } -} diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs new file mode 100644 index 00000000000..a79923e9715 --- /dev/null +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -0,0 +1,66 @@ +use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, match_def_path, paths}; +use hir::{def::Res, ExprKind}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Check for construction on unit struct using `default`. + /// + /// ### Why is this bad? + /// This adds code complexity and an unnecessary function call. + /// + /// ### Example + /// ```rust + /// #[derive(Default)] + /// struct S { + /// _marker: PhantomData + /// } + /// + /// let _: S = S { + /// _marker: PhantomData::default() + /// }; + /// ``` + /// Use instead: + /// ```rust + /// let _: S = Something { + /// _marker: PhantomData + /// } + /// ``` + #[clippy::version = "1.71.0"] + pub DEFAULT_CONSTRUCTED_UNIT_STRUCTS, + complexity, + "unit structs can be contructed without calling `default`" +} +declare_lint_pass!(DefaultConstructedUnitStructs => [DEFAULT_CONSTRUCTED_UNIT_STRUCTS]); + +impl LateLintPass<'_> for DefaultConstructedUnitStructs { + fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if_chain!( + // make sure we have a call to `Default::default` + if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind; + if let ExprKind::Path(ref qpath) = fn_expr.kind; + if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); + if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); + // make sure we have a struct with no fields (unit struct) + if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); + if def.is_struct() && def.is_payloadfree() + && !def.non_enum_variant().is_field_list_non_exhaustive() + && !is_from_proc_macro(cx, expr); + then { + span_lint_and_sugg( + cx, + DEFAULT_CONSTRUCTED_UNIT_STRUCTS, + expr.span.with_lo(qpath.qself_span().hi()), + "use of `default` to create a unit struct", + "remove this call to `default`", + String::new(), + Applicability::MachineApplicable, + ) + } + ); + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9af0b17e27b..657a3d1f431 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -94,7 +94,7 @@ mod crate_in_macro_def; mod create_dir; mod dbg_macro; mod default; -mod default_constructed_unit_struct; +mod default_constructed_unit_structs; mod default_instead_of_iter_empty; mod default_numeric_fallback; mod default_union_representation; @@ -971,7 +971,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation)); store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments)); store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule)); - store.register_late_pass(|_| Box::new(default_constructed_unit_struct::DefaultConstructedUnitStruct)); + store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/default_constructed_unit_struct.rs b/tests/ui/default_constructed_unit_struct.rs deleted file mode 100644 index b64da9b863a..00000000000 --- a/tests/ui/default_constructed_unit_struct.rs +++ /dev/null @@ -1,72 +0,0 @@ -#![allow(unused)] -#![warn(clippy::default_constructed_unit_struct)] -use std::marker::PhantomData; - -#[derive(Default)] -struct UnitStruct; - -#[derive(Default)] -struct TupleStruct(usize); - -// no lint for derived impl -#[derive(Default)] -struct NormalStruct { - inner: PhantomData, -} - -struct NonDefaultStruct; - -impl NonDefaultStruct { - fn default() -> Self { - Self - } -} - -#[derive(Default)] -enum SomeEnum { - #[default] - Unit, - Tuple(UnitStruct), - Struct { - inner: usize, - }, -} - -impl NormalStruct { - fn new() -> Self { - // should lint - Self { - inner: PhantomData::default(), - } - } -} - -#[derive(Default)] -struct GenericStruct { - t: T, -} - -impl GenericStruct { - fn new() -> Self { - // should not lint - Self { t: T::default() } - } -} - -#[derive(Default)] -#[non_exhaustive] -struct NonExhaustiveStruct; - -fn main() { - // should lint - let _ = PhantomData::::default(); - let _: PhantomData = PhantomData::default(); - let _ = UnitStruct::default(); - - // should not lint - let _ = TupleStruct::default(); - let _ = NormalStruct::default(); - let _ = NonExhaustiveStruct::default(); - let _ = SomeEnum::default(); - let _ = NonDefaultStruct::default(); -} diff --git a/tests/ui/default_constructed_unit_struct.stderr b/tests/ui/default_constructed_unit_struct.stderr deleted file mode 100644 index 952d4019644..00000000000 --- a/tests/ui/default_constructed_unit_struct.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_struct.rs:39:31 - | -LL | inner: PhantomData::default(), - | ^^^^^^^^^^^ help: remove this call to `default` - | - = note: `-D clippy::default-constructed-unit-struct` implied by `-D warnings` - -error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_struct.rs:62:33 - | -LL | let _ = PhantomData::::default(); - | ^^^^^^^^^^^ help: remove this call to `default` - -error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_struct.rs:63:42 - | -LL | let _: PhantomData = PhantomData::default(); - | ^^^^^^^^^^^ help: remove this call to `default` - -error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_struct.rs:64:23 - | -LL | let _ = UnitStruct::default(); - | ^^^^^^^^^^^ help: remove this call to `default` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs new file mode 100644 index 00000000000..505be09a50e --- /dev/null +++ b/tests/ui/default_constructed_unit_structs.rs @@ -0,0 +1,72 @@ +#![allow(unused)] +#![warn(clippy::default_constructed_unit_structs)] +use std::marker::PhantomData; + +#[derive(Default)] +struct UnitStruct; + +#[derive(Default)] +struct TupleStruct(usize); + +// no lint for derived impl +#[derive(Default)] +struct NormalStruct { + inner: PhantomData, +} + +struct NonDefaultStruct; + +impl NonDefaultStruct { + fn default() -> Self { + Self + } +} + +#[derive(Default)] +enum SomeEnum { + #[default] + Unit, + Tuple(UnitStruct), + Struct { + inner: usize, + }, +} + +impl NormalStruct { + fn new() -> Self { + // should lint + Self { + inner: PhantomData::default(), + } + } +} + +#[derive(Default)] +struct GenericStruct { + t: T, +} + +impl GenericStruct { + fn new() -> Self { + // should not lint + Self { t: T::default() } + } +} + +#[derive(Default)] +#[non_exhaustive] +struct NonExhaustiveStruct; + +fn main() { + // should lint + let _ = PhantomData::::default(); + let _: PhantomData = PhantomData::default(); + let _ = UnitStruct::default(); + + // should not lint + let _ = TupleStruct::default(); + let _ = NormalStruct::default(); + let _ = NonExhaustiveStruct::default(); + let _ = SomeEnum::default(); + let _ = NonDefaultStruct::default(); +} diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr new file mode 100644 index 00000000000..23ffa278288 --- /dev/null +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -0,0 +1,28 @@ +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_structs.rs:39:31 + | +LL | inner: PhantomData::default(), + | ^^^^^^^^^^^ help: remove this call to `default` + | + = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings` + +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_structs.rs:62:33 + | +LL | let _ = PhantomData::::default(); + | ^^^^^^^^^^^ help: remove this call to `default` + +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_structs.rs:63:42 + | +LL | let _: PhantomData = PhantomData::default(); + | ^^^^^^^^^^^ help: remove this call to `default` + +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_structs.rs:64:23 + | +LL | let _ = UnitStruct::default(); + | ^^^^^^^^^^^ help: remove this call to `default` + +error: aborting due to 4 previous errors + -- cgit 1.4.1-3-g733a5 From 8701009860273828cb6853e1dba79a82e1271619 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Wed, 3 May 2023 20:06:29 +0200 Subject: add more test cases --- .../src/default_constructed_unit_structs.rs | 8 ++-- tests/ui/default_constructed_unit_structs.rs | 45 ++++++++++++++++++++++ tests/ui/default_constructed_unit_structs.stderr | 20 ++++++---- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index a79923e9715..dab76a2c41f 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -42,14 +42,14 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs { if_chain!( // make sure we have a call to `Default::default` if let hir::ExprKind::Call(fn_expr, &[]) = expr.kind; - if let ExprKind::Path(ref qpath) = fn_expr.kind; + if let ExprKind::Path(ref qpath@ hir::QPath::TypeRelative(_,_)) = fn_expr.kind; if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id); if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD); // make sure we have a struct with no fields (unit struct) if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind(); - if def.is_struct() && def.is_payloadfree() - && !def.non_enum_variant().is_field_list_non_exhaustive() - && !is_from_proc_macro(cx, expr); + if def.is_struct(); + if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant(); + if !var.is_field_list_non_exhaustive() && !is_from_proc_macro(cx, expr); then { span_lint_and_sugg( cx, diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs index 505be09a50e..276fc40aa18 100644 --- a/tests/ui/default_constructed_unit_structs.rs +++ b/tests/ui/default_constructed_unit_structs.rs @@ -5,9 +5,23 @@ use std::marker::PhantomData; #[derive(Default)] struct UnitStruct; +impl UnitStruct { + fn new() -> Self { + //should lint + Self::default() + } +} + #[derive(Default)] struct TupleStruct(usize); +impl TupleStruct { + fn new() -> Self { + // should not lint + Self(Default::default()) + } +} + // no lint for derived impl #[derive(Default)] struct NormalStruct { @@ -39,6 +53,13 @@ impl NormalStruct { inner: PhantomData::default(), } } + + fn new2() -> Self { + // should not lint + Self { + inner: Default::default(), + } + } } #[derive(Default)] @@ -51,8 +72,29 @@ impl GenericStruct { // should not lint Self { t: T::default() } } + + fn new2() -> Self { + // should not lint + Self { t: Default::default() } + } +} + +struct FakeDefault; +impl FakeDefault { + fn default() -> Self { + Self + } } +impl Default for FakeDefault { + fn default() -> Self { + Self + } +} + +#[derive(Default)] +struct EmptyStruct {} + #[derive(Default)] #[non_exhaustive] struct NonExhaustiveStruct; @@ -69,4 +111,7 @@ fn main() { let _ = NonExhaustiveStruct::default(); let _ = SomeEnum::default(); let _ = NonDefaultStruct::default(); + let _ = EmptyStruct::default(); + let _ = FakeDefault::default(); + let _ = ::default(); } diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr index 23ffa278288..fa39ef4cda1 100644 --- a/tests/ui/default_constructed_unit_structs.stderr +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -1,28 +1,34 @@ error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:39:31 + --> $DIR/default_constructed_unit_structs.rs:11:13 | -LL | inner: PhantomData::default(), - | ^^^^^^^^^^^ help: remove this call to `default` +LL | Self::default() + | ^^^^^^^^^^^ help: remove this call to `default` | = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:62:33 + --> $DIR/default_constructed_unit_structs.rs:53:31 + | +LL | inner: PhantomData::default(), + | ^^^^^^^^^^^ help: remove this call to `default` + +error: use of `default` to create a unit struct + --> $DIR/default_constructed_unit_structs.rs:104:33 | LL | let _ = PhantomData::::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:63:42 + --> $DIR/default_constructed_unit_structs.rs:105:42 | LL | let _: PhantomData = PhantomData::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:64:23 + --> $DIR/default_constructed_unit_structs.rs:106:23 | LL | let _ = UnitStruct::default(); | ^^^^^^^^^^^ help: remove this call to `default` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 4ed7fd1ecc94eb82d99fe18192c156f367029731 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Wed, 3 May 2023 20:07:02 +0200 Subject: fix failing tests --- tests/ui/box_default.fixed | 1 + tests/ui/box_default.rs | 1 + tests/ui/box_default.stderr | 32 ++++++++++++++++---------------- tests/ui/from_over_into.fixed | 2 +- tests/ui/from_over_into.rs | 2 +- tests/ui/from_over_into.stderr | 2 +- tests/ui/use_self_trait.fixed | 4 ++-- tests/ui/use_self_trait.rs | 4 ++-- tests/ui/use_self_trait.stderr | 2 +- 9 files changed, 26 insertions(+), 24 deletions(-) diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed index 6afce208769..e6331290420 100644 --- a/tests/ui/box_default.fixed +++ b/tests/ui/box_default.fixed @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::box_default)] +#![allow(clippy::default_constructed_unit_structs)] #[derive(Default)] struct ImplementsDefault; diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs index 09365618e63..34a05a29c5a 100644 --- a/tests/ui/box_default.rs +++ b/tests/ui/box_default.rs @@ -1,5 +1,6 @@ //@run-rustfix #![warn(clippy::box_default)] +#![allow(clippy::default_constructed_unit_structs)] #[derive(Default)] struct ImplementsDefault; diff --git a/tests/ui/box_default.stderr b/tests/ui/box_default.stderr index 78e17b9f035..c9834863601 100644 --- a/tests/ui/box_default.stderr +++ b/tests/ui/box_default.stderr @@ -1,5 +1,5 @@ error: `Box::new(_)` of default value - --> $DIR/box_default.rs:22:32 + --> $DIR/box_default.rs:23:32 | LL | let _string: Box = Box::new(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` @@ -7,91 +7,91 @@ LL | let _string: Box = Box::new(Default::default()); = note: `-D clippy::box-default` implied by `-D warnings` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:23:17 + --> $DIR/box_default.rs:24:17 | LL | let _byte = Box::new(u8::default()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:24:16 + --> $DIR/box_default.rs:25:16 | LL | let _vec = Box::new(Vec::::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::>::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:25:17 + --> $DIR/box_default.rs:26:17 | LL | let _impl = Box::new(ImplementsDefault::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:26:18 + --> $DIR/box_default.rs:27:18 | LL | let _impl2 = Box::new(::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:27:42 + --> $DIR/box_default.rs:28:42 | LL | let _impl3: Box = Box::new(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:29:28 + --> $DIR/box_default.rs:30:28 | LL | let _in_macro = outer!(Box::new(String::new())); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:30:34 + --> $DIR/box_default.rs:31:34 | LL | let _string_default = outer!(Box::new(String::from(""))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:31:46 + --> $DIR/box_default.rs:32:46 | LL | let _vec2: Box> = Box::new(vec![]); | ^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:32:33 + --> $DIR/box_default.rs:33:33 | LL | let _vec3: Box> = Box::new(Vec::from([])); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:33:25 + --> $DIR/box_default.rs:34:25 | LL | let _vec4: Box<_> = Box::new(Vec::from([false; 0])); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::>::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:35:16 + --> $DIR/box_default.rs:36:16 | LL | call_ty_fn(Box::new(u8::default())); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:40:5 + --> $DIR/box_default.rs:41:5 | LL | Box::new(bool::default()) | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:57:28 + --> $DIR/box_default.rs:58:28 | LL | let _: Box = Box::new(ImplementsDefault::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:66:17 + --> $DIR/box_default.rs:67:17 | LL | let _ = Box::new(WeirdPathed::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` error: `Box::new(_)` of default value - --> $DIR/box_default.rs:78:18 + --> $DIR/box_default.rs:79:18 | LL | Some(Box::new(Foo::default())) | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::::default()` diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index fc6d937060d..d18f9387565 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -32,7 +32,7 @@ struct SelfKeywords; impl From for SelfKeywords { fn from(val: X) -> Self { - let _ = X::default(); + let _ = X; let _ = X::FOO; let _: X = val; diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index fe1ebee35f1..de8ff0b06bd 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -32,7 +32,7 @@ struct SelfKeywords; impl Into for X { fn into(self) -> SelfKeywords { - let _ = Self::default(); + let _ = Self; let _ = Self::FOO; let _: Self = self; diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 990b905c1b1..6039f86fe67 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -35,7 +35,7 @@ help: replace the `Into` implementation with `From` | LL ~ impl From for SelfKeywords { LL ~ fn from(val: X) -> Self { -LL ~ let _ = X::default(); +LL ~ let _ = X; LL ~ let _ = X::FOO; LL ~ let _: X = val; | diff --git a/tests/ui/use_self_trait.fixed b/tests/ui/use_self_trait.fixed index 4623aeeb0eb..20138a29fd1 100644 --- a/tests/ui/use_self_trait.fixed +++ b/tests/ui/use_self_trait.fixed @@ -33,7 +33,7 @@ impl SelfTrait for Bad { fn nested(_p1: Box, _p2: (&u8, &Self)) {} fn vals(_: Self) -> Self { - Self::default() + Self } } @@ -70,7 +70,7 @@ impl SelfTrait for Good { fn nested(_p1: Box, _p2: (&u8, &Self)) {} fn vals(_: Self) -> Self { - Self::default() + Self } } diff --git a/tests/ui/use_self_trait.rs b/tests/ui/use_self_trait.rs index d7d76dd9623..bf697b01a42 100644 --- a/tests/ui/use_self_trait.rs +++ b/tests/ui/use_self_trait.rs @@ -33,7 +33,7 @@ impl SelfTrait for Bad { fn nested(_p1: Box, _p2: (&u8, &Bad)) {} fn vals(_: Bad) -> Bad { - Bad::default() + Bad } } @@ -70,7 +70,7 @@ impl SelfTrait for Good { fn nested(_p1: Box, _p2: (&u8, &Self)) {} fn vals(_: Self) -> Self { - Self::default() + Self } } diff --git a/tests/ui/use_self_trait.stderr b/tests/ui/use_self_trait.stderr index 090729b9c3d..6257f802dd8 100644 --- a/tests/ui/use_self_trait.stderr +++ b/tests/ui/use_self_trait.stderr @@ -63,7 +63,7 @@ LL | fn vals(_: Bad) -> Bad { error: unnecessary structure name repetition --> $DIR/use_self_trait.rs:36:9 | -LL | Bad::default() +LL | Bad | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition -- cgit 1.4.1-3-g733a5 From 160371550fbb7783200f6184109c02babf06efb3 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Wed, 3 May 2023 21:05:50 +0200 Subject: add `rustfix` annotation --- tests/ui/default_constructed_unit_structs.fixed | 119 +++++++++++++++++++++++ tests/ui/default_constructed_unit_structs.rs | 2 + tests/ui/default_constructed_unit_structs.stderr | 10 +- 3 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 tests/ui/default_constructed_unit_structs.fixed diff --git a/tests/ui/default_constructed_unit_structs.fixed b/tests/ui/default_constructed_unit_structs.fixed new file mode 100644 index 00000000000..4c2d1ea48e1 --- /dev/null +++ b/tests/ui/default_constructed_unit_structs.fixed @@ -0,0 +1,119 @@ +//@run-rustfix + +#![allow(unused)] +#![warn(clippy::default_constructed_unit_structs)] +use std::marker::PhantomData; + +#[derive(Default)] +struct UnitStruct; + +impl UnitStruct { + fn new() -> Self { + //should lint + Self + } +} + +#[derive(Default)] +struct TupleStruct(usize); + +impl TupleStruct { + fn new() -> Self { + // should not lint + Self(Default::default()) + } +} + +// no lint for derived impl +#[derive(Default)] +struct NormalStruct { + inner: PhantomData, +} + +struct NonDefaultStruct; + +impl NonDefaultStruct { + fn default() -> Self { + Self + } +} + +#[derive(Default)] +enum SomeEnum { + #[default] + Unit, + Tuple(UnitStruct), + Struct { + inner: usize, + }, +} + +impl NormalStruct { + fn new() -> Self { + // should lint + Self { + inner: PhantomData, + } + } + + fn new2() -> Self { + // should not lint + Self { + inner: Default::default(), + } + } +} + +#[derive(Default)] +struct GenericStruct { + t: T, +} + +impl GenericStruct { + fn new() -> Self { + // should not lint + Self { t: T::default() } + } + + fn new2() -> Self { + // should not lint + Self { t: Default::default() } + } +} + +struct FakeDefault; +impl FakeDefault { + fn default() -> Self { + Self + } +} + +impl Default for FakeDefault { + fn default() -> Self { + Self + } +} + +#[derive(Default)] +struct EmptyStruct {} + +#[derive(Default)] +#[non_exhaustive] +struct NonExhaustiveStruct; + +fn main() { + // should lint + let _ = PhantomData::; + let _: PhantomData = PhantomData; + let _ = UnitStruct; + + // should not lint + let _ = TupleStruct::default(); + let _ = NormalStruct::default(); + let _ = NonExhaustiveStruct::default(); + let _ = SomeEnum::default(); + let _ = NonDefaultStruct::default(); + let _ = EmptyStruct::default(); + let _ = FakeDefault::default(); + let _ = ::default(); +} diff --git a/tests/ui/default_constructed_unit_structs.rs b/tests/ui/default_constructed_unit_structs.rs index 276fc40aa18..850793dd5de 100644 --- a/tests/ui/default_constructed_unit_structs.rs +++ b/tests/ui/default_constructed_unit_structs.rs @@ -1,3 +1,5 @@ +//@run-rustfix + #![allow(unused)] #![warn(clippy::default_constructed_unit_structs)] use std::marker::PhantomData; diff --git a/tests/ui/default_constructed_unit_structs.stderr b/tests/ui/default_constructed_unit_structs.stderr index fa39ef4cda1..4058943d087 100644 --- a/tests/ui/default_constructed_unit_structs.stderr +++ b/tests/ui/default_constructed_unit_structs.stderr @@ -1,5 +1,5 @@ error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:11:13 + --> $DIR/default_constructed_unit_structs.rs:13:13 | LL | Self::default() | ^^^^^^^^^^^ help: remove this call to `default` @@ -7,25 +7,25 @@ LL | Self::default() = note: `-D clippy::default-constructed-unit-structs` implied by `-D warnings` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:53:31 + --> $DIR/default_constructed_unit_structs.rs:55:31 | LL | inner: PhantomData::default(), | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:104:33 + --> $DIR/default_constructed_unit_structs.rs:106:33 | LL | let _ = PhantomData::::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:105:42 + --> $DIR/default_constructed_unit_structs.rs:107:42 | LL | let _: PhantomData = PhantomData::default(); | ^^^^^^^^^^^ help: remove this call to `default` error: use of `default` to create a unit struct - --> $DIR/default_constructed_unit_structs.rs:106:23 + --> $DIR/default_constructed_unit_structs.rs:108:23 | LL | let _ = UnitStruct::default(); | ^^^^^^^^^^^ help: remove this call to `default` -- cgit 1.4.1-3-g733a5 From 48ae5a071bc32e5fb69669248ab103ecba7509ab Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Wed, 3 May 2023 21:43:10 +0200 Subject: fix lint docs --- clippy_lints/src/default_constructed_unit_structs.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/default_constructed_unit_structs.rs b/clippy_lints/src/default_constructed_unit_structs.rs index dab76a2c41f..e529d81a7e9 100644 --- a/clippy_lints/src/default_constructed_unit_structs.rs +++ b/clippy_lints/src/default_constructed_unit_structs.rs @@ -15,6 +15,7 @@ declare_clippy_lint! { /// /// ### Example /// ```rust + /// # use std::marker::PhantomData; /// #[derive(Default)] /// struct S { /// _marker: PhantomData @@ -26,9 +27,14 @@ declare_clippy_lint! { /// ``` /// Use instead: /// ```rust - /// let _: S = Something { - /// _marker: PhantomData + /// # use std::marker::PhantomData; + /// struct S { + /// _marker: PhantomData /// } + /// + /// let _: S = S { + /// _marker: PhantomData + /// }; /// ``` #[clippy::version = "1.71.0"] pub DEFAULT_CONSTRUCTED_UNIT_STRUCTS, -- cgit 1.4.1-3-g733a5 From 0f7b61d729e20fd486bb26663993f63cce5a68eb Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 5 May 2023 11:45:24 +0000 Subject: Inherit stdout/stderr for `cargo dev dogfood` --- clippy_dev/src/dogfood.rs | 8 +++----- clippy_dev/src/lib.rs | 13 +++++++++++++ clippy_dev/src/lint.rs | 17 +++-------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/clippy_dev/src/dogfood.rs b/clippy_dev/src/dogfood.rs index b69e9f649ec..a0d57f5ab48 100644 --- a/clippy_dev/src/dogfood.rs +++ b/clippy_dev/src/dogfood.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::{clippy_project_root, exit_if_err}; use std::process::Command; /// # Panics @@ -10,7 +10,7 @@ pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) { cmd.current_dir(clippy_project_root()) .args(["test", "--test", "dogfood"]) .args(["--features", "internal"]) - .args(["--", "dogfood_clippy"]); + .args(["--", "dogfood_clippy", "--nocapture"]); let mut dogfood_args = Vec::new(); if fix { @@ -27,7 +27,5 @@ pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) { cmd.env("__CLIPPY_DOGFOOD_ARGS", dogfood_args.join(" ")); - let output = cmd.output().expect("failed to run command"); - - println!("{}", String::from_utf8_lossy(&output.stdout)); + exit_if_err(cmd.status()); } diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 3a8b070d735..56a269288c0 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -10,7 +10,9 @@ extern crate rustc_driver; extern crate rustc_lexer; +use std::io; use std::path::PathBuf; +use std::process::{self, ExitStatus}; pub mod bless; pub mod dogfood; @@ -58,3 +60,14 @@ pub fn clippy_project_root() -> PathBuf { } panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); } + +pub fn exit_if_err(status: io::Result) { + match status.expect("failed to run command").code() { + Some(0) => {}, + Some(n) => process::exit(n), + None => { + eprintln!("Killed by signal"); + process::exit(1); + }, + } +} diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs index aafd0f71a59..a19be1bca6c 100644 --- a/clippy_dev/src/lint.rs +++ b/clippy_dev/src/lint.rs @@ -1,17 +1,6 @@ -use crate::cargo_clippy_path; -use std::process::{self, Command, ExitStatus}; -use std::{fs, io}; - -fn exit_if_err(status: io::Result) { - match status.expect("failed to run command").code() { - Some(0) => {}, - Some(n) => process::exit(n), - None => { - eprintln!("Killed by signal"); - process::exit(1); - }, - } -} +use crate::{cargo_clippy_path, exit_if_err}; +use std::fs; +use std::process::{self, Command}; pub fn run<'a>(path: &str, args: impl Iterator) { let is_file = match fs::metadata(path) { -- cgit 1.4.1-3-g733a5 From 79656cc95e0a1156360b678db71b1b851c3d2a61 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 5 May 2023 17:29:40 +0200 Subject: Bump nightly version -> 2023-05-05 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 91e8ccea1f4..60b8a5ac071 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-04-06" +channel = "nightly-2023-05-05" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] -- cgit 1.4.1-3-g733a5